Skip to content

Instantly share code, notes, and snippets.

@p120ph37
Last active December 12, 2023 23:52
Show Gist options
  • Save p120ph37/51f1354837cf7962b10ce1e5066ab14e to your computer and use it in GitHub Desktop.
Save p120ph37/51f1354837cf7962b10ce1e5066ab14e to your computer and use it in GitHub Desktop.
A simple implementation of a CSD-Wrapper as required for OpenConnect to comply with Cisco AnyConnect "hostscan" policies.
#!/bin/bash
unset URL TICKET STUB GROUP CERTHASH LANGSELEN
shift
while [ "$1" ]; do
if [ "$1" == "-ticket" ]; then shift; TICKET=$1; fi
if [ "$1" == "-stub" ]; then shift; STUB=$1; fi
if [ "$1" == "-group" ]; then shift; GROUP=$1; fi
if [ "$1" == "-certhash" ]; then shift; CERTHASH=$1; fi
if [ "$1" == "-url" ]; then shift; URL=$1; fi
if [ "$1" == "-langselen" ]; then shift; LANGSELEN=$1; fi
shift
done
case "$(uname -s)" in
Darwin)
MD5="md5"
ARCH="darwin_i386"
;;
Linux)
MD5="md5 --tag"
[ "$(uname -m)" == "x86_64" ] && ARCH="linux_x64" || ARCH="linux_i386"
;;
esac
HOSTSCAN_DIR="$HOME/.cisco/hostscan"
mkdir -p $HOSTSCAN_DIR/{bin,lib}
FILE_URL="${URL//\"/}/sdesktop/hostscan/$ARCH"
echo "Manifest URL: $FILE_URL/manifest"
curl -s "$FILE_URL/manifest" | while read line; do
file="${line#*(}" file="${file%)*}" sum="${line##* }"
[[ "$file" =~ \.(dylib|so|dat)$ ]] && filetype=lib || filetype=bin
cd "$HOSTSCAN_DIR/$filetype"
if [ -f "$file" ] && [ "$($MD5 $file)" == "$line" ]; then
echo "$file is up to date."
else
echo "downloading $file"
if curl -Ifs "$FILE_URL/$file.gz" > /dev/null; then
curl -s "$FILE_URL/$file.gz" | gunzip > "$file"
else
curl -s "$FILE_URL/$file" > "$file"
fi
fi
[ "$filetype" == "bin" ] && chmod 755 "$file"
done
# Launch "cstub"
cd $HOSTSCAN_DIR/bin
#ARGS="-log debug -ticket $TICKET -stub $STUB -group $GROUP -url $URL -certhash $CERTHASH"
ARGS="-log error -ticket $TICKET -stub $STUB -group $GROUP -url $URL -certhash $CERTHASH"
echo "Launching: $(pwd)/cstub $ARGS"
./cstub $ARGS
@p120ph37
Copy link
Author

This script works on Darwin, and in theory ought to work on Linux as well, but I haven't tested. The only system dependencies of the script itself are bash, some flavor of md5/md5sum, and curl. Of course, the hostscan binaries which will be downloaded must support your particular OS flavor too...

Caveat: the hostscan binaries are provided at runtime by the VPN server, and are executed locally. This means that by using this script, you are giving the VPN server permission to remotely execute code on your workstation. Depending on your perspective, this might be a security issue. Of course, this is no different than what the Cisco AnyConnect client does... The author of OpenConnect has some things to say about this too: http://www.infradead.org/openconnect/csd.html

In order to use this script with OpenConnect, you will need to add two additional command-line options: --csd-user= and --csd-wrapper=. The "user" option should be set to your login username (OpenConnect uses this to drop sudo permissions for the purpose of running the csd-wrapper script and by extension, the hostscan binaries). The wrapper option should of course be set to the path of this script, which needs to have the execute bit set.

