-
-
Save p120ph37/8213727 to your computer and use it in GitHub Desktop.
#!/usr/bin/expect -f | |
# | |
# VIPAccess.exp | |
# | |
# Command-line emulation of Symantec's VIP Access software token. | |
# Usage: | |
# ./VIPAccess.exp [v] | |
# If the "v" argument (or any argument) is specified, verbose output | |
# will be produced on stderr. The OTP value will be output on stdout. | |
# | |
set timeout 10 | |
log_user 0 | |
set aes_key D0D0D0E0D0D0DFDFDF2C34323937D7AE | |
set keychain /Users/$env(USER)/Library/Keychains/VIPAccess.keychain | |
proc vlog { s } { if $::argc { puts stderr $s } } | |
vlog "Finding machine serial number (used by VIPAccess to secure the keychain.):" | |
spawn /bin/sh -c "ioreg -rac IOPlatformExpertDevice | xpath 'plist/array/dict/key\[.=\"IOPlatformSerialNumber\"\]/following-sibling::*\[position()=1\]/text()' 2>/dev/null" | |
expect eof | |
set serial $expect_out(buffer) | |
vlog " $serial" | |
vlog "Reading encrypted Credential ID and OTP secret key from $keychain:" | |
spawn security unlock-keychain $keychain | |
expect "password to unlock $keychain: " | |
send "${serial}SymantecVIPAccess$env(USER)\n" | |
expect eof | |
spawn security find-generic-password -gl CredentialStore $keychain | |
expect -re \"acct\"<blob>=\"\(\[a-zA-Z0-9/+\]+=\)\" | |
set id_crypt $expect_out(1,string) | |
vlog " $id_crypt" | |
expect -re password:\ \"\(\[a-zA-Z0-9/+\]+=\)\" | |
set key_crypt $expect_out(1,string) | |
vlog " $key_crypt" | |
vlog "Decrypting Credential ID and OTP key:" | |
spawn /bin/sh -c "openssl enc -aes-128-cbc -d -K $aes_key -iv 0 -a <<< '$id_crypt'" | |
expect -re \(.*\)Symantec | |
set id_plain $expect_out(1,string) | |
vlog " $id_plain" | |
spawn /bin/sh -c "openssl enc -aes-128-cbc -d -K $aes_key -iv 0 -a <<< '$key_crypt' | xxd -p" | |
expect -re \[0-9a-f\]+ | |
set key_plain $expect_out(0,string) | |
vlog " $key_plain" | |
vlog "Generating current OTP using secret key." | |
spawn oathtool --totp $key_plain | |
expect -re \\d+ | |
set otp $expect_out(0,string) | |
puts $otp |
Hi,
my question may seem a little dumb, sorry for that. I just stumbled across github for the first time and am not very familiar with it.
Since VIP Access generates a new ID every time I re-install it I'd like to use a different OATH Generator I can backup and use on all my devices.
Could I use your code to extract the secret from my local VIP Access installation to use it in any other OATH compatible generator?
If so how do I do it? Could I just enter your code in terminal (in verbose mode) to get the secret or do I have to install git for mac?
Thanks!
Regards, Denis
Hi, in Brew 0.9.5, oathtool
is available from oath-toolkit
.
bleistift2,
Yes, you can use this script to extract the secret from the VIP Access on Mac (so you can save and reuse the same secret with any oath-compatable tool). Just click the "Download Gist" link, then use chmod 755 VIPAccess.exp
in a terminal to mark it as executable, and ./VIPAccess.exp v
to run it. (the "v" puts it in verbose mode, so you can see all the intermediate steps including the secret, instead of just the final output code). The output should look something like this:
aarons-mbp:Downloads anm$ chmod 755 VIPAccess.exp
aarons-mbp:Downloads anm$ ./VIPAccess.exp v
Finding machine serial number (used by VIPAccess to secure the keychain.):
C02LNGDLFD57
Reading encrypted Credential ID and OTP secret key from /Users/anm/Library/Keychains/VIPAccess.keychain:
OagYZjwfC1pFQrcF+xmoqoYFEzLnB71bIgjgU+ZxqQY=
279r5n5VSVxwCJHuC9CXD7+/o+P3bBHdo3zguGbXIRs=
Decrypting Credential ID and OTP key:
VSST29219676
c3066e7467cbd399dbdfade86981f6d212c5d0b2
Generating current OTP using secret key.
723872
aarons-mbp:Downloads anm$
In that example, the secret was c3066e7467cbd399dbdfade86981f6d212c5d0b2
Hi,
great work.
Id had to re-install my smart phone and therefore also my VIP Access App. Before I noted down my Credential ID (VSMT...).
Do You know what is the relation between the Credential ID and the OTP Key (secret) ?
So: how can I recover my secret from the CredID I noted down before ?
I am pretty sure there must be a connection because when registering the App to a Website I just had to put in the CredID
I just discovered that @cyrozap has taken this a step further with a python implementation of the token-provisioning protocol: https://github.com/cyrozap/python-vipaccess and a blog post about writing it here: http://www.cyrozap.com/2014/09/29/reversing-the-symantec-vip-access-provisioning-protocol/
Vingelar,
The website where you enter your OTP codes doesn't know the secret - they simply pass along the OTP to Symantec, along with the Credential ID they have on file for you, and Symantec gives a good/no-good response.
Unfortunately, only Symantec and your now-deleted phone app knew the relation between the Credential ID and the OTP Key. The short answer is that you cannot recover the OTP Key from the Credential ID, and although Symantec has this information on their side, they will not release it to you. You will have to create a new credential and register it with the website.
The cyrozap implementation is good, but generates a QR code and you need to manually run oathtool to get your 6 digit code. This works better out of the box imo. Especially if you are looking to automate anything or just want to copy/paste the code
Hi @p120ph37. I'm trying to reverse engineer the VIP iOS app and replace it with Authy/1password. Can you comment on how you obtained the AES key? I'm trying to take a similar approach for the iOS app and even though I have the keychain data it (rightfully) seems encrypted with a different key. You key seems to be unique for all installations of the Mac app (since your code works on any computer) so I'd hope that the same applied to the iOS app, I'm just looking for an (easy) way of getting the key to be able to move from there.
@lucianf - I discovered the AES key by tracing the crypto library calls that the VIP application makes.
This is fantastic - thanks so much!
I just wanted to share a version written in bash which runs a little faster than expect:
https://github.com/ykhemani/vipaccess
You'll note that the programmatically generated keychain password is passed to the security unlock-keychain
command via the -p
command line argument. I wasn't sure about this, but given that the password is based on the machine serial number, a string and the user's name, this should not be cause for consternation.
I hope you will find the bash script alternative helpful.
Cheers!
It would we very help full. if it can work for windows as well.
Thanks
Okay, so if you are trying to get this to work with 1password you need to get the key_plain into Base32… basically, I ran
oathtool -v --totp $key_plain
and it spit out the Base32 secret which I was able to paste in to 1password's TOTP field and it generates proper codes that stay in step with the VIP Access apps codes.
BTW, I also had to constantly enter the keychain password the first time I ran this otherwise the keychain password was not getting passed.
Can anyone provide the Powershell version for the listed scripts above in order to test on Win VM? Thank you
Hello everyone, I could use this very much for the purpose of automating the VPN autentication and I can't still figure out how should I use this script.
I only have VIP access app on my phone, do I have to install the desktop version of the app in order for this to work?
Could someone explain a little how can I implement this from scratch so I can test it? sorry I am not a developer and thank you all very much.
a version written in bash which runs a little faster
I only just now got around to looking at this. Nice. The reason I used expect is because this is actually a small piece of a larger automation task I've written which needs expect for some other steps anyway. Absent that, yes, bash is going to be faster/simpler for others to use.
@hgocent, in order to automate VPN authentication, you will need a bit more than just this script. Here are the pieces, and some suggestions for how to address them:
- Provisioning of a 2FA token: In the typical case, you will have been instructed to download the "VIP Access" app, and go through some steps to register it to your account. If you have a Mac, this will result in a "keychain" file (encrypted config file), which my script can then use to generate one-time-passwords. As an alternative to provisioning via the VIP Access app, or if you don't have a mac, you could use this Python script instead.
- Generating the OTP: In the typical case, you are expected to open the VIP Access GUI app and transcribe the shown code manually. If you have a Mac and have already run the VIP Access app, you can use my script above (or this alternate version ) which will use the existing VIP Access app config to generate OTP codes on the command-line where you can tie it into other automation. Alternatively, if you have the plain OTP secret (either from looking at the output of my script, or because you used the Python script instead of the VIP Access app), you can use it with oathtool like this:
oathtool --totp $key_plain
or with a TOTP-capable password-manager like KeePassXC. - Connecting to the VPN: You will probably have been instructed to use something like Cisco AnyConnect for this. In any case, it will usually be some sort of GUI app that prompts for your username/password/OTP. GUI apps are often hard to automate, so you may want to try an alternative such as openconnect
- Providing the OTP to the VPN: During the VPN login process, you will be prompted for the OTP. This is usually not something that can be passed as a command-line parameter to the VPN client app (e.g. openconnect), and is instead part of the interactive text-based login prompt that the server provides during connection. If you are using a GUI app (e.g. Cisco AnyConnect), it will probably be presented as a text-box on-screen. You will probably want to use
expect
scripting, or a password-manager's autotype feature to fill in the password and OTP. The details of how to set that up are going to vary depending on your exact situation.
Here is another post of mine describing how to set up VIP-Access/AnyConnect VPN from a Mac: https://gist.github.com/p120ph37/10999344
@p120ph37,
The password for unlocking VIPAccess keychain i.e. "<value of IOPlatformSerialNumber>SymantecVIPAccess<$USER>"
does not work for me. I just installed the VIP Access application (version 1.0.7) and I am on BigSur 11.2.2 (20D80).
Is this just me or anyone ran into this problem? or did Symantec changed the password?
Any help would be greatly appreciated.
Thanks.
@aselvan, your issue isn't that the password is wrong, it's that since OSX 10.12, there is an additional layer of access-control on keychains, in addition to the unlock
mechanism. The first time this script tries to access your VIPAccess.keychain
, OSX will pop up a prompt window asking (again) for the keychain password. If you paste the password there, and hit "Always Allow", that prompt will not reappear on subsequent runs of this script. (note: the same applies to the shell variant of this script that @ykhemani created).
You can echo the password to your terminal with this command if you like (for easy copy+paste into that popup dialog):
serial=$(ioreg -rac IOPlatformExpertDevice | xpath 'plist/array/dict/key[.="IOPlatformSerialNumber"]/following-sibling::*[position()=1]/text()' 2>/dev/null)
echo ${serial}SymantecVIPAccess${USER}
You can read a little bit about this additional authorization mechanism here: https://mostlikelee.com/blog-1/2017/9/16/scripting-the-macos-keychain-partition-ids
After reading the above article, you might think you can apply the "Always Allow" action directly from the terminal by doing this (but it won't work):
keychain=/Users/${USER}/Library/Keychains/VIPAccess.keychain
security set-generic-password-partition-list -S teamid:9PTGMPNXZ2,apple-tool: -k "${serial}SymantecVIPAccess${USER}" $keychain
It won't work because OSX now checks not only the partition-id but also the application-name of the accessing application, and there is currently no security
subcommand to add application authorizations to an existing keychain entry. So long story short, the simplest way to do this is to just paste the password into the popup and hit "Always Allow". Or use @cyrozap's Python app instead of the Symantec app entirely: https://github.com/cyrozap/python-vipaccess
@p120ph37,
Update: Please ignore my response earlier on password not working. I missed reading your note about the second time prompt. I got past that step and retrieved the secret key which is really what I am after. I have written a script that I use which is a wrapper on top of oathtool for all my other 2F needs so all I needed was the SymantecVIP secret key to generate TOTP. I am good now, thanks again.
In using the serial extraction in the original script (uncommented line in below code excerpt), I get no value returned.
Finding machine serial number (used by VIPAccess to secure the keychain.):
serial
Reading encrypted Credential ID and OTP secret key from...VIPAccess.keychain:
When using the different option mentioned by @p120ph37 (first commented line in below code excerpt) I get the serial, but with quotes and a carriage return
Finding machine serial number (used by VIPAccess to secure the keychain.):
serial "NKXXW9F0J0"
Reading encrypted Credential ID and OTP secret key from ...VIPAccess.keychain:
I found the following code (second commented line in below code excerpt) that gives me just the serial, but it still contains the carriage return, so when it creates the password to unlock the keychain, the result shows with the carriage return so it always fail
Finding machine serial number (used by VIPAccess to secure the keychain.):
serial NKXXW9F0J0
Reading encrypted Credential ID and OTP secret key from ...VIPAccess.keychain:
NKXXW9F0J0
SymantecVIPAccess...
Code options used:
spawn /bin/sh -c "ioreg -rac IOPlatformExpertDevice | xpath 'plist/array/dict/key\[.=\"IOPlatformSerialNumber\"\]/following-sibling::*\[position()=1\]/text()' 2>/dev/null"
# spawn /bin/sh -c "ioreg -rd1 -c IOPlatformExpertDevice | grep 'IOPlatformSerialNumber' | cut -f2- -d'=' | cut -f1 -d','"
# spawn /bin/sh -c "ioreg -l | grep IOPlatformSerialNumber | cut -c 37-46"
expect eof
set serial $expect_out(buffer)
vlog "serial $serial"
Any thoughts on how to remove the carriage return?
@Mike-c-Jackson
I wrote a wrapper script based on the code presented here couple of years back. The script still works fine (I just tried on my iMac/intel and macbook/m2) with the latest macOS version. You can give it a try and see if you can get past your issue. It is at the link below.
https://github.com/aselvan/scripts/blob/master/security/symantec_vipaccess_key.sh
Getting the serial number via ioreg is what occupies most of the execution time for this script. If you don't mind saving your OTP secret key directly into your automation scripts, you can run this once in verbose mode to obtain the secret key, and then just use "oathtool --totp YOUR_KEY_HERE" directly to output your one-time-passwords.