CodeSOD: The 5-Digit Session Identifier
Sawyer was talking with a co-worker about how their unique session IDs got created. The concern was that they were only five characters long, which meant there could easily be collisions.
They started by looking at the random number generation function.
Public Function RandomNumberGenerator(ByVal min As Integer, ByVal max As Integer, Optional ByVal numDecimals As Integer = 0) As String '*** the generates a number as a string Dim strNum As New StringBuilder Dim rnd As New System.Random Dim i, x, n As Integer Try i = rnd.Next(min, max) If numDecimals > 0 Then Try strNum.Append("9", numDecimals) n = CType(strNum.ToString, Int32) x = rnd.Next(0, n) Catch ex As Exception x = 1 End Try End If strNum.Remove(0, strNum.Length) strNum.Append(i.ToString()) If numDecimals > 0 Then strNum.Append(".") If numDecimals > 99 Then numDecimals = 99 End If strNum.Append(x.ToString("D" & numDecimals.ToString())) End If Return strNum.ToString Catch Return "1.00" End Try End Function
You always know it's going to be bad when you see the random number generator returns a string.
If numDecimals is zero, the code is bad, but vaguely sane. Generate a random number using the built in functions, then return it- as a string.
It's the use of numDecimals which makes this weird. We start by appending "9"s to our string builder, converting it to an integer, and then generating a random number from zero to whatever number of nines we're using. This is the code of someone who hates and fears logarithms.
Then we clear out our string builder because we're starting over with the actual number. Then we append a ".", then we append our number, formatted with our number of decimals string, which we force to be no larger than 99. And this is where we get the special kind of weird.
When we're generating our random decimal number, we do this: strNum.Append("9", numDecimals). This is going to put numDecimals 9s on the string. E.g., if numDecimals is 9, this would set strNum to be 999999999. Thus, when we generate a random number, we generate one between 0 and 99999999.
But, when we append that formatted value to the string, we do this:
If numDecimals > 99 Then numDecimals = 99End IfstrNum.Append(x.ToString("D" & numDecimals.ToString()))
Here, we're treating numDecimals as a format string. We're only ever going to output two digits.
The only good news is that while this random function was used everywhere, it wasn't used to generate their random IDs. The bad news, this is how their random IDs.
Public Function RandomQueryStringGenerator() As String '*** the generates an alpha-numeric string 5 digits long such as aa7bb Dim strPwd As New StringBuilder Dim rnd As New System.Random Dim i As Integer Try For x As Integer = 1 To 5 Select Case x Case 1, 2, 4, 5, 8, 9 i = rnd.Next(97, 122) If i Mod 2 = 0 Then strPwd.Append(Chr(i).ToString().ToUpper()) Else strPwd.Append(Chr(i).ToString()) End If Case Else i = rnd.Next(0, 9) strPwd.Append(i.ToString()) End Select Next x Return strPwd.ToString() Catch Return String.Empty End Try End Function
