Kali-Linux-Web-渗透测试秘籍第二版-三-

110 阅读15分钟

Kali Linux Web 渗透测试秘籍第二版(三)

原文:annas-archive.org/md5/d5e1118fa7651dd5af5fc7f2255a2210

译者:飞龙

协议:CC BY-NC-SA 4.0

第十章:OWASP Top 10 漏洞缓解

本章将介绍以下配方:

  • A1 – 防止注入攻击

  • A2 – 构建适当的认证和会话管理

  • A3 – 保护敏感数据

  • A4 – 安全使用 XML 外部实体

  • A5 – 确保访问控制安全

  • A6 – 基本安全配置指南

  • A7 – 防止跨站脚本攻击(XSS)

  • A8 – 实现对象序列化与反序列化

  • A9 – 在第三方组件中查找已知的漏洞

  • A10 – Web 应用安全的日志记录与监控

介绍

每次渗透测试的目标都是识别应用程序、服务器或网络中的潜在薄弱点;这些薄弱点可能是攻击者获取敏感信息或特权访问的机会。检测这些漏洞的原因不仅是为了知道它们的存在并计算与之相关的风险,还要努力减轻这些风险或将其降低到最低风险水平。

本章我们将查看一些示例和建议,了解如何缓解 OWASP 列出的最关键 Web 应用程序漏洞,具体内容可以参考 www.owasp.org/index.php/Category:OWASP_Top_Ten_Project

A1 – 防止注入攻击

根据 OWASP,Web 应用程序中最严重的漏洞类型是某种类型的代码注入,如 SQL 注入、操作系统命令注入和 HTML 注入。

这些漏洞通常是由于应用程序未进行良好的输入验证引起的。在本配方中,我们将介绍一些在处理用户输入和构建使用这些输入的查询时的最佳实践。

如何做...

  1. 防止注入攻击的第一步是正确验证输入。在服务器端,可以通过编写自定义验证程序来实现,尽管最好的选择是使用语言自带的验证程序,因为它们被广泛使用和测试。一个好的例子是 PHP 中的 filter_var 或 ASP.NET 中的验证助手。例如,PHP 中的邮箱验证类似如下:
function isValidEmail($email){  
    return filter_var($email, FILTER_VALIDATE_EMAIL); 
} 
  1. 在客户端,通过创建 JavaScript 验证函数并使用正则表达式来实现验证。例如,邮箱验证程序如下:
function isValidEmail (input) 
{ 
  var result=false; 
  var email_regex = /^[a-zA-Z0-9._-]+@([a-zA-Z0-9.-]+.)+[a-zA-Z0-9.-]{2,4}$/; 
  if ( email_regex.test(input) ) { 
    result = true; 
  } 
  return result; 
} 
  1. 对于 SQL 注入,避免将输入值与查询拼接也是非常有用的。相反,应该使用参数化查询,也叫准备语句。每种编程语言都有其自己的版本:

    • PHP 与 MySQLi:
$query = $dbConnection->prepare('SELECT * FROM table WHERE name = ?'); $query->bind_param('s', $name); $query->execute(); 
    • C#:
string sql = "SELECT * FROM Customers WHERE CustomerId = @CustomerId"; 
SqlCommand command = new SqlCommand(sql); 
command.Parameters.Add(new SqlParameter("@CustomerId", System.Data.SqlDbType.Int)); 

command.Parameters["@CustomerId"].Value = 1; 
    • Java:
String custname = request.getParameter("customerName");  

String query = "SELECT account_balance FROM user_data WHERE user_name =? ";   

PreparedStatement pstmt = connection.prepareStatement( query ); 
pstmt.setString( 1, custname);  
ResultSet results = pstmt.executeQuery( ); 
  1. 遵循深度防御方法,在注入成功的情况下,限制可能造成的损害也是非常有用的。为此,使用低权限的系统用户来运行数据库和 Web 服务器。确保允许应用程序连接到数据库服务器的用户不是数据库管理员。

  2. 禁用或删除允许攻击者执行系统命令或提升权限的存储过程和命令,例如 MS SQL Server 中的xp_cmdshell

它是如何工作的...

防止任何类型代码注入攻击的关键部分始终是正确的输入验证,包括客户端和服务器端的验证。

