Sqli的一些tips

admin 2022年9月9日11:16:04评论16 views字数 3322阅读11分4秒阅读模式

Sqli的一些tips

声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由用户承担全部法律及连带责任,文章作者不承担任何法律及连带责任。

发现漏洞

寻找有效SQLi的第一部分是发现漏洞。这里最重要的是知道你的输入在哪种类型的SQL上下文中。这里有一些基本的例子:


1. SELECT user_input FROM tournament ORDER BY region;

2. INSERT INTO tbl_name (col1,col2) VALUES (15,user_input);

3. DELETE FROM somelog WHERE texts = 'user_input'

如上所示: 可以看到user_input在不同的上下文中结束: () 上面的2,' 上面的3或者没有任何分隔符(上面的1);

这些命令的共同之处在于,一旦a '被注入作为输入,它们都会变成无效的。前两个变量甚至没有分隔符,如果使用不存在的系统变量,也会给出错误,比如:@@versionz(而不是@@version)。

一旦能够使服务器返回错误(主要是HTTP 500状态),必须确认是SQL命令导致了错误,而不是日期解析器之类的东西。要做到这一点,你可以使用一系列技巧:

  • 如果一个'正在导致错误,尝试看看'是否将导致成功的消息(因为反斜杠取消了MySQL中的单引号)。
  • 您还可以尝试在成功消息中注释掉',如:%23'或--'。这样你就告诉MySQL显式忽略后面的所有内容,包括额外的'
  • 如果不允许',你可以在有效和无效的系统变量之间进行比较,比如@@versionz vs @@version,或者无效和有效的函数SLEP(5) vs SLEEP(5)
  • 有时,输入在()中结束,确保输入)%23来测试同时看看是否可以打破这些并利用Union SQLi例如(input) order by 5%23)
  • 如果正常的输入只是一个整数,您可以尝试减去它的一些量,看看这个减法是否有效(id=460-5)。
  • 试着看看偶数数量的引用是否会导致成功消息(例如460“460-”),而奇数数量的引用是否会导致错误消息(例如460“460-”)。

一个例子

为了更清楚地说明这一点,看以下URL:

https://www.example.com/php/sales_dash_poc_handle.php?action=month-breakdown&type_of_report=billing&city=all&month=8&year=2017&poc=35141008

原本的URL返回一个200状态码;输入poc=35141008'返回500错误,poc=35141008'%23(注:%23为#)也返回500错误;但poc=35141008 "返回200状态

这提示参数可能没有使用任何分隔符,因此可以尝试poc=35141008%23',它将返回200状态码;现在我们知道可以简单地在35141008到%23之间进行注入

在此之后,尝试一个简单的测试: 35141008 OR 2 LIKE 2%23起作用了,而35141008 OR 2 LIKE 1%23返回500错误;这证明布尔SQLi在这里是可能的。

利用

在找到一个SQLi之后,必须至少验证输出(对于布尔值和基于时间型(往往有sleep())的)或输出中的敏感数据(对于错误和基于联合的)的差异。有时候在防火墙和黑名单的情况下,这会变得很难。本节将帮助您解决这些问题。

防火墙

在处理防火墙时,应该尝试的第一件事是查看是否可以在设置中找到错误配置;对于大多数这些防火墙和CDN而言,你可以访问不受保护的网站通过访问原始的IP;然后使用原来的域名作为主机值;这里的第一步是找到网站的原始IP,这通常不是太难,可以通过使用 http://viewdns.info/iphistory 来查看其使用的ip历史;

通常,在防火墙IP进来之前使用的是他们现在仍在使用的那个(基本上是在说cloudflare或akamai之后的那个)。在寻找原始IP时,Shodan也非常有用。

当你发现原始IP地址后,尝试用原始主机头访问网站。在cURL中是这样工作的(添加一个头也可以在sqlmap中工作):

curl --header 'Host: www.example.com' 'https://54.165.170.2/' -v -k

如果被禁,尝试一些绕过方式,比如(添加一个点):

curl --header 'Host: www.example.com.' 'https://54.165.170.2/' -v -k

/etc/hosts文件中添加 54.165.170.2 www.example.com将允许你在没有防火墙的情况下在浏览器中浏览www.example.com

至此,限制都应该消失了,SQLi的利用应该相当容易。

绕过黑名单的一些tips

  • 在查询中使用注释作为空格来打破regex或单词组合的防火墙,例如:2/*dhabbc*/OR/*dahdshka*/2/*sd*/LIKE/*da*/"2"/**/%23转换为:2 OR 2=2%23
  • LIKE代替=,用2代替1,用"替换 '
  • MID()SUBSTRING()的工作方式相同,但是后者被禁止了,而前者没有。同样,变量CURRENT_USER()被禁止,而CURRENT_USER没有被禁止。

综合实践

https://www.example.com/php/analyticsExcel.php?action=res_unique_analytics&resid=2100935&start_date=2016-07-11 00:00:00&end_date=2017-08-11 23:59:59&action=res_unique_analytics&entity_type=restaurant

在这里,我可以合法访问2100935,请求2100934将导致一个未经验证的错误。奇怪的是,在2100935之后添加一个单引号将导致500状态错误,而添加两个将使URL再次起到作用;

在这里,为了使利用更容易,使用www.example.com.绕过。在那里(在防火墙部分中描述以绕过Akamai WAF),试图找到一个地方在输入中注入SQL命令,但是小哥没有设法在字符串中注入注释,因此得出结论,这个查询相当复杂。看到这一点,小哥决定专注于一个更简单的OR语句,它几乎可以在任何地方注入。这里注意到' OR 1='1将返回200状态,' OR 1='2将完全相同,'AND1='1相同,' AND 1='2相同,最后没有一个sleep()命令似乎有任何影响。

尝试了 ' OR @@version=5导致200状态,' OR @@versionz=5 导致500错误

这至少证实了我在使用MySQL,并表明注入确实存在。这就指向了MySQL的IF函数,如果我能够根据if语句的真或假返回一个无效的函数,我就可以证明数据可以提取;但是MySQL似乎在执行IF语句之前验证命令,IF语句最终成为解决方案的一部分。

在IF语句中输入一个带有正整数的有效SLEEP命令将导致服务器超时,而从IF语句返回一个简单整数将以快速200状态码的形式返回。这里我开发了以下POC:

TRUE: if @@version starts with a 5:
2100935' OR IF(MID(@@version,1,1)='5',sleep(1),1)='2
Response:
HTTP/1.1 500 Internal Server Error

False: if @@version starts with a 4:
2100935' OR IF(MID(@@version,1,1)='4',sleep(1),1)='2
Response:
HTTP/1.1 200 OK

总结

如果在响应中注入单引用导致不同的输出,请尝试本文中的不同技术,看看您是否正在处理一个SQLi。确定在哪个SQL上下文中工作之后,开发一个POC,它要么显示敏感数据(基于错误和联合),要么根据是真还是假(基于布尔值和时间)显示输出的差异。


原文始发于微信公众号(迪哥讲事):Sqli的一些tips

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年9月9日11:16:04
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   Sqli的一些tipshttp://cn-sec.com/archives/1287454.html

发表评论

匿名网友 填写信息