转载

您是否受到了攻击?检测对 Node.js 应用程序的攻击

黑客尝试攻破一个 Web 应用程序时,他们通常首先跟随每个链接来找到所有有效的路径,以筹划攻击。然后,他们尝试在输入字段中输入各种无效的值,查看应用程序是否存在任何已知的代码注入漏洞。在本教程中,您将学习如何检测这些攻击。检测到它们后,您可关闭来自攻击 IP 地址的访问,将它重定向到一个缓慢的或执行其他操作来变成难以被攻击的目标。

构建您的应用程序所需的准备工作

全新的 developerWorks Premium 会员计划提供了强大的开发工具和资源,包括 500 篇通过 Safari Books Online 提供的顶级技术文章(50 多篇是专门针对安全性开发人员的),最重要开发人员活动的大幅折扣,最近的 O'Reilly 大会的视频回放,等等。立即注册。

  • 一个 Bluemix® 帐户。
  • 了解 HTML 和 JavaScript。
  • 了解 MEAN 应用程序堆栈(至少包括 Node.js 和 Express)。如果不熟悉 MEAN,您可查阅 “ 使用 Bluemix 和 MEAN 堆栈构建自助发表 Facebook 信息的应用程序 ” 来了解它,这是 developerWorks 上的一篇包含 3 部分的教程。
  • 一个可将 Node.js 应用程序上传到 Bluemix 的开发环境,比如 Eclipse。

运行应用程序

获取代码

在本教程中,学习在您的 IBM Bluemix Node.js web 应用程序被扫描和攻击时如何检测出来。

演示应用程序

这个应用程序包含一个主页,其中包含一个登录表单。在表单的顶部,有一些按钮用于方便发出各种攻击。这些按钮下面是向 cookie 中放入危险值的按钮。在页面的底部,显示了在前 1 个小时内检测到的所有攻击的列表。请注意,该应用程序报告的时间为 UTC ,不是您当地的时间。

您是否受到了攻击?检测对 Node.js 应用程序的攻击

点击查看大图

关闭 [x]

您是否受到了攻击?检测对 Node.js 应用程序的攻击

本文中演示的技术可检测 4 种类型的攻击:

  • 应用程序映射,这可能包括访问各种实际不存在的 “页面”。
  • 在查询字符串中编码的攻击(URL 中的问号后面的部分,这是 GET 表单的参数所在的地方)。
  • 在 POST 参数中编码的攻击(包含在 HTTP 头部中,这是 POST 表单的参数所在的地方)。
  • cookie 值中的攻击。

可按如下方式发出任何这些攻击:

  • 应用程序映射
    单击 Link to nowhere ,您将被重定向到一个无效的路径 (/badPath.html)。
  • 查询字符串攻击
    单击 Attack in a query parameter 。您将被重定向到 /login,此查询是有效的(可尝试直接访问它来验证),但有一个危险的查询参数。
  • Post 参数攻击
    自动提供两种 post 参数攻击:一种 SQL 注入 和一种 本地文件包含 。单击这些按钮不会导致浏览器端应用程序自行发出攻击。它会将攻击值放在用户名字段中。您然后键入一个密码(或不键入)并单击 Submit 提交包含攻击值的表单。我采用了这种分两步的方法,因为不同于路径和查询字符串参数,对于 post 参数,您不会看到提交的字符串。
  • Cookie 值攻击
    最后,单击 Put attack in cookie 将一个攻击字符串放在一个浏览器 cookie 中。这个 cookie 值然后会被发送回服务器。如果您改变了想法,可以使用 Clear cookie 清除该 cookie 值。危险之处在于,这个值在其他操作(例如单击 Submit 或尝试一条非法的路径)向服务器发送请求之后才会检测到。为了避免在每个请求上检测到危险的 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 文件来让合法的搜索引擎跳过您的网站。

攻击者不会尝试访问每个可能的路径,因为这种路径太多了。即使限制到仅包含字母和 8 个字符,也有 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 "(表示始终为 false 的条件,比如 <condition> and 1=0 )或一个分号(表示一个批处理命令,就像在这个 XKCD 动画 中一样)。

这是检测这些攻击的方式:

  1. 为各种形式的代码注入创建一个正则表达式数组。此列表仅是一个用于演示用途的子集:
    // 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: /^///} ];
  2. 放入一个中间件调用,用以在危险字符串可能位于的 3 个地方查找它们:查询参数、post 参数和 cookie。这些是包含从浏览器向服务器端应用程序传递的参数的 3 个地方。其他 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(); });
  3. 创建一个函数来在要从中间件调用的字符串中寻找所有攻击正则表达式。
    // 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);   } };
  4. 发现攻击时记录下它们。在这个示例应用程序中,日志是一个简单的数组。
    // 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 对象包含该路径。要从检查中排除一些字段,可创建豁免字段的列表(涵盖所有 3 种类型:get 参数、post 参数和 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 服务,该服务在您的应用程序上运行各种攻击来识别它的漏洞。要确认攻击已记录,可以对您的应用程序运行它(参阅 “ 将 Bluemix AppScan 结果放入 Bluemix Track & Plan 中 ” 中的第 3 步)。在下表中,可以看到一些结果。甚至这个微型 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 注入 2015-11-27T03:43:03.496Z 174.37.31.187 /login?uid=%27+or+true%3B+--&passwd=' or true; --
错误输入:查询参数 "uid" 中的 SQL Or 注入 2015-11-27T03:43:03.496Z 174.37.31.187 /login?uid=%27+or+true%3B+--&passwd=' or true; --
无效路径 2015-11-27T03:43:03.524Z 174.37.31.187 /NonExistentFile
错误输入:查询参数 "uid" 中的 SQL Batch 注入 2015-11-27T03:43:03.525Z 174.37.31.187 /login?uid=%27+or+

结束语

现在您已知道如何检测攻击。检测到攻击后,您可 将它报告给 Track & Plan ,拦截来自该 IP 地址的访问,或者执行其他步骤来让攻击更困难。

相关主题: MEAN Eclipse Bluemix

正文到此结束
Loading...