【前端安全】-【防范xss攻击】

XSS 漏洞的发生和修复

XSS 攻击是页面被注入了恶意的代码

案例

公司需要一个搜索页面,根据 URL 参数决定关键词的内容。小明写的前端页面代码如下:

<input type="text" value="<%= getParameter("keyword") %>">
<button>搜索</button>
<div>
  您搜索的关键词是:<%= getParameter("keyword") %>
</div>

如果这个url是:http://xxx/search?keyword="><script>alert('XSS');</script>,会导致页面弹出两次弹窗,因为当浏览器请求http://xxx/search?keyword="><script>alert('XSS');</script>时,服务端会解析出请求参数keyword,得到"><script>alert('XSS');</script>,拼接到HTML中返回给浏览器。形成了如下的 HTML:

<input type="text" value=""><script>alert('XSS');</script>">
<button>搜索</button>
<div>
  您搜索的关键词是:"><script>alert('XSS');</script>
</div>

浏览器无法分辨出<script>alert('XSS');</script>是恶意代码,因而将其执行。这里不仅仅div的内容被注入了,而且input的value属性也被注入,alert会弹出两次。

解决方案:对特殊字符进行转义:

<input type="text" value="<%= escapeHTML(getParameter("keyword")) %>">
<button>搜索</button>
<div>
  您搜索的关键词是:<%= escapeHTML(getParameter("keyword")) %>
</div>

上述url(http://xxx/search?keyword="><script>alert('XSS');</script>)展示的内容如下:

<input type="text" value="&quot;&gt;&lt;script&gt;alert(&#x27;XSS&#x27;);&lt;&#x2F;script&gt;">
<button>搜索</button>
<div>
  您搜索的关键词是:&quot;&gt;&lt;script&gt;alert(&#x27;XSS&#x27;);&lt;&#x2F;script&gt;
</div>

总结:

  1. 通常页面中包含的用户输入内容都在固定的容器或者属性内,以文本的形式展示。
  2. 攻击者利用这些页面的用户输入片段,拼接特殊格式的字符串,突破原有位置的限制,形成了代码片段。
  3. 攻击者通过在目标网站上注入脚本,使之在用户的浏览器上运行,从而引发潜在风险。
  4. 通过 HTML 转义,可以防止 XSS 攻击

注意特殊的 HTML 属性、JavaScript API

如果要根据URL参数决定跳转路径,前端代码:<a href="<%= escapeHTML(getParameter("redirect_to")) %>">跳转...</a>,假如URL 为http://xxx/?redirect_to=javascript:alert('XSS'),服务端响应就成了:<a href="javascript:alert(&#x27;XSS&#x27;)">跳转...</a>,虽然代码不会立即执行,但一旦用户点击a标签时,浏览器会就会弹出“XSS”。

解决方案:先把getParameter("redirect_to")的值转换成小写,再比对,下文省略了转换成小写的代码

// 禁止 URL 以 "javascript:" 开头
xss = getParameter("redirect_to").startsWith('javascript:');
if (!xss) {
  <a href="<%= escapeHTML(getParameter("redirect_to"))%>">
    跳转...
  </a>
} else {
  <a href="/404">
    跳转...
  </a>
}

如果链接是http://xxx/?redirect_to=%20javascript:alert('XSS')%20javascript:alert('XSS')经过URL解析后变成javascript:alert('XSS'),这个字符串以空格开头。这样攻击者可以绕过后端的关键词规则,又成功的完成了注入。最终,小明选择了白名单的方法,彻底解决了这个漏洞:

// 根据项目情况进行过滤,禁止掉 "javascript:" 链接、非法 scheme 等
allowSchemes = ["http", "https"];

valid = isValid(getParameter("redirect_to"), allowSchemes);

if (valid) {
  <a href="<%= escapeHTML(getParameter("redirect_to"))%>">
    跳转...
  </a>
} else {
  <a href="/404">
    跳转...
  </a>
}

总结:

  1. 做了 HTML 转义,并不等于高枕无忧。
  2. 对于链接跳转,如<a href="xxx"location.href="xxx",要检验其内容,禁止以javascript:开头的链接,和其他非法的scheme。

根据上下文采用不同的转义规则

猜你喜欢

转载自blog.csdn.net/CaraYQ/article/details/131261050
今日推荐