对于 SQL 注入,始终使用参数化查询或预处理查询,而不是将 SQL 语句与输入拼接在一起。参数化查询将函数参数插入 SQL 语句的指定位置,消除了程序员通过拼接构建查询的需要。

在本教程中,我们使用并推荐了语言内置的验证函数,但如果需要使用正则表达式验证特殊类型的输入,您也可以创建自己的验证函数。

除了执行正确的验证外,我们还需要在有人成功注入代码的情况下减少影响。这可以通过在操作系统中为 web 服务器、以及在数据库服务器的数据库和操作系统中,正确配置用户权限来实现。

另见

在数据验证方面,最有用的工具是正则表达式。它们还使渗透测试人员在处理和过滤大量信息时的工作变得更加轻松,因此掌握它们非常方便。我建议您查看以下网站:

  • www.regexr.com/: 这是一个非常好的网站,我们可以在这里获取示例和参考资料,测试自己的表达式,以检查字符串是否匹配。

  • www.regular-expressions.info:该网站包含教程和示例,教您如何使用正则表达式。它还提供了有关最流行编程语言和工具的具体实现的有用参考。

  • www.princeton.edu/~mlovett/reference/Regular-Expressions.pdf(正则表达式 完整教程)由 Jan Goyvaerts 编写:正如标题所示,这是一本非常完整的正则表达式教程,包括多种编程语言的示例。

A2 – 构建正确的认证和会话管理

错误的认证和会话管理是如今 web 应用程序中第二大关键漏洞。

认证是用户证明其身份的过程;通常通过用户名和密码完成。该领域中的一些常见缺陷包括宽松的密码策略和通过模糊化手段的安全性(在所谓隐藏的资源中缺乏认证)。

会话管理是处理已登录用户会话标识符的过程;在 Web 服务器中,通常通过实现会话 cookie 和令牌来完成。攻击者可以使用社交工程、跨站脚本、CSRF 等手段植入、窃取或劫持这些标识符。因此,开发者必须特别注意这些信息的管理方式。

在本教程中,我们将介绍在实施用户名/密码认证和管理已登录用户的会话标识符时的一些最佳实践。

