Last active
May 2, 2018 05:37
-
-
Save jossemarGT/8b4df49c8be1806c6490f28de344649a to your computer and use it in GitHub Desktop.
Generate CMS login session cookie
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| @Grab(group='net.razorvine', module='pyrolite', version='4.20') | |
| @Grab(group='com.jossemargt', module='cookie-twist', version='0.3.1') | |
| // HMAC SHA256 sign | |
| import java.security.InvalidKeyException; | |
| import java.security.NoSuchAlgorithmException; | |
| import java.security.SignatureException; | |
| import java.util.Formatter; | |
| import javax.crypto.Mac; | |
| import javax.crypto.spec.SecretKeySpec; | |
| // Time | |
| import java.time.Instant | |
| // Pickler v0 (Tailor made) | |
| import net.razorvine.pickle.Opcodes; | |
| import java.io.ByteArrayOutputStream; | |
| // Tornado Secure Cookie port | |
| import java.nio.charset.StandardCharsets; | |
| import javax.servlet.http.Cookie | |
| import com.jossemargt.cookietwist.tornado.transform.impl.V2TornadoCookieCodec; | |
| String HMAC_SHA256_ALGORITHM = 'HmacSHA256' | |
| final contestSlug = 'con_test' | |
| final cmsURL = 'http://192.168.7.10' | |
| final cookieSecret = '8e045a51e4b102ea803c06f92841a1fb' | |
| final b64CookieSecret = utf8Bytes(cookieSecret).encodeBase64().toString() | |
| String toHexString(byte[] bytes) { | |
| Formatter formatter = new Formatter(); | |
| for (byte b : bytes) { | |
| formatter.format("%02x", b); | |
| } | |
| return formatter.toString(); | |
| } | |
| String calculateHMACSHA256(byte[] key, byte[] data) throws SignatureException, NoSuchAlgorithmException, InvalidKeyException { | |
| SecretKeySpec signingKey = new SecretKeySpec(key, 'HmacSHA256'); | |
| Mac mac = Mac.getInstance('HmacSHA256'); | |
| mac.init(signingKey); | |
| return toHexString(mac.doFinal(data)); | |
| } | |
| byte[] utf8Bytes (def data) { | |
| return data.getBytes(StandardCharsets.UTF_8) | |
| } | |
| byte[] pickle0dumpsCMS(String username, String password, String timestamp) { | |
| ByteArrayOutputStream bos=new ByteArrayOutputStream(); | |
| def newLine = utf8Bytes('\n') | |
| bos.write(Opcodes.MARK); bos.write(Opcodes.UNICODE); bos.write(utf8Bytes(username)); bos.write(newLine) | |
| bos.write(Opcodes.PUT); bos.write(utf8Bytes('0')); bos.write(newLine) | |
| bos.write(Opcodes.UNICODE); bos.write(utf8Bytes("plaintext:${password}")); bos.write(newLine) | |
| bos.write(Opcodes.PUT); bos.write(utf8Bytes('1')); bos.write(newLine) | |
| bos.write(Opcodes.FLOAT); bos.write(utf8Bytes(timestamp)); bos.write(newLine) | |
| bos.write(Opcodes.TUPLE); bos.write(Opcodes.PUT); bos.write(utf8Bytes('2')); bos.write(newLine) | |
| bos.write(Opcodes.STOP); | |
| bos.flush() | |
| return bos.toByteArray() | |
| } | |
| String tornadoSignedValueField( token ) { | |
| Formatter formatter = new Formatter(); | |
| formatter.format("%d:%s", token.size(), token); | |
| return formatter.toString(); | |
| } | |
| String tornadoCreateSignedValue(secret, name, value, timestamp) { | |
| def toSign = [ '0', timestamp, name, value ].collect{ tornadoSignedValueField(it) } | |
| toSign.add(0, '2') | |
| toSign.add('') | |
| def toSignStr = toSign.join('|') | |
| def signature = calculateHMACSHA256(utf8Bytes(secret), utf8Bytes(toSignStr)) | |
| return toSignStr + signature | |
| } | |
| def epochNow = Instant.now().getEpochSecond() | |
| def pickledHashBytes = pickle0dumpsCMS('u1', 'p1', epochNow.toString()) | |
| def pickledHashStr = new String(pickledHashBytes, StandardCharsets.UTF_8); | |
| def cookieValue = tornadoCreateSignedValue(b64CookieSecret, 'con_test_login', pickledHashBytes.encodeBase64().toString(), epochNow.toString()) | |
| // -------------- Using Tornado secure cookies port | |
| def cookieCoder = V2TornadoCookieCodec.builder().withTimestamp(epochNow).withSecretKey(b64CookieSecret).build(); | |
| def signedCookie = cookieCoder.encodeCookie(new Cookie ("${contestSlug}_login" , pickledHashStr )) | |
| // Manually Generated cookie value | |
| println "---" * 5 | |
| println ">>> Cookie generated within this script:" | |
| println "${contestSlug}_login=\"${cookieValue}\"" | |
| // Doing the same request as the tampered one with the generated cookie value | |
| println ">>> Was it a succesful login? " + "${cmsURL}/${contestSlug}". | |
| toURL(). | |
| getText(requestProperties: ['Cookie': "${contestSlug}_login=\"${cookieValue}\"".toString()]). | |
| contains("Logged in as ") | |
| // cookie-twist generated value | |
| println "---" * 5 | |
| println ">>> Cookie generated with cookie-twist library" | |
| println "$signedCookie.name=\"$signedCookie.value\"" | |
| println ">>> Was it a succesful login? " + "${cmsURL}/${contestSlug}". | |
| toURL(). | |
| getText(requestProperties: ['Cookie': "${signedCookie.name}=\"${signedCookie.value}\"".toString()]). | |
| contains("Logged in as ") | |
| println "---" * 5 | |
| /** | |
| * Console output: | |
| * $ groovy cms_gerate_login.groovy | |
| * --------------- | |
| * >>> Cookie generated within this script: | |
| * con_test_login="2|1:0|10:1525237414|14:con_test_login|56:KFZ1MQpwMApWcGxhaW50ZXh0OnAxCnAxCkYxNTI1MjM3NDE0CnRwMgou|0be2f709c31a73f28eed9a5f6648ea58ba4e75419b533a82f830c7cc878664c4" | |
| * >>> Was it a succesful login? true | |
| * --------------- | |
| * >>> Cookie generated with cookie-twist library | |
| * con_test_login="2|1:0|10:1525237414|14:con_test_login|56:KFZ1MQpwMApWcGxhaW50ZXh0OnAxCnAxCkYxNTI1MjM3NDE0CnRwMgou|0be2f709c31a73f28eed9a5f6648ea58ba4e75419b533a82f830c7cc878664c4" | |
| * >>> Was it a succesful login? true | |
| * --------------- | |
| */ |
Author
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This script was tested against CMS revision f7ebce619b886cbdd4620123889860a908f4ca65 (prior to its 1.3.0 release).
Bear in mind that the latest releases don't base64 encode the cookie_secret anymore, it seems the application transform the secret into its hex string representation using binascii.b2a_hex