发新话题
打印

[转载]青创文章漏洞分析手记

[转载]青创文章漏洞分析手记

本文作者: 不详
文章出处: superhei

《青创文章系统》,经常在一些源码下载站见到,还经常在最前面,但由于各人的偏好,一直没有用过,前不久在网上看到了最新的版本,就下载了一个,总体感觉外观挺好的,设计大方,功能齐全,但看了源码后,原先的好感都没了。

本人拿到是2004-3-10的最新版本(Powered by QCDN_NEWS Version 1.4.3.10.6.0),要说问题当然要从最容易发现的地方了,就说经常用到的一页——list.asp,看一看开头的这几行吧:
复制内容到剪贴板
代码:
<%if Request("method") = 1 then ‘评论
articleid = Request.form("articleid")
face = Request.form("face")
content = Qcdn.checkStr(Trim(Request.form("content")))
username = Qcdn.checkStr(Trim(Request.form("username")))
password = Qcdn.checkStr(Trim(Request.form("password"))) ’虽然用Qcdn.checkStr()进行了过滤,但checkStr()只过滤掉了单引号,由于输出时又用HTMLcode()处理过过了content 所以没有多少利用价值,但face在输出时没有处理,不防可以跨站欺骗一下,不过构造的得好~
‘……省略判断用户的代码
sql = "Insert into article_remark(articleid,username,content,faceid,intime,ip)values("& articleid &",&#39;"& username &"&#39;,&#39;"& content &"&#39;,"& face &",Now(),&#39;"& ip &"&#39;)"
‘……省略代码
‘……省略添加评论代码。
elseif Request("method") = 2 then ‘审核
unid = Request("unid")
sql = "update article_info set Audit = 0 where Unid in ("& unid &")"
conn.execute(sql)
Response.Write("<script>alert(""审核成功"");window.opener.location.reload();window.close();</script>")
Response.End() ’没有一句是判断否是管理员,直接可以把没有审核的文章的地址后加一个&method=2就可以把未审核的文章变为审核了~
elseif Request("method") = 3 then
‘……俺也不知道干什么的
end if
if Request("Unid") = "" then
‘…… 错误报告
else
Unid = Request("Unid") ‘文章编号
end if
ad = Request("ad")
Sql = "Select title,content,Nclassid,classid,Nkey,hits,writer,writefrom,Intime,Popedom from article_info where Unid = " & Unid ‘就代进去了~!!
Set Rs = conn.execute(Sql)
if Rs.eof and Rs.bof then
‘……变量赋值
else
‘……省略部分如果是要求会员才可以观看的限制,虽然是也有漏洞但为了一篇文章摆了一大堆的工具有点不值,还不如注册个会员呢~
end if
sql = "Update article_info set hits=hits+1 where Unid = " & Unid
Conn.execute(sql)
‘……
end if
Rs.close%>
一页里就有N个漏洞,跨站欺骗、免费审核文章、SQL INJECTION、 够可以的了~!

我们看一看common.asp文件内的checkStr()方法:
复制内容到剪贴板
代码:
Public function checkStr(str)
if isnull(str) then
checkStr = ""
exit function
end if
checkStr=replace(str,"&#39;","&#39;&#39;")
end function
只把单引号给替换了,绕过单引号的SQL查询看过很多的介绍,试一下吧。我在浏览器内提交以下内容:http://localhost/清创/list.asp?unid=92 and 1=(select count(*) from article_admin where username<>"")理论上应该不会有错误的,但浏览器提示:

看一看262行有一句 sql = "Select Unid,title from article_info where Unid = "& Unid-1 原来用unid去减东西了,当然会出错了,但上面的查询已经证明是正确的了,换一句试一下,提交http://localhost/清创/list.asp?unid=92 and 1<>(select count(*) from article_admin where username<>"")现在变成了青创的经典错误提示,如右图:
现在真的出错了!没有找到当然错了。基本的攻击思路已经有了,就是运用left()、mid()和asc()三个函数一步步地的到管理员的用户名和密码,如果浏览器返回‘HTTP 错误 500.100 - 内部服务器错误 - ASP 错误’则证明此次查询时正确得,如果返回如图的错误提示则此次查询错误。最后得到的是一个16位MD5加密的密码,后台又是靠Session验证的,不可以进行COOKIE欺骗,只可以爆破,我可没有耐性,不当管理员也罢,看看别的吧。