如何做到……

  1. 如果应用程序中有一个页面、表单或任何仅应由授权用户查看的信息,确保在显示之前进行适当的身份验证。

  2. 确保用户名、ID、密码和所有其他认证数据是

    区分大小写且对每个用户唯一。

  3. 建立强密码策略,强制用户创建符合以下最基本要求的密码:

    • 访问被拒绝

    • 超过 8 个字符,最好为 10 个字符

    • 使用大小写字母

    • 使用至少一个数字字符(0-9)

    • 使用至少一个特殊字符(空格、!、&、#、%、等等)

    • 优选长且易记的短语,而不是短小、复杂和不相关的字符组合。例如,This Is an Acceptable Password!aJk5&$12! 要强得多。

  4. 禁止将用户名、站点名称、公司名称或它们的变体(大小写变化、l33t、它们的片段)用作密码。

  5. 禁止使用www.teamsid.com/worst-passwords-2017/中的最常见密码列表中的密码。

  6. 永远不要在错误信息中指出用户是否存在,或者信息是否符合正确的格式。对于错误的登录尝试、不存在的用户、用户名或密码不符合模式,以及所有其他可能的登录错误,使用相同的通用消息。这样的消息可以是:

    • 登录信息不正确

    • 无效的用户名或密码

    • 访问被拒绝

  7. 密码不能以明文格式存储在数据库中;应使用强哈希算法,如 SHA-2、scrypt 或 bcrypt,这些算法特别设计用于抵御 GPU 破解。

  8. 在将用户输入与密码进行比较时,应先对用户输入进行哈希处理,然后比较两个哈希值。绝不应解密密码与明文用户输入进行比较。

  9. 避免使用基本的 HTML 身份验证。

  10. 如果可能,使用多因素认证(MFA),即使用多个认证因素进行登录:

    • 你知道的东西(账户详情或密码)

    • 你拥有的东西(令牌或手机)

    • 你是的东西(生物识别)

  11. 在可能的情况下,实施证书、预共享密钥或其他无密码认证协议(如 OAuth2、OpenID、SAML 或 FIDO)。

  12. 在会话管理方面,建议使用语言内建的会话管理系统,如 Java、ASP.NET 和 PHP。它们并不完美,但肯定提供了设计良好且经过广泛测试的机制,并且比任何由开发团队为满足发布日期要求而自制的版本更容易实现。

  13. 登录和登录后的页面必须始终使用 HTTPS——显然,应该避免使用 SSL,只接受 TLS v1.1 或更高版本的连接。

  14. 为确保使用 HTTPS,可以使用 HTTP 严格传输安全(HSTS)。它是一种由 Web 应用程序通过使用 Strict-Transport-Security 头部指定的自愿启用的安全功能;当 URL 使用 http:// 时,它会将你重定向到安全选项,并防止覆盖 无效证书 消息(例如在使用 Burp Suite 时显示的那种),www.owasp.org/index.php/HTTP_Strict_Transport_Security

  15. 始终设置 HTTPOnly 和 Secure cookies 属性。

  16. 设置合理但较短的会话过期时间——既不能过长,以至于攻击者能够在合法用户离开后重新使用会话,也不能过短,以至于用户没有机会执行应用程序预期的任务。15 到 30 分钟之间是一个合理的过期时间。

它是如何工作的…

Web 应用程序中的身份验证机制通常简化为用户名/密码登录页面。虽然这不是最安全的选择,但对于用户和开发人员来说是最简单的;在处理密码时,其最重要的方面是密码的强度。

正如我们在本书中看到的,密码的强度取决于其破解的难度,无论是通过暴力破解、字典攻击还是猜测。这个小技巧的第一步是通过设定最小长度来增加密码的暴力破解难度,通过使用混合字符集来增加猜测难度,避免使用更直观的选择(如用户名、常见密码和公司名称),以及通过在存储密码时使用强加密或哈希算法来增强密码被泄露后的破解难度。

关于会话管理,过期时间、会话 ID 的唯一性、强度(已在语言内建机制中实现)以及 cookie 设置中的安全性是关键考虑因素。

在讨论身份验证安全时,可能最重要的一点是,如果安全配置、控制或强密码可以通过中间人攻击被拦截和读取,那么它们都不够安全。因此,使用正确配置的加密通信通道(如 TLS)对于保持用户的身份验证数据安全至关重要。

另见

OWASP 在身份验证和会话管理方面有几个非常好的页面,以下是相关列表。我强烈推荐在构建和配置 Web 应用程序时阅读并考虑这些页面:

A3 – 保护敏感数据

当应用程序存储或使用某种敏感信息(如信用卡号码、社会保障号码、健康记录、密码等)时,应该采取特别措施来保护它,因为如果这些信息被泄露,可能会给负责保护这些信息的组织带来严重的声誉、经济甚至法律损害。

OWASP 十大漏洞中的第六位是敏感数据泄露,它发生在应特别保护的数据以明文形式暴露或使用弱安全措施保护时。

在本教程中,我们将涵盖处理、传输和存储此类数据时的一些最佳实践。

如何做到……

  1. 如果您使用的敏感数据在使用后可以删除,请务必删除。每次向用户请求信用卡信息总比在数据泄露时被盗要好得多。

  2. 处理支付时,始终优先使用支付网关,而不是将此类数据存储在您的服务器中。请查看ecommerce-platforms.com/ecommerce-selling-advice/choose-payment-gateway-ecommerce-store以获取顶级服务提供商的评测。

  3. 如果我们需要存储敏感信息,必须首先采取保护措施。

    给它的最佳方法是使用强加密算法进行加密,并妥善存储相应的强密钥。一些推荐的算法包括 Twofish、AES 和 RSA。

  4. 密码应以数据库哈希的形式存储,使用单向哈希函数,如 bcrypt、scrypt 或 SHA-2。

  5. 确保所有敏感文档仅供授权用户访问;不要将它们存储在 Web 服务器的文档根目录中,而是存储在外部目录,并通过编程访问它们。如果由于某些原因必须将敏感文档存储在服务器的文档根目录中,请使用.htaccess文件防止直接访问:

Order deny,allow 
Deny from all 
  1. 禁用缓存包含敏感数据的页面。例如,在 Apache 中,我们可以通过在httpd.conf中使用以下设置来禁用 PDF 和 PNG 文件的缓存:
<FilesMatch ".(pdf|png)> 
FileETag None 
Header unset ETag 
Header set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" 
Header set Pragma "no-cache" 
Header set Expires "Wed, 11 Jan 1984 05:00:00 GMT" 
</FilesMatch> 
  1. 始终使用安全的通信渠道传输敏感信息,具体来说,如果允许上传文件,应使用 HTTPS 与 TLS 或 FTPS(FTP over SSH)。

它是如何工作的……

在保护敏感数据时,我们需要最大限度地减少数据泄露或交易的风险;因此,正确地加密存储的信息并保护加密密钥是首要任务。如果没有不存储此类数据的可能性,这是理想选择。

密码在存储到数据库之前应使用单向哈希算法进行哈希处理。这样,如果密码被盗,攻击者将无法立即使用它们;如果密码足够强大,并且使用强哈希算法进行加密,它们也无法在现实时间内被破解。

如果我们将敏感文档或敏感数据存储在服务器的文档根目录中(例如在 Apache 中是/var/www/html/),我们就暴露了这些信息,可以通过其 URL 下载。因此,最好将它们存储在其他位置,并在需要时通过特别的服务器端代码检索,并进行预先授权检查。

此外,像archive.org/、WayBackMachine 或 Google 缓存这样的页面,可能会在缓存文件包含敏感信息且在应用程序的早期版本中未得到适当保护时,造成安全问题。因此,重要的是不要允许缓存这些类型的文档。

A4 – 安全使用 XML 外部实体

XML 外部实体XXE)攻击在过去几年里逐渐流行,现已在 OWASP 2017 年十大漏洞榜单中位列第四。与 XML 实体相关的漏洞主要被攻击者用来从目标系统中获取信息并远程执行代码或系统命令(XXE 注入),或导致服务中断(XXE 扩展)。

