dlenski / openconnect

OpenConnect client extended to support Palo Alto Networks' GlobalProtect VPN
679 stars 130 forks source link

Authentication failure #78

Closed errorsmith1010000 closed 6 years ago

errorsmith1010000 commented 6 years ago

Hi - I'm encountering problems when trying to setup a VPN connection. Any help is highly appreciated

  1. I ran openconnect-gp as follows: ./openconnect --protocol=gp -vvv --dump-http-traffic --timestamp --user=USERNAME server.company.com

  2. I cannot authenticcate against the remote server. I validated my credentials multiple times and I confirmed them working with the Windows (GUI) client provided by PAN.

Operating system and openconnect-gp version

openconnect-gp version: OpenConnect version v7.08-252-g9891d2dc Using GnuTLS. Features present: PKCS#11, HOTP software token, TOTP software token, System keys, DTLS, ESP Supported protocols: anyconnect (default), nc, gp

operating system Linux phenom2 4.10.0-35-generic #39-Ubuntu SMP Wed Sep 13 07:46:59 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux

GlobalProtect VPN information

user@phenom2:~/compile/openconnect$ ./openconnect --protocol=gp -vvv --dump-http-traffic --timestamp --user=USERNAME server.company.com
Please enter your username and password
Password: 
[2018-01-10 10:37:59] POST https://server.company.com/ssl-vpn/login.esp
[2018-01-10 10:37:59] Attempting to connect to server XX.XX.XX.XX:443
[2018-01-10 10:37:59] Connected to XX.XX.XX.XX:443
[2018-01-10 10:37:59] SSL negotiation with server.company.com
[2018-01-10 10:37:59] Connected to HTTPS on server.company.com
[2018-01-10 10:37:59] > POST /ssl-vpn/login.esp HTTP/1.1
[2018-01-10 10:37:59] > Host: server.company.com
[2018-01-10 10:37:59] > User-Agent: PAN GlobalProtect
[2018-01-10 10:37:59] > X-Pad: 000000000000000000000000000000000000000000000000000
[2018-01-10 10:37:59] > Content-Type: application/x-www-form-urlencoded
[2018-01-10 10:37:59] > Content-Length: 141
[2018-01-10 10:37:59] > 
[2018-01-10 10:37:59] > jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:&server=server.company.com&computer=phenom2&user=USERNAME&passwd=PASSWORD
[2018-01-10 10:37:59] Got HTTP response: HTTP/1.1 200 OK
[2018-01-10 10:37:59] Date: Wed, 10 Jan 2018 09:37:59 GMT
[2018-01-10 10:37:59] Content-Type: text/html
[2018-01-10 10:37:59] Content-Length: 128
[2018-01-10 10:37:59] Connection: keep-alive
[2018-01-10 10:37:59] ETag: "aad48-2346-59b56ce6"
[2018-01-10 10:37:59] Pragma: no-cache
[2018-01-10 10:37:59] Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
[2018-01-10 10:37:59] Expires: Thu, 19 Nov 1981 08:52:00 GMT
[2018-01-10 10:37:59] X-FRAME-OPTIONS: DENY
[2018-01-10 10:37:59] Set-Cookie: PHPSESSID=d1f7a6d20757c5ee3569c37d76f90d60; secure; HttpOnly
[2018-01-10 10:37:59] Set-Cookie: PHPSESSID=d1f7a6d20757c5ee3569c37d76f90d60; secure; HttpOnly
[2018-01-10 10:37:59] HTTP body length:  (128)
[2018-01-10 10:37:59] < 
[2018-01-10 10:37:59] < var respStatus = "Error";
[2018-01-10 10:37:59] < var respMsg = "Authentication failure: Invalid username or password";
[2018-01-10 10:37:59] < thisForm.inputStr.value = "";
[2018-01-10 10:37:59] < 
[2018-01-10 10:37:59] Authentication failure: Invalid username or password
Failed to obtain WebVPN cookie
dlenski commented 6 years ago

Hmm.

This is very strange because your VPN is returning "Invalid username or password" with an HTTP status of 200 Success, whereas all the servers I've seen before return 512 Custom in this case. So something is different about your VPN's server software.

