← All talks

When Java Plays Unsafe: How A Single Mistake Can Break Memory Safety

BSides London · 202518:39103 viewsPublished 2026-03Watch on YouTube ↗
Speakers
Tags
About this talk
Java's Unsafe class provides direct memory access, bypassing the language's built-in safety guarantees. This talk explores how developers inadvertently use Unsafe for perceived performance gains, demonstrates concrete exploitation via a REST API demo, and reviews static analysis tooling to detect and prevent such vulnerabilities in enterprise codebases.
Show transcript [en]

Uh hi everyone and thank you for attending uh this afternoon. Um so yeah I'm I'm going to talk about memory safety in general and maybe put the you know relay the basics in case I don't know if anybody's really familiar here with the memory safety. So more or less sounds familiar. Okay. Well you you'll be experts after after we're done if I do my job right. Um yeah and so I'm going to focus especially on Java because that's kind of my personal experience but um I also try to generalize to other programming languages. Um so yeah so if that's what you are looking for you're in the right room if you are hoping for AI blockchain

sorry that was the previous talk but uh you can say so um let me start the so first with who am I so I have about 20 years of experience in in Java development mostly everything in Java because I was working a lot for financial institutions so it's a language that is quite popular in in sector and um I had a a big focus on security for the majority of this of this 20 years. I'm also a member of the um open SSF um memory safety um special interest group. Sorry, that's a mouthful but basically the focus of this group is to understand the first openf is to understand open source software security issues and try to help open source

software as much as possible. although we're not limited to open open source software but that's kind of our core um audience and then the memory safety sig is dedicated to the memory safety issue and then on I'm also you know lead at um a quantitive asset management firm in Paris um all right so let's get started so if you need to get the slides they are online um and uh I'll show this again at the end so let me move on um so what is memory safety. So as I said, I'm going to just lay the the first you know layers. So memory for memory safety the name is kind of explicit. It's everything that is related to memory

issues, memory security issues and typically they are split into two categories. Special so special is is as I'm saying here the wrong place. So that's your reading memory that you're not supposed to be able to read to to or writing to. So it's basically you're in the accessing memory in the wrong place. um which is what you want as an attacker but obviously not as a as the author of the software. So typical example you might have heard of is uh you know buffer overflow. So writing after the end of a of a buffer um or actually before the beginning um overflow is just you know you get an infin infinite loop so the stack just grows and explodes.

That's a stack overflow. So you also have the temporal aspect. So you can have a memory safety issue. For example, if you read a variable before it's in what you get if you get data because it was not clear by the previous owner of of this memory that could leak data and that's a safety issue. Um same thing if you use some memory after it's been freed, meaning uh deallocated. It's not you don't own it anymore, but if you still have access to it, you might catch some something that someone wrote right later in that memory. And so that's again an issue. And then race conditions, that's just concurrent accesses. That's debatable if it's a

memory safety issue or not, but you get the idea. So these are pretty um terms. I'm sure you you've heard before. And um and but how big is really the the problem? So I'm just going to go quickly over these, but um Microsoft says that about 70% of the vulnerability that they assign the CV to each year about memory safety. So that's like bulk majority of them. Google. Same thing for Chromium. So, I mean, it's a really really common class of of issues and they can cause a lot of problems. So, so that's a concern. So, the good news is that we have languages that are um what we call memory safe. And what they do basically

is that they put much more constraints on what you know what the code what the source code express is. For example, if you allocate a buffer or something like this, the language will add some features. Typically, there might be the um virtual machine like the JVM. They could be a garbage collector. The there will be some some form of control plane that will kind of enforce the boundaries that you expressed in your code. So for example in Java for those who are familiar with Java. So if you try to get to access some data that is you have you allocate an array and then you try to get over the bounds or outside of the

bounds of your array you automatically get an exception. It's not magic. is because the JVM underneath keep tracks of which part which um memory space is allocated to your array and as soon as it sees that your code at runtime is trying to get out of those bounds it just stops your your your program there throws an exception and says okay there there was a problem there same thing if you run out of memory instead of just you know having the application crashing or maybe you've seen like a segmentation force if you don't see your C++ the JVM will throw an exception So you still have a chance although you are running out of memory you still have a chance to

