Battle.net authentication misconceptions

Hey everybody,

There have been a lot of discussion and misconceptions about Battle.net's authentication lately. Having done a lot of work on the Battle.net protocol, I wanted to lay some to rest.

The first thing to understand is that, at least at the time I was working on this, there were three different login methods (this is before they combined the Web logins with Battle.net logins - I can't speak on those). The three methods are:

  1. CHAT protocol - deprecated a long, long time ago
  2. Old Login System (OLS) - used by Diablo, Warcraft 2 BNE, Starcraft, and Diablo II
  3. New Login System (NLS) - used by Warcraft 3, World of Warcraft, and in some fashion by newer games. Also supported - but unused - by Diablo II

I'll describe, in detail, how each of these work. The summary is, though, that at no point does a game client ever send a plaintext password to the server. The closest is the SHA1 of the password, which is used for account creation in old games. For more information, read on!

CHAT protocol

Creating an account

You can't create an account on CHAT.

Logging in

The login was plaintext, over an insecure connection.

Old Login System

The Old Login System (or OLS) is the original login system used by Battle.net. It uses a modified version of SHA1 hashing that I'm going to call Broken-SHA1 for the remainder of this post. It's identical to SHA1 with the exception of an inverted shift or two. There's been a lot of discussion on whether or not this was intentional - to throw off reverse engineers - or a simple bug. Personally, I lean towards a bug, since there were other similar bugs throughout the login sequence on older games. Additionally, there is no evidence of anti-reverse engineering attempts in any of the Blizzard games I've worked on, even Warden and Lockdown and other measures are pure anti-hacking.

Account creation under OLS

This is quite possibly the riskiest part of the entire process. When you create an account under the OLS, you send it the username and a Broken-SHA1() hash of the uppercased password. The server validates that the username is valid, and if it is, it stores the Broken-SHA1 hash.

Interestingly, you can use any 160-bit value for the Broken-SHA1 hash, it doesn't actually have to be Broken-SHA1. This is because Battle.net simply stores the value it receives on the server side, and validates it when you log in.

Account login under OLS

When you log in, three values are used:

  • A 32-bit token generated by the server (server seed)
  • A 32-bit token generated by the client (client seed)
  • The password

The client seed and server seed are exchanged before the authentication is attempted. As before, the password is converted to uppercase, and hashed with Broken-SHA1. Then, the client and server seeds are appended to the password, and the Broken-SHA1 is calculated again. This gives a 160-bit value that is sent to the server. The server takes the same two values - which were exchanged - and the Broken-SHA1 of the uppercased password - which it has stored - and performs the same calculation. The server compares the hash it generated to the hash that the client sent, and if everything goes according to plan, the hashes match.

New Login System

The New Login System (NLS) first appeared - as unused code - in Diablo 2. It was then used in Warcraft 3, and a slightly modified version was used in World of Warcraft. I can't comment on Starcraft 2 or Diablo 3, having never worked on them.

NLS uses the SRP Version 6 as the basis for its authentication protocol, which uses RSA-like public key cryptography. I explain this in full on my wiki, but I'll summarize the important parts here.

Account creation under NLS

When a user creates an account, the client sends three values, defined as s, v, and the username.

  • s is the salt. It is randomly generated from a cryptographically secure random number generator.
  • v is the validator. It is generated from the formula v = gx % N.
  • g and N are known constants, shared between all installations of all games.
  • x is defined as x = SHA1(s + SHA1(C + ":" + P))
  • C and P are the username and password, respectively, converted to uppercase.

So, to summarize, the client sends the salt, and the verifier. The salt is randomly generated, and the verifier is based on the username, password, and salt.

Account login under NLS

Account logins are a little more complicated. There are four steps.

First, the client sends A and C.

  • A is a 256-bit public key based on a, which is a randomly generated session key. It is derived from A using the following formula: A = ga % N. As before, g and N are constants. a is a private key generated from random bytes.
  • C is the username, converted to uppercase.

Second, the server replies with s and B

  • s - the salt - is the same one the client sent when it created the account.
  • B is a public session key, generated by the server much the same way as A is generated by the client - B = (v + gb) % N, where b is randomly generated.

Third, the client sends M1 (otherwise known as the proof). It is calculated by a fairly complex formula:
M1 = SHA1(I, SHA1(C), s, A, B, K)

Where:

  • I is a constant, calculated in a fairly weird way (see my wiki for more details)
  • C is, as before, the uppercase username
  • s, A, and B are the salt, client public key, and server public key, as exchanged
  • K is a shared key derived from S

S is where all the magic happens. It's generated through a different formula on the server and the client - since the server knows A, B, and b, while the client knows A, a, and B. Here are the respective formulas:

  • (client) S = ((N + B - v) % N)(a + ux) % N
  • (server) S = (A * (vu % N))b % N

Keep in mind that v - the verifier - is what was sent when the account was created, and is based on the uppercase username, uppercase password, and the salt. The variable u is derived from B and x is derived from the username and password.

So, the client calculates its value, and sends it to the server. The server calculates its value, and compares it to what the client sent. If they match, authentication (of the client) is successful and the server returns M2.

And that brings us to the last step. Not only does the client prove to the server that it knows the password, the server also proves to the client that it knows the password. When implementing the protocol, this isn't technically necessary, but it's a security measure so I implemented it anyway.

M2 is simply: M2 = SHA1(A + M1 + K), where A is, as before, the client's public key; M1 is the value from the previous step; and K is, as with M1, the shared key derived from S, which is the complex formula discussed above.

The server and client both generate M2, and the server sends M2 to the client. If the client verifies that M2 is correct, then the client is sure that it's talking to a valid server and it continues the connection.

At this point, the protocols continue on as before. In the beta for Warcraft 3, all messages after the login completed were encrypted with RC4 using K as a shared key. Once Warcraft 3 was released, the encryption was disabled and all traffic after the login is currently plaintext.

What's the point?

The point of writing this blog is to give some insight into Battle.net's protocols, and to demonstrate that, at no time during the normal use of any Battle.net games does Blizzard have access to your plaintext password. Yes, the passwords are converted to uppercase before hashing. That's probably a bad idea - especially in the modern world - but it really dates back to their first Battle.net game - Diablo - from 1996. Since then, they've developed much better login systems, but they've kept the passwords case insensitive.

If you fail a certain number of logins against Battle.net, your IP address is temporarily banned. This makes it fairly difficult to bruteforce most accounts. It requires significant resources (proxies, bots, etc.) to make an attack feasible. It's much easier to compromise accounts via phishing and malware, so that's what attackers do.

There are lots of things I didn't go over - upgrading OLS accounts to NLS, email password resets, password changes, etc. - but they're all fairly logical, and use the minimum amount of information required (typically the same information as you used to create the account). You can find more information on my Battle.net SRP page and on BNetDocs Redux.

There are also Battle.net authenticator tokens, which I haven't researched at all so I can't talk about.

21 thoughts on “Battle.net authentication misconceptions

  1. Reply

    Michael Rose

    Thanks for the writeup. I enjoyed the progression of ideas from OLS to NLS and the guiding hand of traditional public-key crypto in their designs. It's easy to scoff at OLS now, but back in 1996 I don't think I remembered being too worried about that kind of security either. The internet was much less dangerous then.

    I'd love to see an article on the authenticator tokens at some point if it isn't proprietary knowledge -- the theory is easy enough but I've never implemented a similar system.

    1. Reply

      Ron Bowes Post author

      I'm curious about the authenticator tokens too, but I kinda dropped out of the Battle.net scene before WoW came around so I've never looked at them. I'm curious how they fit in.

  2. Reply

    Myst

    Today (in regards to bnet1.0), if an account gets too many failed pw attempts, the account is essentially 'locked', even when accessed on multiple proxies. And is unlocked after a set timeperiod.
    But in regards to other exploits that could compromise Player data, from things that Blizzard implements in certain games, is for example in Starcraft/BroodWar; where you're cdkey is broadcasted, hashed of course with SStrHash() in storm.dll, in 0x09 (When you create a game, key hash in gamestatstring) and in 0x40udp (when you join a game you send host 0x40, part of that data is hash of key). And someone could log these hashes and then attempt to brute those hashes for valid keys, which at current times/research, gets you 1 valid key outa 3 or so attempts (http://darkblizz.org/images/KeyForce.PNG).
    Now if Blizzard did this for one of their games before, in theory its possible for them to do something similar in future games that could compromise some kind of player data.
    But in regards to passwords, it makes no sense how someone could get your pw from a blizzard game anymore, unless you, the player, have been using some third party app that could have compromised your data.

    1. Reply

      Ron Bowes Post author

      Thanks Myst! Cool to see that you read the blog. :)

      I haven't kept up with Battle.net research for a lot of years now, I'm glad to see that some people are still working on it!

  3. Reply

    Myst

    Yeh, good amount of people are continuing on to bnet2.0 research. I don't see much of all the old people that used to run around our little community, I see maybe a few popup here and there in some sc2/d3 dev channel on IRC. But all the big dogs seem to have disappeared. I guess thats what happens with age and more life responsibilities ;)

    But here's some stuff about the passwords for sc2/d3
    http://www.bhfiles.com/files/Battle.net%202/docs/protocol/ProofRequest.txt
    https://github.com/mooege/mooege/blob/master/src/Mooege/Core/Cryptography/SRP6a.cs (Mooege is the D3 Emulator)
    & http://diablo3dev.com (Various D3 info)

    I'm no expert on the technical stuff, but that should give people some kind of insight on how it all works.

  4. Reply

    This Guy

    This isn't related to the data transportation at all, but in addition to the password checking and authenticator, there is also some degree of "unusual activity" checking.

    Over Christmas I visited my parents in another state and attempted to log in to World of Warcraft, and had my account locked and a reset token sent to my e-mail because of usual activity. My original suspicion was that someone was trying to break in, but it also happened to my brother. I should add that both of us used an authenticator as well, meaning there is an assumption that someone compromised not only my user/pass combo, but the authenticator token as well.

    Unfortunately I have no other detail other than it happened.

  5. Reply

    gt

    Nice work about the Battlenet protocol. There's a bug in your writeup though: B = (v + g^b) % N. Actually this step is fairly crucial: without the server's public key including the shared secret v anyone can spoof the server! You also need it in order for the mathematical proof to work...see Table 4 of http://srp.stanford.edu/ndss.html. You also leave out details of the calculation of B on the wiki (as well as the random seed b).

    1. Reply

      Ron Bowes Post author

      @gt - great eye! That's the one line I did from memory, and I managed to mess it up. D'oh! :)

  6. Reply

    gt

    No problem. I suppose though you weren't able to reverse Blizzard servers' code so I can see why this might not have been clear to you. Interesting the "extra security" they add when computing the shared secret K and the proof M1 (details on the wiki). If someone (you!) is going to the effort to reverse the code to determine they are using the SRP protocol things like that should easily come out.

    1. Reply

      Ron Bowes Post author

      We mostly stopped when we had working code - that was our goal, not to audit the system. I didn't actually implement the M[2] check or another server validation check for quite awhile afterwards.

      In many cases, we didn't understand what we were seeing, and we only ever used SRPv1 as a reference (we didn't realize that SRPv6 existed, and that's what it was based on). So, there were a lot of blank spots, and I was quite a bit younger and less experienced that I am today (that was my first RE project)

  7. Reply

    ildon

    I don't know if they've changed their authentication procedures since, but I have to say it seems like your information is at least 5 years old. They've since moved onto global "battle.net 2.0" accounts for WoW/SC2/D3.

    The general idea behind what you've posted is still probably true but the specifics may not be.

  8. Reply

    ildon

    This Guy: World of Warcraft will lock your account for "unusual activity" any time you login from a different IP address than normal (within some threshold for people whose ISPs provide dynamic IPs). You were the cause of "unusual activity" on your account, not anyone else. I used to LAN at my friend's house every other weekend and had to unlock my account almost every time because he had a different ISP, even though I was playing on the exact same hardware.

  9. Reply

    gt

    Spending way too much time on this, but hey at least I learned something: actually it's based exactly on SRPv3: http://srp.stanford.edu/design3.html and http://www.rfc-editor.org/rfc/rfc2945.txt. In the RFC they describe the hash interleaving technique (though it doesn't explain why...)

    SRPv6a is an improved version where B = (kv + g^b) % N, k = H(N,g) and u = H(A,B). But it was published in 2002, probably too late to be implemented in Diablo II.

    1. Reply

      Ron Bowes Post author

      @gt - very cool! I based what we knew off SRPv1, and didn't even know the newer ones existed.

  10. Reply

    while1

    Well, considering that Blizzard has a history of taking a standard (i.e. SHA-1) and putting their own twist to it (BrokenSHA1), it wasn't an unreasonable assumption to make.

  11. Reply

    will

    I have to disagree on the brute side as when I was 12 I wrote a program that did just what you speak of being too expensive ect. It worked for a very long time on one list of proxies then load another repeat. I have found the large company heading up the gold mining and they have a ton of cash to set something like this up on a much larger scale.

  12. Reply

    kyle

    Just popping in to say thanks for this post. I've been reading this blog for awhile and its super awesome!

    Haha. Keep up the good work. Love reading your posts.

  13. Reply

    Brian

    According to the wiki page, the modulus is a 32-byte unsigned integer. Unless I'm missing something about the way the protocol works, this is WAY too small to provide any reasonable security level. RSA and Diffie-Hellman modulus sizes are at least 128 bytes (and even that is considered risky).

    Maybe I'm just misunderstanding something about how the protocol works, but using that small of a modulus size would seem to open up the login process to a number of attacks.

    1. Reply

      Ron Bowes Post author

      I'm not an expert on crypto by any means, but a 1024-bit RSA or DH key is fine, AFAIK. Not optimal, but not (yet) attackable?

  14. Reply

    Brian

    Ron Bowes: That's my understanding as well, 1024 bit RSA/DH keys are fine for right now, although larger key sizes are definitely recommended. But from the way I read the protocol, it's using 256-bit asymmetric keys (32-bytes), which are easily breakable as far as I know. Possibly I'm reading it wrong, or the security of the protocol somehow isn't reliant on the size of the asymmetric keys in a way I'm not seeing.

  15. Reply

    Silinoron

    There was significant anti-reversing work on the new Battle.net libraries and in Starcraft 2.

    WoW, at least, seems to use SRPv6a; the original login system for WoW (which was called GRUNT) used SRPv6 (I'll note the difference between the two is pretty small).

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>