Transcription
Imagine the shock on my face when I awoke Christmas morning to open gifts with my children and instead I was greeted with a CVE that affected MongoDB. Uh, the not, not a great time for anybody who's in the world of database maintenance right now.
Uh, so Mongol is the bug we're talking about today. Uh, it is a vulnerability that allows an unauthenticated attacker to leak sensitive server memory out of the MongoDB server process. It's not a great place to be if you are in the world of maintaining database infrastructure. Also, not a great place to be if you exist on the internet because someone dropped this proof of concept publicly on Christmas. If you're this guy, come on, brother. You couldn't have waited till the next day over? Whatever. It's fine.
Mongol bleed is an allusion to Heartbleed, the vulnerability in OpenSSL from 10 years ago. God, I'm so old. 2014. Uh, which basically the same kind of thing happened to OpenSSL where because of an out-of-bounds read error, you were able to leak memory out of OpenSSL, which was able to leak sensitive cryptographic information about an open SSH server, for example. Okay, so, uh, Mongol is basically the exact same thing.
The way this works is MongoDB is just like any other network-facing daemon, right? You talk to it over some kind of binary format. In this version, it's called BSON, or I think Binary Server Object Notation. And the way that you talk to it, the messages can be compressed over ZLIB, right? It's a compression algorithm. And to talk over ZLIB, you don't need to be authenticated, right? You can actually do the authentication transaction over this Z-LIB compression. So therefore, vulnerabilities that are exposed via ZLIB are exposed to people pre-authentication, right? Unauthenticated attackers.
The way this works is you send the server a compressed message, but inside of the compressed message, you actually control the field that says, "Oh, by the way, the uncompressed size of the data after it's been decompressed is this size, right? You, the attacker, control that data." MongoDB then allocates a buffer based on how big you say your decompress buffer is. The Z-LIB library is going to use the actual data and decompress the data into that buffer, but there's extra room left over because you said the decompressed buffer was actually bigger than it really is. And then MongoDB treats that entire transaction as valid, and it will send you the response, right?
The reason why people are calling this Mongol, by the way, is that this is exactly how Heartbleed worked back in 2014. Okay, the classic XKCD comic kind of explains it pretty, pretty simply.
"Server, are you still there? If so, reply potato. By the way, potato is six letters. User Meg wants these letters. Potato."
"Are you still there? If so, reply bird. Four letters. User Meg wants these four letters. Bird."
Hm. Uh, "Server, if you're still there. If so, reply with the word hat. Oh, and by the way, hat is 500 letters long. User Meg wants these 500 letters. Hat." And then it dumps all of the data behind the variable hat. Right.
So, to show you the vulnerability working, right, we have a vulnerable version of MongoDB set up. This came again with the MongoDB pock that went live on Christmas. Jesus Christ. Um, is you run docker compose up. I have docker desktop running. Uh, and what you can do here is it'll run the server for you. And now you have a vulnerable version of it running locally. Now, if we go into the, um, not hello world. If you go into Mongo, you do a little Python 3 on the Mongoled script, it's going to send the payload to the server and it's going to leak out arbitrary data up to some fixed amount and just write that to a file. Like that is that is the entire exploit. It is that simple.
And before we keep going, look at that guys. I'm almost at a million subscribers. If you could smash that sub button, I really would appreciate it. Mean the world to me. Thank you so much.
So the magic of the exploit is literally just in this one Python function here, send probe. What this function does is sets up a message to send to the server, right? And it does this using zlib compression. And then within the actual message that's going to be compressed, you have this op compressed message, right? It's a structure that MongoDB reads out to, you know, um, to read information about what is being compressed and decompressed. And so you have the original op code, the messages being sent to the server. But here is where all the evil happens, right? You have buffer size. This is the size that the server is being told that the decompressed message length actually is, even though it depends on just what the data actually naturally decompresses to. Right? So because of this, you can say in this message that the size of the data is some astronomically large buffer, and MongoDB will allocate that room for you, decompress your message into the buffer, and then send you the totality of it back.
So what's happening here is we start with this number 20 and we tell the server that we're actually going to send it 20 + 500 bytes, right? We're going to do that over and over and over again up until the number 8192. Now, as far as I understand it, because of the way that the underlying glibc heap works, basically by changing the size, you're telling MongoDB that your buffer decompresses into, you're telling it to use a different, it's called a bin, like a basically the glibc heap is allocated into these things called bins. Bins are basically a function of how big the allocation is. And so if you're trying to leak memory out of the glibc heap, you need to change the size of the field that you're going to allocate, which therefore changes what bin you are leaking from. Right? So if like a sensitive password is allocated in a field that is 6,000 bytes long, you want to allocate a chunk that has that size. So you could potentially allocate that chunk in it.
Now, why this may seem so like benign is that we are literally just being a we literally just being sent uninitialized memory from the server. But the problem is, like, it's not within the threat model of MongoDB for you to be able to read uninitialized memory, right? So like if someone does like a database query, right, where they like they select the password from the user, obviously it's hashed, but my my example is that the metadata of that query from not just you, but other users or other clients connected to the server are being exposed to you by giving you access to that previously used, now uninitialized memory. Because by default, the glibc heap via a malloc call or otherwise, a lot of other calls don't clear the data out. So if you just do malloc and then binary send to send it over the wire, you're going to get that data without any sanitization in it. It's it's crazy.
Now, obviously, the data that I'm showing you here is not super interesting because I'm not hosting a real instance of MongoDB that's doing real transactions with real user data. If this were an actively, like, like a high-traffic instance of MongoDB, this would be littered with user information, like passwords, maybe keys for various things, like things that like the average person should not see that are just the artifact of previous transactions. Like, obviously a real password shouldn't be there. But you see my point, right? Like just things that are sensitive that are not meant for other people could be disclosed through this vulnerability.
And as a result, hackers take no time to take advantage of a good vulnerability. It seems like, uh, Ubisoft claims that Rainbow Six Siege servers have been breached, as well as, uh, Rain. Yeah, Rainbow 6 is also super. So there are a couple of games that have been potentially popped. I don't know. There's no claim here that it is because of the breaking news. Um, so VX Underground, who is a well-known hacker malware person on Twitter, um, basically he kind of did a little rundown of what's actually happening with regard to Rainbow Six Siege. So there have been, I guess, multiple instances of breaches of R rain, Rainbow Six Siege that involved different groups of people. There is a second group of people that is unrelated to this first breach that did exploit the MongoDB instance from Ubisoft using Mongol, which allowed them to pivot to an internal Git repo and then they exfiltrated a large portion of Ubisoft's internal source code, which is probably leading to the gigantic hacks that are happening right now. Again, I'm just scrolling Twitter as I'm making this video, and there are like people who are saying that things they've bought in game is are getting stolen, uh, gifted roughly 339, what is that, billion trillion dollars of in-game currency to players. So there's a lot of bad stuff going on, and yeah, we are talking about like four groups of different people supposedly hacking into Ubisoft servers. So if you're Ubisoft, not having a great time.
I do want to highlight, by the way, that MongoDB's Atlas database, which is their self-hosted version of MongoDB that people can rent out. This was patched well before anything went public. So, if you use Atlas, don't worry about this. The only instances that are still vulnerable are instances that have not been updated that are, you know, still exposed to the vulnerability post the release of the PC on Christmas.
So, TLDDR, right? If you use any of these versions of MongoDB, these versions are affected. And the way that you fix it is you upgrade to the newest version. Just go take care of that right now. I don't think there's any huge interop, like backwards compatibility issues. So, it should be as simple as just run a little update and and you're good to go. Uh, and if you're not going to update, you're you're going to be Ubisoft and you're going to have a bad time.
And the question on your mind, I'm sure, would Rust have fixed this? I mean, the answer technically is yes, right? One of the major features of Rust is that if you do a runtime out-of-bounds read of a buffer, it'll actually kill the process. It'll panic. Now, obviously, in a high-performance server environment, you don't want your servers to die. Obviously, with Rust, you're just choosing that you want to kill the server instead of leaking the information, right? It's kind of a choice of which one is more important to you as a language. And obviously, this one being written entirely, uh, pretty much in C++, it just reminds you that memory safety issues like this are potentially an issue.
Anyway, guys, that's it for now. Thanks for watching. I appreciate it. If you like this video, hit that sub button. I got, I'm very close to a million subs. I can't believe I'm here. It's actually bonkers. It'd be cool if I got to a million by the end of the year. You can make it happen. See you in the next one. Take care.