#!/usr/bin/perl
#
# Copyright 2007-2009 Kees Cook <kees@outflux.net>
# License: GPLv3
#
# Try password:   ' OR 1=1; --
# Try password:    <script>alert('Evil can be done here')</script>
# Try password:    <script>alert(document.cookie)</script>
#
package SQL_Bad;
use base 'CGI::Application';
use strict;
use warnings;
use CGI qw/:standard/;
use DBI;

sub setup {
    my $self = shift;
    $self->start_mode('get_password');
    $self->run_modes(
        'get_password' => 'do_get_password',
        'check_password' => 'do_check_password',
    );

    $self->{'dbh'} = DBI->connect("dbi:SQLite:./sql-demo.dbl");
    $self->{'dbh'}->do("PRAGMA synchronous = ON") if ($self->{'dbh'});
}

sub teardown {
    my $self = shift;

    $self->{'dbh'}->disconnect if ($self->{'dbh'});
}

sub do_get_password
{
    my $self = shift;
    my $output = '';
    my $q = $self->query();

    my $cookie = cookie(-name=>'sessionID',
                                    -value=>'zomg-you-caught-my-cookie!',
                                    -expires=>'+1h',
                                    -path=>'/',
                                    -domain=>'research.outflux.net');
    $self->header_add(-cookie=>$cookie);

    my $title = "Enter Password";
    $output .= $q->start_html(-title => $title );
    $output .= $q->h1($title)."\n";
    $output .= $q->start_form();
    $output .= $q->textfield(-name => 'password', -size => 50);
    $output .= $q->hidden(-name => 'rm', -value => 'check_password');
    $output .= $q->submit(-value => 'Get Secret');
    $output .= $q->end_form();
    $output .= $q->end_html();

    return $output;
}

sub do_check_password
{
    my $self = shift;
    my $output = '';
    my $q = $self->query();

    my $password = $q->param("password");

    my $report = $self->{'dbh'}->selectrow_hashref(
        "SELECT secret FROM users
         WHERE password = '$password'");

    my $secret = $report->{'secret'};

    if (defined($secret)) {
        my $title = "Authenticated";
        $output .= $q->start_html(-title => $title );
        $output .= $q->h1($title)."\n";
        $output .= "Your secret is '$secret'!";
    }
    else {
        my $title = "Bad Password";
        $output .= $q->start_html(-title => $title );
        $output .= $q->h1($title)."\n";
        $output .= "Your password '$password' was invalid!";
    }

    $output .= $q->end_html();
    return $output;
}

package main;
use strict;
use warnings;

my $webapp = SQL_Bad->new();
$webapp->run();