像这样的问题在要得到大类或小类的地方都有,像2j.asp。

由于青创有会员功能,检查会员是用COOKIES验证的,一般在会员修改资料和找回密码的地方都会有漏洞,就看一下找回密码页UserLostPass.asp吧:
复制内容到剪贴板
代码:
<%
if Request("method") = 3 then ‘修改密码
LsNewPass = Qcdn.checkStr(Trim(Request.Form("LsNewPass"))) ‘新的密码
LsNewPass = md5(LsNewPass,16)
userid = Request.Form("userid") ‘用户编号
sql = "Update article_User set [password] = &#39;"& LsNewPass &"&#39; where unid = " & userid
conn.execute(sql)
Response.write("<center>密码修改成功,请回<a href=&#39;index.asp&#39;>首页</a>登陆。</center>")
elseif Request("method") = 2 then ‘回答问题
LsAnswer = Qcdn.checkStr(Trim(Request.Form("LsAnswer")))
userid = Request.Form("userid")
Sql = "Select Unid from article_User where answer = &#39;"& LsAnswer &"&#39;"
‘……%>
……
<%elseif Request("method") = 1 then ‘判断用户
‘……
end if
Rs.close : set rs = nothing%>
从上到下没有一处检查前一步的正确性,可以完全绕过第一和第二步而执行第三步。由于LsNewPass、userid是用Request.Form()方式得到的,所以就不可以直接的在地址栏内提交,得构建一个表单,内容如下:
复制内容到剪贴板
代码:
<title>青创修改会员密码表单</title>
<form name="form1" method="post" action="[url]http://localhost/[/url]清创/UserLostPass.asp">
新密码: <input type="text" name="LsNewPass"> <br>
会员ID: <input type="text" name="userid"> <br>
<input type="submit" name="Submit" value="提交">
<input name="method" type="hidden" id="method" value="3">
</form>
试一下吧。 至于会员的ID怎么得到,既然知道有此人了,找一下密码,察看第二页的源码不就知道了吗?修改成功提示如右图:

遗憾和庆幸的是管理员没有找回密码的功能。

既然找回密码有问题那么修改资料的有没有问题?看一看UserEdit.asp吧:
复制内容到剪贴板
代码:
<% if Request("RegSetp") = 2 then
if Trim(Request.Form("password")) = "" then
Errmsg = Errmsg + "<li>请输入密码。"
FoundErr = true
else
password = Qcdn.checkStr(Trim(Request.Form("password")))
end if
‘……
‘……
Sql = "Update article_User set [password] = &#39;"& password &"&#39;,email = &#39;"& e_mail &"&#39;,question = &#39;"& question &"&#39;,answer = &#39;"& answer &"&#39;,qq = &#39;"& qq &"&#39;,msn = &#39;"& msn &"&#39;,male = "& male &",birth = &#39;"& birth &"&#39;,bloodtype = &#39;"& bloodtype &"&#39;,realname = &#39;"& realname &"&#39;,country = &#39;"& country &"&#39;,province = &#39;"& province &"&#39;,city = &#39;"& city &"&#39;,phone = &#39;"& phone &"&#39;,[address] = &#39;"& address &"&#39;,postcode = "& postcode &",job = &#39;"& job &"&#39;,edu = &#39;"& edu &"&#39;,school = &#39;"& school &"&#39; where username = &#39;"& Request.cookies("qcdn")("user_name") &"&#39;"
conn.execute(sql)
‘……
end if
‘……%>
一堆的代码里就有一个Request.cookies("qcdn")("user_name")来得到该改那一个用户,还是空空的放进去(1’or ‘1’=’1 不知道能不能改了全部用户?),没有进行任何处理也没有判断当前用户是否是要改的用户,也真够绝的。cookies("qcdn")("user_name")的人工构造一个,构造的方法有很多,用NC往自己的浏览器内提交一个构造的HTTP文件头或用iecv.exe修改自己的cookies都可以,不过还不如用直接找回密码的方法呢,我就不多去试验了,至于方法可以不?——理论上应该可以^-^~