catch it and handle it and gracefully you know close your resources. So you there's much less risk by handling this cleanly. I'm not going to go over all the example but Java is supposed to as one of the example of the memory safe languages. It's supposed to kind of help you avoid all those pitfalls. So I'm saying all the pitfalls. So are we done? Does it mean you you if you're doing Java, you have to worry about 70% of you know vulnerability? Well, that would be kind of too easy. Sadly, it's more complicated than this because memory safety is not just a boolean. It's not just, you know, either you're safe or not. It's it's what we like to call a

continuum. And one of the links I'm putting here at the end of the of the slides is to what the open SSF uh published recently which is called the memory safety continuum to express the fact that you can write you know you can write memory safe software in C if you take a lot of time very careful you are very methodic you can do it but it's going to be hard because you have no safeguards no guardrails it's not it's all on you the developer to to do it right if you are trying to do it in Java you have a lot of guardrails So it's going to be much easy easier sorry um especially as the codebase scale but you

can sadly or that's my point of view um escape those guardrails if you really want to if you or if a developer is really bent on on getting out of those things. So that's when the unsafe class comes in. So maybe some of you have, you know, written Java code before, maybe you've heard of it, but it's basically Java's worstkept secret. It's a class that is not documented, that is like clearly not meant to be used by developers, but you know, they found it and it's part of the JDK, the standard Java library. So it's there on every JVM Java implementation. So well, they figured out that they could use it. So what does it do? It's pretty self, you

know, self-explanatory. You can basically access memory. The address here in the memory and you can either store or retrieve uh some some types there depending on on what you what you want to store in the memory. So you just give a memory address, you give the value you want, it will write with with the put method or it will get it with the get method. No question asked, just let's do it. So of course now you're bypassing all those checks I mentioned earlier and so you can get into a lot of trouble. There's other similar method to just allocate large amount of memory. So you can use it safely if you allocate the memory just like if you would do C you would

allocate that memory access it free it at the end then you in theory okay but you have to implement all the checks yourself to make sure that you don't get out of those bounds. So the name of the class is unsafe. That's at least, you know, helpful kind of a hint. So of course, right, if it's unsafe, nobody will use it. You think? Well, sorry. Um, I just did a quick GitHub search and I found 30,000 use of unsafe sunsafe. And there's kind of a sibling class, I'll explain a little bit more about it later, called um unsafe as well, but it's just in a different package. And there's also like 9,000 um you know uses

on GitHub and that's just the tip of the iceberg right that's the public publicly accessible open source code who knows what happens enterprise I've worked on code base of 200 millions of line of codes so really big software you know for some reason banks love big software and uh and you you see everything in there including this uh right so so okay assuming that you're working or your your job is to secure um kind of you know keep in check the developers in your enterprise they're doing Java and again it could be um almost all language have that are memory safe have kind of methods that are shady or risky um what do you do right if your job is to make

sure that you're a developer you should just know about if your job is to make sure that your developers your upset like me are not using those methods what can you do about it um uh and also maybe just Quickly I I'll say just briefly why people do use this the performance it's faster. There's a question about do you really need performance that much right? Uh Donald said famously performance sorry um premature optimization is the root of all evil. So my my opinion is that some people just think that they need the performance at all cost but I'm not sure they actually benchmark it. It is really fast but Java is also very fast natively. There's lots of

optimization and the second reason and it's like a formal study that showed that the other reason is that because people found the advice on stack overflow say sure why not. So I think maybe with a little bit more of of thought. Um so let me just quickly show what happens when you misuse it. And I have a quick demo I'll try to to to show. So

just keep give it one second to find the the terminal and move it around here.

Okay. So,

sorry.

I should have practiced this before. Okay. So, so this is an example of the just vanilla Java code that you would write with just your kind of buffer of longs. And I'm just making a rest service so I can show you an example of an exploit with curl. But the you have two methods, one to store a value, one to retrieve a value in an array of 366 days for nearly years. That would be how you would do it with normal Java and you would get an exception as that you try to get, you know, outside of this buffer by accessing it. this way. But now let's see what happens if um if I'm trying to

use unsafe for some reason because I think I really need to have the fastest, you know, array in the world. So I would just allocate that memory with this unsafe method and then I could go I can do get long or set long to access it, right? So pretty easy. Uh forget about this for a moment. I'll explain later. Um so let me start my server here. All right. So now I have my API rest endpoint and so now let me try to okay let me try to access some of the of the of my endpoint. So for example what happens if I do a get on position zero but I get a value because I'm using this API which

