1.登录功能

1.1.根据路由查找实现代码

登录接口为:/WebGoat/login

全局搜索/login查看相关代码:

1.1

定位到webgoat/WebSecurityConfig.java

可以看出该项目使用的是springSecurity框架,框架关键配置如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
    protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
// http.authorizeRequests()其中这里的意思是指通过authorizeRequests()方法来开始请求权限配置。
.authorizeRequests()
//我们指定任何用户都可以访问多个URL的模式。
//任何用户都可以访问以"/css/**","/images/**", 或者 "/js/**..."开头的URL。
.antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "/registration", "/register.mvc").permitAll()
// .anyRequest().authenticated()是对http所有的请求必须通过授权认证才可以访问。
.anyRequest().authenticated();
security.and()
//通过formlogin方法登录,并设置登录url为/login
.formLogin()
.loginPage("/login")
// 登录成功后跳转到//welcome.mvc页面
.defaultSuccessUrl("/welcome.mvc", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll();
security.and()
// 登出之后删除cookie,使session无效
.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
// 取消csrf防护,说明该项目大概率存在csrf漏洞
security.and().csrf().disable();

http.headers().cacheControl().disable();
// ajax身份认证入口点/login
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
}

@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
// 从数据库读取用户进行身份验证
auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());
}
1
auth.userDetailsService(userDetailsService); //.passwordEncoder(bCryptPasswordEncoder());

从数据库中读取用户进行身份验证:https://www.jianshu.com/p/c3b79a625d84

1.2. 跟进userDetailsService

2.1

userDetailsService为UserService的对象。跟进UserService类。

webgoat-container/src/main/java/org/owasp/webgoat/users/UserRepository.java

2.1

UserService继承JpaRepositoy。采用了jpa的方式,继承JpaRepository即可使用数据的增删改查。

此处的findByUsername,为自定义的简单查询。就是根据方法名来自动生成 SQL

springboot jpa使用方式讲解:Spring Boot(五):Spring Boot Jpa 的使用 - 纯洁的微笑 - 博客园 (cnblogs.com)

1
2
3
Spring Boot Jpa 是 Spring 基于 ORM 框架、Jpa 规范的基础上封装的一套 Jpa 应用框架,可使开发者用极简的代码即可实现对数据的访问和操作。它提供了包括增删改查等在内的常用功能,且易于扩展!学习并使用 Spring Data Jpa 可以极大提高开发效率!

Spring Boot Jpa 让我们解脱了 DAO 层的操作,基本上所有 CRUD 都可以依赖于它来实现

1.3.跟进WebGoatUser类

@Entity注解可以确定该类为webgoat的用户实体类。

2.1

1.4.sql注入判断

登录接口设计到了数据库的查询等操作,自然想到了sql注入,但是有没有sql注入呢?

可以在配置文件中添加打印sql语句配置,在控制台查看输出。

webwolf/src/main/resources/application-webwolf.properties

添加:spring.jpa.show-sql=true

4.1

可以在test中执行测试用例来打印sql语句

webgoat-container/src/test/java/org/owasp/webgoat/users/UserRepositoryTest.java

4.2

可以看到执行的sql语句采用了预编译。所以此处就杜绝了sql注入。

关于springDataJpa的注入问题还发现了一篇很好的文章:

Java代审之SQL注入—SpringDataJpa-SecIN (sec-in.com)

作者给出了两个全局查找注入的搜索方式:
1.order by处无法使用预编译,可以搜索关键字:**JpaSort.unsafe()**

2.再一些复杂的业务场景中,自定义的sql无法满足业务需求,需要自己编写sql语句,此时就可能存在拼接sql语句,存在sql注入的风险。

可直接检索EntityManager的相关使用。

2.注册功能

2.1全局搜索注册路由/register

定位到webgoat-container/src/main/java/org/owasp/webgoat/users/RegistrationController.java

2.1.1

/registration路由会进入registration.html页面。

2.1.2

registration页面的输入会提交到register.mvc路由。

2.2 输入验证

输入的用户名和密码会进入webgoat-container/src/main/java/org/owasp/webgoat/users/UserValidator.java

2.2.1

判断输入用户名数据库中是否存在。第一次和第二次输入的密码是否相同。符合规则则进入

1
userService.addUser(userForm.getUsername(), userForm.getPassword());

2.3添加用户到数据库

addUser():

1
2
3
4
5
6
7
8
9
10
11
12
13
    public void addUser(String username, String password) {
//get user if there exists one by the name
var userAlreadyExists = userRepository.existsByUsername(username);
// 保存用户密码。jpa内置函数此处相当执行sql语句,update
var webGoatUser = userRepository.save(new WebGoatUser(username, password));
//用户在数据库中不存在则进入
if (!userAlreadyExists) {
//保存用户到数据库
userTrackerRepository.save(new UserTracker(username)); //if user previously existed it will not get another tracker
//通过用户名创建课程
createLessonsForUser(webGoatUser);
}
}

createLessonsForUser():

1
2
3
4
5
private void createLessonsForUser(WebGoatUser webGoatUser) {
//此处进行sql语句拼接
jdbcTemplate.execute("CREATE SCHEMA \"" + webGoatUser.getUsername() + "\" authorization dba");
flywayLessons.apply(webGoatUser.getUsername()).migrate();
}

此处的sql语句可以构造用户名payload,进行堆叠注入

1
test;select sleep(5); -- 

但是用户名有限制,只能输入字母和数据,判断正则如下[a-z0-9-]*

1
2
3
4
5
    @NotNull
@Size(min = 6, max = 45)
@Pattern(regexp = "[a-z0-9-]*", message = "can only contain lowercase letters, digits, and -")
// 用户名6-45位,字母数字
private String username;

暂时没想到绕过方式。

2.4 sql注入判断

注册功能的查询,添加,都是用的jpa规范,存在预编译。不存在注入。

添加用户之后会相应的为用户创造一个数据库,此处存在sql注入的风险,但是用户输入用户名存在限制,只能输入数字和字母。可能存在一定的绕过方式。

TODO