
[Music] hi everyone I'm Connor from MWR I'm the head of mobile security and today I want to talk to you about well TLS amongst other things so as you can see the slide is titled terrible lead security and we'll be discussing some ways where people can essentially try and Implement TLs but make mistakes and what the consequences of these things are with me I have Andre who's just going to do a brief introduction of himself so hi everyone my name is Andre I'm also a a mob SEC consultant at MWR cyers sec I joined about a year ago um but in that time I've still Beed witness to uh terrible terrible Horrors Beyond imagination so I'm going to uh show
share my experiences as well so at the end of the day this talk is about certificate chain validation certificate pinning domain and verification and then as an added little extra we've got custom cryptography before we get into the technical details of this talk I'd really just like to talk about some real world examples of how these things have gone really really badly the first example here is a is a paper titled spinner the semi-automatic detection of pinning without host and verification now we'll get into the the nitty-gritty details of this paper in a bit but at the end of the day the really terrifying thing here is large companies were found to have their mobile
applications not even do chain validation I.E they could be man in- the- middle using a self-signed certificate so that is incredibly scary we have names like HSBC here for example the next thing that we're going to discuss is cve 2018 8970 and this is a vulnerability that was identified in implementations of boring SSL as well as Libra SSL which led to what I would dare call a trivial man-in-the-middle attack again we'll we'll get into the nitty-gritty of this a little bit later but I just wanted to kind of prepare you guys for what's to come and so with that I'm going to hand over to Andre and I will catch you guys in a bit thank you Conor all right so um I'll
be going over the first point uh which is a certificate chain validation uh before we actually get into the niges of it let's just go from an example that we're a bit more familiar with so when you uh use a browser to navigate the internet um it will perform a number of certificate validation checks and if any of these checks fail uh it will obviously present you an error this is good and all but we often take this for granted it's a feature we commonly see but is it actually implemented everywhere so often on mobile applications or th clients uh we'll see that the implementation details are often left to the developer um and as
not all developers are familiar with you know the intricacies of how a certificate should be verified this leaves a lot of room for error consequently It's Not Unusual to see uh some errors with custom implementations um but then we have to ask uh what is a good implementation how do we actually get to it so before I jump into code examples let's just uh cover the basics so certificate validation is the process of checking whether or not we have um whether or not we trust the certificate that's being issued to us and as I mentioned on browsers this happens mostly without thought on mobile applications we have more control of the certificate validation process and hence
this becomes a more prevalent feature that we have to keep mind of um the process starts with uh us receiving a certific or chain of certificates this is normally presented as array and I've sort of somewhat highlighted that there Loosely you can somewhat see it's an array um one of the uh certificates will be the leaf certificate which is represented uh uh sorry one of the certificates the leaf certificate which represents the server we're connecting to um and then the others are normally intermediaries in this example here we've got one that's a root certificate um though this might not always be presented as part of the chain so the job of a certificate verification function is to ensure that the chain is
valid and that uh the certificates verify one another and that the end certificate is actually signed by a root CA um that are device trusts so that's all good and well but a visual example might help describe that process a little bit better so let's take let encrypt uh let's encrypt has two root CA certificates uh namely isrg root X1 and X2 um and uh these are sorry yeah these are followed by intermediary certificates which are r10 R11 E5 and E6 um the following certificates at the bottom there you'll notice are the ones that we actually issue to clients so we can see on the right hand side of the screen that um Android 12 or
at least the Android 12 device we were using Imports the isrg route one certificate as part of its system certificates now those of you with a Keen Eye might also notice well hang on that's a little bit weird we we don't we don't import the X2 certificate what's going on there that's a whole another discussion but um the important part is that you do see that the uh X1 certificate is included in the list of trusted system certificates so if an application receives um a certificate chain with both the r10 intermediary certificate and the client's leave certificate the application will have to verify the leaf certificate uh has been signed by the r10 CT and that the r10 CT
has been signed by the x1t all right so now that we've got a little bit of a clearer picture uh let's look at some code examples I should just note that um with chain validation a lot of things can go wrong so we're going to be teaching sort of or going through these slides sort of from the uh perspective of how things can go wrong um the examples I'll be demonstrating will mostly be Java and cotlin the Conor will uh jump into other uh prog programming languages at a later stage um and yeah I just want to make explicitly clear this code is just for demonstration purposes and should not be considered authoritative all right so in our first
example we have um an SSL context object that is used to establish a connection uh you can see it sort of towards the middle there uh we then make use of a custom trust manager uh which you can see sort of at the top uh and that's used to handle uh certificate validation so as I've mentioned numerous times now certificate validation is a difficult and highly error prone process uh so we have to ask ourselves what's wrong with this implementation now this that question is going to be a little bit rhetorical because uh time concerns so I'm just going to jump straight to the solution so if we ignore all of the rest of the
code and focus on the trust manager implementation we can see that the check server trusted method as well as the other two methods above it um don't actually do anything the Czech server trusted method is supposed to validate a certificate chain and if it discovers anything wrong uh it's supposed to raise an exception but in this example it just simply returns uh performing no actions so consequently this function will accept any certificate passed to it this means that it would be possible for an attacker to present their own self-signed certificate and man in the middle of the application you can see at the bottom there we're making a request sorry for those that are sitting a
little bit further away um but we're making a request to uh self-sign DOB ssl.com which is designed to present a self-signed certificate um this is the type of certificate that we would normally expect an attacker to present when they're man in the middling an application for instance using burb Suite but now if we run this code uh we can see that uh a successful connection is made with a 200 okay response and that the certificate has been accepted so you might think okay this is all good but it's an unrealistic example who in their right mind is going to do this but we have actually come across implementations like this in the past regardless though how can we
improve well we can start by providing an implementation so uh in this new code snippet uh We've provided a bit of a naive example of how one might go about verifying uh certificates passed in the chain parameter there are numerous errors with the above um especially considering there's a lot of checks that aren't being performed but we're going to focus primarily on the logic error here so again it's going to be somewhat of a rhetorical question due to time constraints but constraints but can anyone sort of identify the major logical error being performed here um and I should mention that the chain. verify function in the middle does throw an exempt an exception if the chain is
not valid so that's not the issue if I move on to the solution um again ignoring the fact that we don't actually do any other validation checks we can notice that the for Loop here will attempt to follow the chain validation sorry follow the chain and validate each of the certificates it does this by looking at the certificate ahead in the chain obtaining its public key and then using this to verify the current certificate in the loop um so yeah this Loop inherently requires at least two certificates uh be present in the chain parameter as otherwise how's it actually going to go ahead and look ahead in the loop right so that's great but what happens if we pass a single
certificate all of a sudden there's nothing in uh to look ahead in the loop to see you know to retrieve a public key from and this Loop is skipped uh which means that no validation checks are being performed and thus meaning that again a single self- signed certificate will result in a bypass of this function so again if we run the application we can notice that we receive a 200 okay response from the server and um yeah it the uh the single self sign certificate that we passed it which can be seen sorry again if the font's a bit small but it can be seen in our debugger and it can be seen within Firefox all right so basically just as a
recap for the chain validation component uh we've gone over uh an example where chain validation performs no checks and again this does happen um it mostly happens because developers are running into some sort of uh uh chain validation error they're busy on a uh working on some other functionality of an application they don't have time to deal with it just disable all the checks um and we've also gone over an example with some logic errors that would be bypassable with a single uh self-signed certificate which again is it is something that crops up in custom implementations so how do we fix this we could spend hours ensuring that we've encapsulated every Edge case in logic
flaw um and we could uh Ensure that we've correctly validated our certificates and have made sure that they're signed by uh a system trusted CA um but this work has largely already been done for us so going back to our original code example all we can do is simply replace the uh custom trust manager object uh with a null value which uh when initializing the SSL uh con context object itself so this null value will indicate that the default trust manager implementation will be used which does handle many of the cases we face um but it will also be implemented in a much more secure manner than what the average developer you know whose F main focuses on developing some
other functionality uh can do um yeah and at least as well uh you know again a main a normal developer's main concern is developing some other functionality and not dealing with some pesky certificate error um so yeah with this implementation uh the self uh the request to the self-assign dob ssl.com domain will fail with an error message as it should on self-signed uh certificates we've seen a number of custom implementations through the assessments we've performed and uh some of these like I mentioned did the same thing as the first side as the first example uh and others did uh have bypasses that were rep uh similar or rep replicable to um the second logic flaw
that I demonstrated um so yeah these are again as I mentioned mostly just a result of developers trying to avoid certificate validation errors but um it also occurs when developers are trying to implement additional controls and uh this particularly crops up with certificate pinning so what is certificate pinning well um oh yeah and also do we actually need it if we perform chain validation so well it's true that performing uh certificate chain validation does cure Communications to an extent it's actually very integral integral um there are a few additional defense and depth measures that can help make sure that our application is more secure so certificate pinning is one such example uh it is a measure that protects against
a certificate Authority being compromised and then issuing man malicious certificates that can then be used to man in the middle applications so we'll see how this works with a few examples so as usual before we jump into the code uh let's just discuss the how the mechanism Works briefly so certificate pinning is the process of selecting a certificate in the chain that you always expect to see uh for instance in this diagram it's the orange highlighted block um and then once we've picked out the certificate that we expect to see we can maybe for instance hardcode this value in the application and make a point to check that it's present in the chain uh that we receive
if this value does not exist then we can reasonably assume that we've received a chain that doesn't quite make sense and then we can close the connection so um how does it work in code um it follows a similar approach to what we've seen before with uh with the normal chain validation um as usual none of this code uh should be uh considered authoritative these are just for demonstration purposes so in the example I've listed there um we've implemented very basic uh version of certificate pinning uh more specifically we've pinned an intermediary certificate using the chain one parameter it's uh sort of right or the F the second item in the chain array so it's uh sort of three lines
in um we're making again the assumption that in this case at least that the certificate will always be in the second position and then as usual we need we should ask ourselves what could go wrong um so if I just just jump directly to the solution the first thing that we should be a able to identify of course is that we haven't actually implemented chain validation um and that is because we're using the same check server trusted method as before so chain validation and certificate pinning are implemented within the same function which often causes a lot of confusion so with the current logic it would be sufficient uh to submit a chain with an intermediary certificate that contains a
public key that we've pinned and then we can otherwise do whatever we want with the other certificates um and so yeah why is this important well again it allows us to man in the middle of the application so let's go through it step by step um and see how the application can be man in the middled uh when we run our program we'll receive a certificate chain uh in the chain parameter as mentioned previously um yeah so the chain parameter uh if we were to draw it out in a diagram it might look as follows we've seen this a number of times it's an array we've got values 0 1 2 and three uh we have a leaf certificate in
this case two intermediary certificates and a root certificate so now if we move on to the if statement uh or the if uh code Block in our code uh we can see that this code block will throw an exception and it will uh terminate our connection if the pinned certificate doesn't match the received uh intermediary certificate certificate we're expecting in the uh second uh array position so as a visual aid uh let's say that we've pinned a certificate that's referring to a public key in the first intermediary certificate so basically number one there um that means that the the certificate's public key must be present in the chain array in order for validation checks to succeed succeed so
as a malicious user um we may have knowledge about this process because we may have revers engineered the application um and in order to prepare for our attack we can start by generating our own malicious certificate chain that we control um I should note that uh in these cases we were using uh the debugger and sort of mashing in extra certificates in uh but in most cases you would need to actually have a server that can you know will agreeably actually serve that certificate uh chain all right so again since we as the attacker of control we're able to manipulate the Chain's content so therefore we can insert uh a malicious certificate and with a public key that
matches the one that's being checked for in the code so the uh red portion there sort of appears a little bit orange but uh maybe that's just my perspective um so yeah it shows how we've inserted an extra certificate um uh that shows how the chain is being manipulated um and now with this additional modified chain we can uh uh we can pass it to the previously used check Ser trusted method and it will trust this chain and that is because it fulfills the basic prerequisite of having a certificate with the correct public key so under normal circumstances I should mention that this would fail because of chain validation and this is because again our injected certificate
May reference a completely different Leaf certificate if we start from the top or at least from uh point two the public key under the certificate number two would not verify the signature of uh certificate number one this is because uh certificate number two was not used to actually generate certificate number one and likewise with certificate z uh we would not uh certificate Z would not be verified since uh certificate one would not uh have the correct public key to verify its signature so uh if chain validation were to be performed uh this forged chain would immediately be rejected but again it just so happens that in implementing certificate pinning developers will often forego chain validation logic because they occur
within the same function so let's take a look at another example where we've attempted to fix this issue um so this Builds on the previous slide uh again I apologize for the small font um but I'll just describe it so basically here we have um a function that's performing both chain validation and certificate pinning so the top block is calling the default uh certificate uh chain validation uh implementation and the bottom block is doing the certificate pinning that we saw previously um however there is a logic flaw with this code so jumping right to the the reason or what it is uh we can see that uh We've introduced an is trusted or is chain trusted variable
right at the top it's highlighted throughout the uh the code block example um and this is there there is right at the bottom there's an if statement that uh is used to determine whether or not an exception should actually be raised so we can we can see that uh an exception is thrown when the default chain validation error occurs uh with the um the catch statement because our normal chain validation occurs in a tri catch statement and in the catch statement we have the is trusted chain value being set to false so the chain validation part of this code works as expected however the same logic is applied to the certificate pinning portion of code um
so again if the certificate is actually valid the is chain trusted variable is then said to true so because we're sort of assigning uh values to this variable constantly um it means that uh chain validation could be uh invalid right we we could have an invalid chain um but if our certificate if it finds the correct pin certificate um it means okay great the uh you know this is trusted chain and we can move on so this is similar to our previous example um in that again we can just ignore chain validation completely so again that was sort of a bit of a naive example but it show it shows how um implementations do often
have these weird logic bypasses and again if you're a developer who again is focusing on something else you know you're not really there to go in validate certificates it's easy for uh these logic flaws to slip through so just to summarize what we've covered uh we've gone over certificate pinning um or an example that doesn't uh Implement chain validation and we've stepped through the entire process uh We've then proceeded uh to also talk about uh another example that shows how even if we do attempt to implement checks logic flaws may exist again this code gets complicated and it's not always uh clear where those logic flaws might be so again how do we fix this uh again this
code should not be taken as an authoritative example it's just for demonstration but if we want to uh perform what in general what we want to do is we want to perform the default uh certificate validation checks as we did before um and we want to add our certificate pinning checks as well uh afterwards uh again as was shown before however we should not block either of them from raising an except ception so that shouldn't occur in the certificate uh chain validation portion of code shouldn't occur in the uh uh the certificate pinning portion of code so um yeah again this is just an example uh please do not implement this in your projects all right so um as a summary uh
certificate pinning is a defense in depth control its implementation often leads to vulnerabilities in chain validation and this is particularly because both chain validation and cerificate pinning rely on the check server trusted method at least in Java um and it is generally recommended that we call our default uh the default check Ser trusted implementation and add any of our additional checks afterwards um on Android there is a network security uh config.xml file that can be used to make the process of adding or or make the process of certificate pinning easier uh there's also a further discussion to be had about where do we actually pin um on the Chain um but we'll leave that out of
scope for this talk now and move on to another important control so I'll hand over to Connor now who's going to discuss an extra control which might not be thought of as often as it [Applause] should all right thank you Andre so the next control that we're going to talk about is called host and verification so traditionally when you do chain validation the only thing you really know about this chain that's been sent back to you is that we can trust the leaf certificate we don't in fact know that the host that we're talking to is the host that we intended to talk to so the process of host name verification is in reality really simple if you look at
the screen there you can see at the bo at the top we've got a host called bastioncon spox.com and at the bottom we've got the certificate that has a common name of bastioncon spox.com and what we've just done is essentially the process of host name verification we've ensured that the common name in the certificate matches the physical domain name that we connected to now this is incredibly important because if you don't do host name verification you are vulnerable to a trivial man- of- the- middle attack whereby any certificate in the world that is trusted by a certificate Authority and that certificate Authority is on a device can be used to man in the middle your
connection so if this mistake was made by something like a bank for example I could man in the middle of the connection by simply using the certificate that I use for my blog really scary stuff right so you might be surprised to hear that a lot of stacks don't actually treat hostand verification as a part of chain validation I would argue that both these things are absolutely integral to making sure that we can trust the TLs channel so it is very surprising to hear that Java for example does not perform host hand verification out of the box whereas something like go Python and C do perform that so let's jump straight into an example here we can see we're
connecting to a host called wrong. host. bad ssl.com and at the end of the day this is just a raw um TLS socket that is creating an HTTP request as we can see there we're just sending a get and we've got a try catch at the end to let us know if anything went wrong now you're welcome to connect to this host on your phone on your laptop should you have it with you what you'll see immediately is an error telling you that the certificate common name is considered invalid now this is because bad ssl.com serves a wildcard certificate for well wildcard bad ssl.com but the common name that we're trying to connect to is wrong. host BS
sl.com so that mismatch is the thing that's causing the certificate warning however if we go back to our Java implementation we can see that even though there's a mismatch in the common name the response is returned again this just opens you up to a very trivial man- in- the middle attack what's interesting here is just how different Stacks treat something like host and verification so you'll see that a browser for example will give you a warning however if we look at something like a HTTP client it also provides you with a warning you can see at the bot their kill is complaining about the no alternative certificate subject name matches the target host name it's the exact same error and we're
expecting to see this with HTTP clients when we move to TLS clients as with the previous example however you're not necessarily guaranteed that domain and verification is actually being performed so let's look at a very naive implementation we can assume that chain validation is being done however all this is really doing is fetching the common name from the leave certificate and checking if it contains the the keyword google.com turns out that something that passes this constraint is actually really easy to come up with we can go with something as simple as Google doom. attacker.com which would be considered valid and would again allow you to man The M this connection so a safer implementation is
actually incredibly trivial but before we get to that I just want to reiterate what Andre was saying whenever we're trying to increase these controls on our TLS connections or you know God forbid relax them we have to implement this check server Trust mechanism and unfortunately again it's the exact same place where chain validation certificate pinning and domain name validation has to occur and this confusion can lead to vulnerabilities in the software that we test so firstly there's the interface we don't really care about check client trusted or get accepted issuers in this case when you're just doing a normal TLS connection the most important method is check server trusted if we continue we're going to um
essentially just have a look at the two different blocks here so this is a trick that I learned from CSI it's called zoom in enhance and as you can see we're just checking whether or not the leave certificate is a literal match against wildcard ssl.com just ignore the fact that the host name changed there from out under you if we go to the next example so the second critical part of ensuring that this connection can be trusted is performing chain validation so this implementation just essentially gets all of the default trust managers on the device and runs the um check server trusted mechanism with the chain if if an exception is thrown it'll be bubbled up to the
original mechanism and the connection will be killed if there's anything wrong with the chain so let's look at a safe imp implementation for goang and there's a very good reason why I picked this one so firstly at the top well firstly we can see that the code is a lot more simple which is uh a really good thing in my mind so we start by specifying the physical domain in that we want to connect to google.com in the port then we create a TLS config option for which we set the Sni or server name indicator that just tells that receiving server what host am I actually trying to talk to and you'll see that this is set to
facebook.com so this very trivial program emulates what an attacker might do to try and man in the- Middle Google using a valid certificate from Facebook and if you've been reading the news lately this is not such a far-fetched example when we run this example we get an error that says fail to verify the certificate or the x59 certificate and here in lies the the really important part the goang implementation out of the box performs host name verification not deferring or delegating it to the calling application which is secure by Design and which is what we essentially want to go for we're going to come back to this example because it becomes important when talking about one of the
real world examples so this is the uh the research that I was talking about earlier called spinner the semi-automatic detection of pinning without host and verification really some phenomenal research that was done there's a tool that accompanies this that attempts to essentially test whether not a mobile application is vulnerable to this kind of attack but let's maybe just take a step back and first talk about what the constraints are what we need to be able to man in the middle of connection that makes use of certificate pinning chain validation but does not perform host name verification so we've got two pretty decent constraints there the first one is that you need a valid certificate I
mean anyone can go to elect encrypt and just get a certificate for any domain that they want to so that's done fairly easily the second constraint is that somewhere in your chain there must be a public key that matches what's been hardcoded in the application now that is a fairly large task it's you're not going to get the exact same chain but it turns out what you can do if you look at the top at HSBC they use semantic they put one of the semantic certificates so what you could do is go to the same issuer ask for a certificate and essentially send up a prayer and just hope that you happen to receive a chain
that happens to contain the same public key and if you do for the low low price of $1,000 you can now man-in-the-middle hsbc's applications I think the scarier part so so that was already a feat of itself but the scarier part here is that while doing this phenomenal research these guys figured out that there are a bunch of apps on the App Store that just accept self sign certificates so imagine you went through all this effort to do this research and you just didn't need to do any of it at the end of the day so really would highly encourage you guys scan the QR code if you want to go read the paper it is incredible the tool
itself is also linked in the paper um a really good thing to kind of grasp with these these Concepts and understand them a little bit better so moving on to cve 2018 8970 I mentioned that this was a vulnerability in boring SSL and Libra SSL this affected um not Chrome although Chrome does use boring SSL so it was almost very very scary but it did affect open BSD python Alpine and I either postgress or Maria DB I can't remember exactly now but what essentially happened is we need to First understand how do we use op SSL as a caller of that Library so we can see that we have this mechanism called x509 verify parameter
set one host which is a mouthful but it essentially takes three parameters the first one is some kind of magic context object and we honestly couldn't care less about it the second parameter is the host that we're trying to to to validate so does the common name match whatever is contained within verify host and the third one is a size parameter and this is where the interesting bit comes into play so the authors of boring SSL wanted to create an open SSL implementation that is um or at least different goals compared to the original op SSL implementation so they have their own new interface that you can use and this is really important this new
interface does perform host name verification out of the box but the older one so the interface that's compatible with OP SSL it's the same it's the same interface but a different implementation um does not perform host name verification unless you opt in and that's also true for open SSL itself if you just use it out of the box you're not doing host name verification you need to opt in to host name verification so let's just take a very brief look at what this function looks like right we talked about the magic context object we don't care we talked about the verify host parameter the size parameter being zero might be a little bit strange to
the audience at the end of the day what this is is just a C string a character ARR character array of a bunch of byes that just ends with a null Terminator and that's how we know how big this particular host is or at least the string that represents the host so op SSL supports multiple let's call it calling conventions for the argument sake whereby you can use a C string like call as we're doing here where the runtime is responsible for figuring out how big the actual object is or we can specify the object size ahead of time so five bytes for example now the boring SSL authors are not fans of the C string
calling convention the idea that the caller can pass in some kind of object that has an unbounded size and we have no idea what that size is is well frankly a bad idea so they never implemented or never intended to implement support for this particular interface inside a boring SSL so let's just dig a little bit deeper what you can see there at the bottom is that if the name length parameter is set to zero or the name parameter itself is null we immediately return one now the implication of this just for anyone who's not aware in C or C++ anything other than zero is considered as true and zero itself is considered as false so when you run this
function and you use the C string calling convention it it would immediately return without raising an error whilst indicating that host name verification was successful and what I meant by how this leads to a trivial man- in-the-middle attack is that essentially now all we can do is the exact same attack that I discussed earlier where we take a certificate blog.on spox.com for example and we use that to man in the middle Something Like A bank's mobile application now again this impacted openbsd Alpine python a bunch of software not Chrome luckily but I'm sure you can see how something like this could be incredibly impactful so the fix here is actually very interesting I suppose the
vulnerability was introduced by two lines of code and it's only up that the fix is also just two lines of code so all we do is we just check if the name length parameter set to zero and a parameter is actually passed through we determine the size of this parameter and the little bit of code at the bottom that's still responsible for introducing the vulnerability is never executed and thus this was patched with just this is literally the entire commit was just two lines of code what is interesting here before I get to that slide while doing research I came across one of the committers called Adam Langley so I sent him an email asking two questions is it
normal for TLS clients to let's say not perform host and verification and secondly why would the go implementation be so fundamentally different compared to the Java implementation and we've come full circle because the answer is actually quite simple it's older software at the at the end of the day the Java implementation is much older than something like the goang implementation so he did confirm that historically chain validation was performed by your TLS client but was deferred to the calling application as we'll see in a bit recently that's changed it's for any modern Library the idea is that the library will be responsible for handling both chain validation and host and verification seeing as these things are so critically
intertwined so the second question that I asked was why would the goang implementation be so fundamentally different from the Java implementation and he answered in a very funny way he said well I don't think I was the first person to change this implementation to behave in that way at that point I thought maybe I'd bitten off a bit more than I can chew here because I had no idea who Adam Langley actually was so just to put it into perspective he is one of two people who committed to a fix for the heart bed vulnerability in op SSL um he's worked on Google Chrome's networking stack as well as Chrome's or sorry Google's https infrastructure and
he is also the author of Go's entire TLS p package just per chance so the reason that go actually performs host name verification out of the box with the standard library was a direct result of this vulnerability it's a decision that they made to say that look this doesn't seem like a good idea to defer it to the calling application so let's learn from all mistakes let's rather do this for the developers which I think is excellent it shows how as an industry a tech industry we can grow and can learn from our mistakes I do want to highlight um Dominic had this excellent point about Community I do think it's it's really amazing that we work in an
industry where I can reach out to someone who has or is arguably such a behemoth I would I would guess that everyone sitting in this room has at some point used software that relies on something written by someone like Adam Langley so I I just think it's it's incredibly amazing that you can reach out to someone like that and get an answer and it's not been the only scenario where I've had instances of something like that happen so as a summary if you fail to perform host name validation it validates any security that you actually get from TLS and you might as well have just used clear text connections to start with a good HTTP client should
perform host name validation for you which is evident by something like cool or OK HTTP for example all of these clients will perform host name validation without you asking for it an SSL client it gets a little bit more tricky it really depends on which library is this client using if it's a more modern Library like Li pki for boring SSL it should perform host and validation out of the box however if you're linking to something like open SSL I hope you've read the documentation and you know that it's not going to perform host and validation for you I really just want to highlight that if you're building any of these systems it's critically important that you know
what these clients are doing because that informs what you should be doing afterwards just to re highlight Java doesn't perform host and verification out of the box go Python and C actually do and if you're ever on any kind of mobile application assessment thick client assessment um web services where there's some kind of call back testing whether or not hostand validation is actually performed is incredibly important for you to be able to give your clients some kind of security Assurance so let's move on to custom cryptography I want to clarify that this is not someone rolling their own SSL or TLS stack I hope that throughout this talk we've already determined that that would be absolutely insane and that
there's only a handful of people on Earth who are qualified to do something like that rather this is people implementing custom cryptography over and above the use of normal TLS so the implementations that I've personally scene can range from very simple to what I would refer to as love crafty and horror so a really simple one would just use AES above TLS a more complex one would use RSA to perform key exchange and then switch to AES a sort of pseudo TLS over TLS if you want and the really terrible one that still gives me nightmares is all of the above except the application happens to pick and choose which set of keys it uses
depending on which set of functionality it's actually in that's honestly an absolute nightmare to test but I really want to highlight here that these provide absolutely no security benefit by using this custom cryptography if anything you are introducing more risk into your organization because I would make the argument that they are harmful if I could use an analogy I would use a rotten apple tree I mean you don't walk up to a rotten apple tree shaking it and expecting anything other than rotten apples to fall out of it so just basically what does this look like we've got a mobile app sends an encrypted request fairly simple stuff if we were to look at something like Jason
we've got an encrypted payload we we don't know what to do with that and now we first have to go and figure out okay how can we decrypt this payload now in all of the cases that I've tested this logic is embedded within the client which makes it very easy to figure out maybe an hour or two's worth of reverse engineering in some cases it's so easy you can copy the uh Java code from the Android application into an IDE and just run it and there you go you've got your decryption routine right there and then so we really don't want to for every single payload that we want to submit reencrypt the payload by hand that would
be insane it would take way too much time so instead a colleague of mine came up with this idea where basically you create a burp plugin that sits well on top of burp and whenever the mobile application issues an encrypted request that plugin will go decrypt the request so that it's now clear text now we can go and we can use repeater we can use proxy we can use scanner all of your favorite tools but you're essentially interacting with the clear text version of that encrypted request before we send it off back to the API we need to remember that the API expects this to be in an encrypted form so then the plugin is responsible for re-encrypting the
payload vice versa happens when we go from the API back to the mobile application the encrypted response is decrypted by the plug-in but remember that the mobile client expects the response to be encrypted so we have to reencrypt the response as well so this takes something like this which we can't really work with and turns it into something like this that looks a lot more or easier to understand a lot easier iier to understand the QR code there is a blog post by my colleague Dylan it's an excellent introduction into how you could structure such a b plugin I think it's got an example application as well as some scaffolding it's really the first thing that I use
for I reach for whenever we see that we need to implement some kind of plugin to handle custom cryptography the second solution here is a very quick and dirty one and I'll explain why in a bit we're essentially just replacing the plugin with an intermediate API that you develop why I don't prefer this mechanism as much and I only do it if I really don't have time to build a bur plugin is that you're essentially making a set of assumptions about the downstream system that you're testing so if I could use another example let's say that the intermediate Plug-In or the intermediate API is built using uh flask Python and flask if we're testing for something like Json parer
vulnerabilities we are now passing that vulner that um payload through the API first which may make a different set of assumptions about the payload that we're sending as compared to the downstream system you might even end up in situations where you're missing vulnerabilities because of those assumptions that the the intercepting or intermediate API is making about your payload so really wouldn't vouch for this unless you do not have any time left I highly encourage everyone to look at the burp implementation there are other plugins like AES killer for example um we've never actually used that on an assessment it just in all the cases that we've seen custom cryptography there's no one solution fits all you kind of have to spend a few
hours to figure out what the client is doing and what exactly needs to to be encrypted so you do have to tailor the plugin to your specific assessment so for a summary I just want to reiterate that where there's custom crypto there's trouble uh if there's any pen testers in the room I assured you'd agree I don't think I've ever seen a single secure implementation of this it's it's always just very rough assessment assessments that starts with a lot of initial effort and then suddenly the vulnerabilities like rotten apples just come falling out of the tree and then finally I want to use just one real world example is we've heard of situations where companies pay a lot of
money for something as fancy as a w to essentially protect their systems however then they also introduced this layer of custom cryptography and the issue with that is the W fundamentally needs to be able to see the clear text version of these requests and responses to provide you any kind of additional benefit so this just one example I've got a few of these but really if you see this please run for the hills and then we'll be taking any questions thank you so much for the opportunity I hope you guys enjoyed it [Applause]