在本方案中,我们将提供一些建议,指导在构建 Web 应用程序时,如何避免在处理 XML 外部实体时包含漏洞。

如何操作...

  1. 如果可能,避免使用 XML,优先考虑使用更简单的格式,例如 JSON。

  2. 如果 XML 的使用是强制性的,请在应用程序使用的所有解析器中禁用外部实体的使用。

  3. 如果某个功能需要使用外部实体加载文件或访问远程资源,考虑使用其他技术重新实现该功能。

  4. 始终在客户端和服务器端验证用户和第三方提供的数据。对于 XML 格式的数据,使用允许的单词/元素和字符的白名单是一个不错的选择。

  5. 保持 XML 解释器(通常集成在开发工具中)得到适当的修补和更新,以防止和修复常见的漏洞。

工作原理...

尽管 XML 在开发者执行某些任务时可能是一个非常有用的工具,但如今它不是 Web 应用程序中信息交换的最佳格式。这是因为 XML 有许多特性,其中包括外部实体以及其可扩展的特性,这些特性使得它容易包含可能包括系统文件和命令的对象或元素。

XML 解析器允许禁用外部实体以及其他可能导致安全问题的特性,如文档类型定义(DTD)。请查阅所选解析引擎的文档,了解如何执行此操作。

作为注入攻击的一种,XML 相关的攻击可以通过适当的输入验证在很大程度上得到预防,并且由于开发人员已知预期的结构,可以实施一种白名单验证方案,只允许预期的元素并拒绝所有其他内容。

在本食谱的最后,XML 解析器通常会集成到编程框架和语言中。确保所使用的解析器没有任何已公布的漏洞,否则可能会危及应用程序的安全性。

A5 – 保护访问控制

在 OWASP Top 10 2013 中,A7 漏洞是 缺失的功能级别访问控制。在 2017 年的新版本中,该漏洞被整合到更广泛的 访问控制失效 类别中,并排在第五位。这个新类别涵盖了未经认证或未授权的用户可以通过直接浏览访问受限信息,或低权限用户能够提升权限,甚至是 CORS 策略的配置不当等漏洞。

在本食谱中,我们将了解一些改进应用程序访问控制的建议。

