Java代码审计02: 登录注册模块初审计(未完待续)

0x00 前言

上一篇文章简单介绍了Webgoat的环境搭建那么这篇文章我们就正式开始吧

0x01 登录

首先来看我们的登录页面

image-20201103224805668

登录框如果信息没有处理好的话那么很有可能会存在SQL注入,之前也有不少文章是通过SQL注入的万能密码进入的后台,类似如下的例子

admin' or '1'='1

实质上就是利用SQL注入的所以我们来审计一下

首先我们看到我们的网址是

http://localhost:8080/WebGoat/login

那么猜测在后端写的时候可以有类似的语句来设置我们的路由

@PostMapping("/login")

所以我们在我们的IDEA中进行全局搜索

Command + Shift + f 可以进行全局搜索

image-20201103225306878

这里看到我们的搜索结果中没有出现我们之前猜测的那样那么我们就先来看一下我们的配置文件 WebSecurityConfig

根据如下代码可以看出这个项目是用的SpringSecurity来做的权限校验

image-20201104151104621

@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使用的是自定义的身份认证,除了自定义之外我们还可以基于内存的身份信息验证和基于数据库的身份信息认证

image-20201104222626860

关注我们的userDetailsService,因为userDetailsService是传入的信息

定位到这一行

image-20201104223000887

我们继续进行跟踪

首先我们来看到第24行,发现方法名是findByUsername 根据感觉判断应该是和数据库进行交互的方法

同时看到第8行定义了

private final UserRepository userRepository;

image-20201104223032774

继续跟进UserRepository,可以看到继承了JpaRepository

Jpa是一种可以让开发者在使用过程中不使用SQL语句的一种方法,通过ORM框架将数据库中的字段和我们的类的属性进行一个关系映射

可以看到我们的方法 findByUsername 将我们的username作为参数进行查找返回一个类,我们可以跟进看看

image-20201104223331029

这个类其实就是和数据库字段关系起来的类

image-20201104223633245

我们再回过头看之前的那个代码

image-20201104223727973

可以发现这里会进行一个操作,首先会将我们输入的username进行一个数据库查询

image-20201104153653519

如果查询出来的结果为null 那么就抛出一个报错 User not found

那么既然是代码审计,这里进行了一个SQL的查询我们自然是要思考一下这里是否存在SQL注入,因为之前看过文章有很多通过万能密码进入后台的情况

但是可惜的是 jpa会将我们的信息进行一个动态绑定,(可以理解为预编译?

所以其实执行的SQL语句是这样的 ,这样就防止了我们的SQL注入的问题

select * from users where username=?;

image-20201104224055646

反之则会调用 createUser这个方法

0x02 注册

接下来来看我们的注册功能

首先注册一下发现前端将我们的信息传输到了我们的 register.mvc 接口

image-20201105150325778

老样子直接搜索这个接口

image-20201105151428293

来到我们的文件来看我们的代码

看代码我们可以发现这里将我们前端传输过来的数据首先会通过userValidator进行一个验证,我们跟过去

image-20201105151501011

来到如下代码片段

这个UserValidator继承了一个类,Validator 然后复写了validate方法

首先会利用jpd进行一个数据查询查询用户名是否已经存在,然后第二个判断判断密码验证是否一样,由于是JPA是动态绑定,所以不存在SQL注入

image-20201105151643599

同时判断前端传输过来的数据是否符合规定,如下图最小6位最大10位

image-20201105152340094

如果上面都通过了校验的话就执行adduser方法

我们继续进行一个跟踪

发现这里还会进行一个校验如果数据库中没有查询到才会进行一个数据库的存储(需要修改)

image-20201105152513965

0x03 参考链接

文章链接:https://www.anquanke.com/post/id/186417#h2-4

点赞

发表评论

昵称和uid可以选填一个,填邮箱必填(留言回复后将会发邮件给你)
tips:输入uid可以快速获得你的昵称和头像