Java代码审计 漏洞审计篇

前言

分四个部分,基础篇、审计篇、实战篇、框架篇,本文为审计篇。

漏洞审计/sql注入


漏洞原理:

举个栗子。

这是一个新闻详情页面,会显示出新闻的title和content,程序内部会接收这个id参数传递给SQL语句,SQL如下:

这是SQL的原义,也是程序员想要得到的结果,但是如果用户改变了id的内容,修改成如下:

此时内部程序执行的SQL语句为:

这条SQL的原义就会被改变,导致将管理员数据表中的用户名显示在页面title位置,密码显示在页面content位置,攻击成功。

jdbc

在上古时期,人们往往这么从数据库获取数据。

通过拼接字符串来构建sql语句,其中又有用户可控的部分,很容易出现问题。 直接拼接实例代码

预编译处理后的代码(修复后代码)

后来,出现了预编译机制,但是预编译只能处理查询参数,很多场景下仅仅使用预编译是不够的。

  • like like拼接实现代码:

http://localhost:8080/sqli/jdbc/like?username=joy

在使用模糊查询的场景中,

String sql = "select * from user where username like '%?%'";

这种写法是无法进行预编译的,程序会报错。 like预处理报错

http://localhost:8080/sqli/jdbc/likesec?username=joy

图片.pnglike预处理

http://localhost:8080/sqli/jdbc/likesec?username=joy

图片.png

  • order by 需要按照时间、id等信息进行排序的时候,也是无法使用预编译的。 sort=123

String sort = req.getParameter("sort");

String sql = "select * from user order by ?";
PreparedStatement preparedStatement = connection.prepareStatement(sql); //预编译
preparedStatement.setString(1, sort); //绑定参数
ResultSet resultSet = preparedStatement.executeQuery();

如果像上面这样强行使用预编译,数据库会将字段名解析为字符串,即实际执行的sql为

select * from user order by 'sort';

无法达到实际需求。 总结:jdbc方式进行拼接的,可以直接使用预处理来规避sql注入,但是如果有like、order by 进行参数拼接不能直接使用预处理来解决,必须在set处把%拼接上。

Mybatis

前置知识:了解Mybatis框架映射关系 mapper定位java代码 图片.pngparm定位方法

List<User> findByUserNameVuln02(String username);

定位到UserMapper.xml中的id

<select id="findByUserNameVuln02" parameterType="String" resultMap="User">
select * from users where username like '%${_parameter}%'
</select>

Mybatis中两种数据库拼接方法 ${xx}是直接拼接 #{xxx}预处理后拼接   //string   int float。。。 mybatis有两种写法,一种是使用@Param 注解:

@Mapper
public interface CategoryMapper {
@Select("select * from category_ where name= '${name}' ")
public CategoryM getByName(@Param("name") String name);
}

1、${}直接拼接,类似jdbc中的直接拼接审计方法

http://localhost:8080/sqli/mybatis/vuln01?username=joychou
  / * http://localhost:8080/sqli/mybatis/vuln01?username=joychou' or '1'='1
*/
@GetMapping("/mybatis/vuln01")
public List<User> mybatisVuln01(@RequestParam("username") String username) {
return userMapper.findByUserNameVuln01(username);
}

这里使用的是mybatis来进行SQL查询,获取参数username后使用userMapper.findByUserNameVuln01(username)来进行查询。

来看一下findByUserNameVuln01。MyBatis支持两种参数符号,一种是#,另一种是$。这里的参数获取使用的是${username},而不是#{username},而${username}是直接将参数拼接到了SQL查询语句中,就会造成SQL注入。

@Select("select * from users where username = '${username}'")
List<User> findByUserNameVuln01(@Param("username") String username);

注入语句:

http://localhost:8080/sqli/mybatis/vuln01?username=joychou' or '1'='1

${}修复方法

采用#{},也就是预处理的形式

http://localhost:8080/sqli/mybatis/sec01?username=joychou
@Select("select * from users where username = #{username}")
User findByUserName(@Param("username") String username);

2、Mybatis中like审计方法

 

Java代码审计 漏洞审计篇-棉花糖会员站
Java代码审计 漏洞审计篇
此内容为付费阅读,请付费后查看
9999积分
付费阅读
已售 27
© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    请登录后查看评论内容