如何做到这一点...

  1. 仅将用户/客户端执行其职责所必需的权限分配给他们,并阻止访问其他一切(最小权限原则)。

  2. 确保在每一步中都正确检查并强制执行工作流的权限。

  3. 默认拒绝所有访问,然后在明确验证授权后允许用户执行任务/访问信息。

  4. 用户、角色和授权应该存储在灵活的介质中,例如数据库或配置文件,以便它们可以被添加、删除或更新。不要将它们硬编码。

  5. 再次提醒,安全通过模糊化不是一种好的安全策略。

它是如何工作的...

开发人员常常只在工作流的开始时检查授权,并假设后续任务会自动获得用户的授权。攻击者可能会尝试调用工作流中的一个中间步骤的函数、URL 或资源,并且由于缺乏控制,成功地绕过了授权检查。

关于权限,默认拒绝所有访问是最佳实践。如果我们不确定某些用户是否被允许执行某个功能,那么他们就不应该被允许。将权限表转换为授权表。如果某个用户在某个功能上没有明确的授权,那么就拒绝任何访问。

在为用户分配权限和/或设计用户角色时,始终遵循最小权限原则(en.wikipedia.org/wiki/Principle_of_least_privilege)。

在为应用程序的功能构建或实现访问控制机制时,将所有授权存储在数据库或配置文件中(数据库是更好的选择)。

如果用户角色和权限是硬编码的,它们会变得更加难以维护和修改。

或更新。

A6 – 基本安全配置指南

系统的默认配置,包括操作系统和 Web 服务器,通常是为了展示和突出其基本或最相关的功能,而非为了保证安全性。

或者保护它们免受攻击。

一些可能会危及安全的常见默认配置包括数据库、Web 服务器或 CMS 安装时创建的默认管理员账户,以及默认的管理页面和包含堆栈跟踪的错误信息,等等。

在本篇中,我们将讨论 OWASP 前十大最严重漏洞中的第五大漏洞:

安全配置错误。

如何操作...

  1. 如果可能,删除所有管理应用程序,例如 Joomla 的管理员、WordPress 的管理员、phpMyAdmin 或 Tomcat Manager。如果不可能,限制它们仅能从本地网络访问;例如,要拒绝外部网络访问 Apache 服务器中的 phpMyAdmin,可以修改httpd.conf

    文件(或相应的站点配置文件):

<Directory /var/www/phpmyadmin> 

  Order Deny,Allow 
  Deny from all 
  Allow from 127.0.0.1 ::1 
  Allow from localhost 
  Allow from 192.168 
  Satisfy Any 

</Directory> 

这将首先拒绝来自所有地址访问phpmyadmin目录,其次,它将允许来自本地主机和以192.168开头的地址的请求,这些是本地网络地址。

  1. 更改所有管理员账户的密码,包括所有 CMS、应用程序、数据库、服务器和框架,使用其他足够强大的密码。举例如下:

    此类应用程序如下:

    • Cpanel

    • Joomla

    • WordPress

    • PhpMyAdmin

    • Tomcat 管理器

  2. 禁用所有不必要或未使用的服务器和应用功能。每天或每周,CMS 的可选模块和插件都会出现新的漏洞。如果应用程序不需要它们,就没有必要将其保持启用状态。

  3. 始终保持最新的安全补丁和更新。在生产环境中,可能需要设置测试环境,以防止由于更新不兼容的版本而导致网站无法正常工作。

  4. 设置自定义错误页面,不暴露跟踪信息、软件版本、编程组件名称或任何其他调试信息。如果开发人员需要记录错误,或者需要一个标识符来获取技术支持,可以创建一个带有简单 ID 和错误描述的索引,只向用户显示 ID。当错误被报告给支持人员时,他们可以查阅索引,了解错误类型。

  5. 采用最小特权原则。每个级别的每个用户(操作系统、数据库或应用程序)应该只能访问正常操作所严格要求的信息,绝不能更多。

  6. 考虑到以上几点,建立一个安全配置基线,并将其应用于每一个新的实现、更新或发布,以及当前系统。

  7. 强制进行定期的安全测试或审计,以帮助检测配置错误或缺失的补丁。

它是如何工作的...

