查找并利用保存型XSS漏洞
确定保存型XSS漏洞的过程与前面描述的确定反射型XSS漏洞的过程有很多相似之处,都包括提交一个特殊的字符窜作为每个页面的第一个参数。但是,这两个过程之间也存在着一些重要的区别。必须记住这些区别,以确定更多的漏洞。
渗透测试步骤:
(1)向应用程序的每一个可能的位置提交一个特殊的字符串后,必须反复检查应用程序的整个内容与功能,确定这个字符串在浏览器中显示的任何情况。在一个位置(例如,个人信息页面的姓名字段)输入用户控制的数据,这个数据可能会在应用程序的许多不同位置显示(例如,用户主页上,注册用户列表中、任务等工作流程项目中、其他用户的联系列表中、用户提交的消息或问题中、应用程序日志等)。应用程序可能对每个出现的字符串实施了不同的保护性过滤,因此需要对他们进行单独分析。
(2)如果有可能,应检查管理员能够访问的所有应用程序区域,确定其中是否存在任何可被非管理用户控制的数据。例如,应用程序一般允许管理员在浏览器中检查日志文件。
这种类型的功能极有可能包含XSS漏洞,攻击者通过生成含有恶意HTML的日志记录即可对其加以利用。
(3)再向应用程序中的每个位置提交一个测试字符串时,并不总是把它作为每个页面的每一个参数这样简单。在保存被提交的数据之前,许多应用程序功能需要经历几个阶段的操作。例如,注册新用户、处理购物订单、转账等操作往往需要按预定的顺序提交几个不同的请求。为避免遗漏任何漏洞,必须确保每次测试彻底完成。
(4)当探查反射型XSS漏洞时,应该注意能够控制的受害者的请求的每一个方面。包括请求的所有参数和每一个HTTP消息头,因为可以使用一个专门设计的Flash对象控制他们。当探查保存型XSS漏洞时,还应该分析应用程序接受并处理能够控制的输入的任何带外通道。任何这类通道都是引入保存型XSS攻击的适当攻击向量。同时,审查在应用程序解析过程中得到的结果,确定每一个可能的受攻击面。
(5)如果应用程序允许文件上传和下载,应始终探查这种功能是否易于受到保存型XSS攻击。如果应用程序允许HTML或文本文件,且并不确认或净化他们的内容,那么几乎可以肯定他们易于受到攻击。如果它允许JPEG文件且并不确认其中是否包含有效的图像,那么可能易于受到针对Internet Explorer用户的攻击。测试应用程序如何处理它支持的每种文件类型,并弄清浏览器如何处理包含HTML而非正常内容的响应。
(6)充分发挥想象,确定控制的数据是否可通过任何其他方法保存在应用程序中并显示给其他用户。例如,如果应用程序的搜索功能显示常用的搜索项列表,就可以通过多次搜索这个列表,引入一个保存型XSS有效载荷,即使主搜索功能安全处理输入。
确定用户控制的数据被应用程序保存并随后在浏览器中显示的每一种情况后,应当遵循与前面描述的探查潜在的反射型XSS漏洞时相同的过程。也就是说,决定需要提交哪些输入,以在周围的HTML中嵌入有效的JavaScript,然后尝试避开干扰攻击有效载荷执行的过滤
当探查反射型XSS漏洞时,通过每次测试一个参数,并检查每个响应中是否出现输入,就可以轻易确定哪些请求参数易于受到攻击,但是,当探查保存型XSS漏洞时,要确定这一点并不容易。如果在每个页面的每一个参数提交相同的测试字符串。那么可能会发现,这个字符串在应用程序的许多位置重复出现,因而无法准确确定每个出现的字符串由哪个参数负责。为避免出现这个问题,当探查保存型XSS时,可以为每个参数提交一个不同的测试字符窜,例如,把测试字符串与它提交到其中的字段名称连接起来。
查找并利用基于DOM的XSS漏洞
使用以下方法无法确定基于DOM的XSS漏洞:提交一个特殊的字符串作为参数,然后监控响应中是否出现该字符串。
确定基于DOM的XSS漏洞的基本方法是,用浏览器手动浏览应用程序,并修改每一个URL参数,在其中插入一个标准测试字符串,例如:
"<script>alert(document.cookie)</script>
通过在浏览器中显示每一个返回的页面,可以执行所有客户端脚本,必要时引用修改的URL参数。只要包含cookie的对话框出现,就表示发现了一个漏洞(可能基于DOM的或标准的反射型XSS漏洞)。使用一个执行自身JavaSript注释器的工具甚至可以自动完成这个过程。
然而,这种基本的方法并不能确定所有基于DOM的XSS漏洞,如上所述,在一个HTML文档中注入有效JavaScript所需的准确语法,取决于用户可控制的字符串插入点前后已经存在的语法。可能需要终止一个被单引号或双引号引用的字符串,或者结束特殊的标签。有时可能需要插入新标签,但有时并不需要。应用程序可能会以各种方式修改输入,但它仍然易于受到攻击。即使应用程序可能易于受到精心设计的攻击,但如果插入标准测试字符串仍不能得到有效的语法,那么嵌入式JavaScript将不会执行,因此也不会有对话框出现。由于无法在每个参数中提交每一种可能的XSS攻击字符串,这种基本的探查方法必然会遗漏大量的漏洞。
确定基于DOM的XSS漏洞的一种更加有效的方法是检查所有客户端JavaScript,看其中是否使用了任何可能会导致漏洞的DOM属性。
渗透测试步骤:
使用在应用程序解析过程中得到的结果,检查每一段客户端JavaScript,看其中是否出现以下API,他们可用于访问通过一个专门设计的URL控制的数据:
document.location
document.URL
document.URLUnencoded
document.referrer
window.location
确保检查出现的静态HTML页面及动态生成的页面中的脚本,无论页面为何种类型,或者是否看到被提交给页面的参数,任何使用脚本的位置都可能存在基于DOM的XSS漏洞。
在每一个使用上述API的位置,仔细检查那里的代码,确定应用程序如何处理用户可控制的数据,以及是否可以使用专门设计的输入促使任意JavaScript得以执行。尤其注意检查并测试控制的数据被传送至以下任何一个API的情况:
document.write()
document.writeln()
document.body.innerHtml
eval()
window.execScript()
window.setInterval()
window.setTimeout()
和查找反射与保存型XSS漏洞时一样,我们可能会发现应用程序执行了一些过滤,阻止包含某些恶意字符串的请求。即使客户端出现易受攻击的操作,服务器并不在响应中返回用户提交的数据,但是URL仍然被提交给了服务器;因此,当应用程序检测到有效载荷时,他会对数据进行确认,且不会返回易受攻击的客户端脚本。
如果遇到这种防御,渗透测试员应该尝试使用前面在查找反射型XSS漏洞时描述的每一种可能避开过滤的攻击方法,测试服务器数据确认机制的可靠性。除这些攻击外,还有几种专门针对基于DOM的XSS漏洞的技巧可帮助攻击有效载荷避开服务器端确认。
当客户端脚本从URL中提取一个参数时,他们很少将查询字符串正确解析成名称/值对。相反,他们通常会在URL中搜索后面紧跟着等号的参数名称,然后提取出等号后直到URL结束位置的内容。这种行为能够以两种方式加以利用。
(1)如果服务器根据每个参数而不是整个URL应用确认机制,那么可以将有效载荷插入到附加在易受攻击的参数后面的一个虚构参数中。例如:
https://wahh-app.com/error.php?message=Sorry%2c+an+error+occurred&
foo=<script>alert(document.cookie)</script>
这时,虚构的参数被服务器忽略,因此不会受到任何过滤。但是,因为客户端脚本在查询字符串中搜索message=,并提取其后的全部内容,所以它处理的字符串中正好包含该有效载荷。
(2)如果服务器对整个URL而不仅仅是消息参数应用确认机制,仍然可以将有效载荷插入到HTML片段字符#的右边,从而避开过滤。例如:
https://wahh-app.com/error.php?message=Sorry%2c+an+error+occurred#<script>alert(document.cookie)</script>
这时,片段字符串仍然属于URL的一部分,因此被保存在DOM中,并由易受攻击的客户端脚本处理。但是,由于浏览器并不将URL中的片段部分提交给服务器,因此攻击字符串不会传送到服务器中,因而不会被任何服务器端过滤所阻止。因为客户端脚本提取message=后面的全部内容,所以有效载荷仍然被复制到HTML页面源代码中。
一些应用程序使用更加复杂的客户端脚本,对查询字符窜进行更加严格的解析。例如,他在URL中搜索后面紧跟着等号的参数名称,然后提取等号后面的内容,直到遇到一个分隔符,如&或#,在这种情况下,可以对前面的两个攻击进行如下修改:
https://wahh-app.com/error.php?foo message=<script>alert(document.cookie)</script>&message=Sorry%2c+an+error+occurred
https://wahh-app.com/error.php#message=<script>alert(document.cookie)</scirpt>
这这两个示例中,第一个message=后面紧跟着攻击字符串,其中没有任何干扰脚本执行的分隔符,因此攻击有效载荷被处理,且被复制到HTML页面源代码中。
有时候,基于DOM的数据经过非常复杂的处理,仅通过静态审查JavaScript源代码可能很难追踪用户控制的数据采用的不同路径以及对它进行的各种操作。在这种情况下,使用一个JavaScript调试器监控脚本的执行情况可能会有很大帮助。Firefox浏览器的FireBug扩展是一款用于监控客户端代码与内容的优秀调试器,可帮助设置断点(breakpoint)、监视感兴趣的代码或数据,为我们了解复杂脚本的执行过程提供极大的便利
12.1.9 HttpOnly cookie与跨站点追踪
攻击XSS漏洞的一种有效载荷,就是使用嵌入式JavaScript访问document.cookie属性,截获受害者的会话令牌。HttpOnly cookie是某些浏览器所支持的一种防御机制,许多应用程序使用它防止这种攻击有效载荷执行。
当应用程序设定一个cookie时,它可能在Set-Cookie消息头标记为HttpOnly:
Set-Cookie:SessID=12kj234kj2343k5j34lj53l4k5j3;HttpOnly;
当一个cookie以这种方式标记时,支持它的浏览器将阻止客户端JavaScript直接访问该cookie。虽然浏览器仍然会在请求的HTTP消息头中提交这个Cookie,但它不会出现在document.cookie返回的字符串中。因此,使用HttpOnly cookie有助于阻止攻击者使用XSS漏洞实施会话劫持攻击。
HttpOnly cookie不会影响其他可使用XSS漏洞传送的攻击有效载荷。例如,他不会影响前面在MySpace蠕虫中使用的诱使用户执行任意操作的攻击。并不是所有浏览器都支持HttpOnly cookie,这表示不能总是依赖他们阻止攻击。而且,稍后我们会讲到,即使使用HttpOnly cookie,攻击者有时仍然能实施会话劫持攻击。
跨站点追踪(XST)是一种攻击技巧,有时可以利用它避开HttpOnly cookie提供的保护,允许客户端JavaScript访问标记为HttpOnly的cookie值。
这种技巧使用许多Web服务器默认激活的HTTP TRACE方法,它主要用于诊断目的。当服务器收到一个使用TRACE方法的请求时,它通过一条消息作出响应,消息主体中包含服务器收到的Trace请求的原始文本。TRACE方法之所以可用于诊断目的,其原因在于,服务器收到的请求可能不同于客户送出的请求。TRACE方法之所以可用于诊断目的,其原因在于,服务器收到的请求可能不同于客户传送的请求,因为请求会被拦截代理服务器修改。这个方法可用于确定请求在客户与服务器之间传送时发生了哪些变化。
浏览器在HTTP请求中提交所有cookie,包括使用TRACE方法的请求以及标记为HttpOnly的cookie。
12.1.10 防止XSS攻击
尽管XSS的表现形式各异,利用方法各不相同,但从概念上讲,防止这种漏洞实际上相当简单。预防他们之所以存在困难,主要在于我们无法确定用户可控制的数据以潜在危险的方式被处理的每一种情况。任何应用程序页面都会处理并显示一些用户数据。除核心功能外,错误消息与其他位置也可能产生漏洞。因此,XSS漏洞普遍存在也就不足为奇了,即使在最为注重安全的应用程序中也是如此。
由于造成漏洞的原因各不相同,一部分防御方法适用于反射型与保存型XSS漏洞,而另一些则适用于基于DOM的XSS漏洞。
1.防止反射型与保存型XSS漏洞
用户可控制的数据未经适当确认与净化就被复制到应用程序响应中,这时造成反射型与保存型XSS漏洞的根本原因。由于数据被插入到一个HTML页面的源代码中,恶意数据就会干扰这个页面,不仅修改它的内容,还会破坏它的结构(影响引用字符串、起始与结束标签、输入脚本等)。
为消除反射型与保存型XSS漏洞,首先必须确定应用程序中用户可控制的数据被复制到响应中的每一种情形。这包括从当前请求中复制的数据以及用户之前输入的保存在应用程序中的数据,还有通过带外通道输入的数据。为确保确定每一种情形,除仔细审查应用程序的全部源代码外,没有其他更好的办法。
确定所有可能存在XSS风险、需要适当进行防御的操作后,需要采取一种三重防御方法阻止漏洞的发生。这种方法由以下三个因素组成:
#确认输入
#确认输出
#消除危险的插入点
(1)确认输入
如果应用程序对某个位置收到的用户提交的数据将来有可能被复制到它的响应中,应用程序应根据这种情形对这些数据执行尽可能严格的确认。需要确认的数据的潜在特性包括以下几点。
数据不是太长
数据仅包含某组合法字符
数据与一个特殊的正规表达式相匹配
根据应用程序希望在每个字段中收到的数据类型,应尽可能限制性的对姓名、电子邮件地址、账号等应用不同的确认规则。
(2)确认输出
如果应用程序将某位用户或第三方提交的数据复制到它的响应中,那么应用程序应对这些数据进行HTML编码,以净化可能的恶意字符。HTML编码指用对应的HTML实体替代字面量字符。这样做可确保浏览器安全处理可能为恶意的字符,把他们当做HTML文档的内容而非结构处理。一些经常造成问题的字符的HTML编码如下:
" "
' '
& &
< <
> >
除这些常用的编码外,实际上,任何字符都可以用它的数字ASCII字符代码进行HTML编码,
% %;
* *;
再将用户可控制的字符串复制到服务器的响应中之前,ASP应用程序可以使用Server,HTMLEncode API净化其中的常见恶意字符。这个API把字符"&<和>转换成他们对应的HTML实体,并且使用数字形式的编码转换任何大于Ox7f的ASCII字符。
在Java平台中没有与之等效的API;但是可以使用数据形式的编码构造自己的等效方法。例如:
public static String HTMLEncode(String s)
{
StringBuffer out = new StringBuffer();
for(int i = 0;i < s.length();i++)
{
char c = s.charAt(i);
if(c > Ox7f || c=='"' || c=='&'|| c=='<' || c=='>')
out.append("&#"+(int)c+";");
else out.append(c);
}
return out.toString();
}
当处理用户提交的数据时,开发者常常会犯一个错误,即仅对在特殊情况下对攻击者有用的字符串进行HTML编码。例如,如果数据被插入到一个双引号引用的字符串中,应用程序可能只编码"字符;如果数据被插入到一个没有引号的标签中,应用程序智慧编码>字符。这种方法明显增加了攻击者避开确认的风险。攻击者常常利用浏览器接受无效HTML与JavaScript的弱点,改变确认情境或以意外的方式注入代码,而且攻击者可以将一个攻击字符串分布到几个可控制的字段中,利用应用程序对每个字段采用的不同过滤避开其他过滤。一种更加可靠的方法是,无论数据插入到什么地方,始终对攻击者可能使用的每一个字符进行HTML编码。为尽可能的确保安全,开发者可能会选择HTML编码每一个非字母数字字符,包括空白符。这种方法通常会显著增加应用程序的工作压力,同时给任何尝试避开过滤的攻击设置巨大障碍。
应用程序之所以结合使用输入确认与输出净化,原因在于这种方法能够提供两层防御:如果其中那个一层被打破,另一层还能提供一些保护。如上所述,许多执行输入与输出确认的过滤都容易被攻破。结合这两种技巧,应用程序就能够获得额外的保护,即使攻击者发现其中一种过滤存在缺陷,另一种过滤仍然能够阻止他实施攻击。在这两种防御中,输出确认最为重要,必不可少。实施严格的输入确认应被视为一种次要故障恢复。
当然,当设计输入与输出确认机制时,我们应特别小心,尽量避免任何可能导致攻击者避开确认的漏洞。尤其要注意的是,应在实施相关规范化后在对数据进行过滤与编码,而且之后不得对数据实施进一步的规范化。应用程序还必须保证其中存在空字节不会对它的确认造成任何干扰。
(3)消除危险的插入点
应用程序页面中有一些位置,在这里插入用户提交的输入就会造成极大的风险;因此,开发者应力求寻找其他方法执行必要的功能。
应尽量避免直接在现有的JavaScript中插入用户可控制的数据。如果应用程序尝试以安全的方式在其中插入数据。可能会使攻击者有机会避开他实施的防御性过滤。一旦公告记者能够控制它提交的数据插入点,他不用付出多大努力就可以注入任意脚本命令,从而实施恶意操作。
如果一个位置上有JavaScript命令直接出现,那么也应禁止在这里插入用户输入。例如:
<img src="userdata">
<img src="foo.gif" οnlοad="userdata">
<input type="text" name="username" οnfοcus="userdata">
在这些情况下,攻击者就可以直接在引用字符串中注入JavaScript命令。而且,这时通过HTML编码用户数据进行防御也不会生效,因为一些浏览器在处理引用字符串的内容之前,会对他进行HTML解码。例如:
<img src="javascritp:alert(document.cookie)">
<img src="foo.gif" οnlοad="alert('xss')">
如果攻击者通过插入一个相关指令,或者因为应用程序使用一个请求参数指定首选的编码类型,因而能够控制应用程序响应的编码类型,那么这些情况也应该加以避免。在这种情况下,在其他方面经过精心设计的输入与输出过滤可能就会失效,因为攻击者的输入进行了不常见的编码,以致上述过滤并不将其视为恶意输入。只要有可能,应用程序应在他的响应消息头中明确指定一种编码类型,禁止对它进行任何形式的修改,并确保应用程序的XSS过滤与其兼容。例如:Content-Type :text/html;charset=ISO-8859-1
2.防止基于DOM的XSS漏洞
很明显,迄今为止,我们描述的防御机制并不能防止基于DOM的XSS漏洞,因为造成这种漏洞并不需要将用户可控制的数据复制到服务器响应中
应用程序应尽量避免使用客户端脚本处理DOM数据并把它插入到页面中。由于被处理的数据不再服务器的直接控制范围内,有时甚至不在他的可见范围内,因此这种行为存在着固有的风险。
如果无法避免的要以这种方式使用客户端脚本,我们可以通过两种防御方法防止基于DOM的XSS漏洞,他们分别与前面描述的防止反射型XSS漏洞时使用的输入与输出确认相对应。
(1)确认输入
许多时候,应用程序可以对它处理的数据执行严格的确认。确实,在这方面,客户端确认比服务器端确认更加有效。在前面描述的易受攻击的示例中,women你可以通过确认将要插入到文档中的数据仅包含字母数字字符与空白符,从而阻止攻击发生。例如:
<script>
var a = document.URL;
a = a.substring(a.indexof("message=")+8,a.length);
a = unescape(a);
var regex=/^([A-Za-zO-9+\s])*$/;
if (regex.test(a))
document.write(a);
</script>
除这种客户端控制外,还可以在服务器端对URL数据进行严格的确认,实施深层防御,以检测利用基于DOM的XSS漏洞的恶意请求。在刚刚说明的同一个示例中,应用程序甚至只需实施服务器端数据确认,通过确认以下数据来阻止攻击:
查询字符串中只有一个参数;
参数名为message(大小写检查);
参数值仅包含字母数字内容。
实施了这些控制后,客户端脚本仍有必要正确解析出message参数的值,确保其中并不包含任何URL片段字符。
(2)确认输出
与防止反射型XSS漏洞时一样,在将用户可控制的DOM数据插入到文档之前,应用程序也可以对他们进行HTML编码。这样就可以将各种危险的字符与表达式以安全的方式显示在页面中。
例如,使用下面的函数即可在客户端JavaScript中执行HTML编码:
function sanitize(str)
{
var d = document.createElement('div');
d.appendChild(document.createTextNode(str));
return d.innerHtml;
}
3.防止XST
应用程序XST技巧取决于攻击者能否找到某种XSS漏洞,可在其他用户查看的页面中插入任意JavaScript。因此,要想消除全部的XSS漏洞,必须阻断攻击者使用这种技巧的任何机会。尽管如此,我们仍然建议在管理应用程序的Web服务器上将所有Cookie标记为HttpOnly,同时禁止TRACE方法。
12.2 重定向攻击
如果应用程序提取用户可控制的输入,并使用这个数据执行一个重定向,指示用户的浏览器访问一个不同于用户要求的URL,那么就会造成重定向漏洞。相比于可用以执行大量恶意操作的跨站点脚本漏洞,重定向漏洞不大会引起攻击者的兴趣。攻击者主要利用重定向漏洞实施钓鱼攻击,诱使受害者访问一个欺骗性Web站点并输入敏感信息。对受害者而言,重定向漏洞提高了攻击者的可信度,因为它允许攻击者创建一个指向他所针对的可信Web站点的URL,因此更具有说服力,但任何访问这个URL的用户将被悄悄重定向到攻击者控制的一个Web站点。实际上,许多应用程序确实将指向第三方站点的重定向作为他们的正常功能,例如,处理顾客支付贷款。这促使用户在交易过程中信任重定向。当利用重定向漏洞时,攻击者即可对这种认知加以利用。
渗透测试步骤:
(1)确定应用程序中使用重定向的所有位置
(2)要确定所有重定向,一个有效的方法是使用拦截代理服务器浏览应用程序,并监控访问页面的请求(相对于其他资源,如图像、样式表、脚本文件等)。
(3)如果一个导航操作导致几个连续请求,分析它使用什么方法进行重定向。
(4)如果用户数据被一个包含绝对URL的重定向处理,那么修改URL中的域名,并测试应用程序是否将重定向到另一个域。
(5)如果用户被一个包含相对URL的重定向处理,将相对URL修改为指向另一个域的绝对URL,并测试应用程序是否将重定向到这个域
(6)无论是哪一种情况,如果见到以下行为,那么应用程序肯定容易受到重定向攻击;
GET /redir.php?target=http://wahh-attacker.com/ HTTP/1.1
HOST:wahh-app.com
HTTP/1.1 302 object moved
Location:http://wahh-attacker.com/
1.避开攻击中的障碍
(1)阻止绝对URL
应用程序可能会检查用户提交的字符串是否以HttpP//开头,如果是,就阻止该请求。
(2)附加一个绝对前缀
12.2.2防止重定向漏洞
绝不将用户提交的数据合并到重定向目标中是避免重定向漏洞的最有效的方法。
(1)从应用程序中删除重定向页面,用直接指向相关目标URL的链接替代指向重定向页面的链接
(2)建立一个包含所有有效重定向URL的列表,不以参数的形式向重定向页面传送目标URL,相反,传送这个列表的一个索引。重定向页面应在它的列表中查询这个索引,并返回一个指向相关URL的重定向。
(3)应用程序应在所有重定向中使用相对URL,重定向页面应严格确认它收到URL是一个相对URL。它应当确认:用户提交的URL或者以单独一个斜线字符、后接一个字母开头。或者以一个字母开头,并且在第一个斜线前没有冒号。应拒绝而不是净化任何其他输入。
(4)应用程序应该在所有重定向中使用相对于Web根目录的URL,在发布重定向之前,重定向页面应在所有提交的URL前附加http://yourdomainname.com。如果用户提交的URL并不以斜线字符开头,应在它的前面附加http://yourdomainname.com/。
(5)应用程序应对所有重定向使用绝对URL,重定向页面在发布重定向之前,应确认用户提交的URL以http://yourdomainname.com/开头。此外,应拒绝任何其他输入。
12.3 HTTP消息头注入
如果用户控制的数据以不安全的方式插入到应用程序返回的HTTP消息头中,就会出现HTTP消息头注入漏洞。如果攻击者能够在他控制的消息头中注入换行符,他就能再响应中插入其他HTTP消息头,并在响应主体中写入任意内容。
这种漏洞最常见于Location与Set-Cookie消息头中,但也会出现在其他HTTP消息头中。前文已经讲到,应用程序提取用户提交的输入,并将它插入到响应码为3xx的Location消息头中。同样,一些应用程序提取用户提交的输入,把它插入一个cookie值中。例如:GET /home.php?uid=123 HTTP/1.1
HOST:wahh-app.com
HTTP/1.1 200 OK
Set-Cookie:userID=123
....
在上述任何一种情况下,攻击者都可以使用回车符(OxOd)或换行符(OxOa)构造一个专门设计的请求,在他们控制的消息头中注入一个换行符,从而在下面的行中注入其他数据。例如:
GET /home.php?uid=123%0d%0aFoo:+bar http/1.1
HOST:myapp.com
HTTP/1.1 200 OK
Set-Cookie:UserID=123
Foo:bar
....
12.3.1 利用消息头注入漏洞
查找消息头注入漏洞的方法与查找XSS漏洞的方法类似,同样需要寻找用户控制的输入重复出现在应用程序返回的HTTP消息头中的情况。因此,在探查应用程序是否存在XSS漏洞的过程中,还应当确定任何应用程序可能易于受到消息头注入的位置。
渗透测试步骤:
(1)在用户控制的注入被复制到HTTP消息头中的每个位置都可能存在漏洞,确认应用程序是否接受URL编码的回车符与换行符,以及他们是否按原样在响应中返回。
(2)注意,是在服务器的响应中而不是换行符的URL编码形式中寻找换行符本身。如果通过拦截代理服务器查找响应,攻击成功的话,应该会在HTTP消息头中看到另外一个新行。
(3)如果服务器的响应中仅返回两个换行符中的一个,根据实际情况,仍然能够设计出有效的攻击方法。
(4)如果发现换行符被应用程序阻止或净化,那么应该尝试以下攻击方法:
foo%00%0d%0abar
foo%250d%250abar
foo%%0d0d%%0a0abar
如果能够在响应中注入任意消息头和消息主体内容,那么这种行为可通过各种方式用户攻击应用程序的其他用户。
1.注入cookie
攻击者可以建立一个URL,在请求它的任何用户的浏览器中设定任意cookie。
12.4 框架注入
在许多浏览器中,如果一个Web站点创建一个命名框架,那么相同浏览器进程打开的任何窗口都允许写这个框架的内容,即使它的内容已经已由另一个Web站点发布。框架注入漏洞即源于上述事实,它是一种相对于简单的漏洞。
渗透测试步骤:
(1)如果应用程序使用框架,检查主要浏览器窗口的HTML源代码,其中应包含框架标记(frameset)的代码。
(2)如下例所示,如果框架标记在创建每个框架的标签中使用name属性为每个框架指定一个名称,那么应用程序易于受到攻击。
<frameset rows="50,*">
<frame src="top_menu.asp" name="top_menu"
frameborder="yes" title="Left menu">
<frame src="main_display.asp" name="main_display"
frameborder="yes" title="Main display">
</frameset>
(3)如果框架标记使用命名框架,但框架名称含义非常模糊或完全随机,就可从不同的浏览器访问应用程序,并检查框架名称是否发生变化。如果框架名称发生变化并且攻击者无法预测其他用户的框架名称,那么应用程序可能不易受到攻击。
12.4.1 利用框架注入
如果应用程序易于受到框架注入,那么攻击者就可以使用以下步骤利用这种漏洞。
(1)攻击者创建一个看似无害的Web站点,其中包含一段每隔10秒就会自动运行的脚本,并尝试使用它覆写main_display框架的内容。
(2)攻击者或者等待wahh-app.com用户浏览他创建的站点,或者使用其他方法诱使他们这样做,如发送电子邮件、购买横幅广告等。
12.4.2 防止框架注入
以下两种方法可用于防止框架注入漏洞
(1)如果应用程序不要求不同的框架互相通信,就可以通过完全删除框架名称、使用匿名框架防止框架注入。但是,因为应用程序通常都要求框架间相互通信,因此这种方法并不可行
(2)使用命名框架,但在每个会话中使用不同的框架,并且使用无法预测的名称。一种可行的方法是在每个基本的框架名称后附加用户的会话令牌,如main_display。