is not going to clear the memory for me. So I ask for some memory it gave it to me. Whatever was inside before that's my problem. It's not clearing it. Java would have cleared this array first. This this API doesn't do it. Let me try to get another I don't know position one. I get a different value. Okay, cool. Now I'm going to write somewhere. Yeah. So at slash one I'm going to write some number. Fine. Now I'm going to get it again. Cool. I get my number. It's fine. So it works. Okay. So now what happens if I do something like this? Let's go to minus one. Sure, why not? You want minus one?

I'll give it to you. You want? So, remember the I was 366 unknowns. Let's go 1,000. Sure. Three small number, but still something. I can go all over the memory from there and just read freely because there is no boundaries. Yeah. Okay. I'm not going to try too many because at some point I'm going to break something. But if I keep doing this, especially if I write. But so just for fun, let's um I wrote a small script that just takes the you know from 0 to 1,000 does some formatting like just to make it more because they are longs. I want to convert this on by in key to see what I get. So let's kind of try to decode this

memory that I'm getting. So this is the script and oh spoiler it's already running. Okay, I'm just keeping the strings out of the stream. So it's running. is getting is doing 10,000 queries. So this guy is working hard. It's finished and I'm filtering the I'm filtering only the text. Oh, look at this. This is kind of the the what I'm getting out of sorry what I'm getting out of my recent point just like by printing it in ASKI. So all of this now I'm kind of dumping. So for people who are familiar with Java that's typically Java PI code because the the memory contains both the the code of your application and your data. So I'm now

reading some some by code. And if you remember, there were some things I told you to not look at, some secrets in the in the code. So just to shortcut a little bit, I already found them for you. And so if you look down here, you will see that at some point here are my secrets because they are part of my code. I'm temping my code. So here they are. So you can see the problem. You can see the challenge here. So just quickly to conclude with some so now that I've done the kind of the you know bad news let's go to the good news. The good news is there is a way to

tell uh or to help you a tool to help you which is SAS static um code analysis. So but and that's kind of why I I I made this talk. I kind of feel like this problem in particular is kind of a little bit under represented. So lots of SAS tool will have rules for SQL injection like the OS top 10 basically they'll have it but this guy for some reason it's kind of no I don't know it's not very popular so same grip you can do it by some configuration because you can blacklist classes so it's not going to be a specific secret finding but you can put yourself those classes in your in

your in the blacklist uh sona has one but not the other too badql same thing same thing you can do it with some configuration pmd does it but it does unsafe. Why? Because it's deprecated now. So it's allowed don't use duplicated code but no mention of security which I think is the big concern here. I made a pull request for the other one. Uh but they don't seem too keen to accept it for now. I also wrote two p requests for these two other scanners and um hopefully they will be merged. So there's some hope at the end of the tunnel. I guess the other good news is that um it's getting not only deprecated which is funny by the way

deprecating an unofficial API API. So it's not supposed to exist. You're not supposed to use it, but they're officially deprecating it. So that tells you how much people actually actually use it in the real world. So long story short, they are deprecating now. They put some comments. Now there's some warnings when you use it. Soon they soon they swear they will remove it. But Java is like Microsoft, Oracle. They're very careful about not breaking anything. So who knows when they will actually remove it. Meanwhile, there is a new API that is safer. you're still own you're still handling your own memory but with some guard rail at least for the buffer overflow and so you get kind of a mix of

both performance but with some checks so I highly recommend people to migrate to this which is safer it's called FFM or for function memory and it's out in Java 20 which is pretty recent like the Java world moves slowly but it's you know in the LTS version so you should be able to start using it soon and uh so that's my key takeaways here uh prefer memory safe languages. If JavaB do not use the unsafe classes, please try to migrate to the FF API if you can and for software you can't upgrade yourself or that you maybe don't own um use SAS to at least detect it and know about it. Um some of the scanners I showed like flexiles um

spot bugs work on bite code on binaries. So even if you buy software and you're curious about are they using this and if you want to ask them why you can scan their software pretty easily. That's the beauty of Javis. It's easy to scan the binaries and that's it. So that was my presentation.

Any question if we have time for questions? No questions. All right. >> Thank you so much. >> Thank you.