谈到安全性和配置问题时,我们可以说细节决定成败。Web 服务器、数据库服务器、CMS 或应用程序的配置应在完全可用、有效且对用户和所有者都安全之间找到平衡点。

网络应用程序中最常见的配置错误之一是,它包含某种类型的 web 管理站点,并且该站点可以被全网访问;这看起来似乎不是一个大问题,但如果我们考虑到管理员登录页面对黑客的吸引力远大于任何“联系我们”表单,因为前者提供了更高的权限级别,并且几乎每种 CMS、数据库或站点管理工具都有已知的、常见的、默认的密码列表。那么,我们的首要建议是不要将这些管理站点暴露给外界,并尽可能将其移除。

此外,在发布应用程序到公司内部网络时,强密码的使用以及更改默认安装的密码(即使它们很强)应当是强制性的,而在发布到互联网上时,应当更加严格地执行此项措施。如今,当我们将服务器暴露给外界时,它接收到的第一波流量通常是端口扫描、登录页面请求和登录尝试,甚至在第一个用户意识到应用程序已经激活之前。

使用自定义错误页面有助于增强安全性,因为 web 服务器和 web 应用程序的默认错误信息暴露了过多的信息(从攻击者的角度来看),例如错误内容、使用的编程语言、堆栈跟踪、使用的数据库、操作系统等。这些信息不应被暴露,因为它有助于攻击者理解应用程序的构建方式,并提供所用软件的名称和版本。凭借这些信息,攻击者可以搜索已知的漏洞,制定更高效的攻击策略。

一旦我们有了配置正确的服务器及其常驻应用程序和所有服务,我们可以制定安全基线,并将其应用到所有需要配置或更新的新服务器以及目前在生产环境中的服务器,前提是有适当的规划和变更管理流程。

该配置基线需要持续测试,以便不断改进并保护其免受新发现的漏洞威胁。

A7 – 防止跨站脚本攻击

跨站脚本攻击(Cross-Site Scripting,简称 XSS)如前所述,发生在显示给用户的数据没有正确编码,浏览器将其解释为脚本代码并执行时。这也涉及输入验证因素,因为恶意代码通常是通过输入变量插入的。

在本篇教程中,我们将讨论开发者如何进行输入验证和输出编码,以防止应用程序中的 XSS 漏洞。

如何实现……

  1. 应用程序容易受到 XSS 攻击的第一个迹象是,页面会直接反映用户输入的内容。所以尽量避免使用用户提供的信息来构建输出文本。

  2. 当需要将用户提供的数据放入输出页面时,务必验证这些数据。

    防止任何类型代码插入。我们已经在 A1 - 防止注入攻击 部分看到了如何操作。

    A1 - 防止注入攻击 部分。

  3. 如果出于某种原因,允许用户输入特殊字符或代码片段,在插入输出之前,需要进行净化或正确编码。

  4. 对于数据净化,PHP 中可以使用filter_var;例如,如果你想确保以下字符串只包含有效的电子邮件字符:

<?php 
$email = "john(.doe)@exa//mple.com"; 
$email = filter_var($email, FILTER_SANITIZE_EMAIL); 
echo $email; 
?> 

对于编码,可以在 PHP 中使用 htmlspecialchars

<?php 
$str = "The JavaScript HTML tags are <script> for opening, and </script>  for closing."; 
echo htmlspecialchars($str); 
?> 
  1. 在 .NET 中,对于 4.5 及更高版本的实现,System.Web.Security.AntiXss 命名空间提供了必要的工具。对于 .NET Framework 4 及以前的版本,

    我们可以使用 Web Protection 库,地址是 archive.codeplex.com/?p=wpl

  2. 此外,为了防止存储型 XSS,在存储和从数据库检索数据之前,必须对每一条信息进行编码或净化。

  3. 不要忽视页面的头部、标题、CSS 和脚本部分,因为它们也容易被利用。

它是如何工作的...

除了适当的输入验证和不使用用户输入作为输出信息外,数据净化和编码是防止 XSS 攻击的关键方面。

数据净化意味着从字符串中移除不允许的字符;当输入字符串中不应出现特殊字符时,这非常有用。

