- Added new challenges
- Added new webapplication called WebWolf to make attacks more realistic - Added WebWolf lesson to explain the concepts behind this new application
This commit is contained in:
89
webwolf/src/main/java/org/owasp/webwolf/FileServer.java
Normal file
89
webwolf/src/main/java/org/owasp/webwolf/FileServer.java
Normal file
@ -0,0 +1,89 @@
|
||||
package org.owasp.webwolf;
|
||||
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.io.Files;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.SneakyThrows;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.owasp.webwolf.user.WebGoatUser;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
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.util.List;
|
||||
|
||||
/**
|
||||
* Controller for uploading a file
|
||||
*/
|
||||
@Controller
|
||||
@Slf4j
|
||||
public class FileServer {
|
||||
|
||||
@Value("${webwolf.fileserver.location}")
|
||||
private String fileLocatation;
|
||||
|
||||
@PostMapping(value = "/WebWolf/fileupload")
|
||||
@SneakyThrows
|
||||
public ModelAndView importFile(@RequestParam("file") MultipartFile myFile) {
|
||||
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
File destinationDir = new File(fileLocatation, user.getUsername());
|
||||
destinationDir.mkdirs();
|
||||
myFile.transferTo(new File(destinationDir, myFile.getOriginalFilename()));
|
||||
log.debug("File saved to {}", new File(destinationDir, myFile.getOriginalFilename()));
|
||||
Files.touch(new File(destinationDir, user.getUsername() + "_changed"));
|
||||
|
||||
ModelMap model = new ModelMap();
|
||||
model.addAttribute("uploadSuccess", "File uploaded successful");
|
||||
return new ModelAndView(
|
||||
new RedirectView("files", true),
|
||||
model
|
||||
);
|
||||
}
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private class UploadedFile {
|
||||
private final String name;
|
||||
private final String size;
|
||||
private final String link;
|
||||
}
|
||||
|
||||
@GetMapping(value = "/WebWolf/files")
|
||||
public ModelAndView getFiles(HttpServletRequest request) {
|
||||
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
String username = user.getUsername();
|
||||
File destinationDir = new File(fileLocatation, 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();
|
||||
|
||||
List<UploadedFile> uploadedFiles = Lists.newArrayList();
|
||||
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);
|
||||
return modelAndView;
|
||||
}
|
||||
}
|
@ -0,0 +1,43 @@
|
||||
package org.owasp.webwolf;
|
||||
|
||||
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.WebMvcConfigurerAdapter;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
@Configuration
|
||||
public class MvcConfiguration extends WebMvcConfigurerAdapter {
|
||||
|
||||
@Value("${webwolf.fileserver.location}")
|
||||
private String fileLocatation;
|
||||
|
||||
@Override
|
||||
public void addResourceHandlers(ResourceHandlerRegistry registry) {
|
||||
registry.addResourceHandler("/files/**").addResourceLocations("file:///" + fileLocatation + "/");
|
||||
super.addResourceHandlers(registry);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addViewControllers(ViewControllerRegistry registry) {
|
||||
registry.addViewController("/login").setViewName("login");
|
||||
registry.addViewController("/WebWolf/home").setViewName("home");
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void createDirectory() {
|
||||
File file = new File(fileLocatation);
|
||||
if (!file.exists()) {
|
||||
file.mkdirs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
|
||||
/**
|
||||
* ************************************************************************************************
|
||||
* This file is part of WebGoat, an Open Web Application Security Project utility. For details,
|
||||
* please see http://www.owasp.org/
|
||||
* <p>
|
||||
* Copyright (c) 2002 - 20014 Bruce Mayhew
|
||||
* <p>
|
||||
* This program is free software; you can redistribute it and/or modify it under the terms of the
|
||||
* GNU General Public License as published by the Free Software Foundation; either version 2 of the
|
||||
* License, or (at your option) any later version.
|
||||
* <p>
|
||||
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without
|
||||
* even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* General Public License for more details.
|
||||
* <p>
|
||||
* You should have received a copy of the GNU General Public License along with this program; if
|
||||
* not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||
* 02111-1307, USA.
|
||||
* <p>
|
||||
* Getting Source ==============
|
||||
* <p>
|
||||
* Source for this application is maintained at https://github.com/WebGoat/WebGoat, a repository for free software
|
||||
* projects.
|
||||
* <p>
|
||||
*
|
||||
* @author WebGoat
|
||||
* @version $Id: $Id
|
||||
* @since December 12, 2015
|
||||
*/
|
||||
package org.owasp.webwolf;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.owasp.webwolf.user.UserService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
|
||||
/**
|
||||
* Security configuration for WebGoat.
|
||||
*/
|
||||
@Configuration
|
||||
@AllArgsConstructor
|
||||
@EnableWebSecurity
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
|
||||
|
||||
private final UserService userDetailsService;
|
||||
|
||||
@Override
|
||||
protected void configure(HttpSecurity http) throws Exception {
|
||||
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
|
||||
.authorizeRequests()
|
||||
.antMatchers("/css/**", "/images/**", "/js/**", "/fonts/**", "/webjars/**").permitAll()
|
||||
.antMatchers("/WebWolf/**").authenticated()
|
||||
.anyRequest().permitAll();
|
||||
security.and().csrf().disable().formLogin()
|
||||
.loginPage("/login").failureUrl("/login?error=true");
|
||||
security.and()
|
||||
.formLogin()
|
||||
.loginPage("/login")
|
||||
.defaultSuccessUrl("/WebWolf/home", true)
|
||||
.permitAll();
|
||||
security.and()
|
||||
.logout()
|
||||
.permitAll();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Override
|
||||
public UserDetailsService userDetailsServiceBean() throws Exception {
|
||||
return userDetailsService;
|
||||
}
|
||||
}
|
59
webwolf/src/main/java/org/owasp/webwolf/WebWolf.java
Normal file
59
webwolf/src/main/java/org/owasp/webwolf/WebWolf.java
Normal file
@ -0,0 +1,59 @@
|
||||
package org.owasp.webwolf;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webwolf.requests.WebWolfTraceRepository;
|
||||
import org.owasp.webwolf.user.WebGoatUserToCookieRepository;
|
||||
import org.springframework.boot.SpringApplication;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||
import org.springframework.boot.autoconfigure.jms.DefaultJmsListenerContainerFactoryConfigurer;
|
||||
import org.springframework.boot.builder.SpringApplicationBuilder;
|
||||
import org.springframework.boot.web.support.SpringBootServletInitializer;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.jms.config.DefaultJmsListenerContainerFactory;
|
||||
import org.springframework.jms.config.JmsListenerContainerFactory;
|
||||
import org.springframework.jms.support.converter.MappingJackson2MessageConverter;
|
||||
import org.springframework.jms.support.converter.MessageConverter;
|
||||
import org.springframework.jms.support.converter.MessageType;
|
||||
|
||||
import javax.jms.ConnectionFactory;
|
||||
|
||||
|
||||
@SpringBootApplication
|
||||
@Slf4j
|
||||
public class WebWolf extends SpringBootServletInitializer {
|
||||
|
||||
@Bean
|
||||
public TraceRepository traceRepository(WebGoatUserToCookieRepository repository) {
|
||||
return new WebWolfTraceRepository(repository);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
|
||||
return application.sources(WebWolf.class);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public JmsListenerContainerFactory<?> jmsFactory(ConnectionFactory connectionFactory,
|
||||
DefaultJmsListenerContainerFactoryConfigurer configurer) {
|
||||
DefaultJmsListenerContainerFactory factory = new DefaultJmsListenerContainerFactory();
|
||||
// This provides all boot's default to this factory, including the message converter
|
||||
configurer.configure(factory, connectionFactory);
|
||||
// You could still override some of Boot's default if necessary.
|
||||
return factory;
|
||||
}
|
||||
|
||||
@Bean
|
||||
public MessageConverter jacksonJmsMessageConverter(ObjectMapper objectMapper) {
|
||||
MappingJackson2MessageConverter converter = new MappingJackson2MessageConverter();
|
||||
converter.setTargetType(MessageType.TEXT);
|
||||
converter.setTypeIdPropertyName("_type");
|
||||
converter.setObjectMapper(objectMapper);
|
||||
return converter;
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
SpringApplication.run(WebWolf.class, args);
|
||||
}
|
||||
}
|
42
webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java
Normal file
42
webwolf/src/main/java/org/owasp/webwolf/mailbox/Email.java
Normal file
@ -0,0 +1,42 @@
|
||||
package org.owasp.webwolf.mailbox;
|
||||
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.mongodb.core.index.Indexed;
|
||||
import org.springframework.data.mongodb.core.mapping.Document;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@Document
|
||||
public class Email implements Serializable {
|
||||
|
||||
@Id
|
||||
private String id;
|
||||
private LocalDateTime time;
|
||||
private String contents;
|
||||
private String sender;
|
||||
private String title;
|
||||
@Indexed
|
||||
private String recipient;
|
||||
|
||||
public String getSummary() {
|
||||
return "-" + this.contents.substring(0, 50);
|
||||
}
|
||||
|
||||
public String getTime() {
|
||||
return DateTimeFormatter.ofPattern("h:mm a").format(time);
|
||||
}
|
||||
|
||||
public String getShortSender() {
|
||||
return sender.substring(0, sender.indexOf("@"));
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package org.owasp.webwolf.mailbox;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.owasp.webwolf.user.WebGoatUser;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/17/17.
|
||||
*/
|
||||
@RestController
|
||||
@AllArgsConstructor
|
||||
public class MailboxController {
|
||||
|
||||
private final MailboxRepository mailboxRepository;
|
||||
|
||||
@GetMapping(value = "/WebWolf/mail")
|
||||
public ModelAndView mail() {
|
||||
WebGoatUser user = (WebGoatUser) 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;
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package org.owasp.webwolf.mailbox;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.mail.IncomingMailEvent;
|
||||
import org.owasp.webwolf.user.UserRepository;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@Component
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
public class MailboxListener {
|
||||
|
||||
private final MailboxRepository repository;
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@JmsListener(destination = "mailbox", containerFactory = "jmsFactory")
|
||||
public void incomingMail(IncomingMailEvent event) {
|
||||
if (userRepository.findByUsername(event.getRecipient()) != null) {
|
||||
Email email = Email.builder()
|
||||
.contents(event.getContents())
|
||||
.sender(event.getSender())
|
||||
.time(event.getTime())
|
||||
.recipient(event.getRecipient())
|
||||
.title(event.getTitle()).build();
|
||||
repository.save(email);
|
||||
} else {
|
||||
log.trace("Mail received for unknown user: {}", event.getRecipient());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
package org.owasp.webwolf.mailbox;
|
||||
|
||||
import org.bson.types.ObjectId;
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/17/17.
|
||||
*/
|
||||
public interface MailboxRepository extends MongoRepository<Email, ObjectId> {
|
||||
|
||||
List<Email> findByRecipientOrderByTimeDesc(String recipient);
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.owasp.webwolf.requests;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webwolf.user.WebGoatUser;
|
||||
import org.springframework.boot.actuate.trace.Trace;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
|
||||
/**
|
||||
* Controller for fetching all the HTTP requests from WebGoat to WebWolf for a specific
|
||||
* user.
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
@Controller
|
||||
@AllArgsConstructor
|
||||
@Slf4j
|
||||
@RequestMapping(value = "/WebWolf/requests")
|
||||
public class Requests {
|
||||
|
||||
private final WebWolfTraceRepository traceRepository;
|
||||
private final ObjectMapper objectMapper;
|
||||
|
||||
@AllArgsConstructor
|
||||
@Getter
|
||||
private class Tracert {
|
||||
private final Date date;
|
||||
private final String path;
|
||||
private final String json;
|
||||
}
|
||||
|
||||
@GetMapping
|
||||
public ModelAndView get(HttpServletRequest request) {
|
||||
ModelAndView m = new ModelAndView("requests");
|
||||
WebGoatUser user = (WebGoatUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
|
||||
List<Tracert> traces = traceRepository.findTraceForUser(user.getUsername()).stream()
|
||||
.map(t -> new Tracert(t.getTimestamp(), path(t), toJsonString(t))).collect(toList());
|
||||
m.addObject("traces", traces);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
private String path(Trace t) {
|
||||
return (String) t.getInfo().getOrDefault("path", "");
|
||||
}
|
||||
|
||||
private String toJsonString(Trace t) {
|
||||
try {
|
||||
return objectMapper.writeValueAsString(t.getInfo());
|
||||
} catch (JsonProcessingException e) {
|
||||
log.error("Unable to create json", e);
|
||||
}
|
||||
return "No request(s) found";
|
||||
}
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
package org.owasp.webwolf.requests;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.Lists;
|
||||
import com.google.common.collect.Maps;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webwolf.user.WebGoatUser;
|
||||
import org.owasp.webwolf.user.WebGoatUserCookie;
|
||||
import org.owasp.webwolf.user.WebGoatUserToCookieRepository;
|
||||
import org.springframework.boot.actuate.trace.Trace;
|
||||
import org.springframework.boot.actuate.trace.TraceRepository;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
|
||||
import java.net.HttpCookie;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentLinkedDeque;
|
||||
|
||||
import static java.util.Optional.of;
|
||||
|
||||
/**
|
||||
* Keep track of all the incoming requests, we are only keeping track of request originating from
|
||||
* WebGoat and only if there is a cookie (otherwise we can never relate it back to a user).
|
||||
*
|
||||
* @author nbaars
|
||||
* @since 8/13/17.
|
||||
*/
|
||||
@Slf4j
|
||||
public class WebWolfTraceRepository implements TraceRepository {
|
||||
|
||||
private final LoadingCache<String, ConcurrentLinkedDeque<Trace>> cookieTraces = CacheBuilder.newBuilder()
|
||||
.maximumSize(4000).build(new CacheLoader<String, ConcurrentLinkedDeque<Trace>>() {
|
||||
@Override
|
||||
public ConcurrentLinkedDeque<Trace> load(String s) throws Exception {
|
||||
return new ConcurrentLinkedDeque<>();
|
||||
}
|
||||
});
|
||||
private final WebGoatUserToCookieRepository repository;
|
||||
|
||||
public WebWolfTraceRepository(WebGoatUserToCookieRepository repository) {
|
||||
this.repository = repository;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Trace> findAll() {
|
||||
HashMap<String, Object> map = Maps.newHashMap();
|
||||
map.put("nice", "Great you found the standard Spring Boot tracing endpoint!");
|
||||
Trace trace = new Trace(new Date(), map);
|
||||
return Lists.newArrayList(trace);
|
||||
}
|
||||
|
||||
public List<Trace> findTraceForUser(String username) {
|
||||
return Lists.newArrayList(cookieTraces.getUnchecked(username));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void add(Map<String, Object> map) {
|
||||
Optional<String> host = getFromHeaders("host", map);
|
||||
String path = (String) map.getOrDefault("path", "");
|
||||
if (host.isPresent() && ("/".equals(path) || path.contains("challenge"))) {
|
||||
Optional<String> cookie = getFromHeaders("cookie", map);
|
||||
cookie.ifPresent(c -> {
|
||||
Optional<String> user = findUserBasedOnCookie(c);
|
||||
user.ifPresent(u -> {
|
||||
ConcurrentLinkedDeque<Trace> traces = this.cookieTraces.getUnchecked(u);
|
||||
traces.addFirst(new Trace(new Date(), map));
|
||||
cookieTraces.put(u, traces);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<String> findUserBasedOnCookie(String cookiesIncomingRequest) {
|
||||
//Request from WebGoat to WebWolf will contain the session cookie of WebGoat try to map it to a user
|
||||
//this mapping is added to userSession by the CookieFilter in WebGoat code
|
||||
HttpCookie cookie = HttpCookie.parse(cookiesIncomingRequest).get(0);
|
||||
Optional<WebGoatUserCookie> userToCookie = repository.findByCookie(cookie.getValue());
|
||||
Optional<String> user = userToCookie.map(u -> u.getUsername());
|
||||
|
||||
if (!user.isPresent()) {
|
||||
//User is maybe logged in to WebWolf use this user
|
||||
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
|
||||
if (authentication != null && authentication.getPrincipal() instanceof WebGoatUser) {
|
||||
WebGoatUser wg = (WebGoatUser) authentication.getPrincipal();
|
||||
user = of(wg.getUsername());
|
||||
}
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
|
||||
private Optional<String> getFromHeaders(String header, Map<String, Object> map) {
|
||||
Map<String, Object> headers = (Map<String, Object>) map.get("headers");
|
||||
if (headers != null) {
|
||||
Map<String, Object> request = (Map<String, Object>) headers.get("request");
|
||||
if (request != null) {
|
||||
return Optional.ofNullable((String) request.get(header));
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
@ -0,0 +1,33 @@
|
||||
package org.owasp.webwolf.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.owasp.webgoat.login.LoginEvent;
|
||||
import org.owasp.webgoat.login.LogoutEvent;
|
||||
import org.springframework.jms.annotation.JmsListener;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@Component
|
||||
@Slf4j
|
||||
@AllArgsConstructor
|
||||
public class LoginListener {
|
||||
|
||||
private final WebGoatUserToCookieRepository repository;
|
||||
|
||||
@JmsListener(destination = "webgoat", containerFactory = "jmsFactory", selector = "type = 'LoginEvent'")
|
||||
public void loginEvent(LoginEvent loginEvent) {
|
||||
log.trace("Login event occurred for user: '{}'", loginEvent.getUser());
|
||||
repository.save(new WebGoatUserCookie(loginEvent.getUser(), loginEvent.getCookie()));
|
||||
}
|
||||
|
||||
@JmsListener(destination = "webgoat", containerFactory = "jmsFactory", selector = "type = 'LogoutEvent'")
|
||||
public void logoutEvent(LogoutEvent logoutEvent) {
|
||||
repository.delete(logoutEvent.getUser());
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
package org.owasp.webwolf.user;
|
||||
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
public interface UserRepository extends MongoRepository<WebGoatUser, String> {
|
||||
|
||||
WebGoatUser findByUsername(String username);
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
package org.owasp.webwolf.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Service
|
||||
@AllArgsConstructor
|
||||
public class UserService implements UserDetailsService {
|
||||
|
||||
private final UserRepository userRepository;
|
||||
|
||||
@Override
|
||||
public WebGoatUser loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
WebGoatUser webGoatUser = userRepository.findByUsername(username);
|
||||
if (webGoatUser == null) {
|
||||
throw new UsernameNotFoundException("User not found");
|
||||
} else {
|
||||
webGoatUser.createUser();
|
||||
}
|
||||
return webGoatUser;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
package org.owasp.webwolf.user;
|
||||
|
||||
import lombok.Getter;
|
||||
import org.springframework.data.annotation.Id;
|
||||
import org.springframework.data.annotation.Transient;
|
||||
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;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 3/19/17.
|
||||
*/
|
||||
@Getter
|
||||
public class WebGoatUser implements UserDetails {
|
||||
|
||||
public static final String ROLE_USER = "WEBGOAT_USER";
|
||||
public static final String ROLE_ADMIN = "WEBGOAT_ADMIN";
|
||||
|
||||
@Id
|
||||
private String username;
|
||||
private String password;
|
||||
private String role = ROLE_USER;
|
||||
@Transient
|
||||
private User user;
|
||||
|
||||
protected WebGoatUser() {
|
||||
}
|
||||
|
||||
public WebGoatUser(String username, String password) {
|
||||
this.username = username;
|
||||
this.password = password;
|
||||
createUser();
|
||||
}
|
||||
|
||||
public void createUser() {
|
||||
this.user = new User(username, password, getAuthorities());
|
||||
}
|
||||
|
||||
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||
return Collections.singleton(new SimpleGrantedAuthority(getRole()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonExpired() {
|
||||
return this.user.isAccountNonExpired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAccountNonLocked() {
|
||||
return this.user.isAccountNonLocked();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCredentialsNonExpired() {
|
||||
return this.user.isCredentialsNonExpired();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return this.user.isEnabled();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,22 @@
|
||||
package org.owasp.webwolf.user;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.springframework.data.annotation.Id;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
@Getter
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class WebGoatUserCookie implements Serializable {
|
||||
|
||||
@Id
|
||||
private String username;
|
||||
private String cookie;
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
package org.owasp.webwolf.user;
|
||||
|
||||
import org.springframework.data.mongodb.repository.MongoRepository;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author nbaars
|
||||
* @since 8/20/17.
|
||||
*/
|
||||
public interface WebGoatUserToCookieRepository extends MongoRepository<WebGoatUserCookie, String> {
|
||||
|
||||
Optional<WebGoatUserCookie> findByCookie(String cookie);
|
||||
}
|
Reference in New Issue
Block a user