← Back to Writeups
HTBEasyMisc

Cred Hunter

D3v0o0Nu119/2/20264 min read
#misc#htb#easy#email_parsing#lexicographic_sorting#substring_search

Cred Hunter

Platform: HackTheBox | Category: Misc | Type: Challenge | Difficulty: Easy | OS: NA | Author: D3v0o0Nu11 | Date: 2026-02-01 | Status: Solved Techniques: email_parsing, lexicographic_sorting, substring_search

Summary

Task: Parse mixed emails and passwords, find valid credential pairs where the firstname from the email appears as a substring in the password. Solution: Extract firstname from email local part (all chars except last), check substring match against all passwords, sort pairs lexicographically.

Recon

Port scan

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

Enumeration highlights

  • Event: hackthebox | ID: 20260201_hackthebox_cred_hunter
  • Tags: regex, parsing, string_matching, credential_pairing
  • Indicators: email format parsing, firstname extraction, substring matching, credential pairing
  • Source: 20260201_hackthebox_cred_hunter.md

Foothold

Vulnerability / Misconfiguration

  1. email_parsing
  2. lexicographic_sorting
  3. substring_search
bash
<command>

Exploitation

  • See original writeup content for detailed exploitation.

Privilege Escalation

Enumeration

bash
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.
bash
<command>

Flags

FlagLocationValue
flagREDACTED

Key Takeaways / Lessons

  • email_parsing
  • lexicographic_sorting
  • substring_search
  • Tags: regex, parsing, string_matching, credential_pairing

Original Writeup

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

Challenge Info

FieldValue
EventHackTheBox
CategoryProgramming/Misc
DifficultyEasy
Target94.237.56.175:43741
FlagHTB{REDACTED}

Description

The data leaked quietly - unnoticed, unguarded, and brimming with opportunity. You're in deep now. A tangle of credentials spilled from a forgotten system connected to CygnusCorp's sprawling digital perimeter. Half garbage, half gold. Somewhere in this chaos are access keys - real names, real logins, real passwords. You just have to find the ones that match.

Analysis

This is a web-based coding challenge using Monaco editor interface. The task involves:

  1. Input: N strings containing a mix of emails and passwords
  2. Email Format: CygnusCorp uses firstname + first_letter_of_lastname@domain
    • Example: alicej@cygnus.com (Alice J.)
    • Example: joshr@cygnuscorp.eu (Josh R.)
  3. Valid Pair: An (email, password) pair is valid when the firstname (extracted from email) appears as a substring in the password
  4. Output: All valid pairs sorted lexicographically by email, then by password

Key Insight

The email format firstnameX@domain means:

  • Local part = firstname + first_letter_of_lastname
  • Therefore: firstname = local_part[:-1] (remove last character)

For example:

  • lisabethf@cygnuscloud.com -> firstname = lisabeth
  • nevinn@cygnus.com -> firstname = nevin
  • joicep@cygnusdevs.eu -> firstname = joice

Solution

Algorithm

  1. Parse input - Read N strings
  2. Classify strings - Separate emails from passwords using regex
  3. Extract firstnames - For each email, get local_part[:-1]
  4. Find pairs - For each (email, password) combination, check if firstname is substring of password
  5. Sort and output - Sort pairs lexicographically (email first, then password)

Python Solution

python
import re

def solve():
    n = int(input())
    lines = []
    for _ in range(n):
        lines.append(input().strip())
    
    # Email pattern: firstname + first letter of lastname @ domain
    email_pattern = re.compile(r"^[a-z]+@[a-z0-9.-]+\.[a-z]{2,}$", re.IGNORECASE)
    
    emails = []
    passwords = []
    
    for line in lines:
        if "@" in line and email_pattern.match(line):
            local_part = line.split("@")[0]
            if len(local_part) >= 2:
                firstname = local_part[:-1]  # All except last letter
                emails.append((line, firstname))
        else:
            passwords.append(line)
    
    pairs = []
    for email, firstname in emails:
        for password in passwords:
            if firstname in password:
                pairs.append((email, password))
    
    pairs.sort(key=lambda x: (x[0], x[1]))
    
    for email, password in pairs:
        print(f"{email} {password}")

solve()

Example Walkthrough

Input:

17
lisabethf@cygnuscloud.com
nevin2024!@
nevinn@cygnus.com
...
joicep@cygnusdevs.eu
2025joiceTheDev!@

Processing:

  1. lisabethf@cygnuscloud.com -> firstname = lisabeth
  2. nevinn@cygnus.com -> firstname = nevin
  3. joicep@cygnusdevs.eu -> firstname = joice

Matching:

  • lisabeth found in lisabeth2024 -> valid pair
  • nevin found in nevin2024!@ -> valid pair
  • joice found in 2025joiceTheDev!@ and joiceqwerty2025 -> two valid pairs

Output (sorted):

joicep@cygnusdevs.eu 2025joiceTheDev!@
joicep@cygnusdevs.eu joiceqwerty2025
lisabethf@cygnuscloud.com lisabeth2024
nevinn@cygnus.com nevin2024!@

Complexity Analysis

  • Time: O(N^2 * M) where N = number of strings, M = average string length
    • Separating emails/passwords: O(N)
    • Checking all pairs: O(emails * passwords * avg_length)
  • Space: O(N) for storing emails and passwords

Given constraints (N <= 10^4), the O(N^2) approach is acceptable.

Lessons Learned

  1. Email parsing - Understanding corporate email naming conventions can reveal personal information
  2. Credential correlation - Users often include their name/username in passwords (bad practice!)
  3. Simple solutions work - O(N^2) brute force is often sufficient for CTF constraints
  4. Case sensitivity matters - The matching was case-sensitive (no .lower() needed)
</details>

signed by XESXOR