Skip to content

Instantly share code, notes, and snippets.

Forked from zer4tul/gist:6477470
Last active January 19, 2024 11:56
Show Gist options
  • Save l0ki000/56845c00fd2a0e76d688 to your computer and use it in GitHub Desktop.
Save l0ki000/56845c00fd2a0e76d688 to your computer and use it in GitHub Desktop.
Cisco Anyconnect CSD wrapper for OpenConnect (exhanced to autodownload and autoupdate hostscan)
# Cisco Anyconnect CSD wrapper for OpenConnect
# Enter your vpn host here
if [[ -z ${CSD_HOSTNAME} ]]
echo "Define CSD_HOSTNAME with vpn-host in script text. Exiting."
exit 1
BINS=("cscan" "cstub" "cnotify")
# parsing command line
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
ARCH=$(uname -m)
if [[ "$ARCH" == "x86_64" ]]
# creating dirs
for dir in $HOSTSCAN_DIR $LIB_DIR $BIN_DIR ; do
if [[ ! -f $dir ]]
mkdir -p $dir
# getting manifest, and checking binaries
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/manifest" -O "$HOSTSCAN_DIR/manifest"
# generating md5.sum with full paths from manifest
cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ cmd = "find $HOSTSCAN_DIR -iname " $2; while (cmd | getline line) { print $4, line; } }' > $HOSTSCAN_DIR/md5.sum
# check number of files either
MD5_LINES=`wc --lines $HOSTSCAN_DIR/md5.sum | awk '{ print $1; }'`
MANIFEST_LINES=`wc --lines $HOSTSCAN_DIR/manifest | awk '{ print $1; }'`
echo "Got $MANIFEST_LINES files in manifes, locally found $MD5_LINES"
# check md5
md5sum -c $HOSTSCAN_DIR/md5.sum
if [[ "$?" -ne "0" || "$MD5_LINES" -ne "$MANIFEST_LINES" ]]
echo "Corrupted files, or whatever wrong with md5 sums, or missing some file"
# just download every file mentioned in manifest (not ideal, but hopefully should be enough)
FILES=( $(cat $HOSTSCAN_DIR/manifest | sed -r 's/\(|\)//g' | awk '{ print $2; }') )
TMP_DIR=`mktemp -d` && cd $TMP_DIR
for i in ${FILES[@]} ; do
FILE="$(basename "$i")"
echo "Downloading: $FILE to $TMP_DIR"
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/$FILE" -O $FILE
# some files are in gz (don't understand logic here)
if [[ ! -f $FILE || ! -s $FILE ]]
# remove 0 size files
if [[ ! -s $FILE ]]; then
rm $FILE
echo "Failure on $FILE, trying gz"
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/$FILE_GZ" -O $FILE_GZ
gunzip --verbose --decompress $FILE_GZ
# don't know why, but my version of hostscan requires tables to be stored in libs
echo $FILE | grep --extended-regexp --quiet --invert-match ".so|tables.dat"
if [[ "$IS_LIB" -eq "1" ]]
cp --verbose $FILE $LIB_DIR
cp --verbose $FILE $BIN_DIR
for i in ${BINS[@]} ; do
echo "Setting excecution bit on: $BIN_DIR/$i"
chmod u+x $BIN_DIR/$i
rm -rf $TMP_DIR
# cstub doesn't care about logging options, sic!
#ARGS="-log debug -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
ARGS="-log error -ticket $TICKET -stub $STUB -group $GROUP -host $URL -certhash $CERTHASH"
echo "Launching: $BIN_DIR/cstub $ARGS"
$BIN_DIR/cstub $ARGS
Copy link

asarkar commented Oct 29, 2018

I rewrote the script to not use any additional software and tested it on macOS Mojave

Copy link

jcfaracco commented Dec 11, 2018


Is anyone seeing this error like me? Or did anyone have the same experience?

