凡心所向,素履所往

java sql注入

字数统计: 891阅读时长: 3 min
2019/12/13 Share

java sql注入

[TOC]

#0x01 简介
主要内容如下:
【1】易导致 SQL 注入的写法
【2】如何避免和修复 SQL 注入

0x02 JDBC

  • JDBC:Java Database Connectivity
  • 是 Java 访问数据库的 API,不依赖于特定数据库 ( database-independent )
  • 所有 Java 持久层技术都基于 JDBC

0x021 SQL 注入写法

ResultSet rs = st.executeQuery("select * from account where " + " id=" + testid + " and password=" + password );

0x022 防注入写法

参数化查询


```java
        int testid = 6;
        String password ="111' or '1'='1";
        //ResultSet rs = st.executeQuery("select * from account where " + " id=" + testid + " and password=" + password );

        String sql = "SELECT * FROM account WHERE id= ? and password= ?";
        PreparedStatement ps = conn.prepareStatement(sql);
        ps.setInt(1, testid);
        ps.setString(2,password);
        ResultSet resultSet = null;
        resultSet = ps.executeQuery();
        while(resultSet .next()){
            int Id = resultSet .getInt("Id");
            System.out.println(Id);
        }
        System.out.println(resultSet );

        resultSet .close();
        ps.close();
        conn.close();

sql注入的原因在于在用户可控的地方未进行检测和过滤,造成了将用户输入部分带进了数据库编译
-w1008

java中参数化查询 防sql注入的原因在于在用占位符占据时进行数据库编译/解释执行,完成后再结合参数进行填充,不会再次编译/解释执行。占位符进行填充是会进行转义,所以如果在使用预编译之前未使用占位符 仍会存在sql注入。
占位符使用如下:

在setString函数中

-w974
-w1092
单引号未能逃逸
-w1036

-w1120

使用占位符及其执行效果

如果这里未使用占位符,即使使用了PreparedStatement也没有用
-w587

除此之外,部分函数不能使用参数化查询,就需要过滤,以白名单为主

非参数化查询

【1】参数占位符不能用于指定查询中的表和列的名称
【2】参数占位符不能用于查询的其他部分,比如ORDER BY子句中的ASC或者DESC关键词等。

order by

ORDER BY 关键字后跟列名。当该列名的输入对用户可控时,参数化查询级无效了,因为ORDER BY 注入不需要闭合单引号,参数化查询没起到转义的作用,故在此处无效
构造案例 如:

orderby=ASC,if(1=1,1,(select 1 from information_schema.tables))&key=value
orderby=ASC,if(1=2,1,(select 1 from information_schema.tables))&key=value

关于order by注入的案列在下期总结下

like %

jdbc的预编译PreparedStatement是不会转义%的
如下:

  • 写法一
String sql = "select * from goods where min_name like ?";  // 含有参数
st = conn.prepareStatement(sql);
st.setString(1, "%儿童%" + "%"); // 参数赋值
System.out.println(st.toString()); 
//[email protected]: 
select * from goods where min_name like '%儿童%%
  • 写法二
    开发者控制%,单纯提取用户的输入,但同样的有着隐患,如 用户输入关键词加上%: %儿童% 转换为包含查询。
String sql = "select * from goods where min_name like ?";  // 含有参数
st = conn.prepareStatement(sql);
st.setString(1, "%儿童%" + "%"); // 参数赋值
System.out.println(st.toString()); 
//[email protected]: 
select * from goods where min_name like '%儿童%%

案例分析

在一次测试中刚好遇到一次sql注入,经测试 判断为oracle数据库,
在该数据库测试中 基于bool的盲注,and 等字符不可用,但此处有|| 可以使用
【1】使用order by 判断列名;
【2】构造payload如下1/(decode(INSTR(借鉴)判断当前用户:

j_username=11'||1/(decode(INSTR(user,'C',1),1,1,0))||' &j_password=122&submit=ENTER&targetUrlParameter=%2Findex.html
j_username=11'||1/(decode(INSTR(user,'C',2),1,1,0))||' &j_password=122&submit=ENTER&targetUrlParameter=%2Findex.html
j_username=11'||1/(decode(INSTR(user,'O',3),1,1,0))||' &j_password=122&submit=ENTER&targetUrlParameter=%2Findex.html

-w1294

问题

在这个地方使用@@user 结果出来的是当前数据table名,没有搞懂为啥。
-w1303

参考

Java SQL 注入学习笔记
MySQL Order By 注入
sql注入及用PrepareStatement就不用担心sql注入了吗?

CATALOG
  1. 1. java sql注入
  2. 2. 0x02 JDBC
    1. 2.1. 0x021 SQL 注入写法
    2. 2.2. 0x022 防注入写法
      1. 2.2.1. 参数化查询
      2. 2.2.2. 非参数化查询
        1. 2.2.2.1. order by
        2. 2.2.2.2. like %
        3. 2.2.2.3. 案例分析
        4. 2.2.2.4. 问题
  3. 3. 参考