During login, OpenConnect will detect that the VPN server requires the hostscan binaries to be run, and will launch the wrapper script. While it waits for the hostscan process to complete, OpenConnect will continuiously emit the message, Refreshing +CSCOE+/sdesktop/wait.html after 1 second.... Meanwhile, the wrapper script will contact the VPN server to obtain a manifest of the binaries, libraries, and config files needed, and will proceed to download any which are out of date or not present locally (in ~/.cisco/hostscan/{bin,lib}), and then will launch the hostscan binaries via the cstub file. The hostscan binaries should then run as they would under AnyConnect, reporting back to the VPN server the results of their investigation. Once the server is satisfied with the hostscan report, the wait.html fetch that OpenConnect has been polling will finally succeed, and the connection will complete as normal.

@p120ph37
Copy link
Author

License: Public Domain.

@salim-b
Copy link

salim-b commented Jan 29, 2019

Just wanted to remind people, that OpenConnect includes a csd-wrapper.sh as well as a csd-post.sh script these days: https://gitlab.com/openconnect/openconnect/tree/master/trojans

For obvious reasons (see below) it's recommended to use csd-post.sh if possible!

From the official OpenConnect documentation:

The OpenConnect distribution includes two alternative scripts to support the execution or spoofing of the CSD behaviour, in the trojans/ subdirectory:

  • csd-wrapper.sh: This script accepts the same options as some versions of the CSD trojan binary, (-ticket, -stub, -group, -certhash, -url, -langselen), downloads the files required by the binary, and then wraps the execution of the cstub binary. Because of the security dangers of executing a server-provided trojan binary, this script should ideally be executed with the permissions of a low-privilege user (e.g. --csd-user=nobody --csd-wrapper=trojans/csd-wrapper.sh).
  • csd-post.sh: This script does not actually run the CSD trojan binary. Instead, it emulates the behaviour of the CSD trojan, creating a plaintext report similar to the one that the CSD trojans build, and uploading it to the server sent by the VPN gateway. The report may need to be customized in order to be accepted by some servers; the hostscan-bypass tool may help with this. Because this script does not actually execute a trojan binary, and because its complete output is easily visible in the script, the security concerns are greatly alleviated.

@Gilks
Copy link

Gilks commented Feb 23, 2019

Hey! Saw some traffic coming to the hostscan-bypass from this gist. I just wanted to add on to what salim-b was saying. The hostscan-bypass creates a customized csd file for your environment. If you have access to a machine that you know works, you are able to MITM the exact values it uses to authenticate to the VPN endpoint. If the included csd wrappers are not working, hostscan-bypass will.

@p120ph37
Copy link
Author

p120ph37 commented Apr 5, 2019

Thanks @salim-b, looks like Daniel has addressed a few of the issues that kept me from using Nikolay's original csd-wrapper.sh script, and added some additional useful features, so my variation may be unneeded at this point.

Also, the csd-post.sh workaround is certainly useful in some cases where you don't want to execute the trojans at all, but it is nice that openconnect now provides all of those scripts as options to the end-user, so they can select what is appropriate for their scenario.

@asarkar
Copy link

asarkar commented Nov 20, 2019

OpenConnect official script doesn't work for Mac. My version does.
https://gist.github.com/asarkar/fb4452a4abdf9e4a9752a7d55d2cdc93

@virtuosity250
Copy link

(as I only used the script and read the comments after it was working ...)

csd-wrapper.sh
#md5 is not a command in a Redhat derived Linux.

Linux)
MD5="md5 --tag"

should be
Linux)
MD5="md5sum --tag"

I had to locate cstub already in the /opt/cisco directory, copy to my local user.

For completeness:

sudo openconnect --user=<vpn_user> --csd-user= --csd-wrapper=/home//.cisco/csd-wrapper.sh

In my corp system the "Refreshing +CSCOE+/sdesktop/wait.html after 1 second...." takes about 50 seconds, so patience ...

Found my way here after my Corp connect stopped working 2 weeks ago (CISCO GUI Policy error) then I dropped to cmdline to use openconnect, more feedback, searching ... got to the end with this GIST.

Thanks.

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