编码将特殊字符转换为其 HTML 代码表示,例如,将 "&" 转换为 "&" 或将 "<" 转换为 "<"。某些应用允许在输入字符串中使用特殊字符;对于这些应用,净化并不是一个选择,因此在将其插入页面或存储到数据库之前,应对输入进行编码。

另见

OWASP 提供了一个 XSS 防护备忘单,值得阅读,网址是 www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

A8 – 实现对象序列化和反序列化

序列化是将数据结构或对象转化为可以传输的格式的过程,在我们的例子中,是通过 HTTP 请求或响应传输。反序列化是相反的过程。

当一个对象被序列化,例如,转换为 JSON 字符串,并从服务器传送到客户端或反向传输时,攻击者可以查看并理解对象的内容,并进行修改,以便当另一端接收到序列化对象并反序列化时,将其还原为对象格式时,它会将更改后的内容解释为可执行代码并执行。这是反序列化攻击中最常见的场景。

在本配方中,我们将看到开发人员在实现序列化/反序列化机制时应采取的措施,以提高其应用程序的安全性。

如何做...

  1. 如果可能,应该尽量避免使用序列化/反序列化。

  2. 实施完整性检查,如数字签名(MD5,SHA-2),对客户端和服务器端接收的所有序列化对象进行检查,以便在任何对象被篡改时,应用程序在处理或反序列化之前拒绝该对象。

  3. 以低权限用户运行反序列化代码。

  4. 记录并监控序列化和反序列化过程及其所有错误和警告。将监控系统作为安全监控过程的输入,以便生成适当的警报。

它是如何工作的...

与许多使用复杂技术的情况一样,如果没有正确配置和实施,它可能会导致应用程序安全态势的削弱。评估这种技术是否严格必要或是最佳选择,如果不是,请不要使用它。

通过对传出的对象进行哈希或生成校验和,并在接收对象时检查该值,应用程序将能够识别出用户或中间某个实体是否修改了对象,从而丢弃该对象以防止安全风险。

遵循深度安全的哲学,如果序列化攻击成功,并且攻击者在我们的服务器上获得了命令执行权限,则执行恶意命令的用户应具有最低权限级别,以避免造成额外的损害。

在发生安全事件时,应用程序必须保存序列化和反序列化过程的日志,以便调查该事件的专业人员可以利用这些日志找出使用的攻击路径,并进一步提出防止类似事件再次发生的措施。

A9 – 在第三方组件中寻找已知漏洞的位置

当今的 Web 应用程序不再是单个开发者或单个开发团队的工作;如今,开发一个功能完善、用户友好、外观吸引人的 Web 应用程序意味着使用第三方组件,如编程库、外部服务的 API(如 Facebook、Google 和 Twitter)、开发框架以及许多其他在编程、测试和修复方面相关性较小或没有相关性的组件。

有时,这些第三方组件容易受到攻击,并将这些漏洞传递给我们的应用程序。许多实现了易受攻击组件的应用程序需要较长时间才能进行修复,成为整个组织安全的薄弱环节。这就是为什么 OWASP 将使用已知漏洞的第三方组件列为 Web 应用程序安全的第九大关键威胁。

在本节中,我们将探讨在哪里搜索,以确定我们使用的某个组件是否存在已知漏洞,并查看一些此类漏洞组件的例子。

如何做到...

  1. 第一个建议是,总是优先选择已知的软件,这些软件得到支持并且被广泛使用。

  2. 保持更新,了解第三方组件发布的安全更新和补丁。

  3. 寻找某个特定组件漏洞的一个好地方是厂商的网站;它们通常有一个发行说明部分,在这里发布每个版本修复了哪些漏洞或缺陷。在这里,我们可以查找我们正在使用的版本(或更新版本),并检查是否有已知问题被修复或仍未修复。

  4. 此外,厂商通常会有安全咨询网站,例如微软(technet.microsoft.com/library/security/),Joomla (developer.joomla.org/security-centre.html),以及 Oracle (www.oracle.com/technetwork/topics/security/alerts-086861.html)。我们可以利用这些网站,随时更新我们在应用程序中使用的软件的安全信息。

  5. 还有一些不依赖于厂商的站点,专门用于告知我们有关漏洞和安全问题的信息。一个非常好的站点是 CVE Details (www.cvedetails.com/),它汇集了来自不同来源的信息。在这里,我们可以搜索几乎任何厂商或产品,列出其所有已知的漏洞。

    (或者至少是那些有 CV 号的)并按年份、版本进行结果排序,

    和 CVSS 分数。

  6. 此外,黑客发布其利用代码和发现的地方也是一个不错的选择。

    获取我们使用的软件中的漏洞信息。最流行的网站包括 Exploit DB (www.exploit-db.com/),完整披露邮件列表(seclists.org/fulldisclosure/),以及 Packet Storm 的文件部分(packetstormsecurity.com/files/)。

  7. 一旦我们在某个软件组件中发现漏洞,我们必须评估它是否对我们的应用程序至关重要,或者是否可以删除。如果不能删除,我们需要尽早计划修补过程。如果没有可用的修补程序或替代方案,而且漏洞的影响较大,我们必须开始寻找该组件的替代品。

