GlobalProtect: Login fails (invalid session id)
Suddenly, I can no longer perform the GP gateway login with OpenConnect.
% openconnect --version
OpenConnect version v9.12
Using GnuTLS 3.8.1. Features present: PKCS#11, RSA software token, HOTP software token, TOTP software token, Yubikey OATH, System keys, DTLS, ESP
Supported protocols: anyconnect (default), nc, gp, pulse, f5, fortinet, array
Default vpnc-script (override with --script): /usr/local/etc/vpnc/vpnc-script
My portal is using 2FA, therefore I am taking a two step process:
-
openconnect --protocol=gp myportal --user=myuser
which is returning the URL for the authentication process, providing the prelogin cookie echo myprelogincookie | openconnect --passwd-on-stdin --background --protocol=gp --user=myuser --os=win --authgroup=mygatewaylocation --usergroup=portal:prelogin-cookie myportal --csd-wrapper=my_hip_report_script --script=my_vpnc_script
Both prelogin and getconfig requests seem to work correctly, here they are (without the response body, which I think is unnecessary):
POST https://myportal/global-protect/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Windows
Attempting to connect to server 132.132.132.132:443
Connected to 132.132.132.132:443
SSL negotiation with myportal
Connected to HTTPS on myportal with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
> POST /global-protect/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Windows HTTP/1.1
> Host: myportal
> User-Agent: PAN GlobalProtect
>
Got HTTP response: HTTP/1.1 200 OK
Date: Sun, 22 Oct 2023 10:11:06 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 1559
Connection: keep-alive
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Set-Cookie: SESSID=A_SESSION_COOKIE; Path=/; HttpOnly; Secure
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: (1559)
POST https://myportal/global-protect/getconfig.esp
> POST /global-protect/getconfig.esp HTTP/1.1
> Host: myportal
> User-Agent: PAN GlobalProtect
> Cookie: SESSID=A_SESSION_COOKIE
> X-Pad: 0000000000000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 286
>
> jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:&internal=no&ipv6-support=yes&clientos=Windows&os-version=win&server=myportal&computer=MY_HOSTNAME&user=MY_USERNAME&prelogin-cookie=MY_PRELOGIN_COOKIE
Got HTTP response: HTTP/1.1 200 OK
Date: Sun, 22 Oct 2023 10:11:06 GMT
Content-Type: application/xml; charset=UTF-8
Content-Length: 76300
Connection: keep-alive
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Set-Cookie: SESSID=A_DIFFERENT_SESSION_COOKIE; Path=/; HttpOnly; Secure
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: (76300)
First thing I noticed is, the getconfig response from the portal provides a Set-Cookie header which seems to be ignored when performing the gateway login.
POST https://mygateway/ssl-vpn/login.esp
Attempting to connect to server 123.123.123.123:443
Connected to 123.123.123.123:443
SSL negotiation with mygateway
Connected to HTTPS on mygateway with ciphersuite (TLS1.2)-(ECDHE-SECP256R1)-(RSA-SHA256)-(AES-256-GCM)
> POST /ssl-vpn/login.esp HTTP/1.1
> Host: mygateway
> User-Agent: PAN GlobalProtect
> X-Pad: 00000000000000000000000000000000
> Content-Type: application/x-www-form-urlencoded
> Content-Length: 736
>
> jnlpReady=jnlpReady&ok=Login&direct=yes&clientVer=4100&prot=https:&internal=no&ipv6-support=yes&clientos=Windows&os-version=win&server=mygateway&computer=MY_HOSTNAME&portal-userauthcookie=MY_USER_COOKIE&user=MYUSERNAME&prelogin-cookie=MY_PRELOGIN_COOKIE
Got HTTP response: HTTP/1.1 200 OK
Date: Sun, 22 Oct 2023 10:11:07 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
Set-Cookie: SESSID=ANOTHER_SESSION_COOKIE; Path=/; HttpOnly; Secure
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 non-XML server response
Response was: Error: Login fails (invalid session id)
Failed to complete authentication
Moreover, by performing MITM on the original client I noticed that the request flow is a bit different than the one implemented in OpenConnect, namely:
- prelogin request to the Portal, receiving a SESSID cookie in the response
- getconfig request to the portal using the SESSID from the previous response
- prelogin request to the gateway, without SESSID, receiving a different SESSID cookie in the response
- login request to the same gateway, using the SESSID from the previous response
Edited by Federico