[網鼎杯 2020 玄武組]SSRFMe


[網鼎杯 2020 玄武組]SSRFMe

解題思路

打開直接給源碼,沒什么說的,開審

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

代碼審計

  1. 接受用戶傳入的url,判斷其不為空后經函數處理
  2. check_inner_ip函數判斷其是否為合法內網ip,並使用http或gopher等協議
  3. safe_request_url先用上一個函數判斷,不符合即會開啟curl會話,輸入值

看到curl_exec也比較明確是ssrf了,代碼最后提示要從本地端訪問hint.php文件,那么繞過本地驗證即可,方法也有很多,我這里使用

http://[0:0:0:0:0:ffff:127.0.0.1]//hint.php

來到下一層

<?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']);
}

一看到

file_put_contents($content,"<?php exit();".$content);

就知道考file_put_content死亡代碼

具體總結見此博客,非常詳細,可以學到很多東西

好吧好吧,打臉了打臉了,我本地測試了幾個payload,全都本地打出shell了,遠程打不通,又看到代碼中輸出了redispass is root,那考點就不在這,應該是結合redis

redis主從復制

關於redis的主從復制我專門寫了一個博客,詳見我另一篇,這里只講利用流程了

坑點無數!!!!!!

兩篇需要的github地址

項目1

項目2

首先開linux靶機,redis-rogue-server.py無法運行,坑了好久發現linux靶機的python環境是3.5,此項目需要3.6+.這個項目不需要了,也就是說redis-rogue-server這個項目我們只需要把默認的exp.so放在redis-ssrf-master這個項目下!

我們用到的是

  1. 小號開linux靶機,ssh連接,把這兩個py文件和exp.so傳至同一目錄下

  2. 修改ssrf-redis中的三處

    125行改成linux靶機的ip,command改成想要執行的命令,139行ip因為要繞過之前ssrf的限制使用0.0.0.0,159行password改成之前提示的root

  3. 生成payload,因為還需要在url中傳參,會解碼一次,所以還需要url編碼一次

  4. 在linux服務器上使用rogue建立從節點

  5. 將生成的payload打過去

exp.so被成功執行

舒服了

總結思路

代碼審計->看到curl_exec想到ssrf->打內網->根據提示redisgetshell->生成rogueserver(vps或buu中的linux靶機)->利用gopher協議生成payload或者直接反彈shell

知識點

  • 代碼審計
  • ssrf
  • redis4.x/5.xRCE漏洞


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM