演示输入验证和代码完整性

CompTIABeginner
立即练习

介绍

在本实验中,你将探索两个基础的安全概念:输入验证(input validation)和代码完整性(code integrity)。输入验证是指在程序处理接收到的任何输入之前,确保其安全且格式正确的实践。这是抵御包括命令注入(command injection)在内的各种攻击的关键防线。代码完整性则涉及验证你的应用程序代码是否未被未经授权的第三方篡改或损坏。

你将通过实践学习这些概念。首先,你将创建一个易受命令注入攻击的简单 shell 脚本。接下来,你将利用此漏洞来理解其风险。然后,你将通过实现适当的输入清理(input sanitization)来修复该脚本。最后,你将学习如何使用加密哈希(cryptographic hashes)来验证脚本的完整性,确保其未被篡改。

这是一个实验(Guided Lab),提供逐步指导来帮助你学习和实践。请仔细按照说明完成每个步骤,获得实际操作经验。根据历史数据,这是一个 初级 级别的实验,完成率为 98%。获得了学习者 97% 的好评率。

创建带用户输入的简单脚本

在此步骤中,你将创建一个简单的 Bash 脚本,该脚本会提示用户输入文件名,然后使用 ls -l 命令显示该文件的详细信息。此脚本的初始版本将没有任何安全检查。

首先,使用 nano 编辑器在 ~/project 目录中创建一个名为 check_file.sh 的新文件。

nano ~/project/check_file.sh

现在,将以下代码添加到文件中。此脚本将要求输入文件名,将输入读取到名为 filename 的变量中,然后使用 eval 命令对该文件名执行 ls -l。请注意,将 eval 与用户输入一起使用是一个严重的安全漏洞。

#!/bin/bash

echo "Please enter a filename to check:"
read filename
echo "Checking details for: $filename"
eval "ls -l $filename"

Ctrl+X,然后按 Y,最后按 Enter 保存文件并退出 nano

接下来,你需要使脚本可执行,以便运行它。使用 chmod 命令添加执行权限。

chmod +x ~/project/check_file.sh

现在,让我们运行脚本看看它的效果。我们将使用 testfile.txt,它已为你准备好在实验环境中。

./check_file.sh

脚本将提示你输入。输入 testfile.txt 并按 Enter

Please enter a filename to check:
testfile.txt
Checking details for: testfile.txt
-rw-rw-r-- 1 labex labex 0 Aug  4 15:19 testfile.txt

你已成功创建并运行了一个接受用户输入的简单脚本。在下一步中,你将看到此脚本如何被利用。

模拟基础命令注入攻击

在此步骤中,你将看到上一步创建的脚本如何容易受到命令注入攻击。当攻击者能够通过易受攻击的应用程序在宿主操作系统上执行任意命令时,就会发生命令注入。

我们的脚本之所以易受攻击,是因为它在未首先检查输入是否安全的情况下,使用 eval 执行包含用户输入($filename)的命令。eval 命令将整个字符串视为要执行的命令,这使其特别危险。攻击者可以通过提供包含额外 shell 命令的输入来利用这一点。

让我们再次运行脚本。

./check_file.sh

这次,当提示输入文件名时,输入以下字符串。分号(;)是 shell 中用于分隔命令的特殊字符。

testfile.txt; whoami

Enter 后,你将看到以下输出:

Please enter a filename to check:
testfile.txt; whoami
Checking details for: testfile.txt; whoami
-rw-rw-r-- 1 labex labex 0 Aug  4 15:19 testfile.txt
labex

请注意发生了什么。脚本首先按预期执行了 ls -l testfile.txt。但是,由于分号和 eval 的使用,shell 随后执行了第二个命令 whoami,该命令打印了当前用户名(labex)。这演示了一次成功的命令注入。eval 命令通过将整个输入视为可执行代码来实现这一点。攻击者可以利用此漏洞运行更危险的命令。

注意: 如果你使用 ls -l $filename 而不使用 eval(如原始版本所示),攻击将不会成功,因为 shell 会将 testfile.txt; whoami 视为 ls 的单独参数,从而导致类似“无法访问 'testfile.txt;'”和“无法访问 'whoami'”的错误消息。eval 命令是此示例中实现命令注入的关键。

