Let's Get Random: Under the Hood of PHP 7's CSPRNG - PNWPHP 2017

Let's Get Random: Under the Hood of PHP 7's CSPRNG - PNWPHP 2017

Talk given at Pacific Northwest PHP 2017

Randomness is really important in many cryptographic contexts. Unfortunately true randomness is a non-trivial achievement for computers. In fact, using weak sources of randomness can leave your application open to myriad vulnerabilities. Enter: a good cryptographically secure pseudorandom number generator (CSPRNG). We'll discuss the importance of using good sources of randomness, the CSPRNG options we had in PHP 5.x, and how the new-goodness CSPRNG functions in PHP 7 work under the hood.

8c090cc1ccd623a146ddd9159b1bf7e2?s=128

Sammy Kaye Powers

September 08, 2017
Tweet

Transcript

  1. Random Under the hood of PHP 7’s Let’s get CSPRNG

    Sammy Kaye Powers 2017-09-08
  2. joind.in/talk/da53c @SammyK #PNWPHP Slides Get the joind.in/talk/da53c

  3. joind.in/talk/da53c @SammyK #PNWPHP ext/standard/random.c

  4. joind.in/talk/da53c @SammyK #PNWPHP The end

  5. joind.in/talk/da53c @SammyK #PNWPHP Random? What is

  6. joind.in/talk/da53c @SammyK #PNWPHP

  7. joind.in/talk/da53c @SammyK #PNWPHP Finish this sentence On the way home

    I got a flat ____. tire
  8. joind.in/talk/da53c @SammyK #PNWPHP Think of a two-digit number both digits

    different from each other both digits odd between 1 and 100
  9. joind.in/talk/da53c @SammyK #PNWPHP Are you thinking of… 37

  10. joind.in/talk/da53c @SammyK #PNWPHP

  11. joind.in/talk/da53c @SammyK #PNWPHP 11 random? What makes a number

  12. joind.in/talk/da53c @SammyK #PNWPHP 2, 4, 6, 8, __ 10

  13. joind.in/talk/da53c @SammyK #PNWPHP 1337, 42, 0, _ ?

  14. joind.in/talk/da53c @SammyK #PNWPHP 1337, 42, 0, 1337, 42, 0, 1337,

    __ 42
  15. joind.in/talk/da53c @SammyK #PNWPHP Random? What is isn’t Deterministic

  16. joind.in/talk/da53c @SammyK #PNWPHP “True” Random Measurement of atmospheric noise Count

    of the number of electrons coming off of a radioactive material
  17. None
  18. joind.in/talk/da53c @SammyK #PNWPHP Can I haz random number?

  19. joind.in/talk/da53c @SammyK #PNWPHP

  20. joind.in/talk/da53c @SammyK #PNWPHP

  21. joind.in/talk/da53c @SammyK #PNWPHP *sigh* Take this. 42

  22. joind.in/talk/da53c @SammyK #PNWPHP

  23. joind.in/talk/da53c @SammyK #PNWPHP 0

  24. joind.in/talk/da53c @SammyK #PNWPHP 2,4,8, 7,5,1 ?

  25. joind.in/talk/da53c @SammyK #PNWPHP Number Generator …or “PRNG” for short Pseudorandom

  26. joind.in/talk/da53c @SammyK #PNWPHP Pseudorandom? How’s that different than just random?

    Deterministic
  27. joind.in/talk/da53c @SammyK #PNWPHP 2,4,8, 7,5,1 Generator Linear Congruential

  28. joind.in/talk/da53c @SammyK #PNWPHP Generator Linear Congruential

  29. joind.in/talk/da53c @SammyK #PNWPHP

  30. joind.in/talk/da53c @SammyK #PNWPHP The modulus The multiplier The increment The

    seed
  31. joind.in/talk/da53c @SammyK #PNWPHP

  32. joind.in/talk/da53c @SammyK #PNWPHP

  33. joind.in/talk/da53c @SammyK #PNWPHP 2,4,8, 7,5,

  34. joind.in/talk/da53c @SammyK #PNWPHP 2,4,8, 7,5, Deterministic

  35. joind.in/talk/da53c @SammyK #PNWPHP https://xkcd.com/221/

  36. joind.in/talk/da53c @SammyK #PNWPHP

  37. joind.in/talk/da53c @SammyK #PNWPHP

  38. joind.in/talk/da53c @SammyK #PNWPHP 8,7,5, 1,2,

  39. joind.in/talk/da53c @SammyK #PNWPHP 1,2,4, 8,7, BUT!

  40. joind.in/talk/da53c @SammyK #PNWPHP

  41. 5,1,2,4,8,7,5, 1,2,4,8,7,5,1, 2,4,8,7,5,1,2, 4,8,7,5,1,2,4, 8,7,5,1,2,4,8, 7,5,1,2,4, Predictable

  42. joind.in/talk/da53c @SammyK #PNWPHP LCG lcg_value() PHP has a combined

  43. joind.in/talk/da53c @SammyK #PNWPHP PRNG? Is there a better

  44. joind.in/talk/da53c @SammyK #PNWPHP Twister Mersenne mt_rand()

  45. joind.in/talk/da53c @SammyK #PNWPHP

  46. mt_rand() 724937621,955931554,1407935661,821438740,109344 9922,603009103,1540988686,1028238631,798475733, 1057939018,671583233,1853117923,98760648,112245 3373,534404057,900958085,1712824654,476385742,2 9956470,362833620,424798798,746223917,942003531 ,320462445,673296853,1351199651,141566289,16454 09515,995047403,1216151582,1115999460,175322091 7,1312071810,1553254094,1622498991,2080099801,1 704834715,1537620663,1357630828,1317892558,

    219,937-1
  47. joind.in/talk/da53c @SammyK #PNWPHP

  48. mt_rand(0,99) 83,9,64,28,62,48,83,47,46,53,37,26,21,91,61,32,58,1,89,60,65,97,42,56,6,47,76,1 2,98,11,36,61,62,60,43,67,6,16,73,15,39,38,56,19,66,56,98,72,91,24,57,94,8,26,7 3,55,17,14,84,89,39,11,13,48,71,98,89,63,9,95,74,9,81,85,97,24,14,14,77,22,96,4 3,61,91,61,58,19,71,8,49,18,92,38,34,9,36,91,59,14,4,58,59,29,74,52,41,36,67,82 ,67,11,0,58,51,37,4,45,56,35,50,78,91,27,39,80,27,28,95,2,82,51,72,27,41,43,74, 7,82,59,89,72,9,22,61,75,27,64,16,77,57,31,29,59,47,14,67,89,33,94,33,94,22,11, 62,9,13,61,45,78,29,3,11,99,91,52,79,63,64,43,99,53,22,16,10,53,57,15,84,16,30, 17,10,3,35,0,45,83,11,70,66,37,14,59,41,46,52,53,53,62,56,41,82,40,99,8,92,96,2 2,22,43,35,60,45,77,26,96,45,51,62,77,64,23,52,17,17,97,93,57,43,56,45,62,42,24

    ,62,1,59,38,70,13,34,32,48,47,1,42,48,18,2,59,47,53,10,3,66,68,93,4,53,85,20,77 ,63,43,45,16,15,77,73,89,11,64,76,30,46,91,1,85,96,19,63,70,62,35,58,95,63,38,7 8,83,8,97,22,2,28,51,25,29,98,62,74,59,95,79,74,66,47,35,83,56,49,25,32,25,46,1 3,69,77,30,94,24,31,68,23,64,47,28,33,65,69,16,0,98,37,85,93,60,24,10,54,50,42, 64,11,9,13,15,84,3,23,73,83,83,72,9,2,28,23,90,73,2,47,45,93,4,32,25,75,61,98,7 3,79,66,23,20,83,11,45,67,40,39,45,0,65,40,78,74,8,79,86,38,10,87,60,99,30,35,5 0,16,29,24,19,29,16,40,57,87,26,90,1,63,63,34,44,8,36,25,38,50,10,15,17,14,40,6 ,53,88,18,36,46,69,2,13,0,83,59,92,59,34,34,24,40,99,41,6,79,65,98,9,36,31,8,4, 89,98,91,80,42,10,26,72,40,50,39,25,33,45,24,70,54,89,91,53,23,12,20,40,21,25,5 5,48,11,3,84,42,5,7,21,58,85,18,52,92,94,69,20,49,3,8,55,57,4,38,52,37,64,55,82 ,98,5,75,84,35,14,99,74,23,41,69,55,53,22,52,6,68,35,38,73,52,22,52,86,79,15,38 ,3,20,99,36,23,77,33,80,16,97,54,88,11,77,77,99,70,26,5,75,87,4,23,8,50,79,61,5 5,80,25,58,79,25,56,9,81,6,42,27,90,58,6,62,74,25,79,81,61,23,54,92,53,16,66,22 ,49,77,97,84,25,49,32,49,65,51,1,93,63,68,69,67,10,44,99,44,42,89,35,24, 624 = busted
  49. echo mt_rand(0,99); 11

  50. echo mt_rand(0,99); 9

  51. echo mt_rand(0,99); 60

  52. mt_srand(10); echo mt_rand(0,99); 21

  53. mt_srand(10); echo mt_rand(0,99); 21

  54. mt_srand(10); echo mt_rand(0,99); 21

  55. joind.in/talk/da53c @SammyK #PNWPHP CSRF Take for example Tokens

  56. joind.in/talk/da53c @SammyK #PNWPHP Cross-site request forgery (CSRF) tokens help prevent

    unauthorized requests on a user’s behalf.
  57. joind.in/talk/da53c @SammyK #PNWPHP A CSRF token must be unique and

    unpredictable.
  58. joind.in/talk/da53c @SammyK #PNWPHP

  59. joind.in/talk/da53c @SammyK #PNWPHP

  60. joind.in/talk/da53c @SammyK #PNWPHP

  61. joind.in/talk/da53c @SammyK #PNWPHP I’ll just let PHP seed mt_rand() for

    me. Bad idea jeans *Old SNL skit reference
  62. joind.in/talk/da53c @SammyK #PNWPHP

  63. joind.in/talk/da53c @SammyK #PNWPHP What about rand() you ask?

  64. joind.in/talk/da53c @SammyK #PNWPHP Nope

  65. joind.in/talk/da53c @SammyK #PNWPHP rand() mt_rand() …in PHP 7.0 & below

  66. joind.in/talk/da53c @SammyK #PNWPHP rand() Uses the system PRNG (unreliable &

    inconsistent) Is a PRNG (totes predictable) Uniform distribution issues
  67. joind.in/talk/da53c @SammyK #PNWPHP Uniform Distribution

  68. joind.in/talk/da53c @SammyK #PNWPHP 0 0.05 0.1 0.15 0.2 1 2

    3 4 5 6
  69. joind.in/talk/da53c @SammyK #PNWPHP 0 0.1 0.2 0.3 0.4 1 2

    3 4 5 6
  70. joind.in/talk/da53c @SammyK #PNWPHP Uniform Distribution == True Random

  71. joind.in/talk/da53c @SammyK #PNWPHP mt_rand() Implements the MT algorithm incorrectly Is

    a PRNG (totes predictable) Has a modulo bias
  72. joind.in/talk/da53c @SammyK #PNWPHP Modulo Bias

  73. joind.in/talk/da53c @SammyK #PNWPHP 6 % 3 = 0 8 %

    3 = 2 Modulo Operator
  74. joind.in/talk/da53c @SammyK #PNWPHP Random # between 0 & 1 n

    % 2 = 0 or 1 Use mod 2
  75. joind.in/talk/da53c @SammyK #PNWPHP rand_src() = 1, 2, or 3 2

    % 2 = 0 3 % 2 = 1 1 is more likely 1 % 2 = 1
  76. joind.in/talk/da53c @SammyK #PNWPHP rand() mt_rand() …in PHP 7.1 & above

  77. joind.in/talk/da53c @SammyK #PNWPHP mt_rand() Fixes bug in MT algorithm implementation

    Is a PRNG (totes predictable)
  78. joind.in/talk/da53c @SammyK #PNWPHP They’re totes samezies! rand() mt_rand() ===

  79. joind.in/talk/da53c @SammyK #PNWPHP

  80. joind.in/talk/da53c @SammyK #PNWPHP rand() mt_rand() Both suffer from modulo bias

    &
  81. joind.in/talk/da53c @SammyK #PNWPHP Seeds aren’t impossible to predict

  82. joind.in/talk/da53c @SammyK #PNWPHP Entropy *Could be it’s own talk

  83. joind.in/talk/da53c @SammyK #PNWPHP A measure of how accurately we’re able

    to predict the next value in a sequence.* * oversimplification
  84. joind.in/talk/da53c @SammyK #PNWPHP High entropy harder to predict Low entropy

    easier to predict
  85. joind.in/talk/da53c @SammyK #PNWPHP Cryptographically Pseudorandom Secure Number Generator

  86. joind.in/talk/da53c @SammyK #PNWPHP CSPRNG or…

  87. joind.in/talk/da53c @SammyK #PNWPHP “See Spring” or…

  88. Unicorn Magical

  89. Uses seeds that are really really really really ridiculously hard

    to guess
  90. joind.in/talk/da53c @SammyK #PNWPHP High Entropy wee!

  91. joind.in/talk/da53c @SammyK #PNWPHP impossible It’s values are to predict in

    practice 42 82 Suitable for use in cryptographic contexts.
  92. mythical Where can we find this creature?

  93. joind.in/talk/da53c @SammyK #PNWPHP CSPRNG options in 5.x

  94. joind.in/talk/da53c @SammyK #PNWPHP openssl_random_pseudo_bytes() mcrypt_create_iv() /dev/urandom

  95. joind.in/talk/da53c @SammyK #PNWPHP openssl_random_pseudo_bytes() mcrypt_create_iv() /dev/urandom

  96. joind.in/talk/da53c @SammyK #PNWPHP Since the UNIX fork() system call duplicates

    the entire process state, a random number generator which does not take this issue into account will produce the same sequence of random numbers in both the parent and the child […], leading to cryptographic disaster… https://wiki.openssl.org/index.php/Random_fork-safety
  97. joind.in/talk/da53c @SammyK #PNWPHP OpenSSL’s be like 42 CSPRNG

  98. joind.in/talk/da53c @SammyK #PNWPHP OpenSSL cannot fix the fork-safety problem because

    its not in a position to do so. However, there are [solutions] available and they are listed below. https://wiki.openssl.org/index.php/Random_fork-safety
  99. joind.in/talk/da53c @SammyK #PNWPHP Don't use RAND_bytes https://wiki.openssl.org/index.php/Random_fork-safety

  100. joind.in/talk/da53c @SammyK #PNWPHP Instead, you can read directly from /dev/random,

    /dev/urandom or /dev/srandom; or use CryptGenRandom on Windows systems. https://wiki.openssl.org/index.php/Random_fork-safety
  101. joind.in/talk/da53c @SammyK #PNWPHP mcrypt_create_iv() /dev/urandom openssl_random_pseudo_bytes()

  102. joind.in/talk/da53c @SammyK #PNWPHP

  103. joind.in/talk/da53c @SammyK #PNWPHP

  104. joind.in/talk/da53c @SammyK #PNWPHP

  105. joind.in/talk/da53c @SammyK #PNWPHP /dev/urandom openssl_random_pseudo_bytes() mcrypt_create_iv()

  106. joind.in/talk/da53c @SammyK #PNWPHP open_basedir=/foo/dir

  107. joind.in/talk/da53c @SammyK #PNWPHP openssl_random_pseudo_bytes() mcrypt_create_iv() /dev/urandom

  108. joind.in/talk/da53c @SammyK #PNWPHP CSPRNG New goodness 7

  109. joind.in/talk/da53c @SammyK #PNWPHP CSPRNG random_int() random_bytes()

  110. random_int(0,99) 6,17,6,9,17,53,58,98,46,44,62,9,76,65,46,21,42,5,65,34,11,96,85,7,46,89,98,9,9, 80,8,76,87,18,24,68,16,61,27,39,30,32,4,83,83,23,96,27,13,47,6,99,16,40,2,75,27 ,3,79,68,75,60,50,70,63,17,75,29,79,57,9,48,18,86,95,25,40,52,20,86,6,48,94,27, 76,14,9,27,62,14,68,58,12,18,63,19,84,47,7,13,63,28,66,55,2,75,44,92,11,85,51,1 7,42,57,22,4,53,7,3,76,48,55,95,7,45,33,87,36,11,17,66,6,46,87,57,48,22,31,65,5 ,26,10,47,82,97,74,25,32,63,60,29,53,13,24,56,54,52,86,67,4,94,35,48,73,35,45,2 4,74,74,83,49,70,41,49,20,60,29,49,30,35,38,63,4,86,72,97,26,22,36,95,59,94,24, 89,73,46,14,73,51,93,93,39,13,80,9,30,24,20,30,63,20,64,97,29,7,2,82,96,42,61,5 3,28,49,12,90,71,58,72,63,49,32,69,76,50,62,88,31,26,72,79,19,15,3,39,27,80,16,

    65,62,53,82,59,23,85,95,41,68,86,3,92,76,91,88,12,20,96,14,35,50,94,24,23,44,55 ,78,65,81,7,1,86,32,58,46,97,43,78,9,51,1,6,79,73,49,13,40,21,90,14,9,70,95,88, 37,85,14,7,29,42,55,81,46,39,41,45,81,11,93,26,89,4,98,35,30,36,74,97,18,85,97, 23,52,64,88,20,89,12,25,19,21,21,50,60,50,43,84,1,52,5,19,2,86,38,51,48,30,55,9 0,93,97,52,84,29,58,96,78,37,24,14,72,81,9,82,26,83,83,17,35,15,9,87,95,51,71,4 8,9,45,13,61,98,3,18,96,99,28,74,47,58,71,89,68,57,51,86,90,38,21,72,72,30,22,1 3,88,25,48,45,62,59,81,32,10,54,82,60,90,17,98,41,73,98,60,22,99,66,32,41,82,62 ,91,3,85,91,21,17,98,19,48,50,24,67,3,14,62,55,35,99,95,83,76,12,51,77,61,24,24 ,60,15,31,47,24,27,97,98,70,6,24,25,20,23,67,72,55,47,19,53,50,38,22,76,37,63,8 2,67,52,3,75,84,84,71,49,79,26,89,11,77,55,92,32,81,38,23,54,9,40,80,75,20,7,58 ,37,72,75,59,46,32,41,82,90,72,59,5,42,2,94,44,44,4,15,37,29,24,10,51,18,8,42,5 6,9,68,31,99,7,77,59,8,74,80,11,15,93,81,5,72,44,49,39,25,4,18,98,0,93,42,78,36 ,57,47,16,49,2,85,6,31,17,81,10,54,40,95,68,31,80,29,41,86,32,9,58,96,62,79,25, 6,45,56,54,0,61,74,90,12,34,11,56,3,41,39,84,32,30,42,81,36,43,5,
  111. joind.in/talk/da53c @SammyK #PNWPHP bin2hex(random_bytes(16)) f7f5289027cb6c5116d 2d3cc78e5819c

  112. joind.in/talk/da53c @SammyK #PNWPHP You’re not strong until you’re crypto-strong!

  113. CSPRNG under the hood

  114. None
  115. joind.in/talk/da53c @SammyK #PNWPHP On Windows: CryptGenRandom On BSD: arc4random_buf() On

    Linux: getrandom(2) syscall Read directly from /dev/urandom
  116. Fail Closed

  117. joind.in/talk/da53c @SammyK #PNWPHP /dev/urandom So what is this thing?

  118. /dev/urandom Gathers environmental noise from the system like… …device drivers,

    inter-keyboard timings, inter-interrupt timings from some interrupts, and other events which are both (a) non-deterministic and (b) hard for an outside observer to measure. https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/random.c
  119. joind.in/talk/da53c @SammyK #PNWPHP CSPRNG random_bytes() random_int() 7 /dev/urandom Powered by

  120. joind.in/talk/da53c @SammyK #PNWPHP Still on 5.x? paragonie/random_compat Polyfill for PHP

    7 CSPRNG
  121. joind.in/talk/da53c @SammyK #PNWPHP TL;DR Never use LCG, MT, or any

    other PRNG in cryptographic contexts Only use a CSPRNG like /dev/urandom for crypto Use random_bytes() & random_int() in PHP (or install paragonie/random_compat)
  122. joind.in/talk/da53c @SammyK #PNWPHP More Resources

  123. joind.in/talk/da53c @SammyK #PNWPHP Recommendation for the Entropy Sources Used for

    Random Bit Generation Second Draft - NIST SP 800-90B http://csrc.nist.gov/publications/drafts/800-90/sp800-90b_second_draft.pdf
  124. joind.in/talk/da53c @SammyK #PNWPHP New & improved man pages for /dev/urandom

    http://man7.org/linux/man-pages/man7/random.7.html
  125. joind.in/talk/da53c @SammyK #PNWPHP Myths about /dev/urandom Thomas Hühn https://www.2uo.de/myths-about-urandom/

  126. joind.in/talk/da53c @SammyK #PNWPHP Cracking Random Number Generators Three-part blog post

    series James Roper https://jazzy.id.au/2010/09/20/cracking_random_number_generators_part_1.html
  127. joind.in/talk/da53c @SammyK #PNWPHP How I Met Your Girlfriend DEF CON

    18 Samy Kamkar https://www.youtube.com/watch?v=fWk_rMQiDGc
  128. joind.in/talk/da53c @SammyK #PNWPHP Weak RNG in PHP session ID generation

    leads to session hijacking Andreas Bogk http://seclists.org/fulldisclosure/2010/Mar/519
  129. @SammyK SammyK.me THANKS! SAMMY KAYE POWERS Host of @PHPRoundtable @ChiPHPUG

    West Coast Swing /talk/da53c I have stickers!