如今,Web 应用程序无处不在,它们几乎可以用来控制您能想象到的一切。在本节中,我们将研究 Web 应用程序攻击和安全。
当开发人员未实现访问资源的授权要求时,就会出现 IDOR 漏洞。
Eve,通过简单地更改标识符,例如文档Rest 参数,她就可以访问Alice 的文档。
当 Web 应用程序不强制执行对象之间的授权时,就会发生这种情况,从而允许攻击者枚举值并测试对其他数据点的访问。
例如,我们可能有以下伪代码,没有显示授权的迹象:
$id = getInputFromUser();
$doc = getDocument($id);
return $doc;
上面的代码要求用户输入,不执行验证或清理,然后直接使用 getDocument 函数执行查找并返回有问题的文档。
更好的实现是检查权限:
$id = getInputFromUser();
$user = findUsername();
$doc = "";
if (hasAccessToDocument($user, $id)) {
$doc = getDocument($id);
} else {
$doc = "Not authorized for this document";
}
return $doc;
此类漏洞很容易找到,因为您只需更改一个简单的数字即可查看是否可以访问其他人的数据。首先检查用户是否获得授权可以防止此漏洞。
应用程序希望在引用数据时避免使用数字序列。在IDOR 示例中,文档的标识符从1000 到1002。有时这些数字被称为"Magic Numbers",因为它们直接指向服务器上的资源(例如通过数据库),并且可以轻松枚举所有值。例如,攻击者可以检查从 0 一直到 10000 的所有文档标识符,并记录提供数据访问权限的任何结果。
虽然应正确实施授权,但在引用数据时使用 GUID ("Globally Unique Identifier") 或 UUID ("Universally Unique Identifier") 也很有帮助。这些标识符被设计为全局唯一的,并且由于数字生成的内置熵而无法枚举。
GUID 如下所示:
许多 Web 应用程序都连接到数据库。数据库保存 Web 应用程序希望存储和使用的所有信息。
SQL 注入是一种允许攻击者操纵 Web 应用程序开发人员正在使用的 SQL ("Structured Query Language") 的技术。这通常是由于缺乏数据清理而发生的。开发人员经常使用 SQL 来访问数据库资源。
在上图中 Eve 提出的请求中,我们看到她输入了值:1000' OR '1'='1
这会导致生成的 SQL 查询返回表的所有行,因为数据库将该语句评估为始终为 true。想一想:数据库收到一个请求,该请求的值可以是 1000 或 1 等于 1;它每次都会返回一个值!我们可以使用许多不同的 SQL 函数和操作来操纵语法,这个示例只是其中之一。
下面是一个伪代码示例,其中包含 SQL 注入漏洞。
$username = getUserName();
$pw = getPassword();
$user = mysql_query("SELECT * FROM userTable WHERE username = $username AND password = $pw");
if ($user) {
$loggedIn = True;
} else {
$loggedIn = False;
}
对于攻击者来说,他们可以简单地针对目标域制作一个 URL,并在其中进行攻击,如下所示:
/login?username=admin&password=password' OR '1'='1
密码变量设置为包含 SQL 字符,导致生成的 SQL 字符串返回一行,即使我们不知道密码也是如此。生成的 SQL 查询将是:
SELECT * FROM userTable WHERE username = 'admin' AND password = 'password' OR '1'='1'
参数化查询是抵御 SQL 注入的推荐解决方案。在参数化查询中,开发人员仔细确保查询的每个输入都定义为特定值和类型。以下是上述代码中的一个示例,被认为是安全实现:
$username = getUserName();
$pw = getPassword();
$parameterizedQuery = prepare_query("SELECT * FROM userTable where username = ? and password = ?");
$parameterizedQuery.setString(1, $username)
$parameterizedQuery.setString(2, $password)
$user = parameterizedQuery.execute();
if ($user) {
$loggedIn = True;
} else {
$loggedIn = False;
}
在上面的例子中,开发者已经很谨慎地说,参数1应该是一个字符串,并且包含用户名,第二个参数中包含密码。
XSS利用服务器来攻击服务器的访问者。攻击并不针对服务器本身,而是针对用户。
服务器仅用于反映攻击者的值(通常是 JavaScript),然后访问者在自己的浏览器中运行攻击者的数据。攻击者必须制作服务器不会清理和清理的输入,这样当访问者单击包含攻击者值的链接或访问攻击者在攻击中使用的网页上的资源时,用户就会运行以下代码:攻击者提供。
下面是 Eve 向 Alice 发送包含 XSS 攻击的链接的图形示例:
这种攻击称为反射型 XSS,Eve 发现漏洞,然后将包含攻击的链接发送给毫无戒心的用户,并让他们单击该链接。该链接包含攻击,并使网络服务器将攻击返回给单击该链接的受害者。
这背后的代码可能很简单,如以下伪代码示例:
$nickname = etNickName();
echo "Greeting $nickname, nice to meet you!";
另一种 XSS 称为存储型 XSS 攻击。在存储型 XSS 攻击中,攻击者能够在网页上保存内容,每次有人访问该网站时都会反映该内容。它不一定要求有人点击链接。
下图描述了 Eve 如何存储恶意 JavaScript,以便在访问资源时在任何人的浏览器中执行:
XSS 攻击可以完成很多事情,例如:
为了防御 XSS,需要遵循以下几个最佳实践:
HTML 编码允许 Web 应用程序以安全的方式返回通常不安全的字符。例如,以下特殊字符可以编码为其各自的对应字符:
Special Character | HTML Entity |
---|---|
< | < |
> | > |
" | " |
& | & |
' | ' |
这会产生可以安全显示的输出。然后我们可以在客户端使用 JavaScript 安全地将 HTML 实体转换为值。
网络服务器可以控制允许在网站上运行哪种 JavaScript。这不会消除漏洞,而是在存在未知漏洞时增加深度防御。
常见且严格的 CSP 是向 Web 应用程序的用户提供所有接受的 JavaScript 源文件的列表。
此外,CSP 通常会阻止内联 JavaScript 的执行。
为了更轻松地实施和检测正在进行的攻击,CSP 允许客户端向服务器提供的 URL 报告 CSP 违规行为
有许多网络应用程序扫描仪。这些允许扫描应用程序是否存在 SQL 注入和 XSS 等漏洞。与网络漏洞扫描器相反,Web 应用程序扫描器通常基于启发式方法而不是已知漏洞的签名和列表。
Web 应用程序扫描器非常有用,特别是当内置到 CI ("Continuous Integration") 和 CD ("Continuous Delivery") 等开发流程中时