
Testing testing >> good morning everybody welcome to the off track um this morning I would like to introduce Jia who is talking about primitives for security audits lessons from Jakarta Mail thanks very much >> thank you testing right um good morning everyone um I hope you are having a wonderful morning today thank you for taking the time to attend my talk uh it's my second time speaking at a conference And I hope that by the end you'll have some takeaways from this sharing. Uh my name is Ja. Um that's me over there with a very friendly red tail black cockatu. Um I'm a currently a consultant at Elum where we help our clients secure their assets through
pentesting and other services. Uh on the side I'm also interested in web security research during my spare time. So a question for everyone before we get started is um when was the last time that you look into how various libraries are actually implement implemented. So um there are plenty of informative talks these days about identifying vulnerabilities that follow certain bug patterns. They can be very useful when learning about the different vulnerabilities. However, um harden targets are less likely to have this sort of crapable bugs. uh at some point it is going to be useful to audit libraries in order to identify primitives that can potentially be be misused. So uh primitives are not actually like bugs per se. It's more
like features. So that will be the main aim of this sharing today. Uh using a case study around Jakata mail as an example. We'll first look at the background of Jakata mail followed by a short primer on encoded email strings. Then I'll be sharing various primitives I found in chakata mail namely the internet address and my message classes. Similarly primitives in spring framework will also be shared and then we will end with the email annotation from hibernate validator. So what exactly is chakata mail and why is it not called Java mail? Well, the Java Enterprise Edition name can be confusing, especially when we see that Java 2 was renamed to Java and then losing the word Java altogether.
So, um, Java 2 Enterprise Edition or J2E was released in 1999. Uh, this saw the introduction of specifications relating to enterprise technologies such as enterprise Java bins, Java server pages, uh, Java naming and directory interfaces, which we recognize as GNDI. In 2006, J2E was renamed to shake off the number two and Java Enterprise Edition 5 was released. Uh we see big changes such as the introduction of annotations. Finally, uh in 2019 and beyond, Java E was renamed to Jakata Enterprise Edition after being handed over to the Eclipse Foundation uh as Oracle still owns the trademark to the name Java. If you are curious, there's a lot of backstory regarding the change of ownership from Sun Micros Systemystems to Oracle and
finally to Eclipse where development is currently at. Um, so this is just a simplified timeline and today the latest version is Jakata E1 with version 12 in the works. So where does Jakata mail reside within the Jakata E platform? Think of the platform as a container that contains a bunch of different modules. Within this container, there are smaller containers known as profiles uh which comp comprises of a subset of Java components. So developers looking to create a compliant framework will just basically have to refer to this list. And some of the frameworks that we may be familiar with are Apache Tom E IBM web sphere or Eclipse glass fish. So the component that we are looking at
today is Jakata mail and it is part of the broader Jakata e platform. During my research uh I look into Jakata Mail version 2.1 which is the latest version released since Jakata E10. According to their website 2.2 will be released for Jakata chuff. Looking at the Jakata mail page we can see that there's only one known implementation uh which is Angus mail. With that we now know what Jakata e and Jakata mail are. Okay. Um, let's sit track for a bit to for a very quick primer on encoded strings in email addresses. Um, this is uh original. I want to give a shout out to Gareth from Portfiger uh who published a very detailed write up on
potential misusers with encoded strings in email addresses. So, if you haven't already done so, please take a look at his write up and presentation is super interesting. Um so in my in my experience during my research uh I remember his write up and wanted to extend his research to see if there's any issues in this library. Although I did not find any um I believe a quick sharing on what encoded strings are can still be useful when testing email address passing in applications. This is because uh developers may not be aware that the email passing libraries they are using likely allows and passes encoded strings. Okay. So if you are not already aware like I was email address can contain
encoded strings mainly due to email protocols needing a way to transport non-sk characters. This is defined in RFC 2047 uh which is supported by Jakata mail. Um encoded strings are basically wrapped in the equal and the question mark symbols and consists of three distinct sections separated by a question mark. The first section specifies the chets. Um, UTF8 is a commonly supported one. Next up is the encoding which is either B for B 64 or Q for quoted strings. And finally, there's the encoded text which is where the payload goes. >> So we use this example email address that is RSC compliant and deconstruct them into the different components. And this is how it looks like. And so
what can we do with such an email address? Well, uh, in Garrett's research, one misused scenario was he he tried to he was able to inject an encoded now by bite to terminate the email address early. Think of it as being similar to like a now bite injection in PHP strings. So this led to a differential between what is saved as a user's email address by the application and the email address where the emails are actually being sent to. Keep this in mind as we'll look into this differential later. Yeah, so that's a quick primer on encoded email strings and with all the background information covered, we can now move on to the primitives that are
found in Chakata mail and the focus shall be on internet address and the my message classes which are shipped by default. Um so how I found the print was quite interesting as it was just another day of reviewing our customers applications. Uh then I saw references to the native Jakata males internet address class. I decid I decided to take a look at the constructor to see how the input address is actually being passed. I've noted that there were multiple constructors for the internet address class intended for the different scenarios and here's one of it for the single string arguments and the intention is to take an email address and pass it to the pass method which
validates the emails for address for RSC compliance. Afterwards the email and personal name will be assigned to the object itself. Then there are other constructors here and there's two more that takes in two and three strings arguments respectively. Do you notice anything interesting here? If we look at what the code is doing or even the comments, we can immediately see that these constructors are straight up using the input without even calling the pass method. So it is interesting that the single argument constructor actually calls the pass method to check for RFC compliance. But when it comes to this multiple arguments constructor, it doesn't even perform the same checks. Um, it may be an intentional design for
some some reasons such as features. But the fact remains that this inconsistent behavior between the different constructors can certainly catch developers offg guard. Just to do a sanity check, I went to test it out and I just basically attempted to initialize an internet address object with an invalid string. And yeah, only the single argument constructor throws an exception. So this kind of behavior can definitely catch people off guard and that's the first primitive from this class. And we can move on to the next one. If we look at the pass method next, uh we can see how it can cause confusion when passing complex email addresses. And in this implementation, this method takes in a single string and attempts to
pass it according to RFC 822. We'll use this uh string here as an example. There's an email address wrapped in angle brackets followed by another email address. So, how do you think this is going to be passed? Well, um it seems that only the portion in the angle brackets was extracted as the actual email address. So you might be wondering what is the imp implication of this behavior. Let's assume this scenario. Uh say there's an application that identifies its users via their email addresses and it also grants special privileges to accounts from the full.com domain. And if the registration is not restrictive enough, we could register with a email address similar to the example we uh we
have seen earlier. Note that the string now ends with the at@fu.com. So we also know that the from the example earlier that the email will be sent to the address in the angle brackets. So let this be your attacker controlled email address. And so when the application is granting special privileges, it will we assume that it also does a simple match by looking for the last index of the ad symbol and uses the remaining of the string. So this happens more often than you would think and you also trust that the internet address constructor ensures that the input is a valid email string. So the developer may not be aware that the input we have here is a valid email
string. This means we can now register accounts with this special privileges granted to the full domain while verifying it through our example.com domain. And this simple example demonstrate how uh an expectation mismatch between developers and email address passes can actually lead to high impact vulnerabilities in applications. From the passers perspective, it is simply passing the input according to RSC standards. Something something else to think about is that this concept is not just restricted to web applications but also other types of services that rely on passing email addresses uh to establish identities. Well, um, what about encoded email addresses? Uh, this was where I tried to apply Geralt's research and see if no bites or any other special characters
could break the password. Uh, unfortunately, the get address method in the internet address does not perform any form of decoding on the email address component. So, we can't apply any encoding tricks here. Um, before we move on to the next method, I would like to draw your attention to the comments for the pass method. uh it says that it is an ad hoc mess and it is not a perfect passer. So let's take a look and if you look into the source code itself it goes on for around like 450 lines of code in a single method of basically uh positional checks very intensive. U if you're motivated to look into the exact implementation I wouldn't be too
surprised if you can find some issues here. Okay. Um, another method from the internet address class is the get group. So, this method attempts to return an array of internet address from the current group address. You might be wondering what is a group address. Um, it's basically a special string that has the following syntax. So, you start with a group name and then a colon. After the colon is zero or more email addresses with comma being a delimiter and the entire sequence is terminated with a semicolon. So a group address is different from a mailing list address which we might think of when thinking of a group of email addresses. And so a group address will actually
pass uh the passing of the internet address constructor itself. And if we run the get address method to retrieve the pass email, we see that it simply returns it as it is. uh at least now we know that uh a group address is valid RFC 822 syntax and would pass uh this validation uh one example of misusing these primitives could be uh for example application that uses a dangerous reject and that's vulnerable to denial service. So somehow supplying a group address may cause catastrophic backtracking. That's just one example. And now we'll look at the other class from Jakata mail which is uh my message. And this class is used to represent the message envelope which includes the
email headers and body. What's interesting here is that when passing certain email headers such as from, reply to and subject, it will call the intern pass header method to process them. Then the pass header method will call the same pass method that we just saw. This means that primitive applicable to internet address are also valid through the my message class. These are the my message constructors that take in an email envelope as input and then passes the from reply to and subject headers via the internet address pass method. If you happen to come across applications calling any of these my message constructors with user supply email envelopes, be sure to take a closer look at how it uses the input
from these headers. So we use this sample email envelope here and we try to pass it using the my message constructor. We are using um encoded strings here to demonstrate that values in these headers are automatically decoded by the my message class. Uh this is just some sample code used to pass the email envelope and that calls the constructor and pass the envelope as an input stream. Um anyway so um this was the constructor I used to sorry the code I used to to call the constructor to to pass the email envelope as input stream. And if we look at it we can confirm that the encoders values that we supplied were actually decoded by the
constructor. So um a potential misuse scenario here is um maybe an application that accepts an email envelope uh file and maybe it runs an input filter to strip any uh deny listed words from this input. To bypass this check, an attacker could simply supply encoded strings as part of the deny listed words instead. And when the application calls the constructor to create the email object, the encoded strings are automatically decoded. And in this scenario, so we saw that if an application is unaware that uh the my message constructor actually performs input processing in particular decoding encoder strings, it can potentially subvert the input validation logic. >> Okay, so we are still at my message class. The other interesting method is
the get recipients method. So this method receives a header value from the email envelope according to the argument type. There are four acceptable types which are defined as a Java enum. The interesting one that I would like to point attention to is news groups. So um observe that if the recipient type is news groupoups, the get header method will call the will be called to retrieve the values from this news groups header, the get header method then concatenates any duplicate headers with a delimiter which is a comma in this case. What this means is that the method actually accepts duplicated news groups headers and this edge case may not be obvious to developers. Let's take a look at how the concat
concatenated value is being passed. In the pass method, it basically splits the input string by commas and inserts them into an array list of news address objects. And the issue can be found in the news address uh constructor. and observed that the code does not perform any uh validation except to strip white spaces. Also seen in the comments were that it does not throw an exception if a mform input is received. So this behavior is kind of different from how the internet address constructor behaves where exception is thrown if an invalid input is received. And the exact implement implication of this will depend on how application uses these news group header values. Having duplicate values uh dup duplicate
headers may also cause potential issues if developers do not handle them well. So um let's take a look at this in action. So here's an email with multiple news group headers. When passed with the my message, the result is a list of news group address with spacial script. Yeah. Um, so that concludes the primitives in the internet address and my message classes. We'll take a look at a couple of classes from Spring Framework. Next, and they all utilize the Jakata mail library in one way or another. The package that we are looking at is the the ap spring framework.mmail and its sub package java mill which contains support for springs mail infrastructure. We'll be looking at these four classes
shown here which are all found in the java mail package except for sample mail message. The internet address editor class is used to prepare an internet address object using a supply email address. If you look at the source, we can confirm that it simply passes the input string to the internet address constructor. So this is another uh example code which uses which calls the method. And since the input goes directly into the internet address constructor, the personal name field will be decoded if it's an encoded string. As we have seen earlier, the encoded email address are not decoded via the constructor and only the personal name section will be decoded. Nonetheless, a potential misuse will be fishing
attacks. If an application shows the personal name section of an email address first, we can make it look like the email came from a legitimate sender. As for the three remaining classes, we can take a look at them together as they all related. These are the my mail message and it helper implementation as well as the simple mail message classes. They are all implementations of the mail message interface. So the simple mail message class has a pre similar primitive to the internet address editor that we just saw. The address fields will all eventually make its way into the internet address plus method and this will decode any encoded strings in the personal name field which
once again may catch developers off guard. and the sample code used to confirm the behavior. Basically using uh encoded email string here and verifying that the decoding occurs with the person name personal name section of the input address. So um up next is the my mail message which is just an abstract class that represents the email object. The helper class is the one used for handling any logic and the helper constructor takes in a my message object as well as a string which can be sketchy if it's used unsafeely. The string in this constructor represents the encoding type of an encoded email string. The constructor will create encoded string for us if the person name section
contains at least one non-eski character using the encoding that was specified. Once again, uh an application will be spoofing as uh depending on how the application is coded, it may display the decoded uh personal name instead. I'm not sure how much time we have left, but we can look at one primitive I found in the hibernate validator library. So, um the hibernate validator library uses this uh email annotation that developers can use to validate email addresses. Uh, unfortunately for us, the default rejects in use does not approve of encoded strings. However, it also allows custom rejects to be supplied for developers wanting to take matters into their own hands. The default rejects is pretty intense
and it performs validations in two parts, before and after the add symbol. I've played around with the reax to see what kind of strings you could pass the validation. uh I managed to find one instance. Um so the string you see here is uh one that will pass the reject checks. So simply wrap any bad characters in quotes before the add symbol and it will likely succeed. And it usefulness will depend on how uh the application you're looking at uses this email string. For example, if it does a naive split by the ad symbol and uses index one as the domain, then it may potentially lead to some issues. All right, that concludes the sharing we
have today. To recap, we have seen a few primitives from Jakata Mail Library as well as in Spring Framework. Uh the main takeaway I hope everyone has is that we should always take a close look into the libraries that we use or come across, especially if they have potential to have interesting behaviors like we have seen. With that, we have come to the end of the sharing. Thank you for your kind attention throughout and I hope you found it informative.