Apache Wicket is an open source, server side, Java web application framework and used by quite a few big sites. It is discovered that the ‘encrypted url feature‘, which is expected to protect from CSRF (Cross-Site Request Forgery) attack, but it fails to provide enough protection against CSRF attack in Apache Wicket.
Encrypted URLs and stateful URL’s can be defeated by leveraging the use of CryptoMapper, which is the default encryption provider in Apache Wicket before 1.5.13, 6.x before 6.19.0, and 7.x before 7.0.0-M5. It is found that with the default security settings of CryptoMapper to encrypt URL’s is not strong enough to protect against all type os CSRF attacks. Along with CSRF, Apache Wicket is also prone to other attacks such as reflected XSS due to the weak cryptographic protection.
Request mapper CryptoMapper is typically registered into a wicket web application as root request mapper. It encrypts URL’s generated by another mapper. The original URL (both segments and parameters) is encrypted and is represented as URL segment. Apache Wicket had this great idea of encryption so that it will stop an attacker from guessing the URL and thus stop an attacker from doing CSRF and other attacks.
Defeating Encrypted URLs in Apache Wicket:
Apache Wicket’s default implementation ‘org.apache.wicket.util.crypt.SunJceCrypt’ uses the PBEWithMD5AndDES method to encrypt and decrypt the data. The security of this Password-Based Cryptography ultimately dependent on one or more secret text values or passwords. The loophole here is that the implementation uses the default password ‘WiCkEt-FRAMEwork‘. This fixed key allow an attacker to easily decrypt the URLs and generate valid URLs to use it for cross site request forgery and other attacks. Many sites don’t bother about changing default password.
How to defeat Encrypted URLs using default password:
Two default password’s ‘WiCkEt-CrYpT’ and ‘WiCkEt-FRAMEwork’ are chosen by the attacker as shown in the script decrypt.py. And the passwords are hashed with MD5 (with a salt and 17 rounds). And this hash is used as key to decrypt encrypted URL’s ‘mXHxTzUe5kU/mXH2c/HxTd3’, ‘jLBQXvh2Z88wFVtnKfsZMw/jLB0f’, ‘jLBQXvh2Z8_9tdbDCVb40AGz9WkLG1XqXeRj081Q1Jcz4Ns6k8UYfQ/jLB0f’. Attacker is able to decrypt the URLs successfully with the default password ‘WiCkEt-FRAMEwork’ as shown below .
The attacker can now use this URL, modify accordingly and can embed this as a picture in victim’s site (eg. some game profile) as shown below. And when the victim is logged in attacker can see this request on behalf of the user.
Some attackers are not bothered about the content inside the URL to conduct an attack, an attacker can just embed a URL like <img src=”http://www.example.com/jLBQXvh2Z88wFVtnKfsZMw/jLB0f?gold=9999&user=samuirai”> after seeing a form like below, So changing the password or choosing a stronger algorithm doesn’t protect users from CSRF attack.
Defeating Stateful URLs in Apache Wicket:
Apache Wickets stateful URLs are found to be more difficult for attackers to defeat compared to encrypted URL’s. The version number is meant for stateful pages and usually, the first number is always incremented while visiting different pages in that site. While the second number is incremented on multiple refreshes on a single page. This actually makes guessing of URL difficult for an attacker. But this also can be easily bypassed through collection of URL’s as given below,
The encrypted URL’s which are having version number(stateful URLs) as shown in the above diagram are decrypted using the decrypt.py with the default password ‘WiCkEt-FRAMEwork’ as shown below .
Thus it can lead to cryptographic replay or playback attack , in which a valid data transmission is maliciously or fraudulently repeated or delayed.
Apache Wicket should be configured to use org.apache.wicket.util.crypt.KeyInSessionSunJceCryptFactory, which uses the individual session random encryption key, it uses session and UUID to generate it, so that every visitors using their own encryption key (different http session). In Password-Based Encryption mechanism, The “Salt” and “Iterator count” is public, but with a strong encryption key (session + UUID) like above, it just make the Wicket’s URL encode function very hard to decode, even you have the wicket’s source code on hands. And even strong encryption techniques like AES or SHA can be implementes instead of DES.
The users using Apache Wicket feature are recommended to upgrade to:
– Apache Wicket 1.5.13
– Apache Wicket 6.19.0
– Apache Wicket 7.0.0-M5
It would be nice if you could share your decrypt.py script.