缓解 node/express 静态资产请求中的反映 XSS
Mitigating reflected XSS in node/express requests for static assets
我已经 运行 针对我的 node(express)/angular 应用程序进行了渗透测试工具 (Burp),它在尝试 GET
请求时识别了一个反映的 XSS 漏洞对于静态资产(当用户与应用程序交互时发出的任何请求都没有发现明显的漏洞)。
问题详情为:
The name of an arbitrarily supplied URL parameter is copied into a
JavaScript expression which is not encapsulated in any quotation
marks. The payload 41b68(a)184a9=1 was submitted in the name of an
arbitrarily supplied URL parameter. This input was echoed unmodified
in the application's response.
This behavior demonstrates that it is possible to inject JavaScript
commands into the returned document. An attempt was made to identify a
full proof-of-concept attack for injecting arbitrary JavaScript but
this was not successful. You should manually examine the application's
behavior and attempt to identify any unusual input validation or other
obstacles that may be in place.
通过向请求传递任意 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
你可以看到我有 CSP(使用 Helmet 来实现)和其他针对漏洞利用的保护措施。该应用程序通过 https 提供,但不需要用户身份验证。 CSP 将请求限制为仅应用程序的域加上 google 分析。
渗透测试报告建议验证输入(我是,但如果我不是,那肯定会使包括用户发送的数据在内的请求不安全?),并编码 html angular默认情况下。
我真的很难找到一种解决方案来防止或减轻这些对静态资产的请求:
- 我应该在 csp 下将我的应用程序的所有请求列入白名单吗?
- 我什至可以这样做吗,还是它只会将域列入白名单?
- Can/should node/express 对静态资产请求的所有响应都以某种方式编码?
- 报告指出"The name of an arbitrarily supplied URL parameter is copied into a JavaScript expression which is not encapsulated in any quotation marks"。这个表达式可以在处理返回静态资产的快速代码中的某个地方吗?
- 或者可以在我的应用程序代码中以某种方式评估 GET 请求参数?
更新
对此进行了一些调查后,似乎至少部分缓解措施是 escape data in url param values and sanitize the input in the url。
url 的转义已经到位,因此:
curl 'http://mydomain/images/?<script>alert('hello')</script>'
returns
Cannot GET /images/?<script>alert(hello)</script>
我还在上面放了 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 which depends on parseurl.
问题的原因是,对于无效的 GET
请求,表达将 return 类似于:
Cannot GET /pathname/?yourQueryString
这在很多情况下都是有效的响应,即使对于提供静态资产也是如此。然而,在我的情况下,我确信对于其他人来说,对静态资产的唯一有效请求将是这样的:
GET /pathname/your-file.jpg
我有一个自定义 404 处理程序,它 return 是一个数据对象:
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 returned:
之前删除请求查询参数
var data = {
status: 404,
message: 'Not Found',
description: description,
url: url.parse(req.url).pathname // needs a var url = require('url')
};
我已经 运行 针对我的 node(express)/angular 应用程序进行了渗透测试工具 (Burp),它在尝试 GET
请求时识别了一个反映的 XSS 漏洞对于静态资产(当用户与应用程序交互时发出的任何请求都没有发现明显的漏洞)。
问题详情为:
The name of an arbitrarily supplied URL parameter is copied into a JavaScript expression which is not encapsulated in any quotation marks. The payload 41b68(a)184a9=1 was submitted in the name of an arbitrarily supplied URL parameter. This input was echoed unmodified in the application's response.
This behavior demonstrates that it is possible to inject JavaScript commands into the returned document. An attempt was made to identify a full proof-of-concept attack for injecting arbitrary JavaScript but this was not successful. You should manually examine the application's behavior and attempt to identify any unusual input validation or other obstacles that may be in place.
通过向请求传递任意 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
你可以看到我有 CSP(使用 Helmet 来实现)和其他针对漏洞利用的保护措施。该应用程序通过 https 提供,但不需要用户身份验证。 CSP 将请求限制为仅应用程序的域加上 google 分析。
渗透测试报告建议验证输入(我是,但如果我不是,那肯定会使包括用户发送的数据在内的请求不安全?),并编码 html angular默认情况下。
我真的很难找到一种解决方案来防止或减轻这些对静态资产的请求:
- 我应该在 csp 下将我的应用程序的所有请求列入白名单吗?
- 我什至可以这样做吗,还是它只会将域列入白名单?
- Can/should node/express 对静态资产请求的所有响应都以某种方式编码?
- 报告指出"The name of an arbitrarily supplied URL parameter is copied into a JavaScript expression which is not encapsulated in any quotation marks"。这个表达式可以在处理返回静态资产的快速代码中的某个地方吗?
- 或者可以在我的应用程序代码中以某种方式评估 GET 请求参数?
更新
对此进行了一些调查后,似乎至少部分缓解措施是 escape data in url param values and sanitize the input in the url。
url 的转义已经到位,因此:
curl 'http://mydomain/images/?<script>alert('hello')</script>'
returns
Cannot GET /images/?<script>alert(hello)</script>
我还在上面放了 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 which depends on parseurl.
问题的原因是,对于无效的 GET
请求,表达将 return 类似于:
Cannot GET /pathname/?yourQueryString
这在很多情况下都是有效的响应,即使对于提供静态资产也是如此。然而,在我的情况下,我确信对于其他人来说,对静态资产的唯一有效请求将是这样的:
GET /pathname/your-file.jpg
我有一个自定义 404 处理程序,它 return 是一个数据对象:
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 returned:
之前删除请求查询参数var data = {
status: 404,
message: 'Not Found',
description: description,
url: url.parse(req.url).pathname // needs a var url = require('url')
};