0x00 Preface
Record the process of learning java audit.
0x01 JDBC mode
1. Three objects:
-
connection
The connection object represents the database
You can set up automatic database submission. Transaction commit (connection.commit()) and transaction rollback (connection.rollback()).
-
statement
Call connection The createstatement () method returns a statement object.
Is to execute sql statements
-
PreparedStatement
The difference between the statement object and the statement object is that you do not put the SQL statement directly, but use the "statement" first? Perform precompiling as a placeholder. After precompiling is completed, perform precompiling on? After assigning and calling execute, the SQL statement can be executed without adding parameters.
Therefore, when we use JDBC, using statement to directly splice SQL statements may cause SQL injection.
2. Examples
request.getParameter("userId") private String getNameByUserId(String userId) { Connection conn = getConn();//Get connection String sql = "select name from user where id=" + userId; Statement stmt = conn.createStatement(); ResultSet rs=stmt.executeUpdate(sql); }
The above code is not precompiled, and then directly splices the parameters obtained in the previous paragraph to the sql statement for execution, which will produce sql injection;
Here is another example:
request.getParameter("userId") private String getNameByUserId(String userId) { Connection conn = getConn();//Get connection String sql = "select name from user where id=" + userId; PreparedStatement pstmt = conn.prepareStatement(sql); ResultSet rs=pstmt.executeUpdate(); }
In this way, although PreparedStatement is used, precompiling is not standardized, and the same splicing method will also cause sql injection problems;
The following is the method of precompiling of the specification:
//Safe, precompiled, preventing sql injection Connection conn = getConn();//Get connection String sql = "select id, username, password, role from user where id=?"; //The statement will be precompiled before executing sql PreparedStatement pstmt = conn.prepareStatement(sql); pstmt.setString(1, id); ResultSet rs=pstmt.executeUpdate();
0x02 Mybatis
Mybatis review
-
maven configuration for mybatis
<dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.2</version> </dependency>
-
config.xml configuration database connection file
<?xml version="1.0" encoding="UTF-8" ?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3-config.dtd"> <configuration> <environments default="dev"> <environment id="dev"> <transactionManager type="JDBC"/> <dataSource type="POOLED"> <property name="driver" value="com.mysql.cj.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/mybatistest"/> <property name="username" value="root"/> <property name="password" value="123456"/> </dataSource> </environment> </environments> <mappers> <mapper resource="UserMapper.xml"/> </mappers> </configuration>
Mainly pay attention to the xml registered in the configuration file. There are two ways to obtain values, namely ${} and #{}.
difference:
"#{}" treat the incoming data as a string, and add a double quotation mark to the automatically incoming data, which belongs to the correct precompiling, and all the input parameters will become part of the query;
"${}" directly splices the incoming data into sql, resulting in sql injection. For example, where username={username}, if the value passed in is 111, the value when parsing into sql is where username=111; If the value passed in is 1 and 1=1;, The parsed sql is: select id, username, password, role from user where username=1 and 1=1.
MyBatis is prone to three problems
1. like fuzzy query
Use like for fuzzy query in Mybatis:
Select * from news where title like '%#{title}%'
However, this way of writing will report errors and throw exceptions. At this time, changing # to $can work normally, but it also produces security problems;
Correct writing:
select * from news where tile like concat('%',#{title}, '%')
2. Multiple parameters after in
An error will be reported when using # multiple IDS after in
Select * from news where id in (#{ids})
The correct usage is to use foreach instead of # simply replacing it with$
id in<foreach collection="ids" item="item" open="("separatosr="," close=")">#{ids} </foreach>
3. After order by
Select * from news where title ='#{titlename}' order by #{time} asc
It should be noted that after order by is # executed, an error will also be reported. Precompiled cannot be used when using order by statement. The reason is that the field name or field position needs to be added after the order by clause, and the field name cannot be quoted. Otherwise, it will be considered as a string rather than a field name. However, using preparestatement will force the parameter to add ', Therefore, we should be prepared for defense in filtering
Correct writing:
Select * from news where title ='#{titlename}' order by ${time} asc
Therefore, we can observe these problems during the audit.
Summary: you can use idea to search for the $keyword. First filter the xml file to search for $, and analyze it one by one. Pay special attention to the order by injection of mybatis generator. The global search calls out Find in Path, filter the suffix xml, search for the $keyword, find the database file that is mybatis, find the calling function, and ⌘ + f7 view the call chain to check whether the middle is filtered
reference resources
https://www.cnblogs.com/CoLo/p/15225346.html
https://www.cnblogs.com/nice0e3/p/13647511.html
https://zeo.cool/2020/07/24/java Self study of code audit: sql injection/