C# 应用程序漏洞速查指南

1,332 阅读11分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第20天,点击查看活动详情

修复应用程序中漏洞的第一步是了解要查找的内容。下文将罗列影响 C# 应用程序的常见漏洞。

保护应用程序并不是最简单的事情。一个应用程序有很多组件:服务器端逻辑、客户端逻辑、数据存储、数据传输、API 等等。由于要确保所有这些组件的安全,构建安全的应用程序看起来确实令人望而生畏。

值得庆幸的是,大多数的漏洞都有相同的根本原因。通过研究这些常见的漏洞类型、它们产生的原因以及如何发现它们,就可以学会如何预防它们并保护你的应用程序。

使用每种语言、框架或环境都会使应用程序面临一些特有的漏洞。修复应用程序中漏洞的第一步是了解要查找的内容。

我将在这篇文章中介绍的漏洞是:

  • XML 外部实体攻击 (XXE)
  • 不安全的反序列化
  • 远程代码执行 (RCE)
  • SQL注入
  • NoSQL注入
  • LDAP注入
  • 日志注入
  • 邮件注入
  • 模板注入 (SSTI)
  • 正则表达式注入
  • XPath注入
  • 标头注入
  • 会话注入和不安全的 cookie
  • 主机标头中毒

XML 外部实体攻击

XML 外部实体攻击或 XXE 是指攻击者利用 XML 解析器读取你服务器上的任意文件。使用 XXE,攻击者还可能能够检索用户信息、配置文件或其他敏感信息,如 AWS 凭证。为了防止 XXE 攻击,你明确禁用这些功能。

不安全的反序列化

序列化是将编程语言中的对象(例如 Python 对象)转换为可以保存到数据库或通过网络传输的格式的过程。而反序列化指的是相反:它是从文件或网络中读取序列化对象并将其转换回对象。许多编程语言都支持对象的序列化和反序列化,包括 Java、PHP、Python 和 Ruby。

不安全的反序列化是一种漏洞,当攻击者可以操纵序列化对象并在程序流中造成意外后果时就会出现这种漏洞。不安全的反序列化错误通常是非常严重的漏洞:不安全的反序列化错误通常会导致身份验证绕过、拒绝服务甚至任意代码执行。 

为防止不安全的反序列化,你需要首先留意补丁并使依赖项保持最新。许多不安全的反序列化漏洞是通过依赖项引入的,因此请确保你的第三方代码是安全的。它还有助于避免使用序列化对象,而是使用简单的数据类型,如字符串和数组。

远程代码执行

远程代码执行漏洞或 RCE 是一类漏洞,当攻击者可以在你的机器上执行他们的代码时就会发生这种情况。发生这种情况的一种方式是通过命令注入漏洞。它们是一种远程代码执行,发生在用户输入直接连接到系统命令中时。应用程序无法区分用户输入的位置和系统命令的位置,因此应用程序将用户输入作为代码执行。攻击者将能够在机器上执行任意命令。

防止远程代码执行的最简单方法是确保你只执行来自受信任来源的字符串,或者以允许列表的形式实施强大的输入验证。

SQL注入

在 SQL 注入攻击中,攻击者注入数据来操纵 SQL 命令。当应用程序没有正确验证用户输入时,攻击者可以插入 SQL 语言的特殊字符来扰乱查询的逻辑;从而执行任意 SQL 代码。 

SQL 注入允许攻击者代码更改应用程序的 SQL 查询结构,以窃取数据、修改数据或可能在底层操作系统中执行任意命令。防止 SQL 注入的最好方法是使用参数化语句,这使得 SQL 注入几乎不可能。

NoSQL注入

数据库并不总是使用SQL。NoSQL数据库或Not Only SQL数据库是不使用SQL语言的数据库。NoSQL注入是指将数据注入到这些数据库语言逻辑中的攻击。NoSQL注入可能和SQL注入一样严重:它们可能导致身份验证绕过和远程代码执行。现代的NoSQL数据库,如MongoDB、Couchbase、Cassandra、HBase等,都容易受到注入攻击。NoSQL查询语法是特定于数据库的,查询通常是用应用程序的编程语言编写的。出于同样的原因,每个数据库中防止NoSQL注入的方法也是数据库特定的。

LDAP注入

轻型目录访问协议 (LDAP) 是一种查询有关系统用户和设备的目录服务的方法。例如,它用于查询 Microsoft 的 Active Directory。当应用程序在 LDAP 查询中使用不受信任的输入时,攻击者可以提交造成恶意影响的精心设计的输入。使用 LDAP 注入,攻击者可以绕过身份验证并破坏目录中存储的数据。

日志注入

你可能会执行系统日志记录以监视网络中发生的恶意活动,但你是否考虑过你的日志文件条目可能在欺骗你?与其他系统文件一样,日志文件可能会被恶意行为者篡改。攻击者经常修改日志文件以在攻击期间掩盖他们的踪迹。日志注入是攻击者更改日志文件的一种方式。当攻击者欺骗应用程序在你的日志文件中写入虚假条目时,就会发生这种情况。

