Showing posts with label security. Show all posts
Showing posts with label security. Show all posts

Monday, July 15, 2013

DAoC - The middle man

We've already seen that the key generation isn't up to par, neither is the actual way how the RC4 encryption is used... but there's an even bigger issue. The game is susceptible to a man-in-the-middle attack (MITM).

The game client has no way of knowing if the traffic it receives is indeed coming from the official servers. Games like Guild Wars2 use Diffie-Hellman to exchange the encryption key, but they have the server part baked into the client binary. Therefor in a game like that, you can't impersonate the server without changing the client binary (unless they leak their server binary ofcourse *wink*).
Now, in Mythic's defense, the DAoC client does use RSA to transmit the RC4 session key to the server, which means a man in the middle attacker won't be able to decrypt this packet and sniff the encryption key (unless you found a solution for the factoring problem).

So... where's the problem then?

The issue is with the initial connection setup. The client connects to the server and sends a packet with it's info. The server then responds with the following packet:

0000: 22 01 31 01 0a 03

Which tells the client what version the server is running, but more importantly, tells the client to switch to encrypted communication mode. Yes, there's actually 2 modes the client can work in! Encrypted and non-encrypted mode.

This opens the possibility for a MITM attack. If we proxy the data between the client and the server and change the 01 into 00, we can trick the client to work in non-encrypted mode. To the server, we respond with an RSA encrypted RC4 key, which the proxy creates itself. From then on, it's just passing traffic while encrypting/decrypting the data between the 2.

Another big problem is that the communication protocol doesn't use anything like SRP to prevent people from sniffing and reusing the password. Therefor, the attacker will be able to grab the login and plain text password from the intercepted session.


As a proof of concept, I wrote a small proxy that did just that. It ran on a linux machine in between the client and the server and used the transparent proxying (TPROXY) feature of the linux kernel to redirect the traffic to the proxy program. Worked like a charm.

Friday, May 24, 2013

DAoC Random function

As I mentioned before, the generation of the RC4 key in this game can easily be instrumented to generate the secret we want.

The pseudo code to generate the RC4 key looks something like this:

repeat 0x40 times
  use rdtsc to generate 1 byte
  verify the resulting byte isn't 0
  sleep 1
This block is then RSA encrypted and exchanged with the server. From then on, all packets get encrypted with this RC4 key. One interesting thing also, is that the game doesn't use RC4 as a continuous stream cipher, instead each packet resets the RC4 cipher to the initial state. This stems from the fact that the game can use UDP for communication and therefor needs to handle the case where packetloss occurs, which would desync the state, but it also makes this less secure. I'm not an expert in cryptography, but I'm sure this enables some interesting crypto attacks to decipher the content. From what I've read, the first few bytes of RC4 are already less random than they should be, which is why it's suggested to advance the RC4 state a couple of bytes before actually using it on your data, which this game doesn't do. Couple that with knowledge of some of the payloads' fixed bytes and I'm sure a real cryptographer can decipher a stream without much effort. Now there's 1 thing they did to try and counter some of this. Instead of starting the packet encrypt from the first byte of the packet, they start it from the middle of the packet, which helps a bit with the known byte value issue.
They are also feeding back the input into the RC4 state, by incrementing the j variable by the unencrypted input byte.

Another issue with just using the rdtsc instruction to generate random data, is that this instruction can be made priviledged by setting the TSD flag in CR4, ie. cause a system trap to occur when executed in userspace / ring3, which means there's full control over what this RC4 key generator produces without even having to alter the game binary or redirecting system APIs. Example code to do something like this, can be easily found, ie. here.


Tuesday, April 16, 2013

DAoC vulnerability update

So I got a mail back from the janitor at Mythic regarding my vulnerability report:

Hello Karl,

Thank you for contacting Dark Age of Camelot Support.

With regard to your appeal, Ticket#: [XXXXX], we cannot field feedback or suggestions regarding how the game may be altered or improved. However, your opinions and thoughts are always valued!

To appropriately submit your suggestions and feedback regarding game content, mechanics, or design, please go to http://darkageofcamelot.com/contact. On this page, you will find a form which will allow you to submit your suggestions and opinions directly to our development team.

This email address is only for issues of a billing or technical nature, and not issues related to feedback or concerns regarding elements of the game.

Thank you for playing Dark Age of Camelot!
XXXX

 Oh boy... what can I say... FAIL!


Saturday, April 13, 2013

Blast from the past

Since I've been talking about game security the last couple of posts. I figured I revisit an old target I once investigated.

