Skip to content

Instantly share code, notes, and snippets.

@rxwx
Created August 13, 2019 09:04
Show Gist options
  • Star 26 You must be signed in to star a gist
  • Fork 14 You must be signed in to fork a gist
  • Save rxwx/d07495f790d62029b12065c38ac2a86a to your computer and use it in GitHub Desktop.
Save rxwx/d07495f790d62029b12065c38ac2a86a to your computer and use it in GitHub Desktop.
Pulse Secure Version Scanner
import requests
import sys
import re
HEADERS = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0"}
if len(sys.argv) != 2:
print " Usage: python pulseversion.py <target ip/domain>"
sys.exit(1)
r = requests.get("https://%s/dana-na/nc/nc_gina_ver.txt" % sys.argv[1], verify=False, allow_redirects=False)
if r.status_code != 200:
print "[!] Couldn't find target file"
sys.exit(1)
reg = re.compile(r'<PARAM NAME="ProductVersion" VALUE="([\d.]*?)"')
result = reg.search(r.text)
if result:
print "[+] %s, version: %s" % (sys.argv[1], result.group(1))
else:
print "[!] Unable to detect version"
@rxwx
Copy link
Author

rxwx commented Apr 22, 2021

Alternative version:

import requests
import sys
import re

HEADERS = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0"}

if len(sys.argv) != 2:
    print (" Usage: python pulseversion.py <target ip/domain>")
    sys.exit(1)

r = requests.get("https://%s/dana-cached/hc/HostCheckerInstaller.osx" % sys.argv[1], verify=False, allow_redirects=False)

if r.status_code != 200:
    print ("[!] Couldn't find target file")
    sys.exit(1)

reg = re.compile(r'<key>version</key>\n<string>([\d.]*?)</string>')
result = reg.search(r.text)

if result:
    print ("[+] %s, version: %s" % (sys.argv[1], result.group(1)))
else:
    print ("[!] Unable to detect version")

@sei-vsarvepalli
Copy link

Hello @rvwx

A little improvement on your version scanner to detect if Pulse Server at an IP address is likely unpatched to the latest advisories https://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44784/ . Happy to give you credit and put it out for other defenders to use. As always these can give some false/positives.

#!/usr/bin/python3

import requests
import sys
import re
import semver


HEADERS = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:67.0) Gecko/20100101 Firefox/67.0"}

fixed = "9.1.11.12173"

def compare(a,b):
    """ The PCS version numbers do not follow semver convention
    so ignore anything more than 3 levels down for basic comparision
    """
    a = re.sub('[^0-9\.]','',a)
    b = re.sub('[^0-9\.]','',b)    
    fa = a.split(".")
    fb = b.split(".")
    aver = ".".join(fa[0:3])
    bver = ".".join(fb[0:3])
    if semver.compare(aver,bver) > 0:
        return 1
    elif len(fa) > 3:
        av = float("0."+".".join(fa[3:]))
        bv = float("0."+".".join(fb[3:]))
        if av > bv:
            return 1
    return -1
if len(sys.argv) != 2:
    print (" Usage: python pulseversion.py <target ip/domain>")
    sys.exit(1)

r = requests.get("https://%s/dana-cached/hc/HostCheckerInstaller.osx" % sys.argv[1], verify=False, allow_redirects=False)

if r.status_code != 200:
    print ("[!] Couldn't find Host Checker ")
    sys.exit(1)

pattern = re.compile("<key>version</key>[^<]*<string>([^>]+)<")
result = pattern.findall(str(r.content))

if len(result) == 1:
    print ("[+] %s, version: %s" % (sys.argv[1], result[0]))
    if compare(fixed,result[0]) > -1:
        print("Your version: %s is likely vulnerable to VU#213092 and vendor advisory SA44784 vulnerability" %(result[0]))
        print("Please update your PCS immediately learn more at ")
        print("https://kb.pulsesecure.net/articles/Pulse_Security_Advisories/SA44784/")
        print("https://kb.cert.org/vuls/id/213092")
    else:
        print("Your version %s is patched" %(result[0]))
else:
    print ("[!] Unable to detect version")

@RedTeamMagic
Copy link

@sei-vsarvepalli you're the man!

For anyone else who wants to do a quick/simple/dirty manual check

wget https://x.x.x.x/dana-cached/hc/HostCheckerInstaller.osx --no-check-certificate
cat HostCheckerInstaller.osx | grep -a "<key>version</key>" -A 1 

@ihebski
Copy link

ihebski commented Feb 4, 2022

Thanks a lot, awesome work!

  • For a faster check
# Pulse secure version <= R8
curl -k https://IP/dana-na/nc/nc_gina_ver.txt | grep '<PARAM NAME="ProductVersion" VALUE="'

# Pulse secure version > R8 (R9 >>)
curl -k https://IP/dana-cached/hc/HostCheckerInstaller.osx -o version && strings version | grep '<string>'

@S4lt5
Copy link

S4lt5 commented Nov 9, 2022

Very useful, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment