漏洞解决方案-跨站脚本攻击

  • 跨站脚本攻击
  • 1.风险分析
  • 2.详细描述
  • 3.解决方案


跨站脚本攻击

1.风险分析

跨站脚本可能造成用户信息泄露(包括我行内部行员的用户名、密码泄露),配置更改,cookie窃取等造成危害,甚至能够用于对Web服务器进行DOS攻击。黑客也可利用获取的用户信息对我行系统进行进一步攻击。

2.详细描述

跨站脚本发生在以下两种情况:

  1. 数据通过不可靠的源进入Web application,大多数情况下是web request。
  2. 包含在动态内容中的数据在没有经过安全检测就发送给网络用户。
发给web浏览器的恶意内容通常以JavaScript段的形式出现,但也包括HTML, Flash或者其他浏览器能够执行的代码类型。基于XSS的攻击种类几乎是无限的,但是它们通常会包括:传送私有数据(如cookies或者其他session信息)给攻击者,将受害者的浏览器重定向到攻击者所控制的web内容中,或者假借有漏洞的站点在用户机器上进行其他恶意操作。

代码1(JSP):

<% String eid = request.getParameter("eid"); %> 
...
Employee ID: <%= eid %>
上述JSP 代码段从一个HTTP request中读雇员的eid,并将它显示出来,如果eid包含源代码,该源代码就会被浏览器执行。

代码2(JSP):

<%... 
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from emp where id="+eid);	
if (rs != null)
rs.next(); 
String name = rs.getString("name");
%>	
Employee Name: <%= name %>
上述JSP 代码段从一个数据库中读雇员的name,并将它显示出来,如果name包含源代码,该源代码就会被浏览器执行。

代码3(ASP.NET):

protected System.Web.UI.WebControls.TextBox Login;
protected System.Web.UI.WebControls.Label EmployeeID;
...
EmployeeID.Text = Login.Text;
上述ASP.NET代码段从一个HTTP请求中读取雇员的id ,并将它显示给用户。本例中,如果Login只包含了标准的数字和文字内容,那么代码会正确的执行。但如果Login中包括了特殊字符或者源代码,那么此代码将作为HTTP响应被浏览器执行。

代码4(ASP.NET):

protected System.Web.UI.WebControls.Label EmployeeName;
...
string query = "select * from emp where id=" + eid;
sda = new SqlDataAdapter(query, conn);
sda.Fill(dt);
string name = dt.Rows[0]["Name"];
...
EmployeeName.Text = name;

当name符合规范的时候,这段代码能够正确运行。但当name有问题时,代码段中并没有任何措施来阻止其运行。同样的,这段代码看起来危险性较小,因为name的值是从数据库中读取的。很显然,数据库的内容是由应用程序所控制的。然而,如果name的值来自于用户所提供的数据,那么这个数据库就会成为恶意内容的渠道。如果对数据库中存储的所有数据没有一个适当的输入验证,那么攻击者就能够在用户的浏览器上执行恶意内容。这种类型的攻击被称为存储型XSS,它显得尤为隐蔽,因为数据存储所带来的间接性使得这种威胁更难被识别,也使得攻击者能够侵袭更多的用户。XSS攻击可以采用如下形式:一个web站点对访问者进行来宾登记,攻击者在来宾登记中注入JavaScript代码,之后所有进入来宾登记页面的访问者都会执行该恶意代码。

3.解决方案
  1. 使用输入过滤
  2. 输出编码
    跨站产生的原因在于在对用户输入的内容进行显示时,未对html标签以及js内容进行正确的处理,导致数据作为脚本在浏览器中执行了,因此对跨站漏洞的修复要针对变量输出的位置进行不同的处理,具体方案如下:
    (1)当变量输出位置为HTML标签和属性中时,如<div class="$var1">$var2</div>,要对其进行html escape转义,函数需要转移的字符如下:

    (2)当变量的输出位置在js代码中时,如<script> var a = "$var";</script>,首先确保输出内容在“"”中,其次需要做javascriptescape转义,函数需要对以下字符进行转义:

    (3)当变量输出在标签的事件中时,如 <div notallow="fun($var1)"></div>,该种情况比较复杂,通过单纯的htmlescape或javascriptescape无法防御,因为单纯进行javascriptescape,可以对注入内容进行htmlescape,由于浏览器加载内容时,先进行htmlparser,然后进行javascriptparser,因此会将注入内容解析执行,而单纯进行htmlescape,会在浏览器进行htmlparser时直接解析,所以对该类变量输出需要先进行javascriptescape,然后进行htmlescape,即<div notallow="fun(htmlescape (javascriptescape($var1)))"></div> (4) 针对DOM类型的输出,即在js脚本中通过html()等函数将变量输出在html中时,需要对变量先进行htmlescape,然后进行javascriptescape,即javascriptescape(htmlescape($var)); (5)当变量在url中输出时:首先保证完整的url是以“http://”开头,其次对内容进行urlescape,需要转移的字符如下: