In the case of Intel's AMT, I'm not sure what could have possibly gone wrong, but it sounds like this is something that has happened in other applications that use Digest Authentication.
In the case of Renegade's BBS software, I don't exactly recall the specifics and since it's been several years, I may not have this exactly right but I'm fairly certain this is how it happened because I did a lot of work with the code it was based on[0].
The bug occurred only if the user didn't provide a password. So, effectively, you could login by not providing a password or by providing the correct password. In the original Telegard source, the login prompt did nothing if no password was provided, it simply discarded the provided Enter and waited for a password. This was handled by a global function that was used for accepting input. I'm guessing that function was refactored (I ended up doing this ... it was pretty ugly IIRC) in the Renegade code and it became possible to send a blank password. The login routine was an interesting beast, as well. I remember reviewing it in the original code and scratching my head ... it made positively no sense and so I threw it out and replaced it with a much simpler implementation. Rumors had swirled around the release of the source code that this obfuscation was intentional and that there was a back-door built into the login routine. I'm not sure if that's true or not but the sheer amount of code to do a string comparison was a little ridiculous[1] -- passwords were not hashed, they were stored in plain text in a record (struct-like component) dumped to a file and were even viewable in the sysop control panel's User Editor.
It's entirely possible that they didn't refactor this bit of logic but changed something in that mess that caused an empty string to evaluate true along with a matched string. Or it could be that they refactored that like I did and put an OR where an AND belonged. If they refactored that global ReadLine method to allow empty returns, they may have felt a need to check for an empty value at this prompt, though I'm not sure what the motivation for this would have been. An empty or NIL value wouldn't have caused the application to crash -- there's no null reference exceptions when you're dealing in a non-OOP language -- you're not executing methods attached to the String type because such a thing didn't exist in the language.
The developer should have discovered the problem way before it was ever released in the wild, but I get why it was missed. He probably checked a bad value and a good value but never thought to check no value at all. Hell, it was a mystery why all of these Renegade boards were going down and a bunch of folks assumed it was a back-door, as was suspected about the original Telegard code. It was a few weeks before people figured out that it was such a simple screw-up.
[0] The source code wasn't public, it wasn't open source. In fact, it only existed because an older version of Telegard had its source code leaked, which the Renegade developers used to create their product (there were a number of "Telegard Hacks" in those days, including one I wrote and later rewrote from scratch and served as the entire reason I decided to become a software developer).
[1] Sounds suspicious at first glance but there were so many really poorly performing things about Borland Pascal's core libraries that it was not uncommon to write several hundred lines of inline assembly to do things like "write text to the screen quickly". I had done this, myself, on a few occasions -- the specifics were something around writing to memory reserved for use by the display capabilities of the 8088/80286/80386 (BIOS reserved memory IIRC).
[2] NIL was Borland Pascal's "null", and I believe it supported empty strings. Unlike ISO PASCAL at that time, Borland Pascal had a real string type which was stored in memory as a character array with a length field at the 0th index. It didn't use null terminated character arrays like C/C++ which made working with strings in the language elegant by comparison. Strings, however, were 8-bit ASCII ... this being the 90s with the target being DOS and all.
The code compares the correct "hash and the hash response received from the browser, with N set to the length of the response received from the browser". So if the browser returns "", that's compared with the first zero characters in the correct hash, which is also "". Funny.
In the case of Renegade's BBS software, I don't exactly recall the specifics and since it's been several years, I may not have this exactly right but I'm fairly certain this is how it happened because I did a lot of work with the code it was based on[0].
The bug occurred only if the user didn't provide a password. So, effectively, you could login by not providing a password or by providing the correct password. In the original Telegard source, the login prompt did nothing if no password was provided, it simply discarded the provided Enter and waited for a password. This was handled by a global function that was used for accepting input. I'm guessing that function was refactored (I ended up doing this ... it was pretty ugly IIRC) in the Renegade code and it became possible to send a blank password. The login routine was an interesting beast, as well. I remember reviewing it in the original code and scratching my head ... it made positively no sense and so I threw it out and replaced it with a much simpler implementation. Rumors had swirled around the release of the source code that this obfuscation was intentional and that there was a back-door built into the login routine. I'm not sure if that's true or not but the sheer amount of code to do a string comparison was a little ridiculous[1] -- passwords were not hashed, they were stored in plain text in a record (struct-like component) dumped to a file and were even viewable in the sysop control panel's User Editor.
It's entirely possible that they didn't refactor this bit of logic but changed something in that mess that caused an empty string to evaluate true along with a matched string. Or it could be that they refactored that like I did and put an OR where an AND belonged. If they refactored that global ReadLine method to allow empty returns, they may have felt a need to check for an empty value at this prompt, though I'm not sure what the motivation for this would have been. An empty or NIL value wouldn't have caused the application to crash -- there's no null reference exceptions when you're dealing in a non-OOP language -- you're not executing methods attached to the String type because such a thing didn't exist in the language.
The developer should have discovered the problem way before it was ever released in the wild, but I get why it was missed. He probably checked a bad value and a good value but never thought to check no value at all. Hell, it was a mystery why all of these Renegade boards were going down and a bunch of folks assumed it was a back-door, as was suspected about the original Telegard code. It was a few weeks before people figured out that it was such a simple screw-up.
[0] The source code wasn't public, it wasn't open source. In fact, it only existed because an older version of Telegard had its source code leaked, which the Renegade developers used to create their product (there were a number of "Telegard Hacks" in those days, including one I wrote and later rewrote from scratch and served as the entire reason I decided to become a software developer).
[1] Sounds suspicious at first glance but there were so many really poorly performing things about Borland Pascal's core libraries that it was not uncommon to write several hundred lines of inline assembly to do things like "write text to the screen quickly". I had done this, myself, on a few occasions -- the specifics were something around writing to memory reserved for use by the display capabilities of the 8088/80286/80386 (BIOS reserved memory IIRC).
[2] NIL was Borland Pascal's "null", and I believe it supported empty strings. Unlike ISO PASCAL at that time, Borland Pascal had a real string type which was stored in memory as a character array with a length field at the 0th index. It didn't use null terminated character arrays like C/C++ which made working with strings in the language elegant by comparison. Strings, however, were 8-bit ASCII ... this being the 90s with the target being DOS and all.