############################################################# # # COMPASS SECURITY ADVISORY # http://www.csnc.ch/en/downloads/advisories.html # ############################################################# # # Product: Grails Email Confirmation plugin [1] # Vendor: Marc Palmer # CVD ID: CVE-2011-1600 # Subject: Predictable Confirmation Token # Risk: High # Effect: Remotely exploitable # Author: Alexandre Herzog # Date: 02/08/2011 # ############################################################# Introduction: ------------- Grails is an open source web application framework which uses the Groovy programming language (which is in turn based on the Java platform). It is intended to be a high-productivity framework by following the "coding by convention" paradigm, providing a stand-alone development environment and hiding much of the configuration detail from the developer [2]. The Grails Email Confirmation plug-in will send an email to a user, including a link to confirm the provided address. The generated confirmation token is predicable once an initial confirmation link has been retrieved. An application relying on this plug-in may therefore allow attackers to confirm emails and user accounts without having access to the registrered email address. Affected: --------- Vulnerable: * Grails Email Confirmation plugin 1.0.4 Technical Description --------------------- The generation of the confirmation token is done in the PendingEmailConfirmation class [3] by using the returned java.rmi.server.UID appended to a fixed string. The result is padded and Base62 encoded before being used as token. As the Java 6 documentation stats [4]: "The UID() constructor can be used to generate an identifier that is unique over time with respect to the host it is generated on". Unique doesn't imply random and the generated java.rmi.server.UID is sequential, with just the last digit being changed on each new call to its constructor. Here are a few examples of UID (before special character trimming) and the resulting base62 encoded string: Generated UID Base62 encoded result -3e91460a:12d0f663ca9:-7ffa i5E0S6Fc5oT0s2KGdZiZpmPCsYC -3e91460a:12d0f663ca9:-7ff9 i5E0S6Fc5oT0s2KAykor65eXV8u -3e91460a:12d0f663ca9:-7ff8 i5E0S6Fc5oT0s2KuSFtUONEjpim As only a Base62 encoding is used, an initial token can be decoded to get the UID and therefore generate the upcoming valid tokens: groovy> def BASE62 = (('a'..'z')+('A'..'Z')+('0'..'9')).join() groovy> def value = 'j2p7eT40VBBfqMOexPMBBvnzafs' groovy> BigInteger v = 0 groovy> def digitMax = BASE62.size().toInteger() groovy> value.toString().each { c -> groovy> v *= digitMax groovy> v += BASE62.indexOf(c) groovy> } groovy> println v.toByteArray() groovy> def txt = '' groovy> v.toByteArray().each() { i -> groovy> txt += Integer.toHexString(0xFF & i) groovy> } groovy> print txt [69, 53, -83, -25, 18, -48, -126, 10, 105, 103, -5, -3, -22, -37, -18, -3, -22, -37, -18, -16] 4535ade712d082a6967fbfdeadbeefdeadbeef0 4535ade712d082a6967fbf being the trimmed RMI.UID and deadbeefdeadbeef the appended static hex string. The final 0 is nothing but a padding to avoid having the Base62 encoding failing. Therefore an attacker would just need to get 1 token, decode it and generate all the subsequent tokens by decreasing the RMI UID by one to bypass the email confirmation feature. Workaround / Fix: ----------------- Use the secure random java.security.SecureRandom object instead of the java.rmi.server.UID constructor. Timeline: --------- 2011-05-03: Release of fixed Version 1.0.5 2011-04-21: Initial vendor response 2011-04-21: Initial vendor notification 2011-04-05: Assigned CVE-2011-1600 2010-12-22: Discovery by Alexandre Herzog References: ----------- [1] http://www.grails.org/plugin/email-confirmation [2] http://en.wikipedia.org/wiki/Grails_(framework) [3] File grails-app\domain\com\grailsrocks\emailconfirmation\PendingEmailConfirmation.groovy [4] http://download.oracle.com/javase/6/docs/api/java/rmi/server/UID.html