![写入 /sys/class 的脚本存在安全风险](https://linux22.com/image/1160456/%E5%86%99%E5%85%A5%20%2Fsys%2Fclass%20%E7%9A%84%E8%84%9A%E6%9C%AC%E5%AD%98%E5%9C%A8%E5%AE%89%E5%85%A8%E9%A3%8E%E9%99%A9.png)
我正在寻找一种方法来让我的笔记本电脑的特殊键与 i3-wm 兼容。我遇到了这个帖子并使用那里的脚本创建我自己的。
这是我为屏幕亮度想出的值(在我的计算机上,有效值似乎在 0 到 937 之间 - 其他任何值都会导致写入错误):
#!/bin/bash
#
# Usage: lcd_bright.sh <U|D> <value>
#
MODE=`echo $1 | tr '[a-z]' '[A-Z]'`
BRIGHTNESS='/sys/class/backlight/intel_backlight/brightness'
LCDVALUE=`cat $BRIGHTNESS`
if [ "$MODE" = "U" ]
then
NEWVALUE=$(( $LCDVALUE + $2 ))
if [ $NEWVALUE -le 937 ]
then
echo $NEWVALUE > $BRIGHTNESS
else
echo 937 > $BRIGHTNESS
fi
else
NEWVALUE=$(( $LCDVALUE - $2 ))
if [ $NEWVALUE -ge 0 ]
then
echo $NEWVALUE > $BRIGHTNESS
else
echo 0 > $BRIGHTNESS
fi
fi
键盘背光(有 4 个级别):
#!/bin/bash
#
# Usage: kbd_bright.sh <U|D>
MODE=`echo $1 | tr '[a-z]' '[A-Z]'`
BRIGHTNESS='/sys/class/leds/asus::kbd_backlight/brightness'
KBDVALUE=`cat $BRIGHTNESS`
if [ "$MODE" = "U" ]
then
NEWVALUE=$(( $KBDVALUE + 1 ))
if [ $NEWVALUE -le 3 ]
then
echo $NEWVALUE > $BRIGHTNESS
else
echo 3 > $BRIGHTNESS
fi
else
NEWVALUE=$(( $KBDVALUE - 1 ))
if [ $NEWVALUE -ge 0 ]
then
echo $NEWVALUE > $BRIGHTNESS
else
echo 0 > $BRIGHTNESS
fi
fi
我添加了规则,sudoers.d/
因此脚本不需要密码,并且脚本归所有root
并将权限设置为0754
。
我为它们配置的i3如下:
# screen brightness control
bindsym XF86MonBrightnessUp exec sudo /home/ioana/.config/i3/lcd_bright.sh U 100
bindsym XF86MonBrightnessDown exec sudo /home/ioana/.config/i3/lcd_bright.sh D 100
# keyboard brightness control
bindsym XF86KbdBrightnessUp exec sudo /home/ioana/.config/i3/kbd_bright.sh U
bindsym XF86KbdBrightnessDown exec sudo /home/ioana/.config/i3/kbd_bright.sh D
在做这件事的时候,我看到有人提到此类脚本存在安全风险,尤其是如果他们使用输入(我的脚本就是这样的)。我想更多地了解我的脚本的具体安全风险以及它们意味着什么。
答案1
实际所说的内容及其含义
引自链接帖子:
将权限设置为 755,由 root 拥有。然后编辑 sudoers 文件以允许它们以 root 身份运行,或使用 chmod +s 将它们设置为 SUID。
顺便说一句,这种事情被认为是一种安全风险,所以一定要确保权限设置得当。
这里讲两种情况:
- 设置脚本并允许其以 root 身份执行无需输入密码
- 在脚本上设置 SUID 位
剧本通常存在什么问题?Stephane Chazelaz 的回答(我强烈建议阅读),如果在 Web 服务器中运行或特权脚本运行其他内容,shell 脚本可能会出现问题。对于只有桌面的普通用户来说 - 这意味着在大多数情况下系统被破坏 - 可能是攻击者rm -rf /
在某处注入 - 或者计算机被恶意软件控制并成为僵尸网络的一部分以攻击商业服务器。但对于商业服务器,这可能意味着任何事情,从客户信用卡信息被盗到系统被破坏导致系统崩溃和客户转向其他地方而造成的资金损失。因此,当某事被称为安全问题时,您需要知道这对您意味着什么。您还应该知道谁可能是您的潜在攻击者 - 这定义了他们可以使用哪种方法来破坏您的系统,对于对您的信用卡信息或与人交谈感兴趣的人,他们可能会追踪网络流量而不是脚本,这意味着他们可能会选择 MITM 攻击而不是脚本。
您的具体情况可能存在什么问题?
您的脚本执行 3 个命令:
echo $1 | tr
、 和cat
。如果攻击者用恶意程序替换cat
或tr
,则可能意味着系统被破坏,或者每次执行这些命令时都会泄露信息。而且由于您的脚本以 root 级权限运行 - 这些命令也以 root 级权限运行。由于echo
是内置 shell,因此它不受/bin/echo
替换 的攻击(除非您env echo
改为运行 - 这将调用/bin/echo
)。可以说,如果有人能够替换系统级二进制文件,则意味着他们已经拥有 root 访问权限,这比您的脚本更重要。脚本
/home/ioana/.config/i3/
的权限为 0754。好的,没问题。如果您的帐户被盗用,攻击者无需 root 权限 - 他们将使用您的帐户覆盖脚本内容。那么目录的权限呢/home/ioana/.config/i3/
?删除文件需要对文件所在的目录具有写入权限,因此如果您的系统上有其他用户,而他们没有脚本本身的写入权限,如果他们有写入目录的权限,他们就可以删除该脚本(这实际上不是一个安全问题,而是一个小型 DoS,供大家娱乐和搞笑)。理论上,另一个问题可能来自命令行参数。您有
echo $1 | tr '[a-z]' '[A-Z]'
。假设攻击者使用Stephane 的回答中提到的/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*
内容$1
。shell 需要将它们转换*
为实际文件,而所有这些扩展对 CPU 来说都是昂贵的。这是让您的计算机滞后的小方法,再次是小型 DoS。如果你运行的是旧版本的 bash,则可能会通过导出函数受到任意代码注入攻击 - 又名贝壳袜。因此,在运行特权脚本之前,可以导出恶意函数。
如果攻击者热衷于虐待动物,他们可以虐待
cat
当然,所有这些可以结合起来,
wget
在你的计算机上下载其他恶意程序并以 root 权限执行。
最后,你操作的/sys/class/
目录类型并不是问题所在。问题在于 shell 脚本所能做的事情的级别,以及 shell 脚本的机制并不完善。但我们不要过于偏执。就像我说的,如果有人访问了你的帐户(具有sudo
特权)或 root 帐户 - 这已经足够令人担忧了。
也可以看看
答案2
有几种方法可以显著减少脚本的攻击面。请注意,我不是 Bash 专家,因此这不是一份详尽的问题列表,只是我发现您现有代码中存在的一些问题。
- 处理错误和意外的输入和情况!您的代码假定一切都将按计划进行。
- 如果可以避免,请不要要求或关注用户输入。您可以通过编写两个用于键盘亮度的脚本轻松做到这一点(埃。G.、
kbd_brighter
和kbd_dimmer
)。您还可以编写两个脚本来将 LCD 亮度提高和降低 100。 - 在写入文件之前,请对文件进行完整性检查
/sys
。它是否存在?它是否只包含一个整数?如果该整数意外地是负整数,我们该怎么办?妥善处理所有可能的情况。 - 始终用双引号将包含变量的任何表达式引起来,以避免变量填充为空字符串的问题(
[ $1 -eq 5 ]
变成[ -eq 5 ]
只是自找麻烦),并确保正确处理包含特殊字符(如空格或换行符)的变量。 - 使用命令的完整路径来避免
PATH
攻击。例如,/bin/cat
使用 而不是cat
。您可以看到带有 的路径type cat
。 - 使用 Bash 功能代替外部命令。例如,
VARIABLE=`< filename`
使用 代替VARIABLE=`cat filename`
。此外,使用echo
代替 来/bin/echo
使用 Bash 内置echo
命令。您可以看到,内置命令可通过 来使用type echo
。 - 将修改逻辑与文件写入逻辑分开,以避免必须检查多个位置的文件写入错误,尤其是在对文件进行更改时。
总结一下,这是一个示例kbd_brighter
脚本。请注意,我没有测试过它,因为我没有华硕。它可能还存在安全问题,因为我不是专家。
#!/bin/bash
BRIGHTNESS_FILE="/sys/class/leds/asus::kbd_backlight/brightness"
if [ ! -e "$BRIGHTNESS_FILE" ]; then
>&2 echo 'ERROR: Asus keyboard backlight brightness file not found.'
exit 1
fi
BRIGHTNESS="$( < "$BRIGHTNESS_FILE" )"
if [ "$BRIGHTNESS" -eq "$BRIGHTNESS" ] 2>/dev/null; then
if [ "$BRIGHTNESS" -lt "1" ]; then
BRIGHTNESS="1"
elif [ "$BRIGHTNESS" -lt "3" ]; then
BRIGHTNESS="$(( "$BRIGHTNESS" + 1 ))"
else
BRIGHTNESS="3"
fi
else
>&2 echo 'ERROR: Asus keyboard backlight brightness is not an integer.'
exit 1
fi
echo "$BRIGHTNESS" > "$BRIGHTNESS_FILE"