当应用程序未清理写入日志的输入中的换行符“\n”时,通常会发生日志注入。攻击者可以利用换行符将新条目插入到应用程序日志中。攻击者利用日志中的用户输入的另一种方式是,他们可以将恶意 HTML 注入日志条目,以尝试在查看日志的管理员的浏览器上触发 XSS。

为了防止日志注入攻击,你需要一种方法来区分真实日志条目和攻击者注入的假日志条目。一种方法是在每个日志条目前加上额外的元数据,如时间戳、进程 ID 和主机名。你还应该将日志文件的内容视为不受信任的输入,并在访问或操作它们之前对其进行验证。

邮件注入

许多 Web 应用程序会根据用户的操作向用户发送电子邮件。例如,如果订阅了新闻媒体的提要,该网站可能会向你发送一份带有提要名称的确认信息。

当应用程序使用用户输入来确定将电子邮件发送到哪些地址时,就会发生邮件注入。这可能允许垃圾邮件发送者使用你的服务器向用户发送批量电子邮件,或使诈骗者能够通过你的电子邮件地址进行社会活动。

模板注入

模板引擎是一种用于确定网页外观的软件。这些用 Jinja 等模板语言编写的 Web 模板为开发人员提供了一种方法,通过将应用程序数据与 Web 模板相结合来指定页面的呈现方式。Web 模板和模板引擎一起允许开发人员在 Web 开发期间将服务器端应用程序逻辑与客户端表示代码分开。

模板注入是指注入网页模板。根据受感染应用程序的权限,攻击者可能能够使用模板注入漏洞来读取敏感文件、执行代码或提升他们在系统上的权限。

正则表达式注入

正则表达式(regex)是描述文本搜索模式的特殊字符串。有时,应用程序允许用户提供自己的正则表达式模式供服务器执行或使用用户输入构建正则表达式。正则表达式注入攻击或正则表达式拒绝服务攻击(ReDoS)发生在攻击者为正则表达式引擎提供需要很长时间才能评估的模式时。可以在我的帖子中找到这些模式的示例

值得庆幸的是,通过不从用户输入生成正则表达式模式,以及构造设计良好的正则表达式模式(其所需的计算时间不会随着文本字符串的增长而呈指数级增长),可以可靠地防止正则表达式注入。

XPath注入

XPath 是一种用于 XML 文档的查询语言。考虑用于 XML 的 SQL。XPath 用于对存储在 XML 文档中的数据进行查询和操作。例如,XPath 可用于检索存储在 XML 文档中的雇员的薪水信息。它还可用于对该数据执行数值运算或比较。

XPath 注入是一种注入 XPath 表达式以改变查询结果的攻击。与 SQL 注入一样,它可用于绕过业务逻辑、提升用户权限和泄露敏感数据。由于应用程序经常使用 XML 跨系统和 Web 服务传递敏感数据,因此这些地方最容易受到 XPath 注入的攻击。与其他类型的注入漏洞类似,可以通过验证用户输入来防止 XPath 注入。

标头注入

当 HTTP 响应标头是根据不受信任的输入动态构造的时,就会发生标头注入。根据漏洞影响的响应标头,标头注入可能导致跨站点脚本、开放重定向和会话固定。

例如,如果Location标头可以由 URL 参数控制,攻击者可以通过在参数中指定他们的恶意站点来导致开放重定向。攻击者甚至可以在受害者的浏览器上执行恶意脚本,或者通过标头注入向受害者发送完全受控的 HTTP 响应,从而迫使受害者下载恶意软件。 

可以通过避免将用户输入写入响应标头、从用户输入中去除换行符(换行符用于创建新的 HTTP 响应标头)以及使用白名单来验证标头值来防止标头注入。

会话注入和不安全的 Cookie

会话注入是一种标头注入。如果攻击者可以操纵他们的会话 cookie 的内容,或者窃取其他人的 cookie,他们就可以欺骗应用程序认为他们是其他人。攻击者获取他人会话的方式主要有三种:会话劫持、会话篡改和会话欺骗。

会话劫持是指攻击者窃取别人的会话cookie并将其据为己有。攻击者经常通过 XSS 或 MITM(中间人)攻击窃取会话 cookie。会话篡改是指攻击者何时可以更改其会话 cookie 以更改服务器解释其身份的方式。当在 cookie 中传递会话状态并且 cookie 未正确签名或加密时,会发生这种情况。最后,当会话 ID 可预测时,攻击者可以“欺骗”会话。如果是这种情况,攻击者可以伪造有效的会话 cookie 并以其他人的身份登录。防止这些会话管理陷阱需要多层防御。

主机标头中毒

Web 服务器通常在同一个 IP 地址上托管多个不同的网站。HTTP 请求到达某个 IP 地址后,服务器会将请求转发到 Host 标头中指定的主机。虽然主机标头通常由用户的浏览器设置,但它仍然是用户提供的输入,因此不应被信任。

如果 Web 应用程序在使用 Host 标头构造地址之前未验证 Host 标头,则攻击者可以通过 Host 标头发起一系列攻击,例如 XSS、服务器端请求伪造 (  SSRF) 和 Web 缓存中毒攻击。例如,如果应用程序使用 Host 标头来确定脚本的位置,则攻击者可以提交恶意的 Host 标头以使应用程序执行恶意脚本:

var scriptURL = $"https://{Request.Host}/script.js";

未完待续