dlenski / gp-saml-gui

Interactively authenticate to GlobalProtect VPNs that require SAML
GNU General Public License v3.0
293 stars 66 forks source link

HTTP body length: (0) #77

Open brianmay opened 1 year ago

brianmay commented 1 year ago

Trying to connect to vpn server at unimelb:

WEBKIT_DISABLE_COMPOSITING_MODE=1 gp-saml-gui --allow-insecure-crypto vpn.unimelb.edu.au

Setting WEBKIT_DISABLE_COMPOSITING avoids the bug in #41.

`--allow-insecure-crypto seems to be required for this VPN. Yuck.

This in turn works and asks me to run the following command:

echo <censored> |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=bmay@unimelb.edu.au --os=linux-64 --usergroup=portal:prelogin-cookie --passwd-on-stdin vpn.unimelb.edu.au
POST https://vpn.unimelb.edu.au/global-protect/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Connected to 203.5.68.131:443
SSL negotiation with vpn.unimelb.edu.au
Connected to HTTPS on vpn.unimelb.edu.au with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
Enter login credentials
POST https://vpn.unimelb.edu.au/global-protect/getconfig.esp
Portal set HIP report interval to 60 minutes).
1 gateway servers available:
  staff (staff-vpn-gw.unimelb.edu.au)
Please select GlobalProtect gateway.
GATEWAY: [staff]:staff
POST https://staff-vpn-gw.unimelb.edu.au/ssl-vpn/login.esp
Connected to 203.5.68.133:443
SSL negotiation with staff-vpn-gw.unimelb.edu.au
Connected to HTTPS on staff-vpn-gw.unimelb.edu.au with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
Failed to parse server response
Failed to complete authentication

At this stage I am at a bit of a loss to explain what is going on here.

dlenski commented 1 year ago
SSL negotiation with staff-vpn-gw.unimelb.edu.au
Connected to HTTPS on staff-vpn-gw.unimelb.edu.au with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
Failed to parse server response
Failed to complete authentication

At this stage I am at a bit of a loss to explain what is going on here.

When OpenConnect submits the initial login information to the server (POST /ssl-vpn/login.esp), it receives a reply from that it doesn't understand.

Add openconnect --dump-http-traffic to see the details of the reply.

brianmay commented 1 year ago

Ok, thanks for that tip.

[...]
> POST /ssl-vpn/login.esp HTTP/1.1
> Host: staff-vpn-gw.unimelb.edu.au
> User-Agent: PAN GlobalProtect
> X-Pad: 000000000000000000000000000000000000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 711
>
> jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:&internal=no&ipv6-support=yes&clientos=Linux&os-version=linux-64&server=staff-vpn-gw.unimelb.edu.au&<censored>
Got HTTP response: HTTP/1.1 200 OK
Date: Wed, 06 Sep 2023 01:36:20 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 69
Connection: keep-alive
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (69)
< <html>
<   <body>Error: Login fails (invalid session id)</body>
< </html>
Failed to parse server response
Response was: <html>
  <body>Error: Login fails (invalid session id)</body>
</html>
Failed to complete authentication

Seems to be complaining about the session id. But as far as I can tell, we don't appear to be passing any session id.

dlenski commented 1 year ago
Failed to parse server response
Response was: <html>
  <body>Error: Login fails (invalid session id)</body>
</html>
Failed to complete authentication

Seems to be complaining about the session id. But as far as I can tell, we don't appear to be passing any session id.

Unfortunately, GlobalProtect server errors are often similarly inscrutable, and don't give any useful information about what submitted information the server is actually objecting to.

Some ideas based on similar past occurrences:

brianmay commented 1 year ago

Hmmm. --usergroup=gateway:prelogin-cookie gave me "GlobalProtect gateway does not exist" and --os=win didn't seem to change anything.

Forgot to say above, this is openconnect v9.01.

dlenski commented 1 year ago

Hmmm. --usergroup=gateway:prelogin-cookie gave me "GlobalProtect gateway does not exist"

Ah, the hostname changes from the portal (vpn.unimelb.edu.au) to the gateway (staff-vpn-gw.unimelb.edu.au) server. So you'll need to change the hostname on the OpenConnect command-line accordingly.

You might also want to try pointing gp-saml-gui directly at the gateway server, and bypassing the portal altogether: WEBKIT_DISABLE_COMPOSITING_MODE=1 gp-saml-gui --allow-insecure-crypto --gateway staff-vpn-gw.unimelb.edu.au

Unfortunately, there are a vast number of ways that GP SAML gets configured, and seemingly a vast variety of ways that the portal+gateway servers "hand off" to each other, and most of them only get tested by their administrators with the official proprietary client software. MITMing the official clients is the only reasonably-surefire way to figure out what gp-saml-gui and/or OpenConnect might be missing in their communication with the server(s).

brianmay commented 1 year ago

I thought I tried that command before, and it failed. But now it seems to work. Thanks!

But gp-saml-gui does give the wrong host name in the openconnect command:

echo <censored> |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=bmay@unimelb.edu.au --os=linux-64 --usergroup=portal:prelogin-cookie --passwd-on-stdin vpn.unimelb.edu.au

I need to change this to:

 echo <censored> |
        sudo openconnect --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=bmay@unimelb.edu.au --os=linux-64 --usergroup=portal:prelogin-cookie --passwd-on-stdin staff-vpn-gw.unimelb.edu.au

Is there anything I can do to the parameters to get this right?

dlenski commented 1 year ago

Glad you have a working solution at the moment. :partying_face:

I thought I tried that command before, and it failed. But now it seems to work. Thanks!

Does it :point_up: = "try pointing gp-saml-gui directly at the gateway server"?

But gp-saml-gui does give the wrong host name in the openconnect command:

If you run with the -v/--verbose option, gp-saml-gui will warn you about these ambiguities: https://github.com/dlenski/gp-saml-gui/blob/258f47cdc4a8ed57a1eef16667f6cad0d1cb49b1/gp_saml_gui.py#L401-L409

Perhaps we should warn about this unconditionally? :grimacing:

Is there anything I can do to the parameters to get this right?

I wish I knew :man_shrugging:.

If I had access to every response from every every SAML-using GP server in the world, I made be able to make more progress on automatically Doing The Right Thing™ in such cases, but in the meantime https://github.com/dlenski/gp-saml-gui/issues/77#issuecomment-1709252689

brianmay commented 1 year ago

The problem in my case, is I had no idea what the following message meant, as it references terms such as "portal interface" and "gateway interface" that don't mean anything to me. My first thought was this was asking me to supply "--gateway" parameter, which I tried. But seems you need to add "--gateway" and change the address.

IMPORTANT: We started with SAML auth to the portal interface, but received a cookie that's often associated with the gateway interface. You should probably try both.

Maybe if it could print that portal interface == vpn.unimelb.edu.au and gateway interface == staff-vpn-gw.unimelb.edu.au, and give suggested instructions on how to change the command lines. But I suspect this might be a bit of guesswork.

My concern now that I have got this working is copying the command and changing it by hand is somewhat a manual process, and it is going to happen that I forget how to do this.

dlenski commented 1 year ago

Maybe if it could print that portal interface == vpn.unimelb.edu.au and gateway interface == staff-vpn-gw.unimelb.edu.au, and give suggested instructions on how to change the command lines. But I suspect this might be a bit of guesswork.

Indeed, a lot of guesswork. gp-saml-gui will inform you about the change in server/URL in certain cases: https://github.com/dlenski/gp-saml-gui/blob/258f47cdc4a8ed57a1eef16667f6cad0d1cb49b1/gp_saml_gui.py#L401-L405

… but as far as I can tell, in your case there is no clear indication that the portal needs to be bypassed. And in fact, the gateway URL can only be obtained after trying the portal connection.

Based on some testing with the official clients, it appears that the official GP software does an excruciatingly large number of backoffs and retries of different authentication options, and that's at least part of how it papers over all of the ambiguities in the SAML auth flow. :man_facepalming:

brianmay commented 10 months ago

Not sure what has changed, but using staff-vpn-gw.unimelb.edu.au no longer works:

echo ... | sudo openconnect -v --protocol=gp '--useragent=PAN GlobalProtect' --allow-insecure-crypto --user=bmay@unimelb.edu.au --os=linux-64 --usergroup=portal:prelogin-cookie --passwd-on-stdin staff-vpn-gw.unimelb.edu.au
POST https://staff-vpn-gw.unimelb.edu.au/global-protect/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Attempting to connect to server 203.5.68.133:443
Connected to 203.5.68.133:443
SSL negotiation with staff-vpn-gw.unimelb.edu.au
Connected to HTTPS on staff-vpn-gw.unimelb.edu.au with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
Got HTTP response: HTTP/1.1 200 OK
Date: Tue, 07 Nov 2023 21:26:42 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 750
Connection: keep-alive
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
X-Frame-Options: DENY
Strict-Transport-Security: max-age=31536000;
X-XSS-Protection: 1; mode=block
X-Content-Type-Options: nosniff
Content-Security-Policy: default-src 'self'; script-src 'self' 'unsafe-inline'; img-src * data:; style-src 'self' 'unsafe-inline';
HTTP body length:  (750)
GlobalProtect portal does not exist
Failed to complete authentication

vpn.unimelb.edu.au doesn't work either.

Huh? I kept trying the same thing over and over (sign of insanity right?), and then I got the "GlobalProtect gateway does not exist" for vpn.unimelb.edu.au, but then staff-vpn-gw.unimelb.edu.au worked. Huh?

I guess this is going to be very intermittent if it works or not.