Intro
Finally had the time to do some wargames again, but I have come to the point where I need to build my own test enviroment to test certain ideas, because I can't test it online. The current challenge is some form of SQL Injection in perl, abusing the quoted(param())
call.
The perl code online:
if ('POST' eq request_method && param('username') && param('password')){ my $dbh = DBI->connect( "DBI:mysql:natas30","natas30", "<censored>", {'RaiseError' => 1}); my $query="Select * FROM users where username =".$dbh->quote(param('username')) . " and password =".$dbh->quote(param('password')); my $sth = $dbh->prepare($query); $sth->execute(); my $ver = $sth->fetch(); if ($ver){ print "win!<br>"; print "here is your result:<br>"; print @$ver; } else{ print "fail :("; } $sth->finish(); $dbh->disconnect(); }
Perl localhost test enviroment
I have tried to create the important features of the webpage, namely that you can post the username
and password
, compare it to a database entry and give back the result. I have used the HTTP::Server::Simple::CGI
as I think it would be the way of keeping things simple.
My recreated perl webpage
use strict;
use warnings;
{
package Natas30Clone;
use DBI;
use HTTP::Server::Simple::CGI;
our @ISA = qw(HTTP::Server::Simple::CGI);
my %dispatch = (
'/login.pl' => \&resp_index,
);
sub handle_request {
my $self = shift;
my $cgi = shift;
my $path = $cgi->path_info();
my $handler = $dispatch{$path};
if (ref($handler) eq "CODE") {
print "HTTP/1.0 200 OK\r\n";
$handler->($cgi);
} else {
print "HTTP/1.0 404 Not found\r\n";
print $cgi->header,
$cgi->start_html('Nothing here'),
$cgi->h1('Move along sir'),
$cgi->h2('You can got to localhost:8080/index.pl?username=user&password=pass'),
$cgi->start_form(
-method=>'POST',
-action=>'/login.pl',
),
$cgi->p('Username'),
$cgi->textfield(
-name=>'username',
),
$cgi->p('Password'),
$cgi->textfield(
-name=>'password',
-type=>'password',
),
$cgi->submit(
-name=>'submit',
-value=>'login',
),
$cgi->end_form;
}
}
sub resp_index {
my $cgi = shift;
return if !ref $cgi;
my $dbh = DBI->connect( "DBI:mysql:natas30","root", "toor", {'RaiseError' => 1});
my $username = $cgi->param('username');
my $quoted_username = $dbh->quote($username);
my $password = $cgi->param('password');
my $quoted_password = $dbh->quote($password);
my $query="Select * FROM users where username =" . $quoted_username . " and password =" . $quoted_password;
my $sth = $dbh->prepare($query);
$sth->execute();
my $ver = $sth->fetch();
if ($ver){
print $cgi->header,
$cgi->start_html("WIN!"),
$cgi->h1(@$ver),
$cgi->h2("You succeeded with query " . $query),
$cgi->h2("Suplied parameters U:" . $username . " P:" . $password),
$cgi->h2("Quoted parameters U:" . $quoted_username . " P:" . $quoted_password),
$cgi->end_html;
} else {
print $cgi->header,
$cgi->start_html("FAIL!"),
$cgi->h2("You failed with query " . $query),
$cgi->h2("Suplied parameters U:" . $username . " P:" . $password),
$cgi->h2("Quoted parameters U:" . $quoted_username . " P:" . $quoted_password),
$cgi->end_html;
}
$sth->finish();
$dbh->disconnect();
}
}
my $pid = Natas30Clone->new(8080)->background();
print "Use 'kill $pid' to stop server.\n";
MySQL database schema
The MySQL is just a single database natas30
with a table users
that looks like this:
+---------+----------+
| user | password |
+---------+----------+
| natas30 | natas30 |
+---------+----------+
Python program to test ideas
Below is a little python program I used to test if everything went well:
import requests
session = requests.Session()
def natas30(url):
params={"username": "natas30", "password": "natas30"}
response = session.post(url, data=params)
print(response.text)
if __name__ == '__main__':
url = 'http://localhost:8080/login.pl'
natas30(url)
Which gives me the output I expected:
<!DOCTYPE html
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en-US" xml:lang="en-US">
<head>
<title>WIN!</title>
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
</head>
<body>
<h1>natas30 natas30</h1>
<h2>You succeeded with query Select * FROM users where username ='natas30' and password ='natas30'</h2>
<h2>Suplied parameters U:natas30 P:natas30</h2>
<h2>Quoted parameters U:'natas30' P:'natas30'</h2>
</body>
</html>
Questions
- Is this the correct way of setting up localhost servers? I am still new with Perl, but this seemed a module I could use.
- Any general tips and tricks I've missed regarding the perl code?
As always any review is welcome!
print x
instead ofcgi->x
? \$\endgroup\$cgi_this
on your local machine and don't have to worry about any implementation of the server at all. \$\endgroup\$