Simple Machines Forum <= 2.0.3 Admin Password Reset

Simple Machines Forum is a popular web community software written in PHP. Its password reset mechanism had some issues back in 2008. The vulnerability was caused by insecure random numbers generation and was patched right after the exploit was published. This time I found a more interesting vulnerability however at Positive Technologies we didn’t manage to raise awareness of SMF developers. After continuous silence of SMF devs I am disclosing the vulnerability details but I am not going to publish the exploit.

The new vulnerability in password reset algo persists in SMF since the early versions and derives from insecure string handling and PHP weird type casting. The attack scenario based on incorrect string comparison was first described by Omar Ganiev and was applied to phpBB forum. Despite the fact that the actual phpBB code made it infeasible to conduct the attack the core idea is rather interesting. Imagine a web application that generates password reset token that contains only hex symbols (a-f, 0-9) and is rather short. Now let me remind you about PHP type juggling pecularities. If you use == operator to compare strings that contain numbers they will automatically be casted to integers, for example a string “123” will be equal to an integer 123. But what is more interesting is the following abstract from PHP documentation on type juggling:

The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an ‘e’ or ‘E’ followed by one or more digits.

It means that if you compare a string “0e1337” with a string “0” they will be equal, because 0 * 10 power 1337 is zero. Not so many web developers are aware of this kind of unexpected magic, however it leads to a potential security hole. If an attacker starts to send password reset requests and iteratively tries to match it “0” or “1”, one lucky request will let him set admin password.

So, what about SMF? It is an ideal example of one insecure piece of PHP code. Just see this:

if (empty($_POST['code']) || substr($realCode, 0, 10) != substr(md5($_POST['code']), 0, 10))

Lack of !==, only 10 symbols and hex format. Excellent! As you can see $_POST[‘code’] is md5’d, so we need to find such values that will give us 0e[num] or 1e[num]. These values are:

md5(5136) == [0e79548081]b4bd0df3c77c5ba2c23289
// md5(8301) == [1e79596878]b2320cac26dd792a6c51c9
// 1eXXXX will never give us 1 except 1e0, because 1eX = 1 * 10 power X (thx to gifts and Paul4games)

However newer versions of SMF has a limitation of password reset rate to prevent bruteforce:

if (empty($number_tries) || $time_stamp < (time() - 10))
	// If it wasn't *that* long ago, don't give them another five goes.
	$number_tries = !empty($number_tries) && $time_stamp < (time() - 20) ? 2 : 0;
	$time_stamp = time();

