July 26, 2016Kevin Raynel9 min read
Here, we will not be accessing data that should not have been accessible otherwise. Before trying to access data in a way that was not exactly meant to, it is always preferable to contact the company or individuals who are serving this data in the first place.
I contacted Silaexpert regarding this article. I have detected no real security hole in their client, so they gave their approval for its publication.
That being said, let's start!
The context is quite simple. The generation of payslip at Theodo is outsourced to another company: Silaexpert. We were given our credentials, and a url to access our vacations count and our payslips.
This all starts with a link: http://www.silaexpert01.fr/silae.
This link does not work in Chrome, Firefox or Safari. It does not run on a Windows 10 computer, so you can forget connecting from home on your nice gaming rig.
It seems to only work on Internet Explorer on Windows 7: bad news for all the developers at Theodo running Linux or OSX.
Well, obviously, you could find other solutions. You can always borrow a friend or colleague computer running Windows. Great, now all your files are available on a shared computer.
Or you can download a free virtual machine from Microsoft: https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/. For this particular purpose, the VM with IE9 on Windows 7 works well.
So, now you have the virtual machine up and running, you can go to the url and... Whaaat ? It is downloading a fat client and starts some kind of install process. Just from that link. Thank you IE.
Finally, you can login and painfully download your last payslip. And start again next month. If you reset the virtual machine, because, you know, licenses.
Ain't nobody got time for that!
I want to download my file directly from my Mac or Linux computer without going through all this VM nonsense. In order to do this, I have to send the right request to the remote server (I still do not know its address, which is probably hard coded in the downloaded fat client).
So, first things first, let's sniff all that network traffic going out of the VM.
You can use any network sniffing tool available for your platform:
I personnally used Charles Proxy, in spite of its hideous icon.
Start your VM.
Now, if you login into the fat client and download a payslip, you should have enough information to start thinking.
You now have a complete exchange between the client and the server.
The first thing you notice is that all exchanges are done without SSL/TLS encryption. Free data, yeah! That being said, you could still have sniffed encrypted traffic by trusting the fake CA generated by your proxy on the virtual machine.
You can notice several things:
You can try to decode the base64 encoded data, but you will not be able to get anything readable. It is probably encrypted binary data.
The first request made to the server contains only one interesting piece of data, a key
<RSAKeyValue> <Modulus>odfDJj...pEQ2RQ==</Modulus> <Exponent>AQAB</Exponent> </RSAKeyValue>
K is the public RSA key used by the client. The response also contains a key, using the same format, and some kind of identifier
$USR. This received key is the public RSA key that the server will use.
We just witnessed an RSA key exchange. RSA cannot be used to encrypt large amount of data. Depending on the padding technique used, with a 2048 bit key (used here), you can encrypt at most 245 bytes. Not much.
A technique commonly used is to use a private/public RSA key to encrypt a symmetric key, which is then used during the exchange.
Good question. Here, you are either a genius or you need a bit of help.
Ok, you are a genius (I never doubted it), you take the second message, and decode the base64 binary.
echo "AQABAAAOE6jZqMmDnFHefXddjDq...W5A=" | base64 -D | hexdump -C
If you do this several times, over several login request, you might notice a pattern.
The first few bytes are always
01 00 01 00 00. This can be seen directly in the base64: the first letters are always "AQABAA". Something quite interesting is that
00 01 00 00 is the binary representation, on 4 bytes, little endian, of the decimal 256. Nice!
Another thing you might notice is at offset 261 (1 + 4 + 256), the bytes are always
20 00 00 00. This is 32 in decimal.
Here is the genius part. A common symmetric encryption system is AES 256. It uses an initialization vector (IV) of... 32 bytes.
Kwhich was sent to the server during the first phase.
There is only one AES, but many variants. You can try them all, but it will take a really long time and lots of developments.
We did not use all the cards in our hand at this point. Remember the fat client? It is our key to the encryption issue.
Ready to play a game?
My site is not really a site, it uses internet explorer to download an executable binary, which runs only on Windows and asks for specific libraries on Windows 10... In which language is the client developped?
You guessed it, .NET!
Easily decompilable. Note that Java would have been fine too.
Let's take a look at this code. You can get the url for the
.exe by reading the other proxified requests. Import the
.exe into the decompiler (I used the trial version of .Net Reflector in the Windows VM), and look for some interesting code. No luck this time, nothing.
Except for this one little DLL,
Sila.WCFDLL.dll. Export it, and re-import it into the decompiler. And bingo, you have the serialization/deserialization procedures, with all the security stuff.
We were right about the AES. It uses the Rijndael 256 variant of the AES encryption with a custom serialization routine. If you are not a genius and missed the previous paragraph, you have here all the code for re-creating the message.
Oh, in case you were wondering about, the first byte is
01 when it contains AES information,
00 in all other cases.
Here, you are blocked. You cannot decrypt any of the AES keys, because you need the private RSA keys. The only option to get this AES key is to write a Man In The Middle (MITM) server, which intercepts every request between the client and the server and acts as the client for the server, and as the server for the client.
Credits: Miraceti — Man in the middle attack — CC BY-SA 3.0
Once that server is written (avaiblable at https://github.com/kraynel/sila-cli/blob/master/server.js), and you have fixed all the buffer/byte conversion/RSA/mcrypt issues, you can reload your VM and login one more time.
Only this time, you will use the "Map Remote" option of Charles proxy to redirect all traffic going to http://www.silaexpert01.fr/SILAE/IWCF/IWCF.svc to your local endpoint, which will in turn decrypt the exchange and request the real endpoint.
You now have all requests, decrypted, in binary form.
Requests are not directly readable. They are not using xml serialization but a custom, in house serialization technique. Who does that? Why?
But we have the code so we can look into it. And port it to JS (https://github.com/kraynel/sila-cli/blob/master/cbaSerialization.js).
We now have all the requests, and their responses, in plain, readable JS. By playing with the different parameters, we can identify two interesting requests:
AcquisitionBulletins, which lists the avaiblable payslips;
GenererPdf, which downloads a payslip as a pdf file.
Congrats, you know everything about this service! You can write your own client!
Web Developer at Theodo