Abusing XSLT for Practical Attacks
CC Attribution 3.0 Unported:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Arnaboldi, Fernando
Over the years, XML has been a rich target for attackers due to flaws in its design as well as implementations. It is a tempting target because it is used by other programming languages to interconnect applications and is supported by web browsers. In this talk, I will demonstrate how to use XSLT to produce documents that are vulnerable to new exploits. XSLT can be leveraged to affect the integrity of arithmetic operations, lead to code logic failure, or cause random values to use the same initialization vector. Error disclosure has always provided valuable information, but thanks to XSLT, it is possible to partially read system files that could disclose service or system's passwords. Finally, XSLT can be used to compromise end-user confidentiality by abusing the same-origin policy concept present in web browsers. This presentation includes proof-of-concept attacks demonstrating XSLT’s potential to affect production systems, along with recommendations for safe development. Speaker Bio: Fernando Arnaboldi is a senior security researcher and consultant at IOActive, Inc. He has over 10 years of experience in the security research space (Deloitte, Core Security Technologies and IOActive) and holds a Bachelor's degree in Computer Science.
 Hello everyone, thanks for coming. My name is Fernando Nabeldi and I work as a security consultant for IOACTIP. I would like to show you today how accession implementations are vulnerable to multiple practical attacks. And for that matter, the very first question that I would like to be addressed if I would be sitting over there is, why are we talking about accession T? This is a programming language that is not so common, it has been created when XML was created and it was a way to parse XML data. So, a couple of years ago, I came across a real scientist, a co-worker, found an XML vulnerability and an external entity expansion that allowed him to retrieve some passwords and I thought, this is pretty cool, I want to learn more about XML, schemas and accession T. All the technologies related to XML. And I was doing that, I noticed that there were no things breathing about how to exploit accession T implementations. When you're reviewing a language, you may want to know that. So, what we will be doing here is to analyze what are those weaknesses, so we're presenting five different issues in here, and how you can practically exploit them. So, whether you're reviewing code, if you're a penetration tester or so, or if you're developing technologies related to accession T, this will get handy, or you're just trying to abuse any implementations, hopefully this will help. One of the things is that even today, no one of the vulnerabilities have been fixed, so everything will work. And you may be able to affect the confidentiality and integrity of multiple implementations, and that means that you may get even some profit in certain scenarios. So, the good thing is that you're not exploiting flaws in a way that a malicious virus of my world would do it in here. You will see no assembly code, you will see just accession T, and how that can be used to get some fun things. So, we will briefly talk today about how you can identify your target, how numbers will let you affect the integrity, how random numbers may be predictable sometimes. I will show you how to bypass the same origin policy in a web browser using accession T, and finally some information disclosure through Evers. So, basically the idea here is to tell you what accession T does briefly and how accession T can be attacked. And finally, if you don't know... Hello. I was actually expecting this. I know. That's why I'm here. So, use the mic. So, this is your first time at DEF CON, huh? Yes. How's it going? A little bit anxious. You seem a little nervous. Hello. You want me to rub your shoulders? I will feel a little bit uncomfortable. That's okay. I'm dropping. We have a medicine for that. It comes in that bottle, right? Yes, it does. I gave him the right one, right? Yeah. Okay. No. He's the other one. I was like, dude, wait. Why am I getting the water? I don't want the water. Moron. We're over at DEF CON. Thank you very much. Yes. Okay. This will get interesting. You feel much better, don't you? I feel like a man, man. All right. Thank you very much. You want to talk directly into the mic. Very close to it. I can show you later. I would expect that. And as I was saying, you can identify your target language. Thank you. So basically, XSLT is a language that is being used to modify an XML. So what it does is it receives an input, an XML document. It creates a text document or an HTML document or a new XML document for that matter. So there are different versions when it comes to XSLT. There are three. V1, V2, V3. And the different versions doesn't mean that they are improvement. They should be. But they have more functionalities. Each version has more functionality. And V1 is the most implemented version in here because it has been supported by web browsers and because it is supported by previous versions. So an XSLT processor supporting V1, V2 will be supporting V1. So I tested two types of software, server-side processors and client-side processors. Server-side processors means those are standalone things that you can run in common line. Or there could be libraries that are hooked up to different languages. Python, Perl, Java, whatever. And when it comes to client-side processors, basically I believe you have two types. You will have web browsers or eventually XML or XSLT editors. And I believe that that is a very narrow set of people that are using those. So the standalone processors and libraries are mostly three. These are the most important ones. Developed by Nomi, Apache, and Saxonica. And Livex is at least the most widely deployed one. It is not only implemented by server-side processors but also by client-side processors, web browsers. And you also have Salem, developed by Apache people, which comes in two flavors, C++ and Java. And the similar thing goes for Saxon. And the client-side processors here, we have the browsers. All the things that I tested was in the latest versions available of all the server-side libraries and web browsers. So we have three ways to do this. The first one involves an XSLT processor receiving an XML and an XSLT. This normally happens when you're calling a common line processor. And eventually you will get a new document. You will do this if you need to parse an XML. So people will be using this if they need to parse something, server-side. Another possibility which is more common from a client-side perspective is when the XSLT processor is grabbing the XSLT document. So there is this small portion in the XML that says you will find here the XSLT document. Go get it for me. Create the new result document. And finally you can embed the XSLT document along with the XML. And by doing that, you just supply one file to the processor to get the new result. So you may want to know if you don't know already who is your target, which kind of properties do the target have. So by getting which type of version and vendor they have, you may know what type of vulnerabilities you could exploit in this target. Since clients may also support JavaScript, and that would be the case for a typical web browser, you may also retrieve some JavaScript information. All this code that you're seeing here, and you will be seeing here, it is all in the white paper. You can do a copy, paste, and try on your target of choice to see what happens. So at the end of each section, I will show you a brief summary of the server-sides. Here we have all of them. Sailan, Saxon, XSLT Pro, that's the standalone version of LiveXSLT. And PHP, Python, Parallel, Ruby are all related to LiveXSLT in this example. Then you have the client, which would be the web browsers. You will see the first column for the version, the vendor over there. And if it supports JavaScript or not, basically, of course, all web browsers supports JavaScript. There is one final thing, and that's that normally LiveXSLT is most widely deployed than other things. So you will notice that it is sometimes when it is affecting server-side processes, it may also affect the client. Let's start talking about the issues. So this is something present in client-side and server-side. And it doesn't matter if we're talking about floating-point numbers or integers. All numbers will introduce errors in here. So as I was testing this, it felt a little bit weird that sometimes calculation was not working as I expected to be. Certain additions, subtractions were not doing what I was expecting. So the very first thing that I did was to define an astonishing as a simple calculation. What I was trying to do was just to add a few numbers. So for that matter, I had to define a style sheet which has a specific output in here. It's saying that it is a text output. And in the middle, you will have this simple thing, 0.2 plus 0.1 minus 0.3. That should be zero, right? Pretty simple. It may not be that simple for processes. Only two say that this was zero. That was the case for Opera and Chrome. The rest said, well, close to that. Why is this happening? This is weird. And the weird thing is that you will see this across all implementations. Okay. This is cool. But it would be better if we would do something with this. I mean, these are just numbers that were not properly rounded by the programming language. So this is the thing that is present in all programming languages. I realize that you will have this in JavaScript, Perl, Python, C, whatever. This is a common thing. Floating point numbers will have certain decimals that are over there hanging around that you may take. So I created a simple JavaScript application simulating a bank. This is not a real bank. I wouldn't try this on my real bank. My real bank will limit the amount of transactions. I wouldn't allow a very small decimal to be transferred from one account to the other. The first thing I tried was to see, I created this application. I deposited a million dollars on the first account. And the second account has a zero balance at the moment. This is where I will deposit my profit. So I noticed that if I remove a very small number from the million-dollar account, it will not get subtracted, but it will be added to the secondary account because it has a lower number than a million, has a zero. That decimal means more for a zero than it gets for the million. So this program will try to do... The first portion of the program will try to see how big of a number can retrieve. It is a small number. And then it would do millions of transactions to move it to the secondary account. So you will see here that we will be seeing V8, and that's the Chrome JavaScript processor on the standalone version. And we will try to see what's the best profit to get in here. How much money can I steal from a million dollars that would not be noticed? And I will try to... I will start moving that money. Where did that money from the account number zero to account number one? And hopefully that will give me a daily profit of around $1300. It is moving, right? Yeah. So this was good, but it would be better if it would be higher the number. So let's talk about integers. I would have found an XML with ten numbers. And this would be fairly easy to understand, even if you're not developing. You will see that you have five exponential numbers in here, and the same five exponential numbers written just with the number one with a bunch of zeros. The thing is that programming languages do not handle very well when you have more than 16 digits, because of the precision. But what I tried to do was to print in here the same number that I was having on the XML document, and then formatted with the commas and the periods and such, so it would be more legible. In here, you will see that Saxon is doing great. This is what you want to see. You will see number one followed by a bunch of zeros. This is pretty clear. This is awesome. You will have the same for the non-exponential notation. Internet Explorer and Firefox are good. They weren't able to show the exponential notation, but that's okay. The problem comes when you're introducing errors, because there's nothing worth believing that you have the right number when you, in fact, you do not. In fact, it is, I was noting today that how they're finishing is different depending whether you're using exponential notation or not. So we will try to use this number in a couple of minutes. Sailor for Java, almost there. For C, they just don't care about what's going on over there. So anything can happen here. So first I thought, okay, this is something related to an error in the standard, I want to read this standard 754, but the problem is not over there. All implementations have problems. So it is what you do with floating point numbers and the integer, what matters. You should be saying, okay, a number should be between these values and not allowing a value to be so big if you are not able to handle them. Either way, this shouldn't be working like this. So I reported all the issues including this one and the floating point numbers to the vendors. The first thing that I heard was that I should be reading Wikipedia to understand how floating point numbers work. That was interesting, but probably you wouldn't find the answer over there. Then I heard that I should be reading the XSLTV2 specification, but this was affecting purely V1. That was nice as well, but clearly it was not solving the problem that was in here. And the very same person also said that this is something that you will see in JavaScript as well. I mean, that's fine. I know that you can't find this in JavaScript, but I wouldn't like to have this in my programming language, on any programming language, because these errors are everywhere. So we stole some decimals before. Now we're trying to do a similar thing, but with integers. The thing is that if you put a number one followed by 17 zeros and you subtract the number one, the programming language will not notice that the one is missing. So perhaps I created in here a fake cryptocurrency, which I named fakecoin, that the value is very small, very, very small. So I bought a number one followed by 17 zeros of these coins. I have a lot of coins with a total net value of $1,100,000. And I will try to transfer one coin at a time to a secondary account, which will be my profit account. And hopefully by the end of the day, I will have a better profit than moving decimals. The profit will be better if I use more coins. I will be able to transfer more coins at the same time. So I'm just going for the minimum amount possible just to show you. The minimum amount in here will be, will give me a profit of $2,300. If you add a zero to the coins, you will shoot out a zero to the daily profit as well. So that was nice. That was nice. So the very next thing that I did was to see how random numbers work. I mean, if you are developing, if you have ever developed, you need random numbers. This is something that you should normally see it on server side processors. And you should also know that, of course, not any random number generator should be used for cryptographic purposes. I mean, random numbers, you have to be careful with them. In XSLT, this is a function that comes from the extended XSLT, which is an extension of XSLT. It is defined as a function that returns a value between zero and one, as any random function should be. Supposedly, any random number should be a number that doesn't have any pattern. I mean, you shouldn't know what would be the number before calling this method. It would be fairly logical from a random point of view. So we normally have two types of random functions. You have ever developed, you may know that you have functions that are less secure, like random, random, in Python. You have more cryptographically secure mechanism like system, random, in Python. You may want to use that if you're moving cryptographic things. Some of the software that I tested, the server side processors, you're able to see the code, you're able to see how that was developed. For XSLT, XSLT, XSLT, and you will see that in all these scenarios, they are using the random number generator. Which is fine. The problem may come on the implementation. If people are using random numbers for any cryptographic proposal, that may be a problem. Because you may know with the random number generator what's going on. These were the points of the which I see in C and C++ and Java. And a good definition comes from the MAM page. These are just by random number generator. You have to take that into consideration and shouldn't use them for cryptographic proposals. But there's one more thing when it comes to random numbers that you normally pay attention to. Or you should, at least. What happens if there is no initialization vector? This is something basic for any random number. And that's that you need to have some sort of something that is changing when you're getting a random number. Otherwise you may get always the very same value. And that's not very useful if you're expecting a random number. And that's because you may know in advance which numbers you will be getting. So once you have a proper IV in place, you will have different values every time that you're calling the random functions. But let's see again how the functions that we saw before are working with the comes to the any association vector. And here there is only one that doesn't have the IV. Again, the IBSLT. This is not something new to the IBSLT. They know about this since 2006. But this is how it works. So if you try to create an XSLT that will produce a random function, or you see anyone who's trying to produce a random value out of live XSLT, you will see something like this. And you will see these kind of results if you're executing that on common line. I executed twice on the same terminal. And I go twice the same number. You can see that the 7.82, you always get that first number every time that you're executing the random function from live XSLT. So the next thing that I do is to try to understand how this can be used in cipher modes when they are doing block ciphers. That's another way to cipher things if you're using random. So I created two executions at the very first time to understand how these numbers look like. So first I printed the Python version of random, random. And you get two different numbers. Of course, this observed the random number generator. They may not be the best, but they are not predictable. And they are not the same every time that I'm executing that function. But live XSLT, we can recognize again the very same number that we saw on the previous line, the 7.82 thing. That's the very same number. If you're calling Python again with a print random, random function, we will see that we have again two different numbers. So far, 4 for Python and 1 for live XSLT. If we're calling a live XSLT again, you will notice that in the second position, we will always have these new values. These 0.13. And it will be repeated every second time they are calling this. So without having an external seed value such as time, you may know in advance which will be the sequence of numbers that will be generated by live XSLT. Which is pretty cool because you may know in advance what is being encrypted if they are using this or encrypt something. Which will be fairly ridiculous. So again, you may predict values when you see random numbers. The same origin point is something that is present in client-side processors. This means web browsers. Basically, this says that if you're on a website, you shouldn't be reading information from other websites. But again, as always, that may not be the case for certain engineers. So this is important. The origin is always defined by the scheme, the host on the port of a URL. We will be an example of this. The HTTP at the very beginning or HTTPS will be the scheme. The host should be example.com and the port should be either port 80 or port 443 or something like that. So generally speaking, when we are retrieving documents from different origins, the web browsers will not share the information. I mean, when we are taking the same origin over and over, we may have... We will be sending the same cookie over and over to the same website and that would be okay. Normally, JavaScript is used to try to alter this, but you don't necessarily need to use it to affect the same origin policy. You shouldn't be expecting that when you're connecting to Google.com, your browser will be sending the very same cookie to this website because it has the very same origin. If you're connecting to Microsoft.com, you should be seeing a different cookie. This will be a very valid as an area. You just connect to a website. You're on the main web page. You're trying to access a second web page that is being stored over there and that will be fine. That's okay. You're allowed to see that. In fact, you're even allowed to see other web pages on the very same domain. But if you're changing the scheme, if you're changing the host name or if you're changing the port, you shouldn't be allowed to see any of the information that is present on that other website. You're not sharing the private information between websites. That's what you would expect at least. There's only one function that reads documents and that's document. Okay. You may try to use that to read another XML document. In fact, since we're speaking about websites, we could also see in here XHDML, which is a fairly common way to represent a web page by certain web servers. Once we retrieve the XHDML documents, we can see what's inside using either of these two functions, copy off and value off, which will show either an XML representation or an external representation. So the very first thing that you want to do if you want to abuse this, you need to find a server that uses XHDML. Okay. Bing.com uses XHDML. I'm logging in here. What can you do with this? So on the upper right corner, you will see that my name, it is a red box. And that is also reflected in the code. And since it is XHDML, this is some sort of XML. And my name is within an element named ID underscore M. So you may be able to target your web browser to retrieve that value. So let's see how using the document, how using any other functions, we can retrieve that information. In here, we can see that the document function is accessing the URL, www.bing.com. And then right in the middle, we are retrieving the information that we just grabbed from the document. And finally, because I'm lazy, on JavaScript, I will be subtracting the ID underscore M element, which has my name. So let's see a demo of this. First, I will open Safari. And I will show you that I'm using Bing.com as my home page. And then I will open the document that is on the desktop that it is not sharing the same origin. Because one, Bing.com, it is being housed on HTTPS, Bing.com. And the other one, it is file, it is a local file. So let's see what happens. You will notice again, my number in the upper right corner. And when I open that file, I'm reading the document that is being stored by Bing.com. And I'm able to retrieve my name from using XSLT. Even though it is not hosted on Bing.com, Safari doesn't care. We'll show you that information. So basically, Safari will allow you to read this. Internet password may show your warning message. You will retrieve the information, but you won't be sharing anything related to this. And the other browsers just didn't do anything. Another cool thing would be that you may use some of these stuff to try to scan internal networks in case you wanted to. There are multiple ways to try to scan internal networks when you're executing something locally. And this could be another way as well. So another vulnerability that I found and I thought that would be very interesting to discuss would be an information disclosure on file reading through errors. This is something that is present in server side and client side processors. The focus in here is, of course, on server side processors because we wouldn't care what will happen on a web browser. So the cool thing about this is that it is not possible to read text files in XSLT v1. It is only possible to read XML documents or as we saw, XHDML documents. And since it is not possible to read plain text files, it doesn't matter what function we are trying to use in here because all functions shouldn't be capable of doing this. So let's see what happens even though when the W3C consortium says it is not possible. So we saw before that there was one function to read XML documents and that's the document function. This document will allow access to other XML documents other than the main document. Okay, we have that. We can try to use that. There are also other functions used for accessing XSLT documents and that would be the functions include and import. These functions do just retrieve a style sheet and I would try to use it, combine with other styles sheets. We don't care about what the manual says about this because either way we are not trying to read a style sheet in here. So I created a text file that contains three lines, very simple. If you see the contents of my text file, you will see a line 1, a line 2, and a line 3. Pretty simple. And if you read the documentations, you will see that when you are reading a file, this comes from the XML documentation. If you are reading a file, there are a couple of possibilities. The first one is that you may show that the XSLT processor is found an error and that's what some of the processors do. They say this is not allowed in Prolog. Okay, that would be, that's okay. The other possibility would be to return an MTXML document. That's what Ruby does. Ruby will show you that there is nothing to see in here and this is something that is also expected as well. But again, this doesn't solve the problem that we want to read something that was on the test file. LibXSLT comes again to help us with this. So when you send a document, XSLT, PHP, and Perl, we will show you the first line of our test file. Remember the line 1 of the test file? That's not too much, but it's cool. Perhaps we can do something with that. We also try to use other functions to try to access these files later. But having this unexpected behavior in place may allow us to do something with it. So you may know in advance where I'm going with this. Which type of files may have an interesting first line that will be valuable for us. There are certain specific files that sort the most valuable information of a computer on the very first line. So what if we will be able to read, for example, a password file where we could find those passwords? The most common answer for any Linux system would be an instant password. The next one, if you go for bit, they are running this as route, could be the instant shadow. The possibilities are in your imagination here. Depending on what you are trying to read, you may be able to retrieve certain information that may be valuable for you or for someone else. You also have the Apache password and you may have databases passwords. There are a number of possibilities down there. The thing is that this is what you will be seeing when you are using, for example, one of the processors when trying to read the exterior password. You will see an error and also something else. The password. Which is cool. You can also now use access of T to retrieve this information. Another example you are seeing, PHP could be to try to use PHP to read the HG password of an Apache. And again, since this is something that you store in the very first line, you may see a bunch of errors and right in the middle what you are planning to see. The password for Java. In this case. And as I was saying before, just in case they do not care about what they are doing, you could also have someone using the, et cetera, shadow, leaving that available if they are running this as route. And this will happen if you are using Ruby to try to retrieve that file. Again, expect all the errors. But also expect the password for the route over there. So this is pretty neat because I believe this opened the possibility for XSLT to be as interesting perhaps as external entity expansions as a way to retrieve some information if an attacker is able to compromise an XSLT because the application is a low and there are applications that allow XSLT to be uploaded. Or XML that are relying in document input include that may be out there in any way to try to read files. So either if you are able to control an XML and you have an XSLT processor in the back end parsing this, or you are able to control the XSLT, you may compromise the security of an application. As we also saw, we don't always need to do that in place to have the confidentiality and the integrity affected. Because sometimes when using random function or integers, they may be doing that for our profit without doing anything on our side. So I would recommend as a very last thing that you should check your code or someone else in case just wants to see what's going on to use any of these things. So that's what I have for today. Anyone has any questions? So happy to answer them. Thank you very much. And thank you for all these people who helped me with the presentation.
 Hello everyone, thanks for coming. My name is Fernando Nabeldi and I work as a security consultant for IOACTIP.  I would like to show you today how accession implementations are vulnerable to multiple practical attacks.  And for that matter, the very first question that I would like to be addressed if I would be sitting over there is,  why are we talking about accession T?  This is a programming language that is not so common, it has been created when XML was created and it was a way to parse XML data.  So, a couple of years ago, I came across a real scientist, a co-worker, found an XML vulnerability and an external entity expansion  that allowed him to retrieve some passwords and I thought, this is pretty cool, I want to learn more about XML, schemas and accession T.  All the technologies related to XML. And I was doing that, I noticed that there were no things breathing about how to exploit accession T implementations.  When you're reviewing a language, you may want to know that.  So, what we will be doing here is to analyze what are those weaknesses, so we're presenting five different issues in here,  and how you can practically exploit them.  So, whether you're reviewing code, if you're a penetration tester or so, or if you're developing technologies related to accession T,  this will get handy, or you're just trying to abuse any implementations, hopefully this will help.  One of the things is that even today, no one of the vulnerabilities have been fixed, so everything will work.  And you may be able to affect the confidentiality and integrity of multiple implementations,  and that means that you may get even some profit in certain scenarios.  So, the good thing is that you're not exploiting flaws in a way that a malicious virus of my world would do it in here.  You will see no assembly code, you will see just accession T, and how that can be used to get some fun things.  So, we will briefly talk today about how you can identify your target, how numbers will let you affect the integrity,  how random numbers may be predictable sometimes.  I will show you how to bypass the same origin policy in a web browser using accession T,  and finally some information disclosure through Evers.  So, basically the idea here is to tell you what accession T does briefly and how accession T can be attacked.  And finally, if you don't know...  Hello.  I was actually expecting this.  I know.  That's why I'm here.  So, use the mic.  So, this is your first time at DEF CON, huh?  Yes.  How's it going?  A little bit anxious.  You seem a little nervous.  Hello.  You want me to rub your shoulders?  I will feel a little bit uncomfortable.  That's okay.  I'm dropping.  We have a medicine for that.  It comes in that bottle, right?  Yes, it does.  I gave him the right one, right?  Yeah.  Okay.  No.  He's the other one.  I was like, dude, wait.  Why am I getting the water?  I don't want the water.  Moron.  We're over at DEF CON.  Thank you very much.  Yes.  Okay.  This will get interesting.  You feel much better, don't you?  I feel like a man, man.  All right.  Thank you very much.  You want to talk directly into the mic.  Very close to it.  I can show you later.  I would expect that.  And as I was saying, you can identify your target language.  Thank you.  So basically, XSLT is a language that is being used to modify an XML.  So what it does is it receives an input, an XML document.  It creates a text document or an HTML document or a new XML document for that matter.  So there are different versions when it comes to XSLT.  There are three.  V1, V2, V3.  And the different versions doesn't mean that they are improvement.  They should be.  But they have more functionalities.  Each version has more functionality.  And V1 is the most implemented version in here because it has been supported by web browsers  and because it is supported by previous versions.  So an XSLT processor supporting V1, V2 will be supporting V1.  So I tested two types of software, server-side processors and client-side processors.  Server-side processors means those are standalone things that you can run in common line.  Or there could be libraries that are hooked up to different languages.  Python, Perl, Java, whatever.  And when it comes to client-side processors, basically I believe you have two types.  You will have web browsers or eventually XML or XSLT editors.  And I believe that that is a very narrow set of people that are using those.  So the standalone processors and libraries are mostly three.  These are the most important ones.  Developed by Nomi, Apache, and Saxonica.  And Livex is at least the most widely deployed one.  It is not only implemented by server-side processors but also by client-side processors, web browsers.  And you also have Salem, developed by Apache people, which comes in two flavors, C++ and Java.  And the similar thing goes for Saxon.  And the client-side processors here, we have the browsers.  All the things that I tested was in the latest versions available of all the server-side libraries and web browsers.  So we have three ways to do this.  The first one involves an XSLT processor receiving an XML and an XSLT.  This normally happens when you're calling a common line processor.  And eventually you will get a new document.  You will do this if you need to parse an XML.  So people will be using this if they need to parse something, server-side.  Another possibility which is more common from a client-side perspective is when the XSLT processor  is grabbing the XSLT document.  So there is this small portion in the XML that says you will find here the XSLT document.  Go get it for me.  Create the new result document.  And finally you can embed the XSLT document along with the XML.  And by doing that, you just supply one file to the processor to get the new result.  So you may want to know if you don't know already who is your target, which kind of properties  do the target have.  So by getting which type of version and vendor they have, you may know what type of vulnerabilities  you could exploit in this target.  Since clients may also support JavaScript, and that would be the case for a typical web browser,  you may also retrieve some JavaScript information.  All this code that you're seeing here, and you will be seeing here, it is all in the white paper.  You can do a copy, paste, and try on your target of choice to see what happens.  So at the end of each section, I will show you a brief summary of the server-sides.  Here we have all of them.  Sailan, Saxon, XSLT Pro, that's the standalone version of LiveXSLT.  And PHP, Python, Parallel, Ruby are all related to LiveXSLT in this example.  Then you have the client, which would be the web browsers.  You will see the first column for the version, the vendor over there.  And if it supports JavaScript or not, basically, of course, all web browsers supports JavaScript.  There is one final thing, and that's that normally LiveXSLT is most widely deployed than other things.  So you will notice that it is sometimes when it is affecting server-side processes,  it may also affect the client.  Let's start talking about the issues.  So this is something present in client-side and server-side.  And it doesn't matter if we're talking about floating-point numbers or integers.  All numbers will introduce errors in here.  So as I was testing this, it felt a little bit weird that sometimes calculation was not working  as I expected to be.  Certain additions, subtractions were not doing what I was expecting.  So the very first thing that I did was to define an astonishing as a simple calculation.  What I was trying to do was just to add a few numbers.  So for that matter, I had to define a style sheet which has a specific output in here.  It's saying that it is a text output.  And in the middle, you will have this simple thing, 0.2 plus 0.1 minus 0.3.  That should be zero, right? Pretty simple.  It may not be that simple for processes.  Only two say that this was zero.  That was the case for Opera and Chrome.  The rest said, well, close to that.  Why is this happening?  This is weird.  And the weird thing is that you will see this across all implementations.  Okay. This is cool.  But it would be better if we would do something with this.  I mean, these are just numbers that were not properly rounded by the programming language.  So this is the thing that is present in all programming languages.  I realize that you will have this in JavaScript, Perl, Python, C, whatever.  This is a common thing.  Floating point numbers will have certain decimals that are over there hanging around that you may take.  So I created a simple JavaScript application simulating a bank.  This is not a real bank.  I wouldn't try this on my real bank.  My real bank will limit the amount of transactions.  I wouldn't allow a very small decimal to be transferred from one account to the other.  The first thing I tried was to see, I created this application.  I deposited a million dollars on the first account.  And the second account has a zero balance at the moment.  This is where I will deposit my profit.  So I noticed that if I remove a very small number from the million-dollar account,  it will not get subtracted, but it will be added to the secondary account  because it has a lower number than a million, has a zero.  That decimal means more for a zero than it gets for the million.  So this program will try to do...  The first portion of the program will try to see how big of a number can retrieve.  It is a small number.  And then it would do millions of transactions to move it to the secondary account.  So you will see here that we will be seeing V8,  and that's the Chrome JavaScript processor on the standalone version.  And we will try to see what's the best profit to get in here.  How much money can I steal from a million dollars that would not be noticed?  And I will try to... I will start moving that money.  Where did that money from the account number zero to account number one?  And hopefully that will give me a daily profit of around $1300.  It is moving, right? Yeah.  So this was good, but it would be better if it would be higher the number.  So let's talk about integers.  I would have found an XML with ten numbers.  And this would be fairly easy to understand, even if you're not developing.  You will see that you have five exponential numbers in here,  and the same five exponential numbers written just with the number one with a bunch of zeros.  The thing is that programming languages do not handle very well when you have more than 16 digits,  because of the precision.  But what I tried to do was to print in here the same number that I was having on the XML document,  and then formatted with the commas and the periods and such, so it would be more legible.  In here, you will see that Saxon is doing great.  This is what you want to see.  You will see number one followed by a bunch of zeros.  This is pretty clear. This is awesome.  You will have the same for the non-exponential notation.  Internet Explorer and Firefox are good.  They weren't able to show the exponential notation, but that's okay.  The problem comes when you're introducing errors,  because there's nothing worth believing that you have the right number when you, in fact, you do not.  In fact, it is, I was noting today that how they're finishing is different depending whether you're using exponential notation or not.  So we will try to use this number in a couple of minutes.  Sailor for Java, almost there.  For C, they just don't care about what's going on over there.  So anything can happen here.  So first I thought, okay, this is something related to an error in the standard,  I want to read this standard 754, but the problem is not over there.  All implementations have problems.  So it is what you do with floating point numbers and the integer, what matters.  You should be saying, okay, a number should be between these values  and not allowing a value to be so big if you are not able to handle them.  Either way, this shouldn't be working like this.  So I reported all the issues including this one and the floating point numbers to the vendors.  The first thing that I heard was that I should be reading Wikipedia to understand how floating point numbers work.  That was interesting, but probably you wouldn't find the answer over there.  Then I heard that I should be reading the XSLTV2 specification, but this was affecting purely V1.  That was nice as well, but clearly it was not solving the problem that was in here.  And the very same person also said that this is something that you will see in JavaScript as well.  I mean, that's fine. I know that you can't find this in JavaScript,  but I wouldn't like to have this in my programming language, on any programming language,  because these errors are everywhere.  So we stole some decimals before.  Now we're trying to do a similar thing, but with integers.  The thing is that if you put a number one followed by 17 zeros and you subtract the number one,  the programming language will not notice that the one is missing.  So perhaps I created in here a fake cryptocurrency, which I named fakecoin,  that the value is very small, very, very small.  So I bought a number one followed by 17 zeros of these coins.  I have a lot of coins with a total net value of $1,100,000.  And I will try to transfer one coin at a time to a secondary account, which will be my profit account.  And hopefully by the end of the day, I will have a better profit than moving decimals.  The profit will be better if I use more coins.  I will be able to transfer more coins at the same time.  So I'm just going for the minimum amount possible just to show you.  The minimum amount in here will be, will give me a profit of $2,300.  If you add a zero to the coins, you will shoot out a zero to the daily profit as well.  So that was nice.  That was nice.  So the very next thing that I did was to see how random numbers work.  I mean, if you are developing, if you have ever developed, you need random numbers.  This is something that you should normally see it on server side processors.  And you should also know that, of course, not any random number generator should be  used for cryptographic purposes.  I mean, random numbers, you have to be careful with them.  In XSLT, this is a function that comes from the extended XSLT, which is an extension of XSLT.  It is defined as a function that returns a value between zero and one, as any random function should be.  Supposedly, any random number should be a number that doesn't have any pattern.  I mean, you shouldn't know what would be the number before calling this method.  It would be fairly logical from a random point of view.  So we normally have two types of random functions.  You have ever developed, you may know that you have functions that are less secure, like random, random, in Python.  You have more cryptographically secure mechanism like system, random, in Python.  You may want to use that if you're moving cryptographic things.  Some of the software that I tested, the server side processors, you're able to see the code, you're able to see how that was developed.  For XSLT, XSLT, XSLT, and you will see that in all these scenarios, they are using the random number generator.  Which is fine.  The problem may come on the implementation.  If people are using random numbers for any cryptographic proposal, that may be a problem.  Because you may know with the random number generator what's going on.  These were the points of the which I see in C and C++ and Java.  And a good definition comes from the MAM page.  These are just by random number generator.  You have to take that into consideration and shouldn't use them for cryptographic proposals.  But there's one more thing when it comes to random numbers that you normally pay attention to.  Or you should, at least.  What happens if there is no initialization vector?  This is something basic for any random number.  And that's that you need to have some sort of something that is changing when you're getting a random number.  Otherwise you may get always the very same value.  And that's not very useful if you're expecting a random number.  And that's because you may know in advance which numbers you will be getting.  So once you have a proper IV in place, you will have different values every time that you're calling the random functions.  But let's see again how the functions that we saw before are working with the comes to the any association vector.  And here there is only one that doesn't have the IV.  Again, the IBSLT.  This is not something new to the IBSLT.  They know about this since 2006.  But this is how it works.  So if you try to create an XSLT that will produce a random function,  or you see anyone who's trying to produce a random value out of live XSLT,  you will see something like this.  And you will see these kind of results if you're executing that on common line.  I executed twice on the same terminal.  And I go twice the same number.  You can see that the 7.82, you always get that first number every time that you're executing the random function from live XSLT.  So the next thing that I do is to try to understand how this can be used in cipher modes when they are doing block ciphers.  That's another way to cipher things if you're using random.  So I created two executions at the very first time to understand how these numbers look like.  So first I printed the Python version of random, random.  And you get two different numbers.  Of course, this observed the random number generator.  They may not be the best, but they are not predictable.  And they are not the same every time that I'm executing that function.  But live XSLT, we can recognize again the very same number that we saw on the previous line, the 7.82 thing.  That's the very same number.  If you're calling Python again with a print random, random function, we will see that we have again two different numbers.  So far, 4 for Python and 1 for live XSLT.  If we're calling a live XSLT again, you will notice that in the second position, we will always have these new values.  These 0.13.  And it will be repeated every second time they are calling this.  So without having an external seed value such as time, you may know in advance which will be the sequence of numbers that will be generated by live XSLT.  Which is pretty cool because you may know in advance what is being encrypted if they are using this or encrypt something.  Which will be fairly ridiculous.  So again, you may predict values when you see random numbers.  The same origin point is something that is present in client-side processors.  This means web browsers.  Basically, this says that if you're on a website, you shouldn't be reading information from other websites.  But again, as always, that may not be the case for certain engineers.  So this is important.  The origin is always defined by the scheme, the host on the port of a URL.  We will be an example of this.  The HTTP at the very beginning or HTTPS will be the scheme.  The host should be example.com and the port should be either port 80 or port 443 or something like that.  So generally speaking, when we are retrieving documents from different origins, the web browsers will not share the information.  I mean, when we are taking the same origin over and over, we may have...  We will be sending the same cookie over and over to the same website and that would be okay.  Normally, JavaScript is used to try to alter this, but you don't necessarily need to use it to affect the same origin policy.  You shouldn't be expecting that when you're connecting to Google.com, your browser will be sending the very same cookie to this website because it has the very same origin.  If you're connecting to Microsoft.com, you should be seeing a different cookie.  This will be a very valid as an area.  You just connect to a website.  You're on the main web page.  You're trying to access a second web page that is being stored over there and that will be fine.  That's okay.  You're allowed to see that.  In fact, you're even allowed to see other web pages on the very same domain.  But if you're changing the scheme, if you're changing the host name or if you're changing the port, you shouldn't be allowed to see any of the information that is present on that other website.  You're not sharing the private information between websites.  That's what you would expect at least.  There's only one function that reads documents and that's document.  Okay.  You may try to use that to read another XML document.  In fact, since we're speaking about websites, we could also see in here XHDML, which is a fairly common way to represent a web page by certain web servers.  Once we retrieve the XHDML documents, we can see what's inside using either of these two functions, copy off and value off, which will show either an XML representation or an external representation.  So the very first thing that you want to do if you want to abuse this, you need to find a server that uses XHDML.  Okay.  Bing.com uses XHDML.  I'm logging in here.  What can you do with this?  So on the upper right corner, you will see that my name, it is a red box.  And that is also reflected in the code.  And since it is XHDML, this is some sort of XML.  And my name is within an element named ID underscore M.  So you may be able to target your web browser to retrieve that value.  So let's see how using the document, how using any other functions, we can retrieve that information.  In here, we can see that the document function is accessing the URL, www.bing.com.  And then right in the middle, we are retrieving the information that we just grabbed from the document.  And finally, because I'm lazy, on JavaScript, I will be subtracting the ID underscore M element, which has my name.  So let's see a demo of this.  First, I will open Safari.  And I will show you that I'm using Bing.com as my home page.  And then I will open the document that is on the desktop that it is not sharing the same origin.  Because one, Bing.com, it is being housed on HTTPS, Bing.com.  And the other one, it is file, it is a local file.  So let's see what happens.  You will notice again, my number in the upper right corner.  And when I open that file, I'm reading the document that is being stored by Bing.com.  And I'm able to retrieve my name from using XSLT.  Even though it is not hosted on Bing.com, Safari doesn't care.  We'll show you that information.  So basically, Safari will allow you to read this.  Internet password may show your warning message.  You will retrieve the information, but you won't be sharing anything related to this.  And the other browsers just didn't do anything.  Another cool thing would be that you may use some of these stuff to try to scan internal networks  in case you wanted to.  There are multiple ways to try to scan internal networks when you're executing something locally.  And this could be another way as well.  So another vulnerability that I found and I thought that would be very interesting to discuss  would be an information disclosure on file reading through errors.  This is something that is present in server side and client side processors.  The focus in here is, of course, on server side processors because we wouldn't care what will happen on a web browser.  So the cool thing about this is that it is not possible to read text files in XSLT v1.  It is only possible to read XML documents or as we saw, XHDML documents.  And since it is not possible to read plain text files, it doesn't matter what function we are trying to use in here  because all functions shouldn't be capable of doing this.  So let's see what happens even though when the W3C consortium says it is not possible.  So we saw before that there was one function to read XML documents and that's the document function.  This document will allow access to other XML documents other than the main document.  Okay, we have that. We can try to use that.  There are also other functions used for accessing XSLT documents and that would be the functions  include and import. These functions do just retrieve a style sheet and I would try to use it,  combine with other styles sheets. We don't care about what the manual says about this because either way  we are not trying to read a style sheet in here.  So I created a text file that contains three lines, very simple.  If you see the contents of my text file, you will see a line 1, a line 2, and a line 3.  Pretty simple. And if you read the documentations, you will see that when you are reading a file,  this comes from the XML documentation. If you are reading a file, there are a couple of possibilities.  The first one is that you may show that the XSLT processor is found an error and that's what some of the  processors do. They say this is not allowed in Prolog. Okay, that would be, that's okay.  The other possibility would be to return an MTXML document. That's what Ruby does.  Ruby will show you that there is nothing to see in here and this is something that is also expected as well.  But again, this doesn't solve the problem that we want to read something that was on the test file.  LibXSLT comes again to help us with this. So when you send a document, XSLT, PHP, and Perl,  we will show you the first line of our test file. Remember the line 1 of the test file?  That's not too much, but it's cool. Perhaps we can do something with that.  We also try to use other functions to try to access these files later. But having this unexpected  behavior in place may allow us to do something with it. So you may know in advance where I'm going with this.  Which type of files may have an interesting first line that will be valuable for us.  There are certain specific files that sort the most valuable information of a computer on the very first line.  So what if we will be able to read, for example, a password file where we could find those passwords?  The most common answer for any Linux system would be an instant password.  The next one, if you go for bit, they are running this as route, could be the instant shadow.  The possibilities are in your imagination here. Depending on what you are trying to read,  you may be able to retrieve certain information that may be valuable for you or for someone else.  You also have the Apache password and you may have databases passwords.  There are a number of possibilities down there. The thing is that this is what you will be seeing  when you are using, for example, one of the processors when trying to read the exterior password.  You will see an error and also something else. The password. Which is cool.  You can also now use access of T to retrieve this information. Another example you are seeing,  PHP could be to try to use PHP to read the HG password of an Apache.  And again, since this is something that you store in the very first line, you may see a bunch of errors  and right in the middle what you are planning to see. The password for Java. In this case.  And as I was saying before, just in case they do not care about what they are doing,  you could also have someone using the, et cetera, shadow, leaving that available if they are running this as route.  And this will happen if you are using Ruby to try to retrieve that file. Again, expect all the errors.  But also expect the password for the route over there.  So this is pretty neat because I believe this opened the possibility for XSLT to be as interesting perhaps  as external entity expansions as a way to retrieve some information if an attacker is able to compromise  an XSLT because the application is a low and there are applications that allow XSLT to be uploaded.  Or XML that are relying in document input include that may be out there in any way to try to read files.  So either if you are able to control an XML and you have an XSLT processor in the back end parsing this,  or you are able to control the XSLT, you may compromise the security of an application.  As we also saw, we don't always need to do that in place to have the confidentiality and the integrity affected.  Because sometimes when using random function or integers, they may be doing that for our profit  without doing anything on our side.  So I would recommend as a very last thing that you should check your code or someone else  in case just wants to see what's going on to use any of these things.  So that's what I have for today. Anyone has any questions? So happy to answer them.  Thank you very much. And thank you for all these people who helped me with the presentation.
DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_0_515.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_516_671.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_672_3911.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_3912_6803.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_6804_7259.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_7260_8051.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_8052_8903.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_8904_9635.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_9636_9887.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_9888_11183.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_11184_12131.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_12132_13439.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_13440_13835.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_13836_13883.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_13884_14159.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_14160_15359.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_15360_15719.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_15720_17699.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_17700_20987.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_20988_21779.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_21780_22739.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_22740_22919.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_22920_24143.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_24144_25235.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_25236_25319.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_25320_25667.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_25668_26435.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_26436_27827.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_27828_28439.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_28440_28631.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_28632_28919.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_28920_30239.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_30240_31115.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_31116_32555.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_32556_33047.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_33048_33215.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_33216_33311.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_33312_35999.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_36000_36419.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_36420_37463.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_37464_38435.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_38436_38531.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_38532_39311.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_39312_39971.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_39972_40691.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_40692_41063.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_41064_41123.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_41124_41603.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_41604_41867.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_41868_43103.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_43104_44063.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_44064_44531.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_44532_48011.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_48012_49247.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_49248_49355.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_49356_49799.png DEF_CON_23_-_Fernando_Arnabold_-_Abusing_XSLT_for_Practical_Attacks_FCtcza-pP8U_49800_51766.png