如果你非要通过一步步地要回密码的方法来的到某一用户的资料,也可以,看一看admin_UserView.asp文件吧:
复制内容到剪贴板
代码:
<!--#include file="head.asp"-->
<!--#include file="md5.asp"-->
<%
Unid = Request("Unid")
Sql = "Select * from article_User where Unid = " & Unid
set rs = conn.execute(sql)
if rs.eof and rs.bof then
‘……错误提示
end if
‘……变量赋值
rs.close : set rs = nothing
%>
从上到下没有一句是验证察看资料的是管理员还是那一个用户,只有在下面的某个位置有这么一句:
复制内容到剪贴板
代码:
<tr><td width=250> <b>用户名:</b> </td>
<td><%=Request.cookies("qcdn")("user_name")%></td></tr>
只是用户名处要一个名字而已,不要管它,直接提交http://localhost/清创/admin_UserView.asp?U...一孛苈氪鸢浮?/a>

唉,青创文章内有多少是关于用户的页面,就这么多的漏洞,一个个的都是致命的(虽然对管理员和网站的安全没有影响,但对某一个会员的隐私……),后台能用SEESION验证管理员,前台就不能用SESSION吗,要用COOKIE也做得好一点!

虽然后台用SESSION验证用户,但看一看上传的几页:

admin_upfile.asp 上传图片用的表单文件1
admin_upload.asp 处理上传文件的主程序
admin_uploadF.asp 上传图片用的表单文件2

看了这三个文件的源码从上到下没有一处是验证上传用户的,也就是任何用户都可以使用这三个文件,更有趣的是上传文件的路径是直接写在admin_upfile.asp和admin_uploadF.asp文件的html内,我们可以把文件上传到服务器虚拟目录所在盘的任何目录下,也没有多大的危害,是吧?不过是做点垃圾吧。200K的大小限制和gif|jpg|doc|swf|rar|zip|exe的格式限制,想把一个N百G的盘子装满也不知道要用多长时间,不过可以同时上传N百个小文件让服务器超负荷运行,直至超过脚本运行的最长时间,多来几次不知道算DDOS不?放心,服务器CPU占有率肯定是100%。

本地服务器可以上面测试,不知道青创的网站怎么样,光顾青创官网HTTP:// WWW.QCDN.NET。见过有几个网站不用自己开发的文章管理系统呢?或身为官网没有自己的开发产品的演示呢,青创就是一个吧。官网除了有一部分的样式与发行的文章系统一样外,其余的完全不同,还是SQL版的。

回过头来想一想,既然外部发行的系统内有漏洞,自己用的可能也有,因为编程的风格是不会变的。翻了一会证明确实存在SQL INJECTION漏洞,不过可能是服务器设置的好还是别的原因,对官网的文章系统提交长的字符时老错误。但论坛的服务器可能不和文章服务器是同一个,可以得到明显的错误,且每次的错误报的都很详细。从错误提示中得知论坛也是MSSQL的,突然想起一篇文章《MSSQL跨库查询,你想怎么玩?》,赶快翻资料,照着文章的做法得到了一堆的数据库名:
http://www.qcdn.net/town/list.asp?fid=1 and 1=(select count(*) from master.dbo.sysdatabases where name>1 and dbid=9)
……
找到管理员数据库、字段及内容:
http://www.qcdn.net/town/list.asp?fid=1 and 1=(select top 1 password from admin where password>1 and username =&#39;qcsky.net&#39; )
……
最后的得到的错误如上面:

得到上面的结果后,可以通过UPDATE语句修改数据库内容,以及一些危害服务器的操作(添加系统管理员)。由于会危机服务器,所以就不写出详细过程。

可以修改数据,不防试一下,但先得得到管理员的入口,鄙人有点笨,找了半天没有找到管理员的登陆口,所以也就没有进后台看到底还会有什么发现。返到网站首页,看到右边框架内的链接网站内有一个醒目的‘ASP’LOGO在滚动,鼠标放上去一看,没把我给笑坏——动砐XXX,这不是前几天活动的网站吗,管理员、密码,不过没有找到登陆口,两个怎么凑到一块了——同样存在漏洞、同样没有找到登陆口。

写到这也该结束了,写了好几天了。由于只是‘点到’为止,不免有错误。至于怎么修补,关于动网漏洞的文章那么多,看一看也会有所得的。
--------------------------------------------
今天修改了一下,详细请看下载包。
qq310926是我唯一用号,除此之外有其他号码号自称邪八冰血封情,则非本人。

TOP

发新话题