0. 检测
手动:
jaVasCript:/-//*
/'/"/*/(/ */oNcliCk=alert() )//%0D%0A%0d%0a//</stYle/</titLe/</teXtarEa/</scRipt/--!>
工具
Arachni、Mozilla HTTP Observatory、w3af
1. XSS 有常见注入的方法:
- 在 HTML 中内嵌的文本中,恶意内容以 script 标签形成注入。
- 在内联的 JavaScript 中,拼接的数据突破了原本的限制(字符串,变量,方法名等)。
- 在标签属性中,恶意内容包含引号,从而突破属性值的限制,注入其他属性或者标签。
- 在标签的 href、src 等属性中,包含 javascript: 等可执行代码。
- 在 onload、onerror、onclick 等事件中,注入不受控制代码。
- 在 style 属性和标签中,包含类似 background-image:url("javascript:..."); 的代码(新版本浏览器已经可以防范)。
- 在 style 属性和标签中,包含类似 expression(...) 的 CSS 表达式代码(新版本浏览器已经可以防范)。
2. 在处理输入时,以下内容都不可信:
- 来自用户的 UGC 信息
- 来自第三方的链接
- URL 参数
- POST 参数
- Referer (可能来自不可信的来源)
- Cookie (可能来自其他子域注入)
3.XSS 分类
类型 | 储存区 | 插入点 |
---|---|---|
存储型 | 数据库 | HTML |
反射型 | URL | HTML |
DOM | 后端数据库/前端储存/URL | 前端Javascript |
存储型 XSS
- 攻击者将恶意代码提交到目标网站的数据库中。
- 用户打开目标网站时,网站服务端将恶意代码从数据库取出,拼接在 HTML 中返回给浏览器。
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 在部分情况下,恶意代码加载外部的代码,用于执行更复杂的逻辑。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
反射型 XSS
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL 时,网站服务端将恶意代码从 URL 中取出,拼接在 HTML 中返回给浏览器。
- 用户浏览器接收到响应后解析执行,混在其中的恶意代码也被执行。
- 在部分情况下,恶意代码加载外部的代码,用于执行更复杂的逻辑
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
DOM 型 XSS
- 攻击者构造出特殊的 URL,其中包含恶意代码。
- 用户打开带有恶意代码的 URL。
- 用户浏览器接收到响应后解析执行,前端 JavaScript 取出 URL 中的恶意代码并执行。
- 在部分情况下,恶意代码加载外部的代码,用于执行更复杂的逻辑。
- 恶意代码窃取用户数据并发送到攻击者的网站,或者冒充用户的行为,调用目标网站接口执行攻击者指定的操作。
1. keyword(符号过滤)
版本一
<imput type="text" value="<%= getParameter("keyword") %>">
<button>搜索</button>
<div>
您搜索到的关键词是:<%= getParameter("keyword") %>
</div>
http://xxx/search?keyword="><script>alert('XSS');</script>
运行结果
<imput type="text" value=""><script>alert('xss');</script>">
<button>搜索</button>
<div>
您搜索到的关键词是:"><script>alert('xss');</script>
</div>
版本二
1. 加入escape()函数,将常用字符进行转义,意在告诉浏览器接收内容为文本
<input type="text" value="<%= escapeHTML(getParameter("keyword")) %>">
<button>搜索</button>
<div>
您搜索的关键词是:<%= escapeHTML(getParameter("keyword")) %>
</div>
2. redirect_to(javascript:alert('XSS'))
<a href="<%= escapeHTML(getParameter("redirect_to")) %>">跳转...</a>
<a href="javascript:alert('XSS')">跳转...</a>
最终方案
// 根据项目情况进行过滤,禁止掉 "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>
}
3.
<script>
var initData = <%= data.toJSON() %>
</script>
插入 JSON 的地方不能使用 escapeHTML()
,因为转义 "
后,JSON 格式会被破坏。
- 当 JSON 中包含
U+2028
或U+2029
这两个字符时,不能作为 JavaScript 的字面量使用,否则会抛出语法错误。- 当 JSON 中包含字符串<script>时,当前的 script 标签将会被闭合,后面的字符串内容浏览器会按照 HTML 进行解析;通过增加下一个
<script>
标签等方法就可以完成注入。
修复后的代码如下:
<script>var initData = <%= escapeEmbedJSON(data.toJSON()) %>