当一个功能程序需要执行系统命令(system(),exec()),而且提供了用户输入入口时,则可能存在命令行输入。
命令行注入可用于通过主机操作系统上的易受攻击程序来执行任意命令。命令行注入是可行的,当应用程序拿到一个用户数据并没有对它做安全性检查(比如表单,cookies,http头信息)到system shell,攻击方通过一个具有高级别权限的应用程序来运行系统命令,命令注入攻击可能很大程度上是由于对来自客户端输入的数据验证不足。
注意,命令行注入不可以执行自定义命令或代码,只能执行系统命令。
来举几个例:
example 1:
#include
#include
int main(int argc, char **argv) {
char cat[] = "cat ";
char *command;
size_t commandLength;
commandLength = strlen(cat) + strlen(argv[1]) + 1;
command = (char *) malloc(commandLength);
strncpy(command, cat, commandLength);
strncat(command, argv[1], (commandLength - strlen(cat)) );
system(command);
return (0);
}
这是run in linux上的代码,正常用户输入 story.txt,程序执行cat命令,如cat story.txt。但是如果用户输入story.txt;ls,程序也会执行ls命令,如果程序运行在高级别权限,则可以执行更高级别的命令行。
example 2:
int main(char* argc, char** argv) {
char cmd[CMD_MAX] = "/usr/bin/cat ";
strcat(cmd, argv[1]);
system(cmd);
}
这是一段运行在root权限下的代码,所以system()也是运行与root权限下,如果用户输入标准的文件名,则该程序运行正常。但是,如果用户在命令后面增加;rm -rf /,则系统执行cat命令失败,并紧接着执行rm命令地柜删除root分区下的所以文件。
example 3:
...
char* home=getenv("APPHOME");
char* cmd=(char*)malloc(strlen(home)+strlen(INITCMD));
if (cmd) {
strcpy(cmd,home);
strcat(cmd,INITCMD);
execl(cmd, NULL);
}
...
这是一段来自于高级别权限的程序代码,他用环境变量$APPHOME来确定应用程序安装目录,然后执行该目录下的一个初始化脚本。他也可以用来执行任意数量的命令,攻击者可以修改环境变量APPHOME到不同的目录,应为程序不检查读取的环境变量值,当可以控制环境变量时,就可以欺骗应用程序来运行恶意代码。
当然这些代码都是显现的,所以攻击者可以显而易见的看到效果。
example 4:
system("cd /var/yp && make &> /dev/null");
这是一段来自于web cgi程序的代码(当然这是一段硬编码),允许用户修改他们的密码,NIS下的密码更新过程包括在/var/yp目录中运行make,因为是修改密码,所以必定有setuid root的权限。
因为该段程序没有指明make的绝对路径,并在调用命令之前没有做任何抹去环境变量的动作,攻击者可以修改他们的$PATH环境变量指向一个恶意的名为make的二进制文件,从shell命令行提示符执行CGI脚本,因为程序具有setuid root权限,恶意make文件也具有root高级执行权限。
在程序中执行系统命令时环境变量扮演者一个重要的角色。像system()和exec()在执行命令时使用的是程序的环境,攻击者就存在潜在的机会在调用之前去改变他。
web cgi介绍:通用网关接口https://blog.csdn.net/weixin_39609623/article/details/86312439
setuid root:setuid权限-让任意账号以root身份执行命令
example 5:
#include
#include
#include
int main(int argc, char **argv)
{
char command[256];
if(argc != 2)
{
printf("Error: Please enter a program to time!\n");
return -1;
}
memset(&command, 0, sizeof(command));
strcat(command, "time ./");
strcat(command, argv[1]);
system(command);
return 0;
}
这段C代码易受攻击的,我们可以输入ls; cat /etc/shadow来执行系统命令
Java:
java的Runtime.exec和C的system函数其实是不一样的,虽然他们都是允许你调起一个新的程序/进程。但是C的system函数通过传参到shell(/bin/sh)解析,RunTime.exec会将其进行字符分隔成数组,当执行数组的第一个命令时,后面的的字符将作为其参数。runtime.exec不会调起任何shell。许多函数在被shell执行时,容易被添加一些连接符(&,&&,|,||,或者重定向输入和输出)来跳过第一个命令来执行后面的命令。
dvwa的command Injection练习,是一个pingip功能,各等级都是对用户输入参数做不同程度的合法性校验,我们可以通过命令链接特殊字符进行命令行注入,执行unix/windows命令,比如 输入192.168.1.102 && ls , 192.168.1.102 & ls , 192.168.1.102 || ls , 192.168.1.102 | ls , 192.168.1.102 &&ls等等。