dlenski commented 6 years ago

If you look in the log from the official Windows client (PanGPS.log) with logging turned up to the highest level, you may find some information about the login request from the official client.

You can emulate the login request used by openconnect as follows:

curl -v -A 'PAN GlobalProtect' https://SERVERDOMAIN/ssl-vpn/login.esp -d "jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:" \
-d server=SERVERDOMAIN -d computer= $(hostname) -d user=USERNAME -d passwd=PASSWORD

I have never seen a server that requires any parameters besides those in the login request, but the official client sends a few extras which might be required by some server, somewhere. Try adding them and see if you get a successful login?

curl -v -A 'PAN GlobalProtect' https://SERVERDOMAIN/ssl-vpn/login.esp -d "jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:" \
-d "inputStr=&os-version=Microsoft Windows Server 2012, 64-bit&preferred-ip=12.34.56.78&clientos=Windows&clientgpversion=3.0.1-10&portal-userauthcookie=empty&portal-prelogonuserauthcookie=empty&host-id=deadbeef-dead-beef-dead-beefdeadbeef" \
-d server=SERVERDOMAIN -d computer= $(hostname) -d user=USERNAME -d passwd=PASSWORD

The fact that your server isn't returning the same error code as all other GP servers I've seen makes me think that there's some non-standard authentication intermediary running here…

errorsmith1010000 commented 6 years ago

Hi

regards, errorsmith

dlenski commented 6 years ago

V 40.05-8 works for me

I think you mean 4.0.5-8, right? I did my reverse-engineering off of 3.0.1-10. Maybe I need to see if the newer versions of the official client send some different fields in the authentication.

regarding the logs: I'm not sure what I'm searching for. From a first glance I didn't find the request string.

Try searching for ssl-vpn/login.esp (that's the HTTPS path of the login authentication on the server side). Also try searching for username, password, and the strings <jnlp> and 4100. (I'm kind of stabbing in the dark here because something is different in your VPN's auth, so I'm not 100% sure what to look for.)

errorsmith1010000 commented 6 years ago

Hi

Yes, I meant 4.0.5-8 - sorry for this mistake.

I can provide the installer package for this version (via private mail preferrably) or I can run tests in a virtualbox VM (this is where I'm currently testing / confirming that the Windows Version works for me). I will have a closer look at the log files later / tomorrow but from my first impression I would say that either the logfile does not contain the complete login string or the client omits some parts of it.

If I can be of help with "stabbing" just ask ;-)

regards, errorsmith

dlenski commented 6 years ago

Yes, I meant 4.0.5-8 - sorry for this mistake.

I can provide the installer package for this version (via private mail preferrably)

I already tried 4.0.5-8, and what it sends is basically no different from 3.0.1-10 except that it adds additional login/getconfig headers for IPv6 support.

I also checked the detailed log file and it prints the authcookie in plaintext, so here's something to "take a stab at"…

