0x00 前言
上一篇文章简单介绍了Webgoat的环境搭建那么这篇文章我们就正式开始吧
0x01 登录
首先来看我们的登录页面
登录框如果信息没有处理好的话那么很有可能会存在SQL注入,之前也有不少文章是通过SQL注入的万能密码进入的后台,类似如下的例子
admin' or '1'='1
实质上就是利用SQL注入的所以我们来审计一下
首先我们看到我们的网址是
http://localhost:8080/WebGoat/login
那么猜测在后端写的时候可以有类似的语句来设置我们的路由
@PostMapping("/login")
所以我们在我们的IDEA中进行全局搜索
Command + Shift + f 可以进行全局搜索
这里看到我们的搜索结果中没有出现我们之前猜测的那样那么我们就先来看一下我们的配置文件 WebSecurityConfig
根据如下代码可以看出这个项目是用的SpringSecurity来做的权限校验
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry security = http
// 请求授权的规则
.authorizeRequests() // 定义哪些url需要被保护 那些不用
// 定义不需要认证就可以访问的 所有人可以访问
.antMatchers("/css/**", "/images/**", "/js/**", "fonts/**", "/plugins/**", "/registration", "/register.mvc").permitAll()
// 定义需要验证才可以进行访问的
.anyRequest().authenticated();
security.and()
.formLogin()
// 当用户需要登录的时候跳转到我们的登录页面
.loginPage("/login")
.defaultSuccessUrl("/welcome.mvc", true)
.usernameParameter("username")
.passwordParameter("password")
.permitAll();
security.and()
.logout().deleteCookies("JSESSIONID").invalidateHttpSession(true);
security.and().csrf().disable();
http.headers().cacheControl().disable();
http.exceptionHandling().authenticationEntryPoint(new AjaxAuthenticationEntryPoint("/login"));
}
上面是授权那么下面就是我们认证的模块了
这里webgoat使用的是自定义的身份认证,除了自定义之外我们还可以基于内存的身份信息验证和基于数据库的身份信息认证
关注我们的userDetailsService,因为userDetailsService是传入的信息
定位到这一行
我们继续进行跟踪
首先我们来看到第24行,发现方法名是findByUsername 根据感觉判断应该是和数据库进行交互的方法
同时看到第8行定义了
private final UserRepository userRepository;
继续跟进UserRepository,可以看到继承了JpaRepository
Jpa是一种可以让开发者在使用过程中不使用SQL语句的一种方法,通过ORM框架将数据库中的字段和我们的类的属性进行一个关系映射
可以看到我们的方法 findByUsername 将我们的username作为参数进行查找返回一个类,我们可以跟进看看
这个类其实就是和数据库字段关系起来的类
我们再回过头看之前的那个代码
可以发现这里会进行一个操作,首先会将我们输入的username进行一个数据库查询
如果查询出来的结果为null 那么就抛出一个报错 User not found
那么既然是代码审计,这里进行了一个SQL的查询我们自然是要思考一下这里是否存在SQL注入,因为之前看过文章有很多通过万能密码进入后台的情况
但是可惜的是 jpa会将我们的信息进行一个动态绑定,(可以理解为预编译?
所以其实执行的SQL语句是这样的 ,这样就防止了我们的SQL注入的问题
select * from users where username=?;
反之则会调用 createUser这个方法
0x02 注册
接下来来看我们的注册功能
首先注册一下发现前端将我们的信息传输到了我们的 register.mvc 接口
老样子直接搜索这个接口
来到我们的文件来看我们的代码
看代码我们可以发现这里将我们前端传输过来的数据首先会通过userValidator进行一个验证,我们跟过去
来到如下代码片段
这个UserValidator继承了一个类,Validator 然后复写了validate方法
首先会利用jpd进行一个数据查询查询用户名是否已经存在,然后第二个判断判断密码验证是否一样,由于是JPA是动态绑定,所以不存在SQL注入
同时判断前端传输过来的数据是否符合规定,如下图最小6位最大10位
如果上面都通过了校验的话就执行adduser方法
我们继续进行一个跟踪
发现这里还会进行一个校验如果数据库中没有查询到才会进行一个数据库的存储(需要修改)
0x03 参考链接
文章链接:https://www.anquanke.com/post/id/186417#h2-4