它是如何工作的...

在考虑在我们的应用程序中使用第三方软件组件之前,我们必须查找其安全信息,并检查是否有比我们打算使用的版本更稳定或更安全的版本或替代方案。

一旦我们选择并将其集成到应用程序中,我们需要保持其更新。有时,这可能涉及版本变化和不兼容的情况,但如果我们想保持安全,这就是我们必须支付的代价,或者可能涉及实施Web 应用程序防火墙WAF)或入侵防御系统IPS)来防止攻击,如果我们无法更新或修补高影响漏洞的话。

除了在执行渗透测试时有用外,漏洞下载和漏洞披露网站还可以被系统管理员利用,了解预期会遭遇哪些攻击,攻击方式以及如何保护应用程序免受这些攻击。

A10 – 网页应用程序安全的日志记录与监控

记录应用程序活动日志用于分析或记录错误日志用于调试与为了提高信息安全和用户隐私的目标完全不同,因为事件响应团队应该能够重建攻击者突破应用程序安全的路径,而安全监控设备应该能够解读和处理记录的信息,以便在接近实时的情况下生成潜在安全问题的警报;所有这些都需要在保护用户隐私的同时进行,不记录任何敏感或可识别个人身份的信息。

在这篇教程中,我们将涵盖设计和实施网页应用程序日志机制及其监控时需要考虑的关键方面。

如何做到这一点...

  1. 确保不会记录任何用户或公司敏感或可识别个人身份的信息(如真实姓名、地址、密码、信用卡信息、电话号码等)。

  2. 除了应用程序特定的操作和事件外,还需记录所有与用户和账户管理相关的操作,例如用户创建和删除、密码更改、权限级别更改、登录尝试和登出。

  3. 确保所有日志都包含足够的事件上下文,包括事件的日期和时间(精确到毫秒)、生成事件的用户、与事件相关的系统环境条件,以及涉及的实体,如数据库记录、模块、其他用户和使用的客户端。

  4. 实现一个集中式系统,用于收集、处理和分析日志,并根据分析结果生成安全警报(安全信息与事件管理SIEM))。

  5. 配备专门的团队来监控和应对安全事件。

  6. 实施事件响应和事件恢复计划,以便在检测到攻击或发生安全漏洞时,能够遵循标准化的流程,尽快恢复。

它是如何工作的...

大多数时候,在组织中,日志的保护程度不如数据库,且当发生泄露时,这些日志可能包含大量敏感信息,这些信息可能允许攻击者访问网络中的其他系统,因为日志中包含了用户名和密码,或者可能收集电子邮件并用于执行钓鱼攻击,最糟糕的是,这些日志可能包含应用程序用户的姓名、地址和电话号码。因此,开发人员和安全架构师必须确保所有类似的信息都不应出现在任何日志和监控机制中。

通过记录适当的一组事件,应用程序可以生成足够的信息,使得监控团队能够识别异常行为,并在攻击发生的瞬间将其阻止。为了实现这一点,日志中还必须包含足够的上下文信息,更重要的是,必须有一个专门的团队实时监控网络活动、事件日志、安全设备(如 IDS 和防火墙)以及软件(如杀毒软件和数据泄漏防护代理)。此外,这样的团队应该有一套完善的安全事件检测、响应和恢复的政策和程序。