JAVA代码审计 SQL注入篇

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JAVA代码审计 SQL注入篇相关的知识,希望对你有一定的参考价值。

一、SQL注入步骤

第一步:SQL注入点探测。探测SQL注入点是关键的一步,通过适当的分析应用程序,可以判断什么地方存在SQL注入点。通常只要带有输入提交的动态网页,并且动态网页访问数据库,就可能存在SQL注入漏洞。如果程序员信息安全意识不强,采用动态构造SQL语句访问数据库,并且对用户的输入未进行有效性验证,则存在SQL注入漏洞的可能性很大。一般通过页面的报错信息来确定是否存在SQL注入漏洞。 

第二步:收集后台数据库信息。不同数据库的注入方法、函数都不尽相同,因此在注入之前,我们先要判断一下数据库的类型。判断数据库类型的方法很多,可以输入特殊字符,如单引号,让程序返回错误信息,我们根据错误信息提示进行判断;还可以使用特定函数来判断,比如输入“1 and version()>0”,程序返回正常,说明version()函数被数据库识别并执行,而version()函数是mysql特有的函数,因此可以推断后台数据库为MySQL。 

第三步:猜解用户名和密码。数据库中的表和字段命名一般都是有规律的。通过构造特殊SQL语句在数据库中依次猜解出表名、字段名、字段数、用户名和密码。 

第四步:查找Web后台管理入口。WEB后台管理通常不对普通用户开放,要找到后台管理的登录网址,可以利用Web目录扫描工具(如:wwwscan、AWVS)快速搜索到可能的登录地址,然后逐一尝试,便可以找到后台管理平台的登录网址。 

第五步:入侵和破坏。一般后台管理具有较高权限和较多的功能,使用前面已破译的用户名、密码成功登录后台管理平台后,就可以任意进行破坏,比如上传mua、篡改网页、修改和窃取信息等,还可以进一步提权,入侵Web服务器和数据库服务器。

二、注入方法

1、数字型注入

当输入的参数为整型时,如ID、年龄、页码等,如果存在注入漏洞,则可以认为是数字型注入。这种数字型注入最多出现在ASP、php等弱类型语言中,弱类型语言会自动推导变量类型,例如,参数id=8,PHP会自动推导变量id的数据类型为int类型,那么id=8 and 1=1,则会推导为string类型,这是弱类型语言的特性。而对于Java、C#这类强类型语言,如果试图把一个字符串转换为int类型,则会抛出异常,无法继续执行。所以,强类型的语言很少存在数字型注入漏洞。 [7] 

2、字符型注入

当输入参数为字符串时,称为字符型。数字型与字符型注入最大的区别在于:数字型不需要单引号闭合,而字符串类型一般要使用单引号来闭合。

三、statement执行SQL语句

java.sql.Statement 是 Java JDBC 下执行 SQL 语句的一种原生方式,执行语句时需要通 过拼接来执行。若拼接的语句没有经过过滤,将出现 SQL 注入漏洞。

具体步骤 1、注册驱动 2、获取链接 3、创建 4、执行

//注册驱动 
Class.forName("oracle.jdbc.driver.OracleDriver");
//获取连接
Connection conn = DriverManager.getConnection(DBURL, DBUser, DBPassWord);
//创建
Statement 对象 Statement state = conn.createStatement();
//执行
SQL String sql = "SELECT * FROM user WHERE id = " + id + ""; state. executeQuery(sql);

典型代码:

Class.forName("com.mysql.cj.jdbc.Driver");
conn = DriverManager.getConnection("jdbc:mysql://192.168.88.20:3306/iwebsec?&useSSL=false&server
Timezone=UTC","root","root");
String id ="2";
String sql = "select * from user where id = " + id;
ps = conn.createStatement();
rs = ps.executeQuery(sql);
while(rs.next())
System.out.println("id:"+rs.getInt("id")+" username : "+rs.getString("username")+" password:"+rs.
getString("password"));

首先将驱动注册完成后实例化Statement对象,SQL查询语句为

"select * from user where id = " + id;

使用拼接的方式传入id值,id值在通过“String id="2"”设置为2,运行此代码后即成功获取user表中的id信息。


四、PrepareStatement执行SQL语句

PrepareStatement为sql预编译方法,包含了已经编译的SQL语句,会预处理SQL语句,SQL语句可具有一个或者多个IN参数。IN参数的值在SQL语句穿件时没有被指定,而是为每个In参数保留了一个?作为占位符(JAVA代码审计Part1​​https://blog.51cto.com/u_16001677/6118278​​)。

每个?的值必须在该语句执行之前通过适当的setXXX方法来提供。

int型则使用setInt方法                  string型则使用setString方法

特征:

1、PrepareStatement方法比Statement方法执行SQL语句更快

2、可有效防止SQL注入

[JAVA代码审计]OFCMSv1.3.3之前存在SQL注入漏洞

写在前面

好久没碰过Javaweb了,但是感觉自己配环境的时候还是满熟练的哈,这一篇算是超级简单那种了,就开启我的Java审计之旅吧

环境配置

我这里是老古董无敌兼容版本Jdk1.8,开启配置
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

分析

漏洞点在http://url/admin/system/generate/create.json?sqlid=,在com/ofsoft/cms/admin/controller/system/SystemGenerateController.java,能看到这里直接接收了sql参数
在这里插入图片描述
看看传参方式,跟踪getpara函数,只是一个get请求罢了
在这里插入图片描述

再来跟踪update方法

public static int update(String sql) {
        return MAIN.update(sql);
    }

再跟进

public int update(String sql) {
        return this.update(sql, DbKit.NULL_PARA_ARRAY);
    }

终于到了最关键的地方吧,这里...是可变长参数,也就是相当于一个数组,能够传入0个至n个参数,好久没碰java有点忘了,一般可以用foreach取得每个参数

public int update(String sql, Object... paras) {
        Connection conn = null;

        int var4;
        try {
            conn = this.config.getConnection();
            var4 = this.update(this.config, conn, sql, paras);
        } catch (Exception var8) {
            throw new ActiveRecordException(var8);
        } finally {
            this.config.close(conn);
        }

        return var4;
    }

看到先建立数据库链接,再执行update(也太多update了,吐槽,委屈

int update(Config config, Connection conn, String sql, Object... paras) throws SQLException {
        PreparedStatement pst = conn.prepareStatement(sql);
        config.dialect.fillStatement(pst, paras);
        int result = pst.executeUpdate();
        DbKit.close(pst);
        return result;
    }

我们甚至能看到这里还是高科技用了预编译可惜没用,我们传入的完整sql语句直接被执行了,没有一点点过滤,真拉跨,当然既然是update那就直接配合报错注入吧,payload是

update of_cms_link set link_name=updatexml(1,concat(0x7e,(user())),0) where link_id = 4

在这里插入图片描述

以上是关于JAVA代码审计 SQL注入篇的主要内容,如果未能解决你的问题,请参考以下文章

PHP代码审计SQL注入篇

[JAVA代码审计]OFCMSv1.3.3之前存在SQL注入漏洞

[JAVA代码审计]OFCMSv1.3.3之前存在SQL注入漏洞

SQL注入进阶篇一php代码审计

代码审计对Beescms SQL注入漏洞的进一步思考

内部视频 | Java中SQL注入的原理