fork download
  1. import java.io.*;
  2. import java.net.*;
  3. import java.util.Arrays;
  4.  
  5. /**
  6. * In this project you will experiment with a padding oracle attack against a toy web site hosted at
  7. * crypto-class.appspot.com. Padding oracle vulnerabilities affect a wide variety of products, including secure tokens.
  8. * This project will show how they can be exploited. We discussed CBC padding oracle attacks in Lecture 7.6, but if you
  9. * want to read more about them, please see Vaudenay's paper.
  10. * <p/>
  11. * Now to business. Suppose an attacker wishes to steal secret information from our target web site
  12. * crypto-class.appspot.com. The attacker suspects that the web site embeds encrypted customer data in URL parameters
  13. * such as this:
  14. * <p/>
  15. * http://c...content-available-to-author-only...t.com/po?er=f20bdba6ff29eed7b046d1df9fb7000058b1ffb4210a580f748b4ac714c001bd4a61044426fb515dad3f21f18aa577c0bdf302936266926ff37dbf7035d5eeb4
  16. * <p/>
  17. * That is, when customer Alice interacts with the site, the site embeds a URL like this in web pages it sends to Alice.
  18. * The attacker intercepts the URL listed above and guesses that the ciphertext following the "po?er=" is a hex encoded
  19. * AES CBC encryption with a random IV of some secret data about Alice's session.
  20. * <p/>
  21. * After some experimentation the attacker discovers that the web site is vulnerable to a CBC padding oracle attack. In
  22. * particular, when a decrypted CBC ciphertext ends in an invalid pad the web server returns a 403 error code (forbidden
  23. * request). When the CBC padding is valid, but the message is malformed, the web server returns a 404 error code (URL not found).
  24. * <p/>
  25. * Armed with this information your goal is to decrypt the ciphertext listed above. To do so you can send arbitrary HTTP
  26. * requests to the web site of the form http://c...content-available-to-author-only...t.com/po?er="your ciphertext here" and observe the
  27. * resulting error code. The padding oracle will let you decrypt the given ciphertext one byte at a time. To decrypt a
  28. * single byte you will need to send up to 256 HTTP requests to the site. Keep in mind that the first ciphertext block
  29. * is the random IV. The decrypted message is ASCII encoded.
  30. * <p/>
  31. * To get you started here is a short Python script that sends a ciphertext supplied on the command line to the site and
  32. * prints the resulting error code. You can extend this script (or write one from scratch) to implement the padding
  33. * oracle attack. Once you decrypt the given ciphertext, please enter the decrypted message in the box below.
  34. * <p/>
  35. * This project shows that when using encryption you must prevent padding oracle attacks by either using encrypt-then-MAC
  36. * as in EAX or GCM, or if you must use MAC-then-encrypt then ensure that the site treats padding errors the same way it
  37. * treats MAC errors.
  38. */
  39. public class Lesson04 {
  40. final protected static char[] HEX_ARRAY = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
  41. public static final int BLOCK_SIZE = 16;
  42. public static final String CIPHER_TEXT = "f20bdba6ff29eed7b046d1df9fb7000058b1ffb4210a580f748b4ac714c001bd4a61044426fb515dad3f21f18aa577c0bdf302936266926ff37dbf7035d5eeb4";
  43. public static final String ATTACK_URL = "http://c...content-available-to-author-only...t.com/po?er=";
  44.  
  45. public static void main(String[] args) throws IOException {
  46. // cipher text
  47. byte[] c = hexStringToByteArray(CIPHER_TEXT);
  48. // decrypted text
  49. String d = "";
  50.  
  51. for (int block = 0; block < (c.length - BLOCK_SIZE) / BLOCK_SIZE; block++) {
  52. // copy current block and all previous
  53. byte[] cb = Arrays.copyOfRange(c, 0, c.length - block * BLOCK_SIZE);
  54.  
  55. for (int i = 0; i < BLOCK_SIZE; i++) {
  56.  
  57. byte[] cm = cb.clone();
  58. byte found = 0;
  59.  
  60. // position of byte that will be guessed
  61. int pos = cb.length - 1 - BLOCK_SIZE - i;
  62.  
  63. // try to guess value of this byte
  64. for (int b = 0; b < 256; b++) {
  65.  
  66. // pad all bytes from current to the end of the block
  67. for (int k = 0; k < i + 1; k++) {
  68. cm[pos + k] = (byte) (cb[pos + k] ^ (i + 1));
  69. }
  70.  
  71. // xor byte with guessed value
  72. cm[pos] = (byte) (cm[pos] ^ b);
  73.  
  74. int status = getUrlStatus(ATTACK_URL + byteArrayToHexString(cm));
  75.  
  76. // Log request
  77. System.out.println(block + ":" + i + ":" + pos + ":" + b + "> " + status + " = " + byteArrayToHexString(cm));
  78.  
  79. if (status == 404) {
  80. // pad is correct
  81. found = (byte) b;
  82. break;
  83. } else if (status == 200) {
  84. // pad is correct or no changes to guessed value are made
  85. // this can happen if pad equals guessed value, then
  86. // pad ^ guessed = 0
  87. // save this value as possible result
  88. // but wait if 404 is returned
  89. found = (byte) b;
  90. }
  91. }
  92.  
  93. // save found value for next round
  94. cb[pos] = (byte) (cb[pos] ^ found);
  95.  
  96. // save to decrypted value
  97. d = (char) found + d;
  98.  
  99. // Log decrypted value
  100. System.out.println("found >> " + found + " = " + d);
  101. System.out.println();
  102. }
  103. }
  104. }
  105.  
  106. public static int getUrlStatus(String urlPath) throws IOException {
  107. URL url = new URL(urlPath);
  108. URLConnection connection = url.openConnection();
  109.  
  110. connection.connect();
  111.  
  112. if (connection instanceof HttpURLConnection) {
  113. HttpURLConnection httpConnection = (HttpURLConnection) connection;
  114.  
  115. return httpConnection.getResponseCode();
  116. } else {
  117. return 0;
  118. }
  119. }
  120.  
  121. public static byte[] hexStringToByteArray(String s) {
  122. int len = s.length();
  123. byte[] data = new byte[len / 2];
  124. for (int i = 0; i < len; i += 2) {
  125. data[i / 2] = (byte) ((Character.digit(s.charAt(i), BLOCK_SIZE) << 4)
  126. + Character.digit(s.charAt(i + 1), BLOCK_SIZE));
  127. }
  128. return data;
  129. }
  130.  
  131. public static String byteArrayToHexString(byte[] bytes) {
  132. char[] hexChars = new char[bytes.length * 2];
  133. int v;
  134. for (int j = 0; j < bytes.length; j++) {
  135. v = bytes[j] & 0xFF;
  136. hexChars[j * 2] = HEX_ARRAY[v >>> 4];
  137. hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
  138. }
  139. return new String(hexChars);
  140. }
  141.  
  142. }
Compilation error #stdin compilation error #stdout 0s 0KB
stdin
Standard input is empty
compilation info
Main.java:39: error: class Lesson04 is public, should be declared in a file named Lesson04.java
public class Lesson04 {
       ^
1 error
stdout
Standard output is empty