Many many moons ago I blogged about getting Dark Age of Camelot to run in wine. While reversing that game, I also had a look at how the actual game connection works, because that's something that always interests me, ie. the security aspect of it. In this case, there was an extra reason to have a look, since at one time early on in the game's life, a security issue was found and reported to them:

CVE-2004-1855
Dark Age of Camelot before 1.68 live patch does not sign the RSA public key, which could allow remote malicious servers to gain sensitive information via a man-in-the-middle attack.
A more detailed description is available at:
http://capnbry.net/daoc/advisory20031211/daoc-billinginfo-exploit.html

So fast forward 10 years, you'd think it would be pretty secure by now... unfortunately it appears it's still flawed in some way. The thing is, even after all these years, the game is still susceptible to a man-in-the-middle attack. It's perfectly possible to intercept / proxy a connection from the game without needing any details / account info from the player.

So how does the game connection work?

The communication is rather straight forward. There's only 1 connection maintained between the client and the server. The game supports both UDP or TCP for it's game session. This probably stems from the old days where most players actually used a dialup connection, where you don't want TCP retransmissions to cause issues.

Most of the game packets are known. There has been an emulator around for quite some time now and since it's open source, anyone can have a glimpse at how it all works.

The connection is encrypted with RC4. It generates a random session key which gets exchanged via RSA encryption. The generation of the RC4 key could also be improved, since how it currently is done, makes it extremely easy to intercept by using some virtualization techniques. This has as effect that one can get the game to generate the key you want, without having to make any patches to the game client, which is imho not a good thing.

But worse is the fact that this all doesn't matter, due to another vulnerability. But before explaining that one, I'll see if there's still anyone in charge of the game code (most players of the game, seem to think the janitor is the only guy left in the building.. so we'll see how it goes)

Anyway, let's hope the old Mythic gang @ City State Entertainment will have a better security track record if their Kickstarter project, Camelot Unchained, funds!


Thursday, March 28, 2013

Give a man a fish...


I guess ArenaNet has had time enough to react and fix their broken security, so it's
time to explain what exactly they messed up.

As I showed in a previous post, the game connection uses diffie hellman to negotiate the RC4 session key but stores the server's side pre-calculated in the client.

So how in hell did I calculate the server's secret?! ie. For the current release (17368) where do I get this from:

const unsigned char p[] = {
0xa1, 0xc5, 0x67, 0x7b, 0x95, 0xef, 0x74, 0x12, 0xcf, 0x58, 0xab, 0xef, 0xb0, 0x60, 0x9e, 0xa7,
0xab, 0x6c, 0x15, 0x3c, 0x6d, 0xf0, 0x24, 0xac, 0x0d, 0x02, 0x26, 0x66, 0xd1, 0x65, 0x28, 0x53,
0x29, 0xc7, 0xb4, 0xc4, 0x7b, 0xdd, 0xbc, 0x4c, 0x8d, 0xab, 0x7d, 0x6a, 0x7e, 0x26, 0xd7, 0x3c,
0x62, 0xe5, 0x66, 0x5f, 0x38, 0x9f, 0x49, 0x44, 0x6b, 0x18, 0x74, 0x9c, 0x43, 0x7a, 0xf4, 0x17,
};


const unsigned char b[] = {
0x8e, 0xe7, 0x79, 0xf0, 0x00, 0x0d, 0x31, 0xc9, 0xda, 0x45, 0x77, 0x44, 0xd3, 0x47, 0x0a, 0x26,
0x8d, 0x7e, 0xe3, 0x03, 0x02, 0x55, 0x6b, 0x0d, 0x88, 0xc7, 0x65, 0x32, 0x29, 0xbe, 0x1d, 0x71,
0x9f, 0x49, 0x00, 0xf9, 0x65, 0x97, 0xe6, 0x05, 0xda, 0x3b, 0x8f, 0xc0, 0xc7, 0x0b, 0x3a, 0x49,
0xe3, 0xfa, 0x6e, 0x2e, 0x27, 0x54, 0xab, 0x13, 0xae, 0xf5, 0x54, 0x61, 0x29, 0x4f, 0x37, 0x35,
};



To explain it.. we have to look at how the game does it's updates.

ArenaNet is using a content delivery network to distribute game updates. At startup, the game patcher will query an URL on the CDN which contains information about what the current live version is.

This information is at:
  http://assetcdn.101.ArenaNetworks.com/latest/101


Now, if you try to access this with your browser, you'll get an authentication error. To pass the authentication check, a header called 'authCookie' has to be passed. Older clients had this header clearly visible in the executable, ie:

