在服务器端与XSS战斗并不像您想象的那么困难。目标是知道你应该在哪个上下文中编码哪个字符。
基本上有4种不同的情况,我们应该考虑XSS。
HTML语境
如果你想获得XSS在这种情况下,你需要<和>字符攻击。因此只编码这两个字符可以解决基于HTML上下文的XSS。
/**
* XSS protection function for HTML context only
* @usecases
* <title>use this function if output reflects here or as a content of any HTML tag.</title>
* e.g., <span>use this function if output reflects here</span>
* e.g., <div>use this function if output reflects here</div>
* @description
* Sanitize/Filter <and> so that attacker can not leverage them for JavaScript execution.
* @author Ashar Javed
* @Link https://twitter.com/soaj1664ashar
* @demo http://xssplaygroundforfunandlearn.netai.net/final.html
*/
function htmlContextCleaner($input) {
$bad_chars = array("<", ">");
$safe_chars = array("<", ">");
$output = str_replace($bad_chars, $safe_chars, $input);
return stripslashes($output);
}
的Javascript语境
最常见的情况是类似以下代码。
<script> var name = 'USERINPUTISHERE';</script>
或
<script> var name = "USERINPUTISHERE";</script>
或
<button type="submit" onclick="return callSomeFunction('USERINPUTHERE')">
为了防止你对JS基于上下文XSS攻击的应用程序。你需要编码6个特定的字符。请阅读以下说明以了解脚本上下文的攻击媒介。
/**
* XSS protection function for script context only
* @usecases
* @double quoted case e.g.,
* <script> var searchquery = "use this function if output reflects here"; </script>
* @single quoted case e.g.,
* <script> var searchquery = 'use this function if output reflects here'; </script>
* @description
* Sanitize/Filter meta or control characters that attacker may use to break the context e.g.,
* "; confirm(1); " OR '; prompt(1); // OR </script><script>alert(1)</script>
* \ and % are filtered because they may break the page e.g., \n or %0a
* & is sanitized because of complex or nested context (if in use)
* @author Ashar Javed
* @Link https://twitter.com/soaj1664ashar
* @demo http://xssplaygroundforfunandlearn.netai.net/final.html
*/
function scriptContextCleaner($input) {
$bad_chars = array("\"", "<", "'", "\\\\", "%", "&");
$safe_chars = array(""", "<", "'", "\", "%", "&");
$output = str_replace($bad_chars, $safe_chars, $input);
return stripslashes($output);
}
属性上下文
以下代码可以是例如用于属性上下文。
<input name="fname" value="USERINPUTISHERE">
或样例的单引号形式。
<input name='fname' value='USERINPUTISHERE'>
基本上我们需要编码非常特殊的字符才能保证它的安全。我们还需要编码back-tick,以便为旧版本的IE提供安全的上下文。请阅读以下说明和代码。
/**
* XSS protection function for an attribute context only
* @usecases
* @double quoted case e.g.,
* <div class="use this function if output reflects here">attribute context</div>
* In above example class attribute have been used but it can be any like id or alt etc.
* @single quoted case e.g.,
* <input type='text' value='use this function if output reflects here'>
* @description
* Sanitize/Filter meta or control characters that attacker may use to break the context e.g.,
* "onmouseover="alert(1) OR 'onfocus='confirm(1) OR ``onmouseover=prompt(1)
* back-tick i.e., `` is filtered because old IE browsers treat it as a valid separator.
* @author Ashar Javed
* @Link https://twitter.com/soaj1664ashar
* @demo http://xssplaygroundforfunandlearn.netai.net/final.html
*/
function attributeContextCleaner($input) {
$bad_chars = array("\"", "'", "``");
$safe_chars = array(""", "'", "`");
$output = str_replace($bad_chars, $safe_chars, $input);
return stripslashes($output);
}
样式上下文
作为一个攻击者,得到XSS与通常与IE样式上下文。请再次阅读以下说明和代码。
/**
* XSS protection function for style context only
* @usecases
* @double quoted case e.g.,
* <span style="use this function if output reflects here"></span>
* @single quoted case e.g.,
* <div style='use this function if output reflects here'></div>
* OR <style>use this function if output reflects here</style>
* @description
* Sanitize/Filter meta or control characters that attacker may use to execute JavaScript e.g.,
* (is filtered because width:expression(alert(1))
* & is filtered in order to stop decimal + hex + HTML5 entity encoding
* < is filtered in case developers are using <style></style> tags instead of style attribute.
* < is filtered because attacker may close the </style> tag and then execute JavaScript.
* The function allows simple styles e.g., color:red, height:100px etc.
* @author Ashar Javed
* @Link https://twitter.com/soaj1664ashar
* @demo http://xssplaygroundforfunandlearn.netai.net/final.html
*/
function styleContextCleaner($input) {
$bad_chars = array("\"", "'", "``", "(", "\\\\", "<", "&");
$safe_chars = array(""", "'", "`", "(", "\", "<", "&");
$output = str_replace($bad_chars, $safe_chars, $input);
return stripslashes($output);
}
结论
与XSS服务器端编码战斗,如果你知道哪些字符在他们的特殊背景下进行编码时可以很容易。当您使用back tick(`)作为属性分隔符(如下所示)时,只有一个复杂因素。
<input name=`fname` value=`USERINPUTHERE`>
此功能无法保护您的应用程序。但我还没有看到这个案例的真实生活的例子!
我在上面描述的方法是针对数十名黑客/安全研究人员进行测试的,没有人利用它。 (详情:https://twitter.com/soaj1664ashar/status/478939711667712000)。另外Symphonycms使用这种方法来预防XSS(也可以从他们的回购中获取所有代码示例)
正如你所看到的,你需要知道变量会反映哪个位置。通常,开发人员知道变量的输出位置,但是如果您确实不知道DOMPurify对您更有用,但我相信这可能会导致代码复杂性并难以维护。
DOMPurify
DOMPurify是DOM-只,速度超快,超级容错XSS消毒剂对HTML,MathML和SVG。它采用JavaScript编写,适用于所有现代浏览器(Safari,Opera(15+),Internet Explorer(9+),Firefox和Chrome)以及其他几乎所有使用Blink或WebKit的软件。它不会在IE6或其他旧版浏览器上中断。它根本没有做任何事情。
DOMPurify是由在Web攻击和XSS方面拥有丰富背景的安全人员撰写的。不要害怕。
更多信息可以在这里找到(https://github.com/cure53/DOMPurify)