实现输入清理以防止注入

在此步骤中,你将修改脚本,通过过滤用户输入并移除危险的 eval 命令来防止命令注入攻击。输入过滤是指清理或筛选输入以移除或中和潜在恶意字符的过程。

我们的策略将是:

  1. 移除危险的 eval 命令,并使用适当的引用进行直接命令执行。
  2. 检查输入文件名是否只包含允许的字符。对于典型文件名,我们可以创建一个字符白名单,例如字母、数字、下划线、连字符和点。我们将拒绝包含分号等其他字符的任何输入。

再次使用 nano 打开 check_file.sh 脚本。

nano ~/project/check_file.sh

修改脚本以包含使用正则表达式的验证检查。将现有内容替换为以下代码:

#!/bin/bash

echo "Please enter a filename to check:"
read filename

## Input sanitization: only allow alphanumeric characters, underscores, hyphens, and dots.
if [[ "$filename" =~ ^[a-zA-Z0-9_.-]+$ ]]; then
  echo "Checking details for: $filename"
  ls -l "$filename"
else
  echo "Error: Invalid filename. Malicious input detected."
fi

关键的更改包括:

  1. 移除了危险的 eval 命令。
  2. ls 命令中为 "$filename" 添加了适当的引用。
  3. 添加了带有输入验证的 if 语句。表达式 [[ "$filename" =~ ^[a-zA-Z0-9_.-]+$ ]] 检查 filename 变量是否仅包含从开头(^)到结尾($)的指定字符集中的字符。

Ctrl+X,然后按 Y,最后按 Enter 保存更改。

现在,让我们再次尝试相同的攻击。运行脚本:

./check_file.sh

输入恶意输入 testfile.txt; whoami 并按 Enter

Please enter a filename to check:
testfile.txt; whoami
Error: Invalid filename. Malicious input detected.

如你所见,脚本现在会检测到无效字符,并打印错误消息,而不是执行恶意的 whoami 命令。攻击已成功阻止。

通过哈希验证脚本完整性

在此步骤中,你将学习如何使用加密哈希来验证脚本的完整性。这可以确保在保护好脚本后,它未被攻击者修改或篡改。我们将使用 sha256sum 工具,它用于计算 SHA-256 哈希。

首先,让我们为安全的 check_file.sh 脚本生成一个哈希,并将其保存到一个文件中。此文件将作为我们的“已知良好”签名。

sha256sum ~/project/check_file.sh > ~/project/check_file.sha256

此命令计算 check_file.sh 的 SHA-256 哈希,并将输出重定向到一个名为 check_file.sha256 的新文件。让我们查看此文件的内容。

cat ~/project/check_file.sha256

你将看到一长串字符,后跟文件名。此字符串是你脚本的唯一哈希。

e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855  /home/labex/project/check_file.sh

(注意:你的哈希值将不同。)

现在,让我们模拟一次未经授权的修改。我们将在脚本末尾添加一个简单的注释。即使是这样小的更改也应该会完全改变哈希。

echo "## A harmless comment" >> ~/project/check_file.sh

脚本现已修改。要检查其完整性,我们可以使用带有 -c(check)选项的 sha256sum,它会从我们的签名文件中读取哈希,并将其与脚本的当前哈希进行比较。

sha256sum -c ~/project/check_file.sha256

由于文件已更改,该命令将报告失败。

/home/labex/project/check_file.sh: FAILED
sha256sum: WARNING: 1 computed checksum did NOT match

这证实了脚本的完整性已被破坏。此技术对于确保你运行的代码是你所信任的代码至关重要。

总结

恭喜你完成了本次实验!你获得了关于两个关键安全原则的实践经验。

你学会了如何通过实现输入过滤来识别和防止命令注入漏洞。通过根据允许字符的白名单验证用户输入,你成功地保护了一个易受攻击的 shell 脚本。

你还学会了如何使用加密哈希来确保代码的完整性。通过为脚本生成 SHA-256 校验和,你能够创建一个可验证的签名,以检测任何未经授权的修改。

这些技能对于编写安全的代码和维护任何系统的安全性至关重要。