node.js自动化检测
当黑客试图闯入Web应用程序时,他们通常首先通过跟踪每个链接以查找所有有效路径来将其映射出来。 然后,他们尝试在输入字段中输入各种无效值,以查看该应用程序是否遭受任何众所周知的代码注入漏洞。 在本教程中,您将学习如何检测这些攻击。 一旦检测到它们,就可以关闭来自受攻击IP地址的访问,将其重定向到速度较慢的“ tar pit ”中,或执行其他操作以使其成为更难的目标。
构建应用程序所需的条件
- 一个Bluemix®帐户。
- 了解HTML和JavaScript。
- 了解MEAN应用程序堆栈(至少Node.js和Express)。 (如果您不熟悉MEAN,则可以从IBM developerWorks上的一个分为三部分的教程开始“ 使用Bluemix和MEAN stack构建自发布Facebook应用程序 ”。)
- 可以将Node.js应用程序上载到Bluemix的开发环境,例如Eclipse。
“在本教程中,您将学习如何检测何时扫描和攻击IBM Bluemix Node.js Web应用程序。 ”
示范应用
该应用程序包含一个主页,其中包含一个登录表单。 表单顶部有一些按钮,可以轻松发出各种攻击。 在这些按钮下面是将危险值放入Cookie的按钮。 在页面底部,列出了最近一个小时内检测到的所有攻击。 请注意,应用程序报告的时间是UTC而不是您的本地时间。

