通过一个注入漏洞观察Apache与Nginx的区别
0x00 前言
你见过你的SQL注入方式被WEB容器影响吗?
0x01 漏洞分析
打开index.php,看到了include_once,如图
跟进Include/web_inc.php
前两行包含的文件我们先翻一下看一下。
Db_conn.php:
定义了一些数据库配置信息,$db_conn变量为mysqli的实例,我们再来看一下contorl.php
定义了一些函数信息,5-11行进行全局的GET请求过滤。
了解一些东西之后回到Include/web_inc.php下继续往下翻一翻代码。
调用了web_language_ml函数?我们跟进看一下。
发送了一次SELECT查询的SQL语句,携带参数1参数2,我们看一看参数的来源。
注入漏洞产生了,$_SERVER[REQUEST_URI]是用来获取url的(协议://域名/ 除外),如图:
这不是很正常吗?为什么会产生SQL注入漏洞问题?
我们都知道,在发送GET请求时,问号后的内容会被当做参数处理,那么符合REQUEST_URI的气质,问号后的内容也被获取到了。
如图:
在程序判断中通过 斜杠/ 分隔,随后直接引入程序中的SQL语句中,从而引发SQL注入漏洞。你可能会问,刚刚不是还过滤了全局GET吗?
我们再仔细看看,只过滤了GET中的VALUE值:
哈哈哈哈?没注意对吧。
除此之外REQUEST_URI所接收的值不会被url解码而变化,比如我传入%0a(换行符)就原封不动的取出。我们举个例子与$_GET作一下比较。如图:
可能这时候会问,提这个有什么意义呢?
我们都知道%20为空格,我们通常都会通过空格从注入语句中分隔语句。避免造成语法错误。而HTTP请求中GET是不允许出现未urlencode编码过的字符串的,如图:
不符合HTTP协议规则,直接爆出400错误!这里可以想到Mysql中 [空格]--[空格] 的注释方式被BAN掉!!!
又因为程序通过 斜杠(/) 分隔来代入SQL语句中,所以/**/这种注释语句也被BAN掉了!
还有一种#注释姿势,很遗憾,HTTP请求依然不允许,如图:
那么我们只能通过闭合的方式来进行SQL盲注了,
构造Payload:/?'or+if(substr((select+user()),1,1)like'r',sleep(2),1)-'
因为当前处于where条件中,我的闭合语句为-',在MySQL眼里为逻辑减的意思。所以这里可以进行语句闭合。
这里成功完成延时SQL注入。
0x02 开个玩笑
刚刚不是说到HTTP协议的规则嘛,其实标准的HTTP协议规则是那样子的,完全由于Apache对请求包解析太过于严格,下面我们看一下Nginx的请求包情况。~
测试#+无数个空格依然可以正常解析。
然后我们继续追踪PHP代码层
注意图中的
$Urlink=array('url_link'=>$row['language_url'],'url_ml'=>"../",'ID'=>$row['ID']);
将返回结果返回给url_link下标。
然后我们回到web_inc.php文件
这个时候$urlml携带着SQL语句的结果集,我们通过前台模板看一下在哪里输出了该结果集。
将SQL语句下标为url_link拼接给web_url_meate变量,好了,我们回到index.php找一下模板文件。
跟进看一下。
哟西,这个时候简单构造一下联合注入语句
Payload:?111' UNION SELECT 1,2,3,user(),5,6,7,8,9#
0x03 漏洞信息
使用BurpSuite发送GET请求包:
Apache下的SQL盲注:
GET /?'or+if(substr((select+user()),1,1)like'r',sleep(2),1)-'
Nginx下的联合注入:
GET /?111' UNION SELECT 1,2,3,user(),5,6,7,8,9# HTTP/1.1