HipReportCheckPostData.txt_output: POST /ssl-vpn/hipreportcheck.esp HTTP/1.1
Accept: */*
Content-Length: 217
Connection: Keep-Alive
Content-Type: application/x-www-form-urlencoded
Host: GATEWAY-ADDRESS

user=USERNAME&domain=DOMAIN&portal=PORTALNAME&authcookie=AUTHCOOKIE&client-ip=...&client-ipv6=&computer=HOSTNAME&md5=...&client-role=global-protect-full

Try this:

  1. Login via the official client with logging turned on
  2. Find the authcookie above in the logs, and extract this part: user=USERNAME&domain=DOMAIN&portal=PORTALNAME&authcookie=AUTHCOOKIE
  3. Without disconnecting from the official client, run:
    openconnect -vvvv --dump --cookie "user=USERNAME&domain=DOMAIN&portal=PORTALNAME&authcookie=AUTHCOOKIE"
    --prot=gp GATEWAY-ADDRESS
  4. OpenConnect should succeed in connecting to the VPN, using the authentication cookie "borrowed" from the official client. (This will abruptly kill the previously-authenticated session on the official client, by the way.)

If that works, then we at least know that your VPN is "speaking the same language" once it gets past the authentication part.

dlenski commented 6 years ago

Yes, I meant 4.0.5-8 - sorry for this mistake.

I'm guessing your VPN uses the new SAML auth support added in GP v4.0. I don't have a VPN I can test this with.

If that's right, you'll need to run mitmproxy to log the authentication protocol and how it works with SAML auth. :-D

errorsmith1010000 commented 6 years ago

I tested the "borrow a cookie" method: This worked! I can connect to the VPN using the "Windows-Cookie" and after that I'm getting a tun interface and can ping internal IP addresses from the company. And: It did NOT kill my Session I had with the Windows client.

So... Does this mean I need to use the SAML auth stuff? If you need me to do that mitmproxy thing: I would be happy to do this but I would need a pointer on how to do / what I need to do so you get exactly what you need...

dlenski commented 6 years ago

I tested the "borrow a cookie" method: This worked! I can connect to the VPN using the "Windows-Cookie" and after that I'm getting a tun interface and can ping internal IP addresses from the company.

Great!

So... Does this mean I need to use the SAML auth stuff? If you need me to do that mitmproxy thing: I would be happy to do this but I would need a pointer on how to do / what I need to do so you get exactly what you need...

mitmproxy is your best bet unless you have another idea about how to capture and log the authentication negotiation.

Briefly…

  1. Install mitmproxy on linuxbox, and generate the root certificates for it.
  2. Install those mitmproxy root certificates on windowsbox.
  3. Run mitmproxy -p 8080 on linuxbox; you may need to add the --insecure flag to mitmproxy if it can't correctly verify the upstream certificates of the GlobalProtect server.
  4. On windowsbox, configure linuxbox:8080 as the HTTP/HTTPS proxy.
  5. Run GlobalProtect on windowsbox, and try to login.
  6. If all goes well, the HTTPS traffic will get sent through mitmproxy, which will capture it, decrypt it, and show you the details of the authentication flow in exquisite detail… while also sending it along to the final destination… and neither the Windows box nor the GlobalProtect server will complain.

That's the theory.

In practice, GlobalProtect has a few tricks up its sleeve for telling the client which certificates it should actually trust (in the /global-protect/getconfig.esp reply)… if you make it to (6.) and GlobalProtect refuses to accept the server certificate, then you'll need to write a little Python shim to intercept the aforementioned reply and lie to windowsbox about which certificates it should trust.

errorsmith1010000 commented 6 years ago

Hi

After a bit of trial and error I managed to set up two VM's for testing, where one is a fresh Win7 and the other an XUbuntu 17 minimal, this is the box with mitmproxy. The Win is configured to use the Linux as proxy and has the certs installed. I confirmed this setup working. I also confirmed the Client working without mitmproxy. It doesn't work with the proxy though, it complains about an invalid certificate. D'oh

What I found out now is that the first query string differs a bit from what openconnect currently uses: https://vpn.company.tld/global-protect/prelogin.esp?kerberos-support=yes&tmp=tmp&clientVer=4100&host-id=dead-beef-dead-beef-dead&clientos=Windows&os-version=Microsoft+Windows+7+Professional+Service+Pack+1%2c+64-bit&ipv6-support=yes

So it looks like I would need to write some python... :-( Can you help me here? I never wrote python code, so I'm a bit at a loss here.

dlenski commented 6 years ago

What I found out now is that the first query string differs a bit from what openconnect currently uses: https://vpn.company.tld/global-protect/prelogin.esp?kerberos-support=yes&tmp=tmp&clientVer=4100&host-id=dead-beef-dead-beef-dead&clientos=Windows&os-version=Microsoft+Windows+7+Professional+Service+Pack+1%2c+64-bit&ipv6-support=yes

Yeah, this is a good point. Every GlobalProtect client sends this request first before the actual login; I've just ignored it in openconnect, because it never gives any useful information. However, maybe on your VPN it will give information about the SAML login process. Is the response like this, or something more interesting?

<?xml version="1.0" encoding="UTF-8" ?>
<prelogin-response>
<status>Success</status>
<ccusername></ccusername>
<autosubmit>false</autosubmit>
<msg></msg>
<authentication-message>Enter login credentials</authentication-message>
<panos-version>1</panos-version><region>US</region>
</prelogin-response>

It doesn't work with the proxy though, it complains about an invalid certificate. D'oh

Well… you've just got to peel back the layers one at a time until you figure out how the authentication works. Go through the request and response flows. What can you glean out about how your client authenticates to the VPN? Are we on the right track with the suspicion that it uses SAML?

After the prelogin.esp response, the next request is probably the "portal config" (/global-protect/getconfig.esp). Use this Python script as a starting point to poke and play with that request.

$ ./test-globalprotect-login.py https://$SERVER/global-protect/getconfig.esp -u $USERNAME -p $PASSWORD > /tmp/gpconfig.xml

Here is a cleaned-up template of the portal config XML from my VPN. Yours probably differs; hopefully it contains more clues about the authentication process. I've highlighted some of the interesting parts: the list of gateways, the list of certificates to trust, and a flag that controls whether or not the client should accept other certificates.

If/when you need to get past the /global-protect/getconfig.esp request, you'll need to read up on mitmproxy replacements and figure out how to fake out the client by telling it to trust the mitmproxy cert.

errorsmith1010000 commented 6 years ago

Is the response like this, or something more interesting? [snipped] No, its exactly the same, the only difference is that I'm using a different region.

Here is the cleaned up response from "my" VPN. No direct hint on SAML though.

<?xml version='1.0' encoding='UTF-8'?>
<policy>
  <portal-name>GP-Portal</portal-name>
  <portal-config-version>4100</portal-config-version>
  <version>4.0.5-8                                                         </version>
  <client-role>global-protect-full</client-role>
  <agent-user-override-key>****</agent-user-override-key>
  <client-cert>
    <passphrase>REDACTED</passphrase>
    <pem>
----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,8CCFA203AFDD4B9F
-----END RSA PRIVATE KEY-----
??</pem>
    <pkcs12>
??</pkcs12>
  </client-cert>
  <connect-method>user-logon</connect-method>
  <on-demand>no</on-demand>
  <refresh-config>yes</refresh-config>
  <refresh-config-interval>24</refresh-config-interval>
  <authentication-modifier>
    <none/>
  </authentication-modifier>
  <authentication-override>
    <accept-cookie>no</accept-cookie>
    <generate-cookie>no</generate-cookie>
    <cookie-encrypt-decrypt-cert/>
  </authentication-override>
  <use-sso>yes</use-sso>
  <ip-address/>
  <host/>
  <gateways>
    <cutoff-time>5</cutoff-time>
    <external>
      <list>
        <entry name="vpn.company.tld">
          <priority-rule>
            <entry name="Any">
              <priority>1</priority>
            </entry>
          </priority-rule>
          <priority>1</priority>
          <description>VPN</description>
        </entry>
      </list>
    </external>
  </gateways>
  <gateways-v6>
    <cutoff-time>5</cutoff-time>
    <external>
      <list>
        <entry name="VPN">
          <fqdn>vpn.company.tld</fqdn>
          <priority-rule>
            <entry name="Any">
              <priority>1</priority>
            </entry>
          </priority-rule>
          <priority>1</priority>
        </entry>
      </list>
    </external>
  </gateways-v6>
  <agent-ui>
    <can-save-password>yes</can-save-password>
    <passcode/>
    <agent-user-override-timeout>0</agent-user-override-timeout>
    <max-agent-user-overrides>0</max-agent-user-overrides>
    <help-page/>
    <welcome-page>
      <display>no</display>
      <page/>
    </welcome-page>
    <agent-user-override>allowed</agent-user-override>
    <enable-advanced-view>yes</enable-advanced-view>
    <enable-do-not-display-this-welcome-page-again>yes</enable-do-not-display-this-welcome-page-again>
    <can-change-portal>yes</can-change-portal>
    <show-agent-icon>yes</show-agent-icon>
    <password-expiry-message/>
  </agent-ui>
  <hip-collection>
    <hip-report-interval>3600</hip-report-interval>
    <max-wait-time>20</max-wait-time>
    <collect-hip-data>yes</collect-hip-data>
    <default>
      <category>
        <member>host-info</member>
        <member>data-loss-prevention</member>
        <member>patch-management</member>
        <member>firewall</member>
        <member>antivirus</member>
        <member>anti-spyware</member>
        <member>disk-backup</member>
        <member>disk-encryption</member>
      </category>
    </default>
  </hip-collection>
 <agent-config>
    <save-user-credentials>1</save-user-credentials>
    <portal-2fa>no</portal-2fa>
    <internal-gateway-2fa>no</internal-gateway-2fa>
    <auto-discovery-external-gateway-2fa>no</auto-discovery-external-gateway-2fa>
    <manual-only-gateway-2fa>no</manual-only-gateway-2fa>
    <client-upgrade>transparent</client-upgrade>
    <logout-remove-sso>yes</logout-remove-sso>
    <krb-auth-fail-fallback>yes</krb-auth-fail-fallback>
    <retry-tunnel>30</retry-tunnel>
    <retry-timeout>5</retry-timeout>
    <enforce-globalprotect>no</enforce-globalprotect>
    <captive-portal-exception-timeout>0</captive-portal-exception-timeout>
    <traffic-blocking-notification-delay>15</traffic-blocking-notification-delay>
    <display-traffic-blocking-notification-msg>yes</display-traffic-blocking-notification-msg>
    <traffic-blocking-notification-msg>&lt;div style="font-family:'Helvetica Neue';"&gt;&lt;h1 style="color:red;text-align:center; margin: 0; font-size: 30px;"&gt;Notice&lt;/h1&gt;&lt;p style="margin: 0;font-size: 15px; line-height: 1.2em;"&gt;To access the network, you must first connect to GlobalProtect.&lt;/p&gt;&lt;/div&gt;</traffic-blocking-notification-msg>
    <allow-traffic-blocking-notification-dismissal>yes</allow-traffic-blocking-notification-dismissal>
    <display-captive-portal-detection-msg>no</display-captive-portal-detection-msg>
    <captive-portal-detection-msg>&lt;div style="font-family:'Helvetica Neue';"&gt;&lt;h1 style="color:red;text-align:center; margin: 0; font-size: 30px;"&gt;Captive Portal Detected&lt;/h1&gt;&lt;p style="margin: 0; font-size: 15px; line-height:1.2em;"&gt;GlobalProtect has temporarily permitted network access for you to connect to the Internet. Follow instructions from your internet provider.&lt;/p&gt;&lt;p style="margin: 0; font-size: 15px; line-height: 1.2em;"&gt;If you let the connection time out, open GlobalProtect and click Connect to try again.&lt;/p&gt;&lt;/div&gt;</captive-portal-detection-msg>
    <certificate-store-lookup>user-and-machine</certificate-store-lookup>
    <scep-certificate-renewal-period>7</scep-certificate-renewal-period>
    <ext-key-usage-oid-for-client-cert/>
    <retain-connection-smartcard-removal>yes</retain-connection-smartcard-removal>
    <rediscover-network>yes</rediscover-network>
    <resubmit-host-info>yes</resubmit-host-info>
    <can-continue-if-portal-cert-invalid>yes</can-continue-if-portal-cert-invalid>
    <user-switch-tunnel-rename-timeout>60</user-switch-tunnel-rename-timeout>
    <pre-logon-tunnel-rename-timeout>-1</pre-logon-tunnel-rename-timeout>
    <show-system-tray-notifications>no</show-system-tray-notifications>
    <max-internal-gateway-connection-attempts>0</max-internal-gateway-connection-attempts>
    <portal-timeout>30</portal-timeout>
    <connect-timeout>60</connect-timeout>
    <receive-timeout>30</receive-timeout>
    <enforce-dns>yes</enforce-dns>
    <flush-dns>no</flush-dns>
    <proxy-multiple-autodetect>no</proxy-multiple-autodetect>
    <wsc-autodetect>yes</wsc-autodetect>
    <mfa-enabled>no</mfa-enabled>
    <mfa-listening-port>4501</mfa-listening-port>
    <mfa-trusted-host-list/>
    <mfa-notification-msg>You have attempted to access a protected resource that requires additional authentication. Proceed to authenticate at</mfa-notification-msg>
    <ipv6-preferred>no</ipv6-preferred>
  </agent-config>
  <user-email>mailname@company.tld</user-email>
  <portal-userauthcookie>empty</portal-userauthcookie>
  <portal-prelogonuserauthcookie>empty</portal-prelogonuserauthcookie>
  <scep-cert-auth-cookie>REDACTED GIBBERISH</scep-cert-auth-cookie>
</policy>

What I find interesting: The flag for the cert verification is set to "accept invalid certs" for me. The client doesn't accept the mitm cert nonetheless, so I think our best bet will be injecting the mitm cert. I'll start reading on how to do this now... Thanks for getting so far, I'll report back if I find something or when I'm stuck

dlenski commented 6 years ago

Wait a sec. You told me right up top that you do not use a client cert to connect, but the portal config is very clearly calling one out.

You should pull out this whole thing, slap it in a cert.pem file, and try connecting with openconnect -c cert.pem.

----BEGIN CERTIFICATE-----
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: DES-EDE3-CBC,8CCFA203AFDD4B9F
-----END RSA PRIVATE KEY-----
errorsmith1010000 commented 6 years ago

I was not provided with a cert nor told to use one. Where does this come from?

Sorry if I did not give the correct information, I did as to my best knowledge... The last time I had to use a client cert, I received it from the firewall guys (I'm system engineer with limited access to the firewalls) and had to provide it to the client before authenticating.

(will try providing the client cert in the afternoon today)

Update: Using the client certificate and the passphrase I can connect, authenticate to the VPN and ping internal addresses. I can't connect via SSH or RDP though. I'm not sure if this is a problem with openconnect or something else.

dlenski commented 6 years ago

I was not provided with a cert nor told to use one. Where does this come from?

It appears that this "client cert" is not actually stored on the client… but only on the portal… so the client is supposed to connect to the portal, obtain the "client cert" from the portal, and use it to authenticate to the gateway. ¯\_(ツ)_/¯

I had no idea that GP allowed such a bizarre configuration. It's total security theater, providing zero benefit over just accepting a username and password.

Using the client certificate and the passphrase I can connect, authenticate to the VPN and ping internal addresses. I can't connect via SSH or RDP though. I'm not sure if this is a problem with openconnect or something else.

HIP report needed, maybe? I won't be surprised if your VPN has a few more ekstra speshul securiteh features.

errorsmith1010000 commented 6 years ago

The funny thing about that is that the client cert is transmitted in the very same response as the passphrase needed to decrypt it. I have no idea what this should provide or whatever.

Regarding HIP: According to the response from the portal, there is no HIP report needed. We have a very mixed environment, so it wouldn't make sense to force HIP. I will investigate this further - I cannot exclude my own environment here as I'm running a pretty locked down firewall-router between my environment and "the internet". Can I provide more information to help here?

And: Of course for my special case I can extract the cert and all but a more convenient solution would be nice... Does openconnect support any parameters or so to use it without setting up a two-box environment for extracting the certificate?

dlenski commented 6 years ago

Regarding HIP: According to the response from the portal, there is no HIP report needed. We have a very mixed environment, so it wouldn't make sense to force HIP.

HIP is just another layer of security theater. Many GP VPNs demand it, and then don't appear to do anything with the response other than check that it's valid XML containing the right sections and client identifiers. It might as well be called "echo check."

Your portal log shows the following, and the actual openconnect log will also a request to /ssl-vpn/hipreportcheck.esp, with a response that indicates whether or not the portal wants a HIP report submitted.

  <hip-collection>
    <hip-report-interval>3600</hip-report-interval>
    <max-wait-time>20</max-wait-time>
    <collect-hip-data>yes</collect-hip-data>
    <default>
      <category>
        <member>host-info</member>
        <member>data-loss-prevention</member>
        <member>patch-management</member>
        <member>firewall</member>
        <member>antivirus</member>
        <member>anti-spyware</member>
        <member>disk-backup</member>
        <member>disk-encryption</member>
      </category>
    </default>
  </hip-collection>

And: Of course for my special case I can extract the cert and all but a more convenient solution would be nice... Does openconnect support any parameters or so to use it without setting up a two-box environment for extracting the certificate?

Now that we know about this, anyone with a VPN similarly configured to yours should be able to use the test-globalprotect-login.py script to extract their "client cert" from the portal.

There just seem to be too many weird and fiddly things that the GlobalProtect portals can do to monkey with the way that the client is supposed to connect to the gateway. I don't really want to support them all in openconnect itself, and probably can't. Once GP gets past the portal, the protocol for connection to the gateway is (relatively) straightforward and reasonable. ¯\_(ツ)_/¯

errorsmith1010000 commented 6 years ago

Don't get me wrong on this - I'm not asking for nor expecting you to support all kinds of weird VPN configurations. My idea was to use /existing/ flags / options to make more convenient. I'm not sure how to extract cert and password using test-globalprotect-login.py script though as I'm getting only this when executing it:

user@homecomputer:~/compile/openconnect$ ./test-globalprotect-login.py -u USERNAME -p PASSWORD https://vpn.company.tld/global-protect/getconfig.esp 
<?xml version="1.0" encoding="UTF-8" ?>
<policy>
<has-config>no</has-config>
<user-group-loaded>yes</user-group-loaded>
<portal-userauthcookie>empty</portal-userauthcookie>
<portal-prelogonuserauthcookie>empty</portal-prelogonuserauthcookie>
</policy>

The key & pass I used were captured using mitmproxy - without the mitmproxy box I'm not able to get cert & passphrase.

dlenski commented 6 years ago

The key & pass I used were captured using mitmproxy - without the mitmproxy box I'm not able to get cert & passphrase.

Now I'm really confused… You've told me that…

Am I correct?

At this point I would say, "You're mistaken. Your VPN requires a certificate which is stored on your computer and you just somehow overlooked way back in step one. Quit wasting my time :stuck_out_tongue_closed_eyes:."

But… you told me clearly…

Authentication at our system is done against an AD server, nothing special. I do not need any tokens, certs or whatever. In fact I can install the official client on any computer I want to and log on using my credentials.

So… like I said… I'm really confused. :joy:

At this point it's clear that your VPN requires an SSL certificate to authenticate to the portal or the gateway. That's perfectly normal and standard practice. However, the way the client certificate is stored in your setup is insane. My best guess is that the client certificate is embedded in a custom GP installer which is distributed at your site and is not specific to any one user. You should inspect the cert with openssl x509 or certtool or whatever to confirm the properties of this cert.

I think I already mentioned my high suspicion that something is weirdly hacked together or customized in your VPN. It returns HTTP status 200 on invalid login… all the "normal" GP servers return 512:

> POST /ssl-vpn/login.esp HTTP/1.1
> Host: server.wherever.com
> User-Agent: PAN GlobalProtect
> X-Pad: 0000000000000000000000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 149
> 
> jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:&server=wherever.com&computer=localhost&user=nobody&passwd=alsdkfjasdf
Got HTTP response: HTTP/1.1 512 Custom error
Date: Mon, 15 Jan 2018 06:09:38 GMT
Content-Type: text/html
Content-Length: 128
Connection: keep-alive
Pragma: no-cache
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
x-private-pan-sslvpn: auth-failed
Expires: Thu, 19 Nov 1981 08:52:00 GMT
HTTP body length:  (128)
< 
< var respStatus = "Error";
< var respMsg = "Authentication failure: Invalid username or password";
< thisForm.inputStr.value = "";
< 
Unexpected 512 result from server
dlenski commented 6 years ago

@errorsmith1010000, any updates on how the client cert is getting distributed/discovered…?

banderlog commented 4 years ago

I had similar situation. In my case openconnect --os=win VPN_ADDRESS solved my problem after few hours of trying figure out what is wrong. Do not know why, someone messed-up server preferences, probably.

dlenski commented 4 years ago

GlobalProtect servers are a giant mess when it comes to behaving in insane and counter-intuitive ways when presented with values of clientos that they don't expect. Very little can be done to improve the default behavior.

Read these two commit messages for why:

(Locking this issue; please take any further GP OS issues upstream to https://gitlab.com/openconnect/openconnect/)