There is another bug. If an attacker sends a password reset request within 10-20 second interval the $number_tries will be set to 0 instead of 2. Obviously this was not SMF devs intention.
The successful attack requires about 6-10 k requests and can be done in a night. The older versions of SMF do not have this limitation, so you will be able to set new password in few hours.


  1. Beched, 25. January 2013, 20:32

    Nice finding!
    Just some small remarks =)
    Actually, the similar technique was presented in some other attacks, for example, by Greg Kopf (??), I don’t remember the initial author (failed to google it out right now, hallucinations? oO).

    Substantial thought is that we need to get the form (0+e\d+), not strictly (0e\d+).
    So, it’s quite easy to find the strings, which give a hash, the part of which casts to zero.
    It’s much more common pattern than (1e\d+).

    $ php -r ‘var_dump(“000000e123″==”0”);’

  2. dob, 25. January 2013, 21:52

    SMF Devs are dump as ignorant…

    No one can help them, just like the GitHub retards.

  3. Chris, 26. January 2013, 0:30
  4. Raz0r, 26. January 2013, 0:50

    @Beched @Chris thanks!

  5. emanuele, 26. January 2013, 1:25

    Hello Raz0r,

    > This time I found a more interesting vulnerability however at Positive Technologies we didn’t manage to raise awareness of SMF developers.

    May I ask you when did you send the report?

  6. Raz0r, 26. January 2013, 1:57

    Hello! We sent it in August 2012

  7. dob, 26. January 2013, 13:25

    August 2012? Srsly as I read your Topic i moved instantly in my scripts and fixxed it, just handy move…

    Why someone should ignore that vuln for so long? In fact that this one is a critical one…

  8. bleh, 26. January 2013, 18:56

    So, Mr. Superhacker,
    are you aware that MD5() does not return a number at all? It’s always worthwile to read the docs before making an unfounded claim. The function’s signature is:

    string md5 ( string $str [, bool $raw_output = false ] )

    No conversion. No exploit. Too bad.

    If you had complained about the actual use of MD5 (which is vulnerable to collision attacks) you would be looking much less like a fool.

  9. Raz0r, 26. January 2013, 21:47

    You are right, it’s easy as a pie, but we got no response after SMF devs wished to know the vulnerability details.

    Are you kidding me? Please read on PHP typecasting and don’t be a fool yourself. I have an exploit and it works perfectly.

  10. badsect, 27. January 2013, 10:35

    would i be correct at assuming in order to find probable candidates to be passed as $_POST[‘code’] one could use plaintext candidates where when passed through md5 they would match something along the lines of

    preg_match(‘/^0e[0-9]{8}/’,substr(md5($test), 0, 10))

    ive been trying to recreate this in a local test scenario as i find vulnerabilities such as this one to be rather intersting and less common (or atleast unnoticed in many cases)

  11. Raz0r, 27. January 2013, 11:23

    Yes, you are right, but not only [0-1]e[0-9]{8}, as @beched has already noticed strings like 00e… 000e… 0000e etc also will be equal to zero.

  12. emanuele, 28. January 2013, 18:19

    > You are right, it’s easy as a pie, but we got no response after SMF devs wished to know the vulnerability details.

    Yeah, I know it just sounds like a lame excuse, though the mail went lost in a change of people around…
    We have learned the lesson and we have changed the way the security reports are handled.

    Thanks for spotting these three (including handling of security reports) vulnerabilities on our system.
    A patch was already ready for another set of vulnerabilities, we are applying the fixes for this too it should be out in few days.

  13. Raz0r, 28. January 2013, 20:15

    @emanuele glad to hear this!

  14. badsect, 9. February 2013, 10:01

    was doing some random browsing on the interwebs and i happened to stumble across this very same exploit posted back in 2010

  15. Raz0r, 9. February 2013, 19:08

    Haven’t seen this, I downloaded SMF 1.1.11 and it has the same code:

    if (empty($_POST['code']) || substr($realCode, 0, 10) != substr(md5($_POST['code']), 0, 10))

    $_POST[‘code’] is md5’d so this “exploit” makes no sense because md5(0eb3d1f811) produces no 0e[num] or 1e[num].
    BTW there is a related thread on SMF board, exploit is bogus.

  16. badsect, 9. February 2013, 19:30

    ive checked most of the smf versions starting with 1.1.10 and all of them do contain the same code for handling this, it just suprised me seeing this as far back as 2010 and without jumping to any plausible conclusions i think it could be possible that it could be the same flaw and said party did not share full details. it is probably likely that they obtained that information elsewhere and didnt quite understand the full details (most likely a copy and paste kiddie that just wanted something for his name (like most of them from HackTeacH with their fake or bogus/copy paste bugs lol)

  17. flax, 27. February 2013, 13:00

    Для защиты я так понял надо указать что типы являются строковыми и сравнивать через “===” ?

  18. nbd, 1. March 2013, 6:13

    @flax change != to !== where “!=” is “not equal” and “!==” is “not identical”

  19. Антон Владимирович Завьялов, 1. March 2013, 23:56

    How could i use this exploit,i thought of doing curl but can’t seem to do it on my own forum,can’t get session variables…
    Would you post or send me the code to run the exploit.I am frustrated that i can’t run this to my own forum

  20. flax, 2. March 2013, 1:16

    @nbd, ты про то что не имеет смысла использовать сравнение типов, раз сам их выставляешь?, это да.

  21. oleg, 12. March 2013, 1:15

    Как это заюзать, есть эксплоит?


    […]    La vulnerabilidad de los foros SMF que han liberado estos días permitía a un atacante poder resetear la contraseña a un administrador. Este es el post original del disclosure. […]

  23. asdf, 9. January 2014, 5:58

    >because 0 power 1337 is zero.

    В коментах уже написали, 0e1337 = 0*10^1337, так что с 1 работать не будет. Поправь статью.

  24. Raz0r, 10. January 2014, 11:44

    В статье уже давно исправлено:
    // 1eXXXX will never give us 1 except 1e0, because 1eX = 1 * 10 power X (thx to gifts and Paul4games)


Write a comment: