在node/express请求静态资源中减轻反射型XSS攻击

4
我使用了一款名为Burp的渗透测试工具对我的node(express)/angular应用进行了测试,发现在尝试获取静态资源时(明显地,在用户与应用程序交互时未发现漏洞),它识别出了一个反射型XSS漏洞。
问题详情如下:
引号中没有封装的JavaScript表达式复制了任意提供的URL参数的名称。在任意提供的URL参数的名称中提交了负载41b68(a)184a9=1。此输入在应用程序的响应中未经修改地回显。
这种行为表明可以将JavaScript命令注入返回的文档中。尝试识别注入任意JavaScript的全面攻击的尝试失败了。您应该手动检查应用程序的行为,并尝试确定是否存在任何异常的输入验证或其他障碍。
通过向请求传递任意的url参数来测试漏洞,例如:
GET /images/?41b68(a)184a9=1

响应是:

HTTP/1.1 404 Not Found
X-Content-Security-Policy: connect-src 'self'; default-src 'self'; font-src 'self'; frame-src; img-src 'self' *.google-analytics.com; media-src; object-src; script-src 'self' 'unsafe-eval' *.google-analytics.com; style-src 'self' 'unsafe-inline'
X-XSS-Protection: 1; mode=block
X-Frame-Options: DENY
Strict-Transport-Security: max-age=10886400; includeSubDomains; preload
X-Download-Options: noopen
X-Content-Type-Options: nosniff
Content-Type: text/html; charset=utf-8
Content-Length: 52
Date: Wed, 08 Oct 2015 10:46:43 GMT
Connection: close

Cannot GET /images/?41b68(a)184a9=1

您可以看到我已经使用Helmet实施了CSP并采取了其他防范措施来防范漏洞。应用程序通过https提供服务,但不需要用户身份验证。CSP仅限于向应用程序域和Google Analytics发出请求。
渗透测试报告建议验证输入(我正在进行,但如果我没有这样做,那么包括用户发送的数据在内的请求肯定是不安全的),并且Angular默认情况下对HTML进行编码。
我真的很难找到一个解决方案来防止或减轻这些静态资源请求的问题:
  • 我应该将所有对我的应用程序的请求列入CSP白名单吗?
  • 我能做到这一点吗,还是只会列入域名白名单?
  • 从节点/express返回的所有静态资源请求的响应都应以某种方式进行编码吗?
  • 报告指出:“任意提供的URL参数的名称被复制到未封装在任何引号中的JavaScript表达式中”。这个表达式可能在处理返回静态资源的express代码中吗?
  • 或者说GET请求参数可以在我的应用程序代码中进行评估?

更新

经过一些调查,看起来至少有一部分缓解方法是对url参数值进行转义清理url中的输入内容

Url的转义已经完成,所以:

curl 'http://mydomain/images/?<script>alert('hello')</script>'

返回
Cannot GET /images/?&lt;script&gt;alert(hello)&lt;/script&gt;

我还在这个基础上加入了express-sanitized

然而,如果我使用curl测试原始请求,请求参数仍然会被反射回来。

curl 'http://mydomain/images/?41b68(a)184a9=1'
Cannot GET /images/?41b68(a)184a9=1

你会期望这种情况的发生,因为HTML没有插入到URL中。
对于静态资源的GET请求响应都由app.use(express.static('static-dir'))处理,所以查询被传递到其中。express.static基于serve-static,后者依赖于parseurl
1个回答

1
问题的原因是对于无效的GET请求,express会返回类似以下内容:
Cannot GET /pathname/?yourQueryString

在很多情况下,这是一个有效的响应,即使是为服务静态资产。然而,在我的情况和我相信对于其他人来说,对于静态资产的唯一有效请求将会是像这样的内容:
GET /pathname/your-file.jpg

我有一个自定义的404处理程序,返回一个数据对象:
var data = {
    status: 404,
    message: 'Not Found',
    description: description,
    url: req.url
}; 

这仅在app.js中处理无效的模板请求:

app.use('/template-path/*', function(req, res, next) {
    custom404.send404(req, res);
});

我现在为静态文件夹的请求添加了显式处理程序:

app.use('/static-path/*', function(req, res, next) {
        custom404.send404(req, res);
});

在返回404之前,我可以选择剥离请求查询参数:

var data = {
    status: 404,
    message: 'Not Found',
    description: description,
    url: url.parse(req.url).pathname // needs a var url = require('url')
};

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接