[Tue Dec 11 15:23:26.098 2018][cstub][debug][hs_download_file] attempting to download file: /CACHE/sdesktop/hostscan/linux_x64/
[Tue Dec 11 15:23:26.098 2018][cstub][trace][hs_transport_setpeer] setting peer
[Tue Dec 11 15:23:26.098 2018][cstub][trace][hs_transport_setpeer] setting l2 peer: (https://MY_HOSTNAME)
[Tue Dec 11 15:23:26.098 2018][cstub][trace][hs_transport_setpeer] setting peer done. peer = https://MY_HOSTNAME, referrer = https://MY_HOSTNAME
[Tue Dec 11 15:23:26.098 2018][cstub][trace][hs_transport_setredircount] setting redirects
[Tue Dec 11 15:23:26.099 2018][cstub][trace][hs_transport_setredircount] setting redirects: (10)
[Tue Dec 11 15:23:26.099 2018][cstub][trace][hs_transport_setredircount] setting redirects done
[Tue Dec 11 15:23:26.099 2018][cstub][trace][hs_transport_get] sending get request
[Tue Dec 11 15:23:26.460 2018][cstub][debug][hs_transport_curl_get] libcurl error: Error

[Tue Dec 11 15:23:26.460 2018][cstub][warn][hs_transport_get] sending get request failed
[Tue Dec 11 15:23:26.460 2018][cstub][error][hs_download_file] unable to contact peer: (https://MY_HOSTNAME).

Obviously, I'm using MY_HOSTNAME to hide my server name. How can I avoid/fix libcurl errors since I'm not using or downloading it?
Btw, I can ping and access the real server name hidden by MY_HOSTNAME.

Copy link

Jomik commented Dec 18, 2018

I seem to be missing cnotify, which I guess could be what causes the loop that people have mentioned.
I also get the an error when trying to execute cstub, both via the script and manually.

Failed to execute process './cstub'. Reason:
The file './cstub' does not exist or could not be executed.

The file is there though.

Copy link

salim-b commented Jan 29, 2019

Just wanted to remind people, that OpenConnect includes a (based on this Gist) as well as a script these days:

For obvious reasons (see below) it's recommended to use 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:

  • 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/
  • 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.

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.

Copy link

So based on all the Q&A above, how would one summarize the instructions needed to emulate a Cisco Anyconnect VPN connection?

Copy link

asarkar commented Mar 23, 2019

@salim-b There is no documentation for the usage of the csd scripts from openconnect. Those are just as useful as the trash I took out this morning.

Copy link

blancNoir commented Apr 5, 2019

thank you, this worked like a charm! (running on manjaro)

Copy link

Marston commented Sep 2, 2019

Trying to run this on a Mac Mojave but it's caught in a loop where I get:

Refreshing +CSCOE+/sdesktop/wait.html after 1 second...
SSL negotiation with
Connected to HTTPS on

What's going on here? How can I fix it?

Copy link

silveiralexf commented Oct 27, 2019

thanks for this!

Copy link

I've got Bad CPU type in executable. I guess because of my os is catalina? Any solutions?

Copy link

@AlexLu202 Same here - have you learned anything?

Copy link


Never mind, the solution appears quite simple.

Find this line:


Replace with:


It worked for me.

Copy link

dlewis7444 commented Mar 16, 2020

Seemed to work - downloaded a bunch of files - but then I'm getting "drbg_instantiate failed".

No idea what that means. Google not much help. Anybody?

Refreshing +CSCOE+/sdesktop/wait.html after 1 second...
drbg_instantiate failed
drbg_instantiate failed
GET https:///+CSCOE+/sdesktop/wait.html
SSL negotiation with
double free or corruption (!prev)
Connected to HTTPS on
Refreshing +CSCOE+/sdesktop/wait.html after 1 second...

And continues on forever

Copy link

@dlewis7444 same issue here, did you find a solution?

Copy link

regarding the loop problem, i had to tweak the csd-wrapper script to get it to work with my servers:

#PINNEDPUBKEY="-s ${CSD_SHA256:+"-k --pinnedpubkey sha256//$CSD_SHA256"}"
PINNEDPUBKEY="--insecure ${CSD_SHA256:+"-k --pinnedpubkey sha256//$CSD_SHA256"}"

then it started working, once the script succeeded downloading the files on $HOSTSCAN_DIR ($HOME/.cisco/hostscan)

Copy link

regarding the loop problem, i had to tweak the csd-wrapper script to get it to work with my servers:

#PINNEDPUBKEY="-s ${CSD_SHA256:+"-k --pinnedpubkey sha256//$CSD_SHA256"}"
PINNEDPUBKEY="--insecure ${CSD_SHA256:+"-k --pinnedpubkey sha256//$CSD_SHA256"}"

then it started working, once the script succeeded downloading the files on $HOSTSCAN_DIR ($HOME/.cisco/hostscan)

What did you tweak?

Copy link

How to make this work for Raspberry-Pi ( ARM Based Processor ) ?
THanks on Advance

Copy link

miratim commented Sep 2, 2020

Recently upgraded to ubuntu 20.10 because I'm an idiot, and since then, the is failed with a very specific set of errors.

I can't make heads or tails of it. Any quick tips on what I need to look at here?


  1. From the VPN panel dialog logs:
    XML POST enabled
    CSD script '/home/mirat/.cisco/' returned non-zero status: 243
    Authentication may fail. If your script is not returning zero, fix it.

  2. From within the cstub.log under .cisco/hostscan:

[Wed Sep 02 11:35:16.482 2020][cstub]Function: hs_file_verify_with_killdate Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/common/libcommon/hs_file_verify_linux.c Line: 354 Level: debug :: verifying file signature: file = [/home/mirat/.cisco/hostscan/lib/], signer = [Cisco Systems, Inc.], type = [2]
[Wed Sep 02 11:35:16.494 2020][cstub]Function: verify_cb Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/common/libcommon/hs_file_verify_linux.c Line: 694 Level: error :: Error 20, unable to get local issuer certificate
[Wed Sep 02 11:35:16.494 2020][cstub]Function: verify_cert Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/common/libcommon/hs_file_verify_linux.c Line: 978 Level: error :: Certificate is not trusted
[Wed Sep 02 11:35:16.495 2020][cstub]Function: hs_file_verify_with_killdate Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/common/libcommon/hs_file_verify_linux.c Line: 458 Level: error :: unable to verify the certificate trust.
[Wed Sep 02 11:35:16.495 2020][cstub]Function: hs_dl_load Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/common/libcommon/hs_dlhandler.c Line: 101 Level: error :: file signature invalid, not loading library (/home/mirat/.cisco/hostscan/lib/
[Wed Sep 02 11:35:16.495 2020][cstub]Function: get_csd_handle Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/asa/libcsd/libcsd_static.c Line: 42 Level: error :: unable to load csd library: /home/mirat/.cisco/hostscan/lib/
[Wed Sep 02 11:35:16.495 2020][cstub]Function: run Thread Id: 0x13900300 File: /tmp/build/thehoff/Negasonic_MR30.221858515975/Negasonic_MR3/posture/asa/cstub/main.c Line: 821 Level: error :: unable to initialize csd library.

Copy link

gskjold commented Oct 26, 2020

I have the same issue after upgrade to Ubuntu 20.10 as you @miratim , did you find any solution?

Copy link

miratim commented Oct 26, 2020 via email

Copy link

I had same issue. From log I found that file .cisco/hostscan/lib/ signed by Cisco Systems, Inc. cant be verified.
Solved by adding VeriSign G5 among ca-certificates.

Copy link

Thanks @sharkodlak,
I had the same issue on ubuntu, and fixed adding the certificate as suggested by you.

Here is a guide on how to do that:

Copy link

ghost commented Feb 5, 2021

@sharkodlak @danparisi do you have this certificate's fingerprint? I cant find it on Any links? Thanks!

Copy link

danparisi commented Feb 5, 2021

@unb9rn No I don't, I just followed the guide I linked above. I think it's an old certificate but I didn't find any other solution to let it work

Copy link

Nothing is working

POST https://myvpn/global-protect/prelogin.esp?tmp=tmp&clientVer=4100&clientos=Linux
Connected to myvpn:443
SSL negotiation with myvpn
Connected to HTTPS on myvpn with ciphersuite (TLS1.2)-(RSA)-(AES-256-GCM)
Enter login credentials
POST https://myvpn/global-protect/getconfig.esp
Portal set HIP report interval to 60 minutes).
1 gateway servers available:
  GW-*** (myvpn)
Please select GlobalProtect gateway.
GATEWAY: [GW-***]:GW-***
POST https://myvpn/ssl-vpn/login.esp
GlobalProtect login returned authentication-source=Auth_Seq_Standard
GlobalProtect login returned usually-equals-4=4
GlobalProtect login returned usually-equals-unknown=unknown
POST https://myvpn/ssl-vpn/getconfig.esp
Session will expire after 43200 minutes.
Tunnel timeout (rekey interval) is 180 minutes.
Idle timeout is 180 minutes.
No MTU received. Calculated 1422 for ESP tunnel
POST https://myvpn/ssl-vpn/hipreportcheck.esp
/usr/lib/openconnect/ line 122: /home/nobody/.cisco/hostscan/manifest: No such file or directory
/usr/lib/openconnect/ line 129: /home/nobody/.cisco/hostscan/bin/cstub: No such file or directory
POST https://myvpn/ssl-vpn/hipreport.esp
Missing or invalid required input parameters
HIP report submission failed.
Creating SSL connection failed

Copy link

cer28 commented Feb 8, 2021

Thanks @sharkodlak and @danparisi, this solution also worked for me to get past the unable to get local issuer certificate error validating the signed file. There was no indication what certificate it needed, so this was vital information.

For me on Ubuntu 20.04 it was a slightly different process:

Copy link

Thank you @sharkodlak and @danparisi and also thank you @cer28 for summarizing, it works for me.

Copy link

Thanks @sharkodlak @danparisi @cer28, it works for me too

Copy link

janotav commented May 4, 2022

The workaround I used on Ubuntu 22.04:

  1. Build custom docker image based on older Ubuntu where security wasn't that strict, something like
FROM ubuntu:18.04

RUN apt update \
  && apt install -y wget

and build it:

docker build -t unsecuressl:latest .
  1. In the script replace direct wget invocation with one using this image. Instead of
wget --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/manifest" -O "$HOSTSCAN_DIR/manifest"


docker run --rm --entrypoint wget unsecuressl:latest --no-check-certificate -c "https://${CSD_HOSTNAME}/CACHE/sdesktop/hostscan/$ARCH/manifest" -O- > "$HOSTSCAN_DIR/manifest"

Similarly replace other occurrences.

After doing these changes, I was able to connect.

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