Apply formatting

This will make sure we have a consistent style across our project and the PRs are only concerned with actual changes and no longer about style.
This commit is contained in:
Nanne Baars
2023-01-04 08:07:23 +01:00
committed by GitHub
parent b03777d39b
commit d2a1546dff
336 changed files with 13921 additions and 12688 deletions

View File

@ -22,6 +22,12 @@
package org.owasp.webgoat.webwolf;
import static org.springframework.http.MediaType.ALL_VALUE;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import javax.servlet.http.HttpServletRequest;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@ -41,81 +47,77 @@ import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.view.RedirectView;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import static org.springframework.http.MediaType.ALL_VALUE;
/**
* Controller for uploading a file
*/
/** Controller for uploading a file */
@Controller
@Slf4j
public class FileServer {
@Value("${webwolf.fileserver.location}")
private String fileLocation;
@Value("${server.address}")
private String server;
@Value("${server.port}")
private int port;
@Value("${webwolf.fileserver.location}")
private String fileLocation;
@RequestMapping(path = "/file-server-location", consumes = ALL_VALUE, produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getFileLocation() {
return fileLocation;
@Value("${server.address}")
private String server;
@Value("${server.port}")
private int port;
@RequestMapping(
path = "/file-server-location",
consumes = ALL_VALUE,
produces = MediaType.TEXT_PLAIN_VALUE)
@ResponseBody
public String getFileLocation() {
return fileLocation;
}
@PostMapping(value = "/fileupload")
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
var user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var destinationDir = new File(fileLocation, user.getUsername());
destinationDir.mkdirs();
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
return new ModelAndView(
new RedirectView("files", true),
new ModelMap().addAttribute("uploadSuccess", "File uploaded successful"));
}
@AllArgsConstructor
@Getter
private class UploadedFile {
private final String name;
private final String size;
private final String link;
}
@GetMapping(value = "/files")
public ModelAndView getFiles(HttpServletRequest request) {
WebGoatUser user =
(WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
File destinationDir = new File(fileLocation, username);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("files");
File changeIndicatorFile = new File(destinationDir, user.getUsername() + "_changed");
if (changeIndicatorFile.exists()) {
modelAndView.addObject("uploadSuccess", request.getParameter("uploadSuccess"));
}
changeIndicatorFile.delete();
var uploadedFiles = new ArrayList<>();
File[] files = destinationDir.listFiles(File::isFile);
if (files != null) {
for (File file : files) {
String size = FileUtils.byteCountToDisplaySize(file.length());
String link = String.format("files/%s/%s", username, file.getName());
uploadedFiles.add(new UploadedFile(file.getName(), size, link));
}
}
@PostMapping(value = "/fileupload")
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) throws IOException {
var user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var destinationDir = new File(fileLocation, user.getUsername());
destinationDir.mkdirs();
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
return new ModelAndView(
new RedirectView("files", true),
new ModelMap().addAttribute("uploadSuccess", "File uploaded successful")
);
}
@AllArgsConstructor
@Getter
private class UploadedFile {
private final String name;
private final String size;
private final String link;
}
@GetMapping(value = "/files")
public ModelAndView getFiles(HttpServletRequest request) {
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username = user.getUsername();
File destinationDir = new File(fileLocation, username);
ModelAndView modelAndView = new ModelAndView();
modelAndView.setViewName("files");
File changeIndicatorFile = new File(destinationDir, user.getUsername() + "_changed");
if (changeIndicatorFile.exists()) {
modelAndView.addObject("uploadSuccess", request.getParameter("uploadSuccess"));
}
changeIndicatorFile.delete();
var uploadedFiles = new ArrayList<>();
File[] files = destinationDir.listFiles(File::isFile);
if (files != null) {
for (File file : files) {
String size = FileUtils.byteCountToDisplaySize(file.length());
String link = String.format("files/%s/%s", username, file.getName());
uploadedFiles.add(new UploadedFile(file.getName(), size, link));
}
}
modelAndView.addObject("files", uploadedFiles);
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
return modelAndView;
}
modelAndView.addObject("files", uploadedFiles);
modelAndView.addObject("webwolf_url", "http://" + server + ":" + port);
return modelAndView;
}
}

View File

@ -22,15 +22,14 @@
package org.owasp.webgoat.webwolf;
import java.io.File;
import javax.annotation.PostConstruct;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.PostConstruct;
import java.io.File;
/**
* @author nbaars
* @since 8/13/17.
@ -38,29 +37,31 @@ import java.io.File;
@Configuration
public class MvcConfiguration implements WebMvcConfigurer {
@Value("${webwolf.fileserver.location}")
private String fileLocation;
@Value("${webwolf.fileserver.location}")
private String fileLocation;
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**").addResourceLocations("file:///" + fileLocation + "/");
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/files/**").addResourceLocations("file:///" + fileLocation + "/");
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/webwolf/static/css/");
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/webwolf/static/js/");
registry.addResourceHandler("/images/**").addResourceLocations("classpath:/webwolf/static/images/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("webwolf-login");
registry.addViewController("/home").setViewName("home");
}
@PostConstruct
public void createDirectory() {
File file = new File(fileLocation);
if (!file.exists()) {
file.mkdirs();
}
registry.addResourceHandler("/css/**").addResourceLocations("classpath:/webwolf/static/css/");
registry.addResourceHandler("/js/**").addResourceLocations("classpath:/webwolf/static/js/");
registry
.addResourceHandler("/images/**")
.addResourceLocations("classpath:/webwolf/static/images/");
}
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/login").setViewName("webwolf-login");
registry.addViewController("/home").setViewName("home");
}
@PostConstruct
public void createDirectory() {
File file = new File(fileLocation);
if (!file.exists()) {
file.mkdirs();
}
}
}

View File

@ -1,4 +1,3 @@
/*
* This file is part of WebGoat, an Open Web Application Security Project utility. For details, please see http://www.owasp.org/
*
@ -37,55 +36,50 @@ import org.springframework.security.config.annotation.web.configurers.Expression
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
/**
* Security configuration for WebGoat.
*/
/** Security configuration for WebGoat. */
@Configuration
@AllArgsConstructor
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
private final UserService userDetailsService;
private final UserService userDetailsService;
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
.authorizeRequests()
.antMatchers("/css/**", "/images/**", "/js/**", "/fonts/**", "/webjars/**", "/home").permitAll()
.antMatchers(HttpMethod.GET, "/mail/**", "/requests/**").authenticated()
.antMatchers("/files").authenticated()
.anyRequest().permitAll();
security.and().csrf().disable().formLogin()
.loginPage("/login").failureUrl("/login?error=true");
security.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home", true)
.permitAll();
security.and()
.logout()
.permitAll();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security =
http.authorizeRequests()
.antMatchers("/css/**", "/images/**", "/js/**", "/fonts/**", "/webjars/**", "/home")
.permitAll()
.antMatchers(HttpMethod.GET, "/mail/**", "/requests/**")
.authenticated()
.antMatchers("/files")
.authenticated()
.anyRequest()
.permitAll();
security.and().csrf().disable().formLogin().loginPage("/login").failureUrl("/login?error=true");
security.and().formLogin().loginPage("/login").defaultSuccessUrl("/home", true).permitAll();
security.and().logout().permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService); // .passwordEncoder(bCryptPasswordEncoder());
}
@Bean
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService;
}
@Bean
@Override
public UserDetailsService userDetailsServiceBean() throws Exception {
return userDetailsService;
}
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
@Bean
public NoOpPasswordEncoder passwordEncoder() {
return (NoOpPasswordEncoder) NoOpPasswordEncoder.getInstance();
}
}

