2

Lately I've been inspecting a key generator program in IDA Pro. I believe the thread here discusses a similar key generator. Therefore, it may be referred to for certain details. The key generator takes a device serial number as input and generates a 32 byte (character) master key along with a OTPAUTH URI of the form in the link aforementioned.

  • The master key is only a function of the current time (in seconds from epoch). Therefore changes every second regardless of different serial numbers.

Since the key changes every second, so does the OTPAUTH URI. I wonder how is the server supposed to verify a TOTP once a client enters it under this situation?

Edit: So now there are some new questions:

  • How do I authenticate to a server with this keygen knowing that the keygen is using srand(time(NULL)) for the seed while calling rand() 8 consecutive times to generate a 32-byte random sequence.
  • Is it logical to say the time step for the OTP codes is still 30 seconds while we know that the key and consequently secret are changing every second? Does this translate to the fact that the OTP validity is 1 seconds now?

Vulnerability: Isn't the server susceptible to creating TOTPs of the future and saving them in a repository by an adversary? While I'm writing this section 1476946414 seconds have passed since epoch. Assume creating a TOTP for the time equivalent to 1476947000 seconds passed from epoch. The keygen may be modified such that 1476947000 is passed to srand() instead of time(NULL). Presumably there will also be enough time to derive the TOTP from the OTPAUTH URI.

Patching using IDA Pro 6.8:

So I thought its better to continue in a hands on fashion. Scrolling through the disassembly, I changed the call to time(NULL) to a mov instruction, assigning my favorite time to eax. In order to check my patch I ran the original keygen on the favorite time. The results were equivalent. Three things still bother me:

  1. May the validation process the server carries out be concealed in the keygen or the keygen is what its only expected to be, a keygen?!
  2. The disassembly has a bunch of strings resembling openssl subroutines I presume. For instance digest.c, pmeth_gn.c, pmeth_lib.c, etc. The codes are available on the web. However, I found no lucid documentation for a layman. I suspect if the server's validation parameters are defined here. I've also been able to detect SHA256 and SHA512 cryptographic constants in the disassembly using findcrypt2.
  3. I've been cautioned that the keys are generated using Linux. What effect may this have? I'm still on the Windows track!

Switching to Linux:

  1. So I installed Ubuntu 16.04 and ran the patched linux binary keygen. The key file and the secret were completely different from the ones generated by Windows for the same time. Before reaching the specified time, I created the HMAC and derived the TOTP codes for that specific time and entered them exactly on the specific time. However, I was not able to authenticate. It may seem that the server is not expecting TOTPs for the current time. I have no idea TOTPs for what time should I feed to the server!

  2. While findcrypt2 did not find any sign of AES in Windows keygen binary, it did notice multiple Rijndael 's in the Linux keygen binary (just adding as additional info).

  3. I have been able to receive the server binary. I think the authentication procedure must be outlined there. But where should I look?

Here is the Final Problem: The key generator program is used to produce device specific keys. There is a weakness in how these keys are generated which should be exploited to generate valid one-time codes for any device.

  1. The serial number may be any 9-digit number. I personally have been working with 381151134.

  2. Usage: keygen [-g OR -m master_key_file] -k serial -o master_output_file

  3. To download the keygen Linux binary click here. The Windows binary is found here.

  • The question is a bit confusing to me. Can you perhaps edit it and add some order and clarifications? From what i can tell i think digest is related to the actual hash generation and if i'd have to guess i'd say the rand() values are fed into the hash's digest function. – NirIzr Oct 17 '16 at 20:13
  • @NirIzr I just modified the question. In case more info is needed, please let me know. I was trying to keep it short though! – Newbie Oct 17 '16 at 20:36
  • 1
    @NirIzr I cut the question into pieces. It's easier to proceed step by steps! – Newbie Oct 18 '16 at 6:23
  • 1
    That's easy, the server could just generate 300 master keys to allow the password generated last 5 minutes be valid. – kennytm Oct 18 '16 at 11:44
  • @kennytm Won't the server be under risk then? Let me ask another way. What should a client do to authenticate to the server, assuming the server will simply generate one TOTP having no database? I want to know why on earth should the server care about a clients authentication, holding a bunch of master keys? Shouldn't the client sort out the way to properly authenticate to the server once the rules are on ground? – Newbie Oct 18 '16 at 12:04
1

Since the key changes every second, so does the OTPAUTH URI. I wonder how is the server supposed to verify a TOTP once a client enters it under this situation?

