 Hi, everyone. My talk is going to be on breaking PRNG, pseudo-random generator. There have been many talks in the past on PRNG, a good one on Black Hat in 2013 and 2013 about various types of PRNG. In general, it's really low talk with a lot of content. I'm going to try to focus on one algorithm, so bear with me, it's going to be a mathematics a bit, but really easy stuff, multiplication, addition, so you should follow. It's going to be very visual, no absolute code, so it should be really visual. There's one recent talk I should mention that specifically addressed Merchant Twister that was done at B-Site Las Vegas, which is also a good talk because it focused only on one algorithm. Instead of seeing so many algorithms in one talk and not understanding fully one algorithm, it's good to have a really specific subject, and my target will be LCG, so linear congruential generator. So the way I divide my talk, there's going to be a first part, which is going to be a vulnerability that I found in a Java framework specifically in Struts and Spring. LCG are in many languages, so it's a categories of a generator I'm going to present, so it's also going to apply on another language, and after at the end I'm going to present tooling, so what can you do in your pentest that you do, but the first part will be more theoretical, but also how the exploitation works, because since you need to understand really how it works to exploit it if you have the source code, or if you're trying to guess how the stem works, it's really important to have a good understanding of how it works. You can not just blindly use tools. So, yeah. So first, there are many types of pseudo-random generators. So pseudo-random generators are generators that are not targeting security, but they are in a language to generate value, because we always need random value if it's a game that you need to generate anything that is not linear. But the most common implementation we see is linear congruential generator. So the language, if they use LCG, it's going to be the same algorithm, but they use different constants. So it's a smaller variation, but the mechanism I'm going to present, if you see an LCG in another language, it's going to be the same thing, just different constants, same operation. Arribaise, it's a different category that we see across a different language. Mercent Twister is used. So in PHP, when you see anti-rand, that's Mercent Twister, but that's not the focus of this talk. And there are many algorithms that are specific to language, for example, V8, as its own specific algorithm. Same thing for Pearl. So there are still many algorithms, but LCG and Mercent Twister are the most common one. So this is the focus of my presentation. So you're probably not going to be able to read the snippet of code, but I hope so. So just a small puzzler to maybe have an interest for what's going to follow in the presentation. We have a snippet of code that is taken from Spring, which is actually still in the code. So they need to generate ID for various types of things. So it's going to be unique identifier for messaging, for ID in database, but it's basically a good representation of an ID. So in two lines, what it does is first generating with secure random value, then it's using this value as a seed for the random, to a random instance, and then it's obtaining value from it. So the important step to identify, so maybe I give you 10 seconds to think about it. So the first part is generating value from secure random, then passing it to random instance, and then obtaining the next value. So the thing to see and a potential weakness, it's potentially the developer saw the implementation of random and saw, okay, the default seed is just the timestamp, current millisecond. So we're going to try to have something secure. So we're going to generate a random seed to be sure that nobody can predict our value. But the thing is that the seed is secure, but the random instance is going to be used, the state is going to be predictable. And this is what my talk would focus. So if we can receive some value, we're going to be able to predict all the previous one and all the following one, okay? So just to highlight that first it was secure random that was used, but in the end the values are generated from a random instance. So in other language, the different part time is we have random API and secure random, and just in another language in C sharp, you're going to see system random, and there's in the cryptography namespace random number generators. So in our language, you're always going to have the basic random one that is the quickest to use, and then there's a cryptographically secure API. So what's really the difference between those two types of API? So LCG versus secure random, what goal is it trying to achieve? So first, the goal is not security. The idea is to have equal distribution. So if you're generating random value for a game or to just generate data, you don't want to have the same value repeat. So you generate two, three, and then all of a sudden it's just the same value. So it breaks the purpose of having a random value. So it should be equalized, equal distribution among a large set of values. So that's the objective. But so far, nothing about I cannot predict the next value or the previous one. And also performance. So if you're doing a game and you're generating values or you need anything that doesn't require security, you don't want to spend too much CPU effort on generating those values because it's going to slow down your application if you have no security requirements. On the other end, cryptographically secure random have different objectives. So first, the equal distribution is also going to be a characteristic because if the first few bits are always, have more probability to be such a value than others, then it's not cryptographically secure. But the most important criteria is it needs to be unpredictable. So if you have one value, you shouldn't be able to predict the next one. So that's what those API has as a contract. So we know the API says it's secure and the other one has comment in the documentation shouldn't be used as a secure, but if you see those API being used, so is it explorable in practice? And the answer is most of the time it's going to be explorable. So the next step, now that we know that the SCG are not secure, I'm going to describe how an SCG work and we're going to see where it can be attacked. So the SCG algorithm will be the same if it's an SCG in whatever language. The constant, if I mention some, it will be associated to the Java implementation. But it's going to be the same algorithm across different language. So you're going to see each box being as a state of the value. So as the added box is created, it's just an evolution of the value. So everything starts with a seed. So the seed could be a timestamp or a random value or a static value. But we need a starting point. So that's the state of the SCG at the time zero. So the first step we do in an SCG, it's a multiplication with a constant. So the language will choose a generally big value. Then there's an add-in with a generally small value. And then the 48-bit are going to be kept. It's the most, the less significant one that are going to be kept. But sometimes it's truncation due to overflow. But in this case, in Java, it's really the only kept 48-bit. Then we have our second state. So that's a seed. But that's not the value that we first generated. So the first integer we're going to take from the seed, only the 42-bit, but the most significant one that were kept from the previous state. So then we have one value generated. And this is the same state we're going to go through for each value we want to generate. So basically, we have generate value one and then value two. It's going to be the same operation one after the other. So, okay. So we have the same step, but with a value. So we have an initial seed of 1337, so we multiply it with the big multiplier. We have another value. We add it BL, which is just B, actually. And then we do a XOR with those FFF. So actually at the bottom is the current value. So we multiply the value with this constant. Then we add the value B, which is L just for long. It's an artifact. And then we XOR it with FFF to just keep the bits we want, the less significant one. Then this is going to be RSC that is going to be used for the next value. And then the last operation is the less significant bit that are truncated. Then this is going to be the NIN value that is generated by the pseudo-random generator. So we can see that through those steps, we don't have the complete information. It's not reversible just by mathematical operation because we have lost the least significant bit. And then we also truncation at the last step before obtaining the seed. And the multiplication generally overflow the value. But an attacker will have at least one of these values. So that's one of the attack scenarios we're looking for. So if we have the first value, and for example, as a scenario you can keep in mind if a website has a reset link for password that they are sending to the email, they're going to need to generate a value. So at some point for your user, you're clicking the button for your email, I want to reset my password so they send you a link to your email and it's going to be the first value for example. But the thing is that if you trigger the same operation for another account that you're targeting, you shouldn't be able to predict this value because this way you'll be able to reset its password and then you're going to win. So what we're targeting with those operations, there's actually one step. Okay, so the objective is to go from one value to the other. The thing is that there's only one step and this part that we need to, we're missing some information. And it's the part where the least significant bit were targeted. Other than that if we start from the, if we have the C number two, we can just go through all the operation and then we have the next value. So first thing we see is there's not that much information that we're missing. So if we have a value, the only part we're missing to generate the next value, it's a 16 bit. So the only thing we need in those cases is to brute force the 16 bit and then for each try do the same loop and then if we obtain actually for an attacker to do this attack, the easiest way is to have two value. So if the attacker can generate, for example, a reset password for two times, he'll be able to take the value, the two value, the sequential value and then just do the operation and then once the try he makes result with the same value, then he can guess it's potentially the good seed that he has found. So then with the seed, he can generate all the subsequent values. So once we have found it, then we can just obtain all the next value. So one thing we need to consider is that most LCG will generate ints. But the thing is that the implementation of the software will represent those ints in different forms. So sometime the int will be, the API will call with next long instead of just obtaining the int. So most of the time, the API will just concentrate two values. So a quick question, if I need two ints to find the seed, if I get how many long value do I need to be able to find the seed? Anybody? Guillem-Ross pointing one value, that's exact, because if we have just one long value or actually eight bytes will be also equivalent, we have two subsequent value. So we'll be able to do the bridge and find the seed without doing many requests and it will work. So that's one way. Also another potential implementation, sometime next int will be called and from this int, it will be a convert to an alphabet. So we're losing more bits and more analysis and more brute force. So I don't know if I have that much of time. Perfect. So with the screen being a bit small, instead of opening my console, it's really just two common. You're going to see it's going to be quite easy. So I'm going to present it just on the slide, but it's how to use a prankster that supports many LCG. It also supports other implementation but the prankster is currently the most versatile tool to support many implementation and I'm going to show you what things you need to consider in order to use it on a potential next pentas. So the scenario, we have a recovered password functionality. So we have reset our own password. So we have received various things. So for those who cannot read the API, it's ACME slash recover. And then we have a parameter token. So we have three values that we know. And then we have generate one for another user, but we don't have on our end this value. So our objective is to predict what's going to be the next value. So the first step to do with prankster is just to accumulate those values and these will be our input values. So just create an input that text and then it's going to be the content that's going to include just the token we have. So the next step, we're going to do the recover version with prankster. So it's the R parameter. Then the algorithm. So the algorithm, you're going to find it, it's going to be guessing most of the case. So unless you have access to the source code and you know exactly what the implementation, you're going to need to guess, okay, I see it's probably JavaScript V8 because I see this framework. It's expressed, for example. If it's a Tomcat server, so potentially it's going to be a PRNG in Java. So you're going to need to do a good guess. And if you have no idea about the technology, it's going to be pretty hard because there are many implementation and there are also other parameters to do a bit of guessing. But the first part that you need to identify is what's the algorithm. So in this case, it's PRNG Java for the GVM. And the second parameter is the alphabet. So for each next M that is called, we guess that if it's a weak implementation with a weak PRNG, it's going to be converted to a character. So this is the part where you're going to need to do a bit of guessing. So it's not going to include alphanumerical with an uppercase, lowercase, all that time. So a good way to maybe identify this alphabet, it's having more samples. So if you have just two samples, you could do a lot of guessing. But if you have many, you can have a more precise guess on what was the alphabet being used. So the command is really easy. So once you have all those parameters, the last thing you need to do is put in input all your generated value. And PRNG server will recover the seed. So this seed is going to be the state of your PRNG prior the value that you have put as input. So if I go back, the seed being printed out 113, this is the seed prior generating the GKC, the first value. So the next step, we want to generate the next value. So we have the state of the PRNG. So it's really just a smaller step that is required. So we have a more parameter. So again, we have, since we have a potential seed, the same algorithm, the same alphabet that we have used. And then we specify the seed and the length. So how many character do we need to generate? So in this case, we have found a seed. It's potential that, in some case, there's many potential seeds. So you're going to need to retire a few. And then the length. So in this case, we have four values. So what would be the fourth one? And now we have what was the token that was generated from the user we're targeting. And PRNG server, that's one tool that will cover most LCG. There is on twister, if you're looking to attack Merson twister. But this one has many algorithm support. And depending on the implementation, it's possible that you need to modify the tool to make it work to what you're targeting. And that's it. That's the end of my short