浅析命令执行漏洞


title: 浅析命令执行漏洞
date: 2022-12-01 00 :02 :36
tags: 漏洞
categories: 学习笔记


漏洞描述

命令执行漏洞是指服务器没有对执行的命令进行过滤,用户可以随意执行系统命令,命令执行漏洞属于高危漏洞之一
如PHP的命令执行漏洞主要是基于一些函数的参数过滤不足导致,可以执行命令的函数有**system( )、exec( )、shell_exec( )、passthru( )、pcntl_execl( )、popen( )、proc_open( )**等,当攻击者可以控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行攻击
PHP执行命令是继承WebServer用户的权限,这个用户一般都有权限向Web目录写文件,可见该漏洞的危害性相当大

漏洞原理

应用程序有时需要调用一些执行系统命令的函数,如在PHP中,使用system、exec、shell_exec、passthru、popen、proc_popen等函数可以执行系统命令,当黑客能控制这些函数中的参数时,就可以将恶意的系统命令拼接到正常命令中,从而造成命令执行漏洞

常见危险函数

php代码相关
eval()
assert()
preg_replace
call_user_func()
call_user_func_array()
create_function
array_map()

系统命令执行相关
system()
passthru()
exec()
pcntl_exec()
shell_exec()
popen()
proc_open()
`(反单引号)
ob_start()

特殊函数
phpinfo()
#这个文件里面包含了PHP的编译选项,启动的扩展、版本、服务器配置信息、环境变量、操作系统信息、path变量等非常重要的敏感配置信息
symlink():
#一般是在linux服务器上使用的,为一个目标建立一个连接,在读取这个链接所连接的文件的内容,并返回内容
getenv
#获取一个环境变量的值
putenv($a)
#添加$a到服务器环境变量,但环境变量仅存活于当前请求期间。 在请求结束时环境会恢复到初始状态

危险函数:

system

system — 执行外部程序,并且显示输出

该函数会把执行结果输出
并把输出结果的最后一行作为字符串返回
如果执行失败则返回false
这个也最为常用

语法

system(string $command, int &$result_code = null): string|false
同 C 版本的 system() 函数一样,本函数执行 command 参数所指定的命令,并且输出执行结果。
如果 PHP 运行在服务器模块中,system() 函数还会尝试在每行输出完毕之后,自动刷新 web 服务器的输出缓存。
如果要获取一个命令未经任何处理的原始输出,请使用 passthru() 函数。

参数

command
要执行的命令。

result_code
如果提供 result_code 参数,则外部命令执行后的返回状态将会被设置到此变量中

返回值

成功则返回命令输出的最后一行,失败则返回 false

例子

<?php
echo '<pre>';

// 输出 shell 命令 "ls" 的返回结果
// 并且将输出的最后一样内容返回到 $last_line。
// 将命令的返回值保存到 $retval。
$last_line = system('ls', $retval);

// 打印更多信息
echo '
</pre>
<hr />Last line of the output: ' . $last_line . '
<hr />Return value: ' . $retval;
?>

exec

exec — 执行一个外部程序

不输出结果
返回执行结果的最后一行
可以使用output进行输出

语法

exec(string $command, array &$output = null, int &$result_code = null): string|false
//exec() 执行 command 参数所指定的命令。    

参数

command
要执行的命令。

output
如果提供了 output 参数, 那么会用命令执行的输出填充此数组, 每行输出填充数组中的一个元素。 数组中的数据不包含行尾的空白字符,例如 \n 字符。 请注意,如果数组中已经包含了部分元素,exec() 函数会在数组末尾追加内容。如果你不想在数组末尾进行追加, 请在传入 exec() 函数之前 对数组使用 unset() 函数进行重置。

result_code
如果同时提供 output 和 result_code 参数,命令执行后的返回状态会被写入到此变量。

返回值

命令执行结果的最后一行内容。 如果你需要获取未经处理的全部输出数据, 请使用 passthru() 函数。

失败时返回 false。

如果想要获取命令的输出内容, 请确保使用 output 参数。

例子

<?php
// 输出运行中的 php/httpd 进程的创建者用户名
// (在可以执行 "whoami" 命令的系统上)
$output=null;
$retval=null;
exec('whoami', $output, $retval);
echo "Returned with status $retval and output:\n";
print_r($output);
?>
    
输出:
Returned with status 0 and output:
Array
(
    [0] => cmb
)

passthru

passthru — 执行外部程序并且显示原始输出

此函数只调用命令
并把运行结果原样地直接输出
没有返回值。

语法

passthru(string $command, int &$result_code = null): ?bool

exec() 函数类似, passthru() 函数 也是用来执行外部命令(command)的。 当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec()system() 函数。 常用来执行诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置 Content-type 为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚本中直接输出图像到浏览器。

参数

command
要执行的命令。

result_code
如果提供 result_code 参数, Unix 命令的返回状态会被记录到此参数

返回值

成功时返回 null, 或者在失败时返回 false。

例子

<?php
highlight_file(__FILE__);
passthru('ls');
?>

shell_exec

shell_exec — 通过 shell 执行命令并将完整的输出以字符串的方式返回

不输出结果,返回执行结果
使用反引号(``)时调用的就是此函数

语法

shell_exec(string $command): string|false|null

参数

command
要执行的命令。

返回值

string 包含已执行命令的输出,如果无法建立管道,则为 false,如果发生错误或者命令不产生输出则为 null

注意:当进程执行过程中发生错误,或者进程不产生输出的情况下,都会返回 null。使用本函数无法检测执行是否成功。当需要访问程序退出代码时,应使用 exec()。

例子

<?php
$output = shell_exec('ls -lart');
echo "<pre>$output</pre>";
?>

命令连接符

windows系统

“|”:直接执行后面的语句
例如:ping www.baidu.com|whoami

img

“||”:如果前面执行的语句执行出错,则执行后面的语句
例如:png www.baidu.com||whoami

img

“&”:如果前面的语句为假则直接执行后面的语句,前面的语句可真可假
例如:png www.baidu.com&whoami或者ping www.baidu.com&whoami

image-20221201002944212

“&&”:如果前面的语句为真先执行第一个命令后执行第二个命令;为假则直接出错,也不执行后面的语句
例如:ping www.baidu.com&&whoami png www.baidu.com&&whoami

image-20221201003001512

Linux系统

“;”执行完前面的命令执行后面的

image-20221201003033493

“|”:显示后面语句的执行结果

image-20221201003055218

“||”:当前面的语句执行出错时,执行后面的语句

image-20221201003110978

“&”:如果前面的语句为假,则直接指向后面的语句,前面的语句可真可假

image-20221201003140444

“&&”:如果前面的语句为假则直接出错,也不执行后面的语句

image-20221201003158699

常用命令

Windows

netstat -ano:查看所有进程
(1)netstat –ano|findstr [指定端口号]:该命令查看哪个程序或进程占用了端口

tasklist:列出所有任务及进程号
(1)tasklist|findstr [进程名称]:找到进程名称对应的详细信息,例如PID

taskkill:杀进程
(1)强制结束进程,按名称:taskkill /f /im notepad.exe(关闭记事本)
(2)强制结束进程,按 PID:taskkill /f /pid 1234(关闭 PID 为 1234 的进程)

--help或/?:查看帮助信息

cd:切换目录

D::跳转到其他硬盘

ping:测试IP

ipconfig:查看网络详情,类似于linux的ifconfig

dir:显示目录中的文件内容,类似于linux的ls

type:查看文件,类似于linux的cat、less、more;用法:type 文件名

md:创建文件夹,类似于linux的mkdir;用法:md 目录名

tree:查看目录结构

tracert:路由跟踪,确定IP数据包访问目标时所选择的路径;用法:tracert 域名或IP

copy:复制文本文件;用法:copy 文件1 文件2
注:
参数/b指定以二进制格式复制、合并文件,用于图像类/声音类文件
参数/a指定以ASCII格式复制、合并文件,用于txt等文档类文件
图片马制作:copy x.jpg/b + x.php/a xx.jpg

net start 服务名;net stop 服务名

cls:清空cmd命令行,类似于linux的clear

ctrl+C:结束或退出cmd正在执行的脚本

find:查找
find /c “所要搜索的文件所包含的字符串” 文件的绝对路径

for:对一个或一组文件,字符串或命令结果中的每一个对象执行特定命令
(1)找出C盘下的所有文件,并将所有文件名都输出出来
for /r C: %i in (*) do @echo %i
(2)找出C盘下所有后缀是.txt的文件,并将其输出
for /r C: %i in (*.txt) do @echo %i
(3)找出C盘下所有后缀是.txt和.jpg的文件,并将其输出
for /r C: %i in (*.txt,*.jpg) do @echo %i

Linux

cd:切换当前工作目录;用法:cd后面加目录
(1)cd /root:进入/root 目录
(2)cd …/:返回上一级目录
(3)cd ./:进入当前目录

ls:显示指定工作目录下的内容;用法:ls 文件或目录
(1)ls:./ 查看当前目录所有的文件和目录
(2)ls -l:以长格式显示目录下的内容列表
(3)ls -a:查看所有的文件,包括隐藏文件,以.开头的文件

cp:拷贝文件;用法:cp 要复制的文件 目标路径
(1)cp xx.txt /home/backup.txt ,拷贝文件至/home目录下并且重命名为bak.txt
(2) cp xx –r /home:拷贝xx目录到/home目录下

cat:查看文件内容;用法:cat 文件绝对路径
(1)cat test.txt:查看test.txt文件内容

echo:回显;用法:输入什么就打印什么
(1)echo hello

>:表示追加覆盖;常见用法echo world > test.txt

>>:表示追加;常见用法echo world >> test.txt

find:查找指定文件;用法:find 目录 -name 文件
(1)find /home -name “*.txt” :查找/home目录下,所有以.txt 结尾的文件或者目录。

groupadd:创建组;用法:groupadd 组名;注:在/etc/group中查看组名;注:将某用户加入root用户组:usermod –g root 用户名

groupdel:删除组;用法:groupdel 组名

grep:用于查找文件里符合条件的字符串;用法:grep 参数 目标
-r:指定要查找目标的是目录而非文件时使用
-n:显示具体行数
–include:指定后缀文件
(1)grep -rn “eval“ target:搜索target目标(目录/文件)中是否含有eval的文件,并且确定在所含有的文件中是第几行
(2)grep -rn --include=‘*.php’ ‘eval(’ target:搜索target目标(目录/文件)中是否含有eval的文件(注:这里是指定只搜索.php后缀的文件),并
且确定在所含有的文件中是第几行

head:默认查看文件前10行内容;用法:head 文件名;如果查看前20行,用法:head -20 文件名

tail:默认查看文件后10行内容;用法:tail 文件名,如果查看后20行,用法:tail -20 文件名

more或less:分页查看文件内容;用法:more 文件名或less 文件名
注:cat 和 more 同时使用例如: cat test.txt |more 分页显示 text 内容,|符号是管道符,用于把|前的输出作为后面命令的输入

useradd:创建用户;用法:useradd 用户名,注:在/etc/passwd中可查看
(1)将用户添加到指定组中: useradd -g 组名 用户

userdel:删除用户;用法:userdel 用户名

passwd: 设置密码;passwd 用户名,不加用户名默认修改当前用户

vi:修改文件(命令行模式、文本输入模式、末行模式),vi或vim打开一个文件,首先是命令行模式,然后按 i 进入文本输入模式,可以
在文件里写入字符等信息。写完后,按 esc 进入命令模式,然后输入:进入末行模式,例如输入 :wq 表示保存退出。如果想直接退出,不
保存,可以执行 :q , 如果无法退出可以使用 q! 强制退出。

id:显示用户的ID,以及所属群组的ID

ifconfig:显示网络详情

netstat:显示网络状态
netstat –anplt:查看所有tcp端口
netstat –anplu:查看所有udp端口

kill:删除执行中的程序或工作
kill -9:强制执行

ping:检测主机;用法:ping ip

ps:显示当前进程的状态,类似于 windows 的任务管理器

reboot:重启;用法:reboot -f(强制重启)

su:切换用户;用法:su 用户名

sudo:使用root用户执行命令;用法:sudo 命令

uname:显示系统信息;用法:uname –a(显示系统详细信息)

whoami:显示自身用户名称

--help:命令使用详情查询;用法:命令 –help

clear:清空命令行

pwd:显示当前所在的目录

mkdir:创建目录;用法:mkdir 目录名

rmdir:删除空目录,非空不可删除;用法:rmdir 空目录名称

rm:删除文件或者目录,用法:rm –rf 文件名或目录 (-r 表示递归,-f 表示强制)

touch:创建文件;用法:touch 文件名,如果文件存在,则修改当前文件时间,文件内容不变

mv:重命名或者移动文件/目录;用法: mv 原文件名 新文件名 或 mv 原文件位置 新文件位置

chmod:修改文件或目录的权限
chmod u+x 目录/文件:给该目录/文件所有者赋予执行权限
chmod ug-x 目录/文件:给该目录/文件所有者和组用户减去执行权限
chmod 777 目录/文件:给该目录/文件所有者、组用户、其他用户赋予所有权限
chmod 764 目录/文件:给该目录/文件所有者赋予全部权限,组用户赋予读写权限,其他用户赋予读权限

scp:复制文件和目录
(1)从本地复制到远程
scp local_file remote_username@remote_ip:remote_folder
或者
scp local_file remote_username@remote_ip:remote_file
(2)从远程复制到本地
scp remote_username@remote_ip:remote_folder local_file
或者
scp remote_username@remote_ip:remote_file local_file

部分文章内容和图片应用自:

https://blog.csdn.net/weixin_44604541/article/details/109558036

https://blog.csdn.net/LYJ20010728/article/details/117349106

https://blog.csdn.net/qq_41617034/article/details/115583211
感谢这几位师傅了

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值