本文演示的技术可检测四种类型的攻击:
- 应用程序映射,可以包括访问实际上并不存在的各种“页面”。
- 查询字符串中编码的攻击(问号后面的URL部分,这是GET表单的参数所在的位置)。
- 以post参数(HTTP标头的一部分,这是POST形式的参数所在的位置)中编码的攻击。
- 攻击cookie值。
您可以按以下方式发出任何攻击:
- 应用程序映射
单击“ 无处链接” ,您将被重定向到无效路径(/badPath.html)。 - 查询字符串攻击
在查询参数中单击“ 攻击” 。 您将被重定向到有效的/ login(尝试直接访问以进行验证),但带有危险的查询参数。 - 后参数攻击
自动提供两种后参数攻击: SQL注入和本地文件包含 。 单击这些按钮不会导致浏览器端应用程序自行发出攻击。 而是将攻击值放在用户名字段中。 然后,您输入密码(或不输入密码),然后单击Submit提交包含攻击的表单。 我采用了两步方法,因为与路径和查询字符串参数相比,使用post参数时,您看不到发布的字符串。 - Cookie价值攻击
最后,单击“ 将攻击放入cookie”以将攻击字符串放入浏览器cookie。 然后,此cookie值将发送回服务器。 如果您改变主意,请使用清除cookie清除cookie值。 危险是直到其他操作(例如,单击“ 提交”或尝试使用非法路径)将请求发送到服务器后,才能检测到该值。 为了避免在每个请求中都检测到危险的cookie值,告诉用户检测到攻击的页面还将清除cookie值。
现在您已经看到了检测到的攻击,让我们看一下代码,看看它是如何完成的。
检测访问无效页面的尝试
第一步是检测尝试访问各种无效页面的尝试。 这将检测映射尝试,这是攻击的正常前奏。
Express应用程序包使此步骤变得很简单。 在Express中,您将处理程序注册到路径,这些处理程序可以完全处理请求,也可以进行部分处理(例如,解析请求中的cookie),然后继续进行处理。 处理程序按照声明的顺序进行处理。
要获取所有没有附加页面的请求,只需在末尾注册一个处理程序即可。 如果已经有一个默认处理程序返回404 page unavailable
错误,请向该处理程序添加攻击检测代码。
app.use("/", function(req, res) {
res.send("Attempt to access " + req.path + " duly noted." + goBack);
logBadPathAttack(req);
});
注意:并非所有映射尝试都是恶意的。 搜索引擎通常会将网站映射到能够链接到其各个页面的位置。 您可以使用robots.txt文件使合法的搜索引擎将您的网站保留下来。
攻击者不会尝试访问所有可能的路径,因为路径太多了。 即使只限于字母和八个字符,也有26 ^8≈2·10 ^ 11种可能性。 如果攻击者可以在一秒钟内发送10,000个请求,则检查所有请求仍将花费230天以上。
取而代之的是,黑客扫描他们从应用程序合法获得的网页,并寻找URL来向他们显示可以扫描的内容。 要使他们扫描无效的页面,请在HTML代码链接中放入合法用户永远不会看到的链接。
例如,您可以使用使链接不可见的代码:
<a href="should_be_invisible.html" style="color: white; background-color: white">Invisible</a>
如果您使用Angular框架进行客户端编程,则可以使用ng-if
来指定无效链接永远不会发生的条件。 这些条件的优点是扫描器可能难以评估它们。 例如,在不跟踪所有范围变量的情况下,扫描程序将不知道没有名为no-such-var
变量,因此该变量的值永远不会是'hello'
。
<div ng-if="false">
<a href="index_false.html">Don't go here</a>.
</div>
<a href="index_1_is_2.html" ng-if="1==2"">Link to nowhere.</a>
<a href="index_complex_false.html" ng-if="no-such-var == 'hello'">Another useless link.</a>
检测使用无效值进行代码注入的尝试
许多攻击都依赖于提供无效数据。 例如, SQL注入依赖于使用SQL字符串终止符'
,后跟“ or
”(对于始终为true的条件,例如, correctPassword='<input value>' or 1=1
),“ and
”(对于始终为假的条件,例如<condition> and 1=0
)或分号(对于分批命令,例如此XKCD卡通 )。
以下是检测此类攻击的方法:
- 为各种形式的代码注入创建一个正则表达式数组。 此列表是用于演示目的的子集:
// Regular expressions that indicate attacks var inputAttacks = [ { title: "SQL Batch Injection", regex: /'.*;/}, { title: "SQL Or Injection", regex: /'.*or/i}, { title: "SQL And Injection", regex: /'.*and/i}, { title: "File Inclusion", regex: /\.\.\//}, { title: "File Inclusion", regex: /^\//} ];
- 放入一个中间件调用,该调用在危险字符串可能位于的三个位置查找:查询参数,发布参数和cookie。 这三个地方包括从浏览器传递到服务器端应用程序的参数。 其他HTTP标头字段(例如Content-Type和Encoding)由系统软件处理,因此不太可能包含我们试图检测其利用的漏洞类型。
// Check all the body parameters for validity app.use("/", function(req, res, next) { var key; // Check all GET queries for (key in req.query) checkInputAttacks("query parameter " + key, req.query[key], req, res); // Check all POST data for (key in req.body) checkInputAttacks("post parameter " + key, req.body[key], req, res); // Check all cookies for (key in req.cookies) checkInputAttacks("cookie " + key, req.cookies[key], req, res); // If we ran res.send (which checkInputAttacks does when it detects an attack), // next() won't continue the processing anyway. next(); });
- 创建一个函数,该函数查找要从中间件调用的字符串中的所有攻击正则表达式。
// Check for attacks in a string we got from the user. var checkInputAttacks = function(location, str, req, res) { for(var i=0; i<inputAttacks.length; i++) if (str.match(inputAttacks[i].regex)) { logBadInputAttack(req, str, inputAttacks[i].title + " in the " + location); res.send("Your " + inputAttacks[i].title + " attack in the " + location + " has been noted." + goBack); } };
- 发现攻击时记录日志。 在此示例应用程序中,日志只是一个数组。
// Log a bad input attack var logBadInputAttack = function(req, str, title) { var entry = {}; entry.timeStamp = new Date(); entry.title = "Bad input: " + title; entry.target = req.originalUrl; entry.value = str; entry.attacker = req.ip; loggedAttacks.push(entry); };
请注意,此方法可能会遭受误报。 例如,假设用户在描述字段中键入以下内容:“ This is the user's choice; the user can either apply this feature or ignore it
”
文本与SQL批处理攻击的正则表达式匹配:撇号('),后跟多个字符,后跟分号(;)。 如有必要,可以指定对于某些路径,不检查某些字段。 req对象包含路径。 要使某些字段免于检查,请创建免除字段的列表(所有三种类型:获取参数,发布参数和cookie):
// Fields that are not checked for the three field types
var exemptGet = [];
var exemptPost = ["/login:exempt"];
var exemptCookie = [];
修改检查这些字段的调用,以首先检查它们是否在适用的免税列表中,如果是,则不检查它们:
// Check all the body parameters for validity
app.use("/", function(req, res, next) {
var key;
// Check all GET queries
for (key in req.query)
if (exemptGet.indexOf(req.path + ":" + key) === -1) // Don't check exempt fields
checkInputAttacks('query parameter "' + key + '"', req.query[key], req, res);
// Check all POST data
for (key in req.body)
if (exemptPost.indexOf(req.path + ":" + key) === -1) // Don't check exempt fields
checkInputAttacks('post parameter "' + key + '"', req.body[key], req, res);
// Check all cookies
for (key in req.cookies)
if (exemptCookie.indexOf(req.path + ":" + key) === -1) // Don't check exempt fields
checkInputAttacks('cookie "' + key + '"', req.cookies[key], req, res);
// If we ran res.send (which checkInputAttacks does when it detects an attack),
// next() won't continue the processing anyway.
next();
});
测试攻击日志
IBM Bluemix包含一个AppScan服务,该服务会在您的应用程序上运行各种攻击以识别其漏洞。 要验证是否记录了攻击,可以对您的应用程序运行攻击。 在下表中,您可以看到一些结果。 即使是这个很小的Web应用程序,也检测到AppScan进行了364次不同的攻击尝试。
类型 | 时间 | 攻击IP | 路径 |
---|---|---|---|
无效的路径 | 2015-11-27T03:43:03.481Z | 174.37.31.187 | /badPath.html |
无效的路径 | 2015-11-27T03:43:03.493Z | 174.37.31.187 | /index_1_is_2.html |
输入错误:查询参数“ uid”中SQL Batch Injection | 2015-11-27T03:43:03.496Z | 174.37.31.187 | / login?uid =%27 + or + true%3B +-&passwd = '或真实; - |
输入错误:查询参数“ uid”中为SQL或注入 | 2015-11-27T03:43:03.496Z | 174.37.31.187 | / login?uid =%27 + or + true%3B +-&passwd = '或真实; - |
无效的路径 | 2015-11-27T03:43:03.524Z | 174.37.31.187 | / NonExistentFile |
输入错误:查询参数“ uid”中SQL Batch Injection | 2015-11-27T03:43:03.525Z | 174.37.31.187 | / login?uid =%27 + or + |
结论
现在您知道了如何检测攻击。 一旦检测到攻击,您可以将其报告给“跟踪与计划” ,阻止对该IP地址的访问,或采取其他措施使攻击更加困难。
node.js自动化检测