$ strings gw2.exe.524178 |grep md5=|cut -c1-
authCookie=access=/latest/*!/manifest/program/*!/program/*~md5=4e51ad868f87201ad93e428ff30c6691

In newer clients it's build through printf style formatting, so it's a bit more effort to get it:

$ strings gw2.exe.570713 |grep md5=|cut -c1-
authCookie=access=/latest/*!/manifest/program/*!/program/*~md5=%s

However, the md5 value is always the same (haven't verified this on the latest clients anymore), so you can just use this value.

$ curl http://assetcdn.101.ArenaNetworks.com/latest/101 -b 'authCookie=access=/latest/*!/manifest/program/*!/program/*~md5=4e51ad868f87201ad93e428ff30c6691'
17368 570713 22680128 570709 5108


This tells us the latest release is 17368, has a fileid of 570713 on the CDN and is 22Mb in size. Equipped with this information, we can download the latest gw2 executable:

$ curl http://assetcdn.101.ArenaNetworks.com/program/101/1/0/570713 -b 'authCookie=access=/latest/*!/manifest/program/*!/program/*~md5=4e51ad868f87201ad93e428ff30c6691' -o gw2.exe

Easy enough...


An update contains much more than just the gw2 executable, there's also patches for the data files and other stuff.

And this is where ArenaNet made a gigantic mistake in my opinion. If you take the previous link and  increment the filenumber by one, you get something VERY interesting! For some unknown reason,  the actual server code and authentication code is also on the CDN and it's even accessible to everyone that wants a copy!!

If you take fileid 570714 and run it through objdump, you will see it's actually called GwSrv.dll and fileid 570715 is called AuthSrv.dll

Imagine my surprise when I discovered this. By that time, I had already reversed the encryption protocols used on both connections, so it didn't help me for that part, but I also knew one of those 2 DLLs would need access to the server side secret and after some investigating, it was clear the key was contained inside the DLL itself (it could aswell have been loaded from an external file).

Equipped with that info, I wrote a small tool using libbfd which looks for the keys and just dumps them. I later verified they were in fact correct.


To this day, I'm still gobsmacked that a company can make such an error. Makes you wonder how they store all the credit card information of people!

The GwSrv.dll will be particularly interesting for people trying to write an emulator, but it's also nice to get an idea of how their backend is setup.

ie.

$ strings GwSrv.dll |grep -P '^[A-Z].*Srv$'
FileSrv
BuildSrv
DllSrv
AuthSrv
GwSrv
DbSqlSrv
DbCacheSrv
StreamSrv
SiteSrv
DistSrv
AcctHttpSrv
AcctMailSrv
CrashDumpSrv
EventLogSrv
LogQuerySrv
BeaconSrv
CrashSrv
UTournSrv
ConfigSrv
DbNameSrv
BugMailSrv
LogImportSrv
CensusSrv
DummyCliSrv
DbNameTestSrv
DbSrv
RankSrv
FileIdChkSrv
IpBlockSrv
PitchingSrv
ConfigSrv
ObsCtrlSrv
GuildSrv
ReplicationSrv
AssetSrv
EconDataSrv
EconSrv
ClientErrorLogSrv
TournSrv
EmptySrv
PlayerlessSrv
BrokerSrv
ExchangeSrv
GemStoreSrv
TradeSrv
CharUserDataSrv
PortalSrv
HealthSrv
ClientErrorSrv
MetricsSrv
ItemSearchSrv
ItemDataSrv
RestoreSrv
ListTaskSrv
TournSearchSrv
ContentSrv

Pity they didn't put them all on the CDN ;-)


Tuesday, March 12, 2013

Proximus fail!

I got a Nexus4 the other day, but since it uses a micro sim whereas my old phone used a normal sim card, I had to get a replacement for it.
Much to my surpise, the only info I needed to provide, was my current phone number! No id card, no proof of ownership, no pin number, not even the old sim card I was replacing, .. nothing!

What's this proximus?! Social engineering courses for dummies?!

Monday, March 11, 2013

Portal Connection - update

Something I just noticed today when investigating an IMAP SSL connection issue (using openssl's s_client), is that the handshake packets looked quite similar to the SSL setup of the gw2 portal connection.

ie. what I originally had:

0x14 = ack
0x15 = server error
0x16 = auth phase
0x17 = game packet

is actually:


enum {
       change_cipher_spec(20), alert(21), handshake(22),
       application_data(23), (255)
   } ContentType;
 
As shown in RFC5246 - The Transport Layer Security (TLS) Protocol, makes sense actually that they used a library for that instead of rolling their own TLS version.

Wednesday, December 12, 2012

Hmm it's been far too long since I posted something here...


GuildWars 2


So a while ago I got interested in seeing how game security was, more specifically how games these days protect people from snooping the traffic. But I was also interested in what counter measures are present to prevent or detect tampering, since bots/cheats are a big issue these days and can potentially ruin a game.

Since I was planning on playing Guild Wars 2 for a bit, I figured it would be a nice target to  investigate. The investigation was done on the beta client somewhere in march so my memory is already a bit fuzzy on some details. I've waited this long to post about it, since I didn't want to help bot makers, but I doubt it still matters today. A quick search on google will show there's already plenty of hacks out there, so anything posted here won't make much of a difference.


A First look


First thing I noticed was how much information was present in the binary. My initial thought was that this was due to it being a beta client, hence probably contained more debug info. Unfortunately a quick look at a recent binary shows this not to be the case.. there's still lots of useful information present.

For example, even just issuing strings gw2.exe is quite revealing:

!((m_view == VIEW_GAMEPLAY) && !CharClientContext()->GetControlledCharacter())
!iterator.IsValid()
DNot supported in this configuration!
..\..\..\Game\View\Headless\VhdContext.cpp
N@onRendered
..\..\..\Game\View\Default\VdfRender.cpp
metric < arrsize(m_metrics)
..\..\..\Game\View\Default\VdfLoad.cpp
m_state == STATE_LOAD_MANIFEST
m_state == STATE_MODELS_STREAM
m_mapId == mapId
m_state == STATE_LOAD_CONTENT || m_state == STATE_LOAD_MANIFEST || m_state == STATE_SERVER_WAIT
mapContentLoaded
mapDef != NULL
m_state == STATE_LOAD_CONTENT
m_state == STATE_SERVER_WAIT
m_state == STATE_MAP_STREAM

Even today's binary (16247) still shows all this detail. Anyone who has ever reversed code will understand how valuable this is during the reversing process.

The game was written in C++ with RTTI enabled, which is also a great source for information. (See Igor Skochinsky's post Recon 2012: Compiler Internals)

Anyway I'll explain the network protocols used by GuildWars 2 on here, which might help some people that are interested in writing a gw2 server emulator. I'll probably spread this over a couple of posts.

While reversing the client, I also discovered a security issue, which to this day is still present. Therefor I've notified ArenaNet today. I'll refrain from explaining the issue for some time, or until ArenaNet resolves the issue. Whichever comes first.

On to the nitty gritty now.


The connections


GuildWars 2 uses 2 ports for network communication:

- port 6600 : portal connection
- port 6112 : game server connection

Actually, ports 80 and 443 are also required, but those aren't involved in actual gameplay and it's pretty known which protocol is used on those :-)


Portal Connection


The portal connection starts as a clear text protocol, but immediately issues an AUTH TLS command, which initiates a secured connection. The actual data protocol used on this port is XML based. The game uses RapidXML to do the XML parsing.

Example XML piece:
<Reply>
<UserId>99999999-9999-9999-9999-999999999999</UserId>
<UserCenter>1</UserCenter>
<HasPhone>0</HasPhone>
</Reply>

The encryption used on this connection is AES in CBC mode. With a separate session key for incoming and outgoing traffic. An HMAC digest hash is also used, again one for incoming and one for outgoing communications.

The key exchange between the client and server is done via SRP (RFC5054, Secure Remote Password). Since SRP uses Diffie-Hellman, it won't prevent proxying this connection, which would allow people interested in writing cheats to get access to the communication on an external machine, without having to tamper with the actual client binary.

However this doesn't matter much as the game binary I investigated contained no security checks.

The game goes through some key expansion functions to generate the AES & HMAC keys.

NOTE: this is not vulnerable to MITM attacks, as one needs to know the password to be able to proxy the connection.

Game server connection


The connection to the game servers is over an RC4 encrypted connection. Again Diffie-Hellman is used as a key exchange, but in this case the server side packet is precomputed and stored in the game client, ie. the result of ga mod p has been precalculated and is stored in the game binary. Each release uses a new set of keys, so there's no point in trying to find the server key a (would take too long anyway).

The same key is used for transmitting and receiving data, but both paths use a separate state.

From what I heard, this is the same as how it was in GuildWars 1.

The actual data protocol used is a binary protocol with variable sized packets. The client has a MsgPack/Unpack function to (de)serialize the data to/from a C structure.

Again this is similar to how GuildWars 1 worked.


This is a quick overview of how the communication works, I'll go into greater detail in a following post.