View File

@ -36,9 +36,8 @@ import org.springframework.context.annotation.PropertySource;
@EnableAutoConfiguration
public class WebWolf {
@Bean
public HttpTraceRepository traceRepository() {
return new WebWolfTraceRepository();
}
@Bean
public HttpTraceRepository traceRepository() {
return new WebWolfTraceRepository();
}
}

View File

@ -1,5 +1,8 @@
package org.owasp.webgoat.webwolf.jwt;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
@ -7,30 +10,32 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE;
import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
@RestController
public class JWTController {
@GetMapping("/jwt")
public ModelAndView jwt() {
return new ModelAndView("jwt");
}
@GetMapping("/jwt")
public ModelAndView jwt() {
return new ModelAndView("jwt");
}
@PostMapping(value = "/jwt/decode", consumes = APPLICATION_FORM_URLENCODED_VALUE, produces = APPLICATION_JSON_VALUE)
public JWTToken decode(@RequestBody MultiValueMap<String, String> formData) {
var jwt = formData.getFirst("token");
var secretKey = formData.getFirst("secretKey");
return JWTToken.decode(jwt, secretKey);
}
@PostMapping(value = "/jwt/encode", consumes = APPLICATION_FORM_URLENCODED_VALUE, produces = APPLICATION_JSON_VALUE)
public JWTToken encode(@RequestBody MultiValueMap<String, String> formData) {
var header = formData.getFirst("header");
var payload = formData.getFirst("payload");
var secretKey = formData.getFirst("secretKey");
return JWTToken.encode(header, payload, secretKey);
}
@PostMapping(
value = "/jwt/decode",
consumes = APPLICATION_FORM_URLENCODED_VALUE,
produces = APPLICATION_JSON_VALUE)
public JWTToken decode(@RequestBody MultiValueMap<String, String> formData) {
var jwt = formData.getFirst("token");
var secretKey = formData.getFirst("secretKey");
return JWTToken.decode(jwt, secretKey);
}
@PostMapping(
value = "/jwt/encode",
consumes = APPLICATION_FORM_URLENCODED_VALUE,
produces = APPLICATION_JSON_VALUE)
public JWTToken encode(@RequestBody MultiValueMap<String, String> formData) {
var header = formData.getFirst("header");
var payload = formData.getFirst("payload");
var secretKey = formData.getFirst("secretKey");
return JWTToken.encode(header, payload, secretKey);
}
}

