输入和输出

已完成

当前应用程序最普遍的安全弱点在于无法正确处理从外部源接收的数据,特别是用户输入。 在使用任何输入之前,始终应该认真检查,确保它已经过验证。 如果未能分析用户输入中是否有潜在攻击,则可能导致数据丢失或泄露、提升特权,甚至在其他用户的计算机上执行恶意代码。

该情况中的悲剧在于这本是很容易解决的一个问题。 本单元将将介绍在数据接收时、数据在屏幕上显示时,以及在数据存储供稍后使用时如何处理数据。

为何需要验证输入?

假设你正在生成一个界面,用户通过它能够在你的网站上创建帐户。 个人资料数据包括姓名、电子邮件,以及要向该网站的任何访客显示的昵称。 如果某个新用户在创建个人资料时输入了包含一些 SQL 命令的昵称该怎么办? 例如,如果恶意用户输入下述引用之类的内容该怎么办:

Eve'); DROP TABLE Users;--

如果我们草率地将此值插入数据库,它可能会修改 SQL 语句,使其执行我们绝对不想运行的命令! 该示例被称作“SQL 注入”攻击,这是众多恶意利用类型中的一种,可能在你不当处理用户输入时发出。 那么,我们可如何弥补这一情况? 本单元将讲解何时要验证输入、如何将输出编码,以及如何创建参数化的查询(这可以解决上述恶意利用问题!)。 这些方法就是防止在应用程序中输入恶意内容的三大主要防范方法。

何时需要验证输入?

答案是“始终”。 必须验证应用程序的每项输入。 这包括 URL 中的参数、用户的输入、数据库中的数据、API 中的数据,以及以明文形式传入的、用户可能要处理的任何内容。 请始终使用“允许列表”方法,它是指你只能接受“已知良好的”输入,而不是采用“阻止列表”(此情况下会专门查找恶意输入),原因是没法想象出包含潜在恶意输入的完整列表。 在服务器而不是客户端上完成此工作(也可同时在客户端上完成此工作),确保不会绕过防御机制。 将所有数据视为不受信任,这样,在遇到大多数常见的 Web 应用漏洞时可以保护自己。

如果使用 ASP.NET,该框架可为客户端和服务器端的输入验证提供很好的支持

如果使用其他 Web 框架,可以通过 OWASP 输入验证速查表中提供的一些极佳方法执行输入验证。

始终使用参数化查询

通常使用 SQL 数据库来存储数据;例如,你的应用程序可将用户个人资料信息存储在数据库中。 切勿在代码中使用原始用户输入来创建内联 SQL 或其他数据库查询,也不要将其直接发送到数据库中;此行为后患无穷,前面已对此进行过描述。

例如,不要创建类似于以下内联 SQL 示例的代码:

string userName = Request.QueryString["username"]; // receive input from the user BEWARE!
...
string query = "SELECT *  FROM  [dbo].[users] WHERE userName = '" + userName + "'";

在这里,我们将文本字符串连接起来创建查询,从用户处获取输入并生成一个动态 SQL 查询来查找用户。 同样,如果恶意用户意识到我们编写了这种代码,或者尝试不同的输入样式来确定是否存在漏洞,则我们最终可能会遭受重大灾难。 应使用参数化 SQL 语句或存储过程,如下所示:

-- Lookup a user
CREATE PROCEDURE sp_findUser
(
@UserName varchar(50)
)

SELECT *  FROM  [dbo].[users] WHERE userName = @UserName

通过此方法,可以从代码安全调用过程,并向其传递 userName 字符串,而无需担心该过程被视为 SQL 语句的一部分。

始终将输出编码

以可视方式或者在文档中提供的任何输出应始终经过编码并转义。 如果在清理过程中遗失了数据,或者代码意外生成了可被恶意使用的内容,上述做法可以提供保护。 此设计原则将确保所有内容都显示为输出,且不会无意中被解释为应执行的内容,后者就是另一种被称作“跨站点脚本”(XSS) 的常见攻击技术。

由于 XSS 防范是一种常见的应用程序要求,因此该安全方法也由 ASP.NET 代为操作。 默认情况下,所有输出均已编码。 如果使用其他 Web 框架,可以使用 OWASP XSS 防护速查表来验证网站上用于输出编码的选项。

总结

必须清理和验证你的输入以确保该输入有效且可安全使用和存储。 大多数现代 Web 框架都提供了可自动处理其中部分操作的内置功能。 可查看首选框架的文档,了解它所提供的功能。 虽然最常在 Web 应用中进行此操作,但请记住,其他类型的应用程序也可能同样易受攻击。 不要因为新应用程序是桌面应用程序就认为自己是安全的。 仍需正确处理用户输入,确保不会有人利用你的应用来损坏数据,或损害公司的声誉。

知识检查

1.

需要验证下面哪些数据源?

2.

参数化查询(SQL 中的存储过程)是与数据库通信的安全方式,因为:

3.

需要对以下哪些数据进行输出编码?