The server must be aware of previously generated keys to provide usability. Either by generating previous keys on the fly (I can imagine an algorithm that tries t-0 and if that fails t-1 and if that fails t-2 for a predefined range to allow users to input a value some time after moving to the next.

Otherwise the entire generate-insert-send-validate process is limited to a short window. Accepting more than one valid key at a time is acceptable because the range remains short, values are still hard to predict, brute-forcing remains impossible (this can be further mitigated by limiting the accepted key's range after several incorrect attempts).

How do I authenticate to a server with this keygen knowing that the keygen is using srand(time(NULL)) for the seed while calling rand() 8 consecutive times to generate a 32-byte random sequence.

Without reverse engineering the entire key generation algorithm and actual generation process it is impossible to know. You'll need to reverse engineer the function calling rand() and build a simulator for the key generation process.

If what you described is the entire process, You're left with figuring out how are those rand() values are joined together (are they concatenated? xored to each other? How is the final value encoded?)

EDIT: Answer additional question presented under 'Vulnerability'

Isn't the server susceptible to creating TOTPs of the future and saving them in a repository by an adversary?

It is, but as I mentioned in this answer in response to you're first question that does not necessarily happens. The validation code can generate the TOTP keys it considered reasonable/potential every time it needs to execute a validation.

Additionally, this requires an adversary to hack gain access to that secure storage however if an adversary gained access to that secure storage to steal the TOTP keys, he might as well steal the master key used to generate those keys and gain the ability to generate TOTP keys as he wishes. For this reason storing the keys in the same place the master key is stored does not increase risk.

Obviously, the server has the ability to generate keys in order to validate them, and must be made sure to be trustworthy for the mechanism to function securely. This is a common requirement for most cryptographic protocols that certain points are to be trusted. After all, in order for the server to validate the user, it is reasonable to assume the server is protected.

One could consider some kind of asymmetric key protocol instead of a symmetric key. However since this protocol is designed to validate a user by the server, it becomes moot whenever the server becomes untrusted.

If an adversary hacks into a server to generate future keys, once this is detected replacing the master key (and all future TOTP keys accordingly) is a requirement.

May the validation process the server carries out be concealed in the keygen or the keygen is what its only expected to be, a keygen?!

The keygen and the server carry out the same basic process. Once as a way to provide proof of knowledge (the keygen), and one to verify it (server).

The keygen is able to execute perform validations and the server is able to crete proofs, but that shouldn't happen (although it might, and that can ge risky and expose the protocol to vulnerabilities).

The disassembly has a bunch of strings resembling openssl subroutines I presume. For instance digest.c, pmeth_gn.c, pmeth_lib.c, etc. The codes are available on the web. However, I found no lucid documentation for a layman. I suspect if the server's validation parameters are defined here. I've also been able to detect SHA256 and SHA512 cryptographic constants in the disassembly using findcrypt2.

I'm not really sure what's the question here. I don't think any SSH functionality is directly related to the key generation, but I might be wrong.

I've been cautioned that the keys are generated using Linux. What effect may this have? I'm still on the Windows track!

Windows and Linux implement srand and rand differently. Specifically, they're using different constants or a different number of iterations and combinations between iterations. The basic block for common rand functions is this:

int myrand(void) {
    next = next * 1103515245 + 12345;
    return((unsigned)(next/65536) % 32768);
}

Where 1103515245 and 12345 are two constant values that often change between implementations.

This is glibc's version. You can see it's more complicated. Reverse engineering the specific implementation is probably the safest way.

  • I am convinced by the first section of your answer. As for the second part however, I proposed a much simpler scheme than an entire reverse engineering. It's been added to the main question as 'vulnerability'. I'll appreciate your opinion on it! – Newbie Oct 20 '16 at 7:20
  • @Newbie I updated my answer to address your new question. It feels as if another question is supposed to exist under the vulnerability title, but i couldn't figure what it should be. You're encouraged to edit your question again to highlight that additional question. – NirIzr Oct 20 '16 at 22:15
  • I appreciate your additional explanation. Actually questions are upcoming quite frequently but I will keep the step by step fashion if you dont mind. I implemented the vulnerability scenario I proposed myself in the question by modifying the srand (time (NULL)) to simply srand (preferred epoch time). In doing so I used IDA Pro 6.8 to modify a function call to time_(NULL) to _mov eax, preferred time in hex The patch works. Both the key & OTPAUTH URI generated by the patched program equal the results of the initial keygen ran on that specific time. – Newbie Oct 20 '16 at 22:36
  • step-by-step questions are perfectly fine, but if you don't mind, can you add additional details to the original question instead of in comments? Once you do that I'll edit my answer again with any needed clarifications. – NirIzr Oct 20 '16 at 22:39
  • Sorry for making it hard for you. Its one huge question now! – Newbie Oct 20 '16 at 23:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.