View File

@ -1,7 +1,13 @@
package org.owasp.webgoat.webwolf.jwt;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.util.Base64Utils.decodeFromUrlSafeString;
import static org.springframework.util.StringUtils.hasText;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.Map;
import java.util.TreeMap;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Getter;
@ -15,14 +21,6 @@ import org.jose4j.jwx.CompactSerializer;
import org.jose4j.keys.HmacKey;
import org.jose4j.lang.JoseException;
import java.util.Map;
import java.util.TreeMap;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.jose4j.jwx.CompactSerializer.serialize;
import static org.springframework.util.Base64Utils.decodeFromUrlSafeString;
import static org.springframework.util.StringUtils.hasText;
@NoArgsConstructor
@AllArgsConstructor
@Getter
@ -30,108 +28,111 @@ import static org.springframework.util.StringUtils.hasText;
@Builder(toBuilder = true)
public class JWTToken {
private String encoded = "";
private String secretKey;
private String header;
private boolean validHeader;
private boolean validPayload;
private boolean validToken;
private String payload;
private boolean signatureValid = true;
private String encoded = "";
private String secretKey;
private String header;
private boolean validHeader;
private boolean validPayload;
private boolean validToken;
private String payload;
private boolean signatureValid = true;
public static JWTToken decode(String jwt, String secretKey) {
var token = parseToken(jwt.trim().replace(System.getProperty("line.separator"), ""));
return token.toBuilder().signatureValid(validateSignature(secretKey, jwt)).build();
public static JWTToken decode(String jwt, String secretKey) {
var token = parseToken(jwt.trim().replace(System.getProperty("line.separator"), ""));
return token.toBuilder().signatureValid(validateSignature(secretKey, jwt)).build();
}
private static Map<String, Object> parse(String header) {
var reader = new ObjectMapper();
try {
return reader.readValue(header, TreeMap.class);
} catch (JsonProcessingException e) {
return Map.of();
}
}
private static String write(String originalValue, Map<String, Object> data) {
var writer = new ObjectMapper().writerWithDefaultPrettyPrinter();
try {
if (data.isEmpty()) {
return originalValue;
}
return writer.writeValueAsString(data);
} catch (JsonProcessingException e) {
return originalValue;
}
}
public static JWTToken encode(String header, String payloadAsString, String secretKey) {
var headers = parse(header);
var payload = parse(payloadAsString);
var builder =
JWTToken.builder()
.header(write(header, headers))
.payload(write(payloadAsString, payload))
.validHeader(!hasText(header) || !headers.isEmpty())
.validToken(true)
.validPayload(!hasText(payloadAsString) || !payload.isEmpty());
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(payloadAsString);
headers.forEach((k, v) -> jws.setHeader(k, v));
if (!headers.isEmpty()) { // otherwise e30 meaning {} will be shown as header
builder.encoded(
CompactSerializer.serialize(
new String[] {jws.getHeaders().getEncodedHeader(), jws.getEncodedPayload()}));
}
private static Map<String, Object> parse(String header) {
var reader = new ObjectMapper();
try {
return reader.readValue(header, TreeMap.class);
} catch (JsonProcessingException e) {
return Map.of();
}
// Only sign when valid header and payload
if (!headers.isEmpty() && !payload.isEmpty() && hasText(secretKey)) {
jws.setDoKeyValidation(false);
jws.setKey(new HmacKey(secretKey.getBytes(UTF_8)));
try {
builder.encoded(jws.getCompactSerialization());
builder.signatureValid(true);
} catch (JoseException e) {
// Do nothing
}
}
return builder.build();
}
private static String write(String originalValue, Map<String, Object> data) {
var writer = new ObjectMapper().writerWithDefaultPrettyPrinter();
try {
if (data.isEmpty()) {
return originalValue;
}
return writer.writeValueAsString(data);
} catch (JsonProcessingException e) {
return originalValue;
}
private static JWTToken parseToken(String jwt) {
var token = jwt.split("\\.");
var builder = JWTToken.builder().encoded(jwt);
if (token.length >= 2) {
var header = new String(decodeFromUrlSafeString(token[0]), UTF_8);
var payloadAsString = new String(decodeFromUrlSafeString(token[1]), UTF_8);
var headers = parse(header);
var payload = parse(payloadAsString);
builder.header(write(header, headers));
builder.payload(write(payloadAsString, payload));
builder.validHeader(!headers.isEmpty());
builder.validPayload(!payload.isEmpty());
builder.validToken(!headers.isEmpty() && !payload.isEmpty());
} else {
builder.validToken(false);
}
return builder.build();
}
public static JWTToken encode(String header, String payloadAsString, String secretKey) {
var headers = parse(header);
var payload = parse(payloadAsString);
var builder = JWTToken.builder()
.header(write(header, headers))
.payload(write(payloadAsString, payload))
.validHeader(!hasText(header) || !headers.isEmpty())
.validToken(true)
.validPayload(!hasText(payloadAsString) || !payload.isEmpty());
JsonWebSignature jws = new JsonWebSignature();
jws.setPayload(payloadAsString);
headers.forEach((k, v) -> jws.setHeader(k, v));
if (!headers.isEmpty()) { //otherwise e30 meaning {} will be shown as header
builder.encoded(CompactSerializer.serialize(new String[]{jws.getHeaders().getEncodedHeader(), jws.getEncodedPayload()}));
}
//Only sign when valid header and payload
if (!headers.isEmpty() && !payload.isEmpty() && hasText(secretKey)) {
jws.setDoKeyValidation(false);
jws.setKey(new HmacKey(secretKey.getBytes(UTF_8)));
try {
builder.encoded(jws.getCompactSerialization());
builder.signatureValid(true);
} catch (JoseException e) {
//Do nothing
}
}
return builder.build();
}
private static JWTToken parseToken(String jwt) {
var token = jwt.split("\\.");
var builder = JWTToken.builder().encoded(jwt);
if (token.length >= 2) {
var header = new String(decodeFromUrlSafeString(token[0]), UTF_8);
var payloadAsString = new String(decodeFromUrlSafeString(token[1]), UTF_8);
var headers = parse(header);
var payload = parse(payloadAsString);
builder.header(write(header, headers));
builder.payload(write(payloadAsString, payload));
builder.validHeader(!headers.isEmpty());
builder.validPayload(!payload.isEmpty());
builder.validToken(!headers.isEmpty() && !payload.isEmpty());
} else {
builder.validToken(false);
}
return builder.build();
}
private static boolean validateSignature(String secretKey, String jwt) {
if (hasText(secretKey)) {
JwtConsumer jwtConsumer = new JwtConsumerBuilder()
.setSkipAllValidators()
.setVerificationKey(new HmacKey(secretKey.getBytes(UTF_8)))
.setRelaxVerificationKeyValidation()
.build();
try {
jwtConsumer.processToClaims(jwt);
return true;
} catch (InvalidJwtException e) {
return false;
}
}
private static boolean validateSignature(String secretKey, String jwt) {
if (hasText(secretKey)) {
JwtConsumer jwtConsumer =
new JwtConsumerBuilder()
.setSkipAllValidators()
.setVerificationKey(new HmacKey(secretKey.getBytes(UTF_8)))
.setRelaxVerificationKeyValidation()
.build();
try {
jwtConsumer.processToClaims(jwt);
return true;
} catch (InvalidJwtException e) {
return false;
}
}
return false;
}
}

View File

@ -23,16 +23,15 @@
package org.owasp.webgoat.webwolf.mailbox;
import com.fasterxml.jackson.annotation.JsonIgnore;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import javax.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import javax.persistence.*;
import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
/**
* @author nbaars
* @since 8/20/17.
@ -44,31 +43,32 @@ import java.time.format.DateTimeFormatter;
@NoArgsConstructor
public class Email implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@JsonIgnore
private LocalDateTime time = LocalDateTime.now();
@Column(length = 1024)
private String contents;
private String sender;
private String title;
private String recipient;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public String getSummary() {
return "-" + this.contents.substring(0, Math.min(50, contents.length()));
}
@JsonIgnore private LocalDateTime time = LocalDateTime.now();
public LocalDateTime getTimestamp() {
return time;
}
@Column(length = 1024)
private String contents;
public String getTime() {
return DateTimeFormatter.ofPattern("h:mm a").format(time);
}
private String sender;
private String title;
private String recipient;
public String getShortSender() {
return sender.substring(0, sender.indexOf("@"));
}
public String getSummary() {
return "-" + this.contents.substring(0, Math.min(50, contents.length()));
}
public LocalDateTime getTimestamp() {
return time;
}
public String getTime() {
return DateTimeFormatter.ofPattern("h:mm a").format(time);
}
public String getShortSender() {
return sender.substring(0, sender.indexOf("@"));
}
}

View File

@ -22,6 +22,7 @@
package org.owasp.webgoat.webwolf.mailbox;
import java.util.List;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
@ -34,32 +35,30 @@ import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.ModelAndView;
import java.util.List;
@RestController
@AllArgsConstructor
@Slf4j
public class MailboxController {
private final MailboxRepository mailboxRepository;
private final MailboxRepository mailboxRepository;
@GetMapping(value = "/mail")
public ModelAndView mail() {
UserDetails user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
ModelAndView modelAndView = new ModelAndView();
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
if (emails != null && !emails.isEmpty()) {
modelAndView.addObject("total", emails.size());
modelAndView.addObject("emails", emails);
}
modelAndView.setViewName("mailbox");
return modelAndView;
}
@PostMapping(value = "/mail")
public ResponseEntity<?> sendEmail(@RequestBody Email email) {
mailboxRepository.save(email);
return ResponseEntity.status(HttpStatus.CREATED).build();
@GetMapping(value = "/mail")
public ModelAndView mail() {
UserDetails user =
(UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
ModelAndView modelAndView = new ModelAndView();
List<Email> emails = mailboxRepository.findByRecipientOrderByTimeDesc(user.getUsername());
if (emails != null && !emails.isEmpty()) {
modelAndView.addObject("total", emails.size());
modelAndView.addObject("emails", emails);
}
modelAndView.setViewName("mailbox");
return modelAndView;
}
@PostMapping(value = "/mail")
public ResponseEntity<?> sendEmail(@RequestBody Email email) {
mailboxRepository.save(email);
return ResponseEntity.status(HttpStatus.CREATED).build();
}
}

View File

@ -22,9 +22,8 @@
package org.owasp.webgoat.webwolf.mailbox;
import org.springframework.data.jpa.repository.JpaRepository;
import java.util.List;
import org.springframework.data.jpa.repository.JpaRepository;
/**
* @author nbaars
@ -32,6 +31,5 @@ import java.util.List;
*/
public interface MailboxRepository extends JpaRepository<Email, String> {
List<Email> findByRecipientOrderByTimeDesc(String recipient);
List<Email> findByRecipientOrderByTimeDesc(String recipient);
}

View File

@ -22,26 +22,31 @@
package org.owasp.webgoat.webwolf.requests;
import java.util.concurrent.Callable;
import javax.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import javax.servlet.http.HttpServletRequest;
import java.util.concurrent.Callable;
@Controller
@Slf4j
@RequestMapping("/landing/**")
public class LandingPage {
@RequestMapping(method = {RequestMethod.POST, RequestMethod.GET, RequestMethod.DELETE, RequestMethod.PATCH, RequestMethod.PUT})
public Callable<ResponseEntity<?>> ok(HttpServletRequest request) {
return () -> {
log.trace("Incoming request for: {}", request.getRequestURL());
return ResponseEntity.ok().build();
};
}
@RequestMapping(
method = {
RequestMethod.POST,
RequestMethod.GET,
RequestMethod.DELETE,
RequestMethod.PATCH,
RequestMethod.PUT
})
public Callable<ResponseEntity<?>> ok(HttpServletRequest request) {
return () -> {
log.trace("Incoming request for: {}", request.getRequestURL());
return ResponseEntity.ok().build();
};
}
}

View File

@ -22,8 +22,11 @@
package org.owasp.webgoat.webwolf.requests;
import static java.util.stream.Collectors.toList;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.Instant;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@ -38,13 +41,8 @@ import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.servlet.ModelAndView;
import java.time.Instant;
import static java.util.stream.Collectors.toList;
/**
* Controller for fetching all the HTTP requests from WebGoat to WebWolf for a specific
* user.
* Controller for fetching all the HTTP requests from WebGoat to WebWolf for a specific user.
*
* @author nbaars
* @since 8/13/17.
@ -55,52 +53,58 @@ import static java.util.stream.Collectors.toList;
@RequestMapping(value = "/requests")
public class Requests {
private final WebWolfTraceRepository traceRepository;
private final ObjectMapper objectMapper;
private final WebWolfTraceRepository traceRepository;
private final ObjectMapper objectMapper;
@AllArgsConstructor
@Getter
private class Tracert {
private final Instant date;
private final String path;
private final String json;
@AllArgsConstructor
@Getter
private class Tracert {
private final Instant date;
private final String path;
private final String json;
}
@GetMapping
public ModelAndView get() {
var model = new ModelAndView("requests");
var user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var traces =
traceRepository.findAllTraces().stream()
.filter(t -> allowedTrace(t, user))
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t)))
.collect(toList());
model.addObject("traces", traces);
return model;
}
private boolean allowedTrace(HttpTrace t, UserDetails user) {
Request req = t.getRequest();
boolean allowed = true;
/* do not show certain traces to other users in a classroom setup */
if (req.getUri().getPath().contains("/files")
&& !req.getUri().getPath().contains(user.getUsername())) {
allowed = false;
} else if (req.getUri().getPath().contains("/landing")
&& req.getUri().getQuery() != null
&& req.getUri().getQuery().contains("uniqueCode")
&& !req.getUri().getQuery().contains(StringUtils.reverse(user.getUsername()))) {
allowed = false;
}
@GetMapping
public ModelAndView get() {
var model = new ModelAndView("requests");
var user = (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
var traces = traceRepository.findAllTraces().stream()
.filter(t -> allowedTrace(t, user))
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))).collect(toList());
model.addObject("traces", traces);
return allowed;
}
return model;
}
private boolean allowedTrace(HttpTrace t, UserDetails user) {
Request req = t.getRequest();
boolean allowed = true;
/* do not show certain traces to other users in a classroom setup */
if (req.getUri().getPath().contains("/files") && !req.getUri().getPath().contains(user.getUsername())) {
allowed = false;
} else if (req.getUri().getPath().contains("/landing") && req.getUri().getQuery()!=null && req.getUri().getQuery().contains("uniqueCode") && !req.getUri().getQuery().contains(StringUtils.reverse(user.getUsername()))) {
allowed = false;
}
return allowed;
}
private String path(HttpTrace t) {
return (String) t.getRequest().getUri().getPath();
}
private String path(HttpTrace t) {
return (String) t.getRequest().getUri().getPath();
}
private String toJsonString(HttpTrace t) {
try {
return objectMapper.writeValueAsString(t);
} catch (JsonProcessingException e) {
log.error("Unable to create json", e);
}
return "No request(s) found";
private String toJsonString(HttpTrace t) {
try {
return objectMapper.writeValueAsString(t);
} catch (JsonProcessingException e) {
log.error("Unable to create json", e);
}
return "No request(s) found";
}
}

View File

@ -23,14 +23,12 @@
package org.owasp.webgoat.webwolf.requests;
import com.google.common.collect.EvictingQueue;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.actuate.trace.http.HttpTrace;
import org.springframework.boot.actuate.trace.http.HttpTraceRepository;
import java.util.ArrayList;
import java.util.List;
/**
* Keep track of all the incoming requests, we are only keeping track of request originating from
* WebGoat.
@ -41,28 +39,38 @@ import java.util.List;
@Slf4j
public class WebWolfTraceRepository implements HttpTraceRepository {
private final EvictingQueue<HttpTrace> traces = EvictingQueue.create(10000);
private final List<String> exclusionList = List.of("/tmpdir", "/home", "/files",
"/images/", "/favicon.ico", "/js/", "/webjars/", "/requests", "/css/", "/mail");
private final EvictingQueue<HttpTrace> traces = EvictingQueue.create(10000);
private final List<String> exclusionList =
List.of(
"/tmpdir",
"/home",
"/files",
"/images/",
"/favicon.ico",
"/js/",
"/webjars/",
"/requests",
"/css/",
"/mail");
@Override
public List<HttpTrace> findAll() {
return List.of();
}
@Override
public List<HttpTrace> findAll() {
return List.of();
}
public List<HttpTrace> findAllTraces() {
return new ArrayList<>(traces);
}
public List<HttpTrace> findAllTraces() {
return new ArrayList<>(traces);
}
private boolean isInExclusionList(String path) {
return exclusionList.stream().anyMatch(e -> path.contains(e));
}
private boolean isInExclusionList(String path) {
return exclusionList.stream().anyMatch(e -> path.contains(e));
}
@Override
public void add(HttpTrace httpTrace) {
var path = httpTrace.getRequest().getUri().getPath();
if (!isInExclusionList(path)) {
traces.add(httpTrace);
}
@Override
public void add(HttpTrace httpTrace) {
var path = httpTrace.getRequest().getUri().getPath();
if (!isInExclusionList(path)) {
traces.add(httpTrace);
}
}
}

View File

@ -30,5 +30,5 @@ import org.springframework.data.jpa.repository.JpaRepository;
*/
public interface UserRepository extends JpaRepository<WebGoatUser, String> {
WebGoatUser findByUsername(String username);
WebGoatUser findByUsername(String username);
}

View File

@ -33,24 +33,23 @@ import org.springframework.stereotype.Service;
@Service
public class UserService implements UserDetailsService {
private UserRepository userRepository;
private UserRepository userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
public UserService(UserRepository userRepository) {
this.userRepository = userRepository;
}
@Override
public WebGoatUser loadUserByUsername(final String username) throws UsernameNotFoundException {
WebGoatUser webGoatUser = userRepository.findByUsername(username);
if (webGoatUser == null) {
throw new UsernameNotFoundException("User not found");
}
webGoatUser.createUser();
return webGoatUser;
}
@Override
public WebGoatUser loadUserByUsername(final String username) throws UsernameNotFoundException {
WebGoatUser webGoatUser = userRepository.findByUsername(username);
if (webGoatUser == null) {
throw new UsernameNotFoundException("User not found");
}
webGoatUser.createUser();
return webGoatUser;
}
public void addUser(final String username, final String password) {
userRepository.save(new WebGoatUser(username, password));
}
public void addUser(final String username, final String password) {
userRepository.save(new WebGoatUser(username, password));
}
}

View File

@ -22,17 +22,15 @@
package org.owasp.webgoat.webwolf.user;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import java.util.Collection;
import java.util.Collections;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Transient;
import java.util.Collection;
import java.util.Collections;
import lombok.Getter;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
/**
* @author nbaars
@ -42,48 +40,43 @@ import java.util.Collections;
@Entity
public class WebGoatUser implements UserDetails {
@Id
private String username;
private String password;
@Transient
private User user;
@Id private String username;
private String password;
@Transient private User user;
protected WebGoatUser() {
}
protected WebGoatUser() {}
public WebGoatUser(String username, String password) {
this.username = username;
this.password = password;
createUser();
}
public WebGoatUser(String username, String password) {
this.username = username;
this.password = password;
createUser();
}
public void createUser() {
this.user = new User(username, password, getAuthorities());
}
public void createUser() {
this.user = new User(username, password, getAuthorities());
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList();
}
public Collection<? extends GrantedAuthority> getAuthorities() {
return Collections.emptyList();
}
@Override
public boolean isAccountNonExpired() {
return this.user.isAccountNonExpired();
}
@Override
public boolean isAccountNonExpired() {
return this.user.isAccountNonExpired();
}
@Override
public boolean isAccountNonLocked() {
return this.user.isAccountNonLocked();
}
@Override
public boolean isAccountNonLocked() {
return this.user.isAccountNonLocked();
}
@Override
public boolean isCredentialsNonExpired() {
return this.user.isCredentialsNonExpired();
}
@Override
public boolean isCredentialsNonExpired() {
return this.user.isCredentialsNonExpired();
}
@Override
public boolean isEnabled() {
return this.user.isEnabled();
}
@Override
public boolean isEnabled() {
return this.user.isEnabled();
}
}