Hidden Exploitable Behaviors in Programming Languages
By
Fernando Arnaboldi
In February 28th 2015 Egor Homakov wrote an article[1] exposing the dangers in the open() function from Ruby. The function is commonly used when requesting URLs programmatically with the open-uri library. However, instead of requesting URLs you may end up executing operating system commands.
Consider the following Ruby script named open-uri.rb:
require ‘open-uri’
print open(ARGV[0]).read
The following command requests a web page:
# ruby open-uri.rb “https://ioactive.com”
And the following output is shown:
<!DOCTYPE HTML>
<!–[if lt IE 9]><html class=”ie”><![endif]–>
<!–[if !IE]><!–><html><!–<![endif]–><head>
<meta charset=”UTF-8″>
<title>IOActive is the global leader in cybersecurity, penetration testing, and computer services</title>
[…SNIP…]
Works as expected, right? Still, this command may be used to open a process that allows any command to be executed. If a similar Ruby script is used in a web application with weak input validation then you could just add a pipe and your favorite OS command in a remote request:
The difference between the two executions is just the pipe character at the beginning. The pipe character causes Ruby to stop using the function from open-uri, and use the native open() functionality that allows command execution[2].
Applications may be susceptible to unpredictable security issues when using certain features from programming languages. There are a number of possibilities to be abused in different implementations that could affect secure applications. There are unexpected scenarios for the interpreted programming languages parsing the code in Javascript, Perl, PHP, Python and Ruby.
Come and join me at Black Hat Europe[3] to learn more about these risky features and how to detect them. An open source extended differential fuzzing framework will be released to aid in the disclosure of these types of behaviors.
[1] Using open-uri? Check your code – you’re playing with fire! (https://sakurity.com/blog/2015/02/28/openuri.html)
Applications always contain security flaws, which is why we rely on multiple layers of defense. Applications are still struggling with their defenses, even though we go through exhaustive measures of testing and defense layers. Perhaps we should rethink our approach to application defense, with the goal of introducing defensive methods that cause attackers to cease, or induce them to take incorrect actions based on false premises.
There are a variety of products that provide valuable resources when basic, off-the-shelf protection is required or the application source code is not available. However, implementations in native code provide a greater degree of defense that cannot be achieved using third-party solutions. This document aims to:
Enumerate a comprehensive list of current and new defensive techniques.
Multiple defensive techniques have been disclosed in books, papers and tools. This specification collects those techniques and presents new defensive options to fill the opportunity gap that remains open to attackers.
Enumerate methods to identify attack tools before they can access functionalities.
The tools used by attackers identify themselves in several ways. Multiple features of a request can disclose that it is not from a normal user; a tool may abuse security flaws in ways that can help to detect the type of tool an attacker is using, and developers can prepare diversions and traps in advance that the specific tool would trigger automatically.
Disclose how to detect attacker techniques within code.
Certain techniques can identify attacks within the code. Developers may know in advance that certain conditions will only be triggered by attackers, and they can also be prepared for certain unexpected scenarios.
Provide a new defensive approach.
Server-side defense is normally about blocking malicious IP addresses associated to attackers; however, an attacker’s focus can be diverted or modified. Sometimes certain functionalities may be presented to attackers only to better prosecute them if those functionalities are triggered.
Provide these protections for multiple programming languages.
This document will use pseudo code to explain functionalities that can reduce the effectiveness of attackers and expose their actions, and working proof-of-concept code will be released for four programming languages: Java, Python, .NET, and PHP.
Fernando Arnaboldi appeared at Ruxcon to present defensive techniques that can be embedded in server-side applications. The techniques described are included in a specification, along with sample implementations for multiple programming languages.
XML eXternal Entity (XXE) attacks are a common threat to applications using XML schemas, either actively or unknowingly. That is because we continue to use XML schemas that can be abused in multiple ways. Programming languages and libraries use XML schemas to define the expected contents of XML documents, SAML authentications or SOAP messages. XML schemas were intended to constrain document definitions, yet they have introduced multiple attack avenues.
XML parsers should be prepared to manage two types of problematic XML documents: malformed files and invalid files. Malformed files do not follow the World Wide Web Consortium (W3C) specification. This results in unexpected consequences for any software that parses the file. Invalid files abuse XML schemas and exploit actions that are built into programming languages and libraries. This may unwillingly put any software relying on these technologies at risk.
I analyzed possible attacks affecting XML and discovered new attacks in the previous categories. Among them:
Schema version disclosure: Parsers may disclose type and version information when retrieving remote schemas.
Unrestrictive schemas: Major companies still rely on schemas that cannot provide the restrictions required for their XML documents. DTD schemas continue to be common, even though they are often unable to accomplish their goal.
Improper data validation: As companies move away from DTD schemas and attempt to implement better restrictions, they may provide incomplete protection for their systems. XML schemas provide highly granular constraints, and if they are not properly defined, the approved document may affect the underlying security of applications.
Some of the proposed examples provided by the W3C include vulnerable methods of defining XML documents. To illlustrate with a basic example, the W3C states that an application can use a DTD to verify that XML data is valid, and provides the following example:
<?xml version=”1.0″?>
<!DOCTYPE note [
<!ELEMENT note (to,from,heading,body)>
<!ELEMENT to (#PCDATA)>
<!ELEMENT from (#PCDATA)>
<!ELEMENT heading (#PCDATA)>
<!ELEMENT body (#PCDATA)>
]>
<note>
<to>Tove</to>
<from>Jani</from>
<heading>Reminder</heading>
<body>Don’t forget me this weekend</body>
</note>
This example document contains an embedded DTD that constrains the contents to the previously defined elements. However, those elements do not provide a constraint on how large they are or what type of data they contain. Moreover, since the DTD declaration can simply be changed or removed from the previous document, you can even have a valid, well-formed document without an XML schema.
As always, we would love to hear from other security types who might have a differing opinion. All of our positions are subject to change through exposure to compelling arguments and/or data.
Just a few days after installing Drupal v7.39, I noticed there was a security update available: Drupal v7.41. This new version fixes an open redirect in the Drupal core. In spite of my Drupal update process checking for updates, according to my local instance, everything was up to date:
Issue #1: Whenever the Drupal update process fails, Drupal states that everything is up to date instead of giving a warning.
The issue was due to some sort of network problem. Apparently, in Drupal 6 there was a warning message in place, but this is not present in Drupal 7 or Drupal 8.
Nevertheless, if the scheduled update process fails, it is always possible to check for the latest updates by using the link that says “Check Manually“. This link is valuable for an attacker because it can be used to perform a cross-site request forgery (CSRF) attack to force the admin to check for updates whenever they decide:
http://yoursite/?q=admin/reports/updates/check
Since there is a CSRF vulnerability in the “Check manually” functionality (Drupal 8 is the only one not affected), this could also be used as a server-side request forgery (SSRF) attack against drupal.org. Administrators may unwillingly be forcing their servers to request unlimited amounts of information from updates.drupal.org to consume network bandwidth.
Issue #2: An attacker may force an admin to check for updates due to a CSRF vulnerability on the update functionality
An attacker may care about updates because they are sent unencrypted, as the following Wireshark screenshot shows:
To exploit unencrypted updates, an attacker must be suitably positioned to eavesdrop on the victim’s network traffic. This scenario typically occurs when a client communicates with the server over an insecure connection, such as public WiFi, or a corporate or home network that is shared with a compromised computer.
The update process downloads a plaintext version of an XML file at http://updates.drupal.org/release-history/drupal/7.x and checks to see if it is the latest version. This XML document can point to a backdoored version of Drupal.
The current security update (named on purpose “7.41 Backdoored“)
The security update is required and a download link button
The URL of the malicious update that will be downloaded
However, updating Drupal is a manual process. Another possible attack vector is to offer a backdoored version of any of the modules installed on Drupal. In the following example, a fake “Additional Help Hint” update is offered to the user:
Offering fake updates is a simple process. Once requests are being intercepted, a fake update response can be constructed for any module. When administrators click on the “Download these updates” buttons, they will start the update process.
This is how it looks from an attacker’s perspective before and after upgrading the “Additional Help Hint” module. First it checks for the latest version, and then it downloads the latest (malicious) version available.
As part of the update, I included a reverse shell from pentestmonkey (http://pentestmonkey.net/tools/web-shells/php-reverse-shell) that will connect back to me, let me interact with the Linux shell, and finally, allow me to retrieve the Drupal database password:
Issue #3: Drupal security updates are transferred unencrypted without checking the authenticity, which could lead to code execution and database access.
You may have heard about such things in the past. Kurt Seifried from Linux Magazine wrote an article entitled “Insecure updatesare the rule, not the exception” that mentioned that Drupal (among others) were not checking the authenticity of the software being downloaded. Moreover, Drupal itself has had an open discussion about this issue since April 2012 (https://www.drupal.org/node/1538118). This discussion was reopened after I reported the previous vulnerabilities to the Drupal Security Team on the 11th of November 2015.
You probably want to manually download updates for Drupal and their add-ons. At the moment of publishing there are no fixes available.
TL;DR – It is possible to achieve code execution and obtain the database credentials when performing a man-in-the-middle attack against the Drupal update process. All Drupal versions are affected.
Sometimes when buying something that costs $0.99 USD (99 cents) or $1.01 USD (one dollar and one cent), you may pay an even dollar. Either you or the cashier may not care about the remaining penny, and so one of you takes a small loss or profit.
Rounding at the cash register is a common practice, just as it is in programming languages when dealing with very small or very large numbers. I will describe here how an attacker can make a profit when dealing with the rounding mechanisms of programming languages.
Lack of precision in numbers
IEEE 754 standard has defined floating point numbers for more than 30 years. The requirements that guided the formulation of the standard for binary floating-point arithmetic provided for the development of very high-precision arithmetic.
The standard defines how operations with floating point numbers should be performed, and also defines standard behavior for abnormal operations. It identifies five possible types of floating point exceptions: invalid operation (highest priority), division by zero, overflow, underflow, and inexact (lowest priority).
We will explore what happens when inexact floating point exceptions are triggered. The rounded result of a valid operation can be different from the real (and sometimes infinitely precise) result and certain operations may go unnoticed.
Rounding
Rounding takes an exact number and, if necessary, modifies it to fit in the destination’s format. Normally, programming languages do not alert for the inexact exception and instead just deliver the rounded value. Nevertheless, documentation for programming languages contains some warnings about this:
Ruby clearly states that floating point has a different arithmetic and is a inexact number.
To exemplify this matter, this is how the number 0.1 looks internally in Python:
The decimal value 0.1 cannot be represented precisely when using binary notation, since it is an infinite number in base 2. Python will round the previous number to 0.1 before showing the value.
Salami slicing the decimals
Salami slicing refers to a series of small actions that will produce a result that would be impossible to perform all at once. In this case, we will grab the smallest amount of decimals that are being ignored by the programming language and use that for profit.
Let’s start to grab some decimals in a way that goes unnoticed by the programming language. Certain calculations will trigger more obvious differences using certain specific values. For example, notice what happens when using v8 (Google’s open source JavaScript engine) to add the values 0.1 plus 0.2:
Perhaps we could take some of those decimals without JavaScript noticing:
But what happens if we are greedy? How much can we take without JavaScript noticing?
That’s interesting; we learned that it is even possible to take more than what was shown, but no more than 0.00000000000000008 from that operation before JavaScript notices.
I created a sample bank application to explain this, pennies.js:
// This is used to wire money
function wire(deposit, money, withdraw) {
account[deposit] += money;
account[withdraw] -= money;
if(account[withdraw]<0)
return 1; // Error! The account can not have a negative balance
for(i = 0.000000000000000001; i < 0.1; i+=0.0000000000000000001) {
reset_values();
wire(1, i, 0); // I will transfer some cents from the account 0 to the account 1
if(account[0]==initial_deposit && i>profit) {
profit = i;
// print(“I can grab “+profit.toPrecision(21));
} else {
break;
}
}
print(” Found: “+profit.toPrecision(21));
print(“n2) Let’s start moving some money:”);
reset_values();
start = new Date().getTime() / 1000;
for (j = 0; j < 10000000000; j++) {
for (i = 0; i < 1000000000; i++) {
wire(1, profit, 0); // I will transfer some cents from the account 0 to the account 1
}
finish = new Date().getTime() / 1000;
print_balance(finish-start);
}
The attack against it will have two phases. In the first phase, we will determine the maximum amount of decimals that we are allowed to take from an account before the language notices something is missing. This amount is related to the value from which we are we taking: the higher the value, the higher the amount of decimals. Our Bank Account 0 will have $1,000,000 USD to start with, and we will deposit our profits to a secondary Account 1:
Due to the decimals being silently shifted to Account 1, the bank now believes that it has more money than it actually has.
Another possibility to abuse the loss of precision is what happens when dealing with large numbers. The problem becomes visible when using at least 17 digits.
Now, the sample attack application will occur on a crypto currency, fakecoin.js:
// This is used to wire money
function wire(deposit, money, withdraw) {
account[deposit] += money;
account[withdraw] -= money;
if(account[withdraw]<0) {
return 1; // Error! The account can not have a negative balance
wire(1, j, 0); // I will transfer a few cents from the account 0 to the account 1
if(account[0]==initial_deposit && j > profit) {
profit = j;
} else {
break;
}
}
print(” Found: “+profit);
reset_values();
start = new Date().getTime() / 1000;
print(“n2) Let’s start moving some money”);
for (j = 0; j < 10000000000; j++) {
for (i = 0; i < 1000000000; i++) {
wire(1, profit, 0); // I will transfer my 29 cents from the account 0 to the account 1
}
finish = new Date().getTime() / 1000;
print_balance(finish-start);
}
We will buy 10000000000000000 units of Fakecoin (with each coin valued at $0.00000000011 USD) for a total value of $1,100,000 USD. We will transfer one Fakecoin at the time from Account 0 to a second account that will hold our profits (Account 1). JavaScript will not notice the missing Fakecoin from Account 0, and will allow us to profit a total of approximately $2,300 USD per day:
Depending on the implementation, a hacker can used either float numbers or large numbers to generate money out of thin air.
Conclusion
In conclusion, programmers can avoid inexact floating point exceptions with some best practices:
If you rely on values that use decimal numbers, use specialized variables like BigInteger in Java.
Do not allow values larger than 16 digits to be stored in variables and truncate decimals, or
Use libraries that rely on quadruple precision (that is, twice the amount of regular precision).
Recursion is the process of repeating items in a self-similar way, and that’s what the XML Entity Expansion (XEE)[1] is about: a small string is referenced a huge number of times.
Technology standards sometimes include features that affect the security of applications. Amit Klein found in 2002 that XML entities could be used to make parsers consume an unlimited amount of resources and then crash, which is called a billion laughs attack. When the XML parser tries to resolve, the external entities that are included cause the application to start consuming all the available memory until the process crashes.
This example shows an XML document with an embedded DTD schema that performs the attack.
The entity LOL9 in the example will be resolved as the 10 entities defined in LOL8; then each of these entities will be resolved in LOL7 and so on. Finally, the CPU and/or memory will be affected by parsing the 3*109 (3.000.000.000) entities defined in this schema and it could make the parser crash.
The SOAP specification states that a SOAP message must not contain a Document Type Declaration (DTD). Therefore, a SOAP processor can reject any SOAP message that contains a DTD.
Regardless of what the specification indicates, certain SOAP implementations do parse DTD schemas within SOAP messages:
CVE-2013-1643: The SOAP parser (in PHP before 5.3.22 and 5.4.x before 5.4.13) allows remote attackers to read arbitrary files via a SOAP WSDL file containing an XML external entity declaration in conjunction with an entity reference.
CVE-2010-1632: Apache Axis2 before 1.5.2 (as used in IBM WebSphere Application Server 7.0 through 7.0.0.12, IBM Feature Pack for Web Services 6.1.0.9 through 6.1.0.32, IBM Feature Pack for Web 2.0 1.0.1.0, Apache Synapse, Apache ODE, Apache Tuscany, Apache Geronimo, and other products) does not properly reject DTDs in SOAP messages.
CVE-2004-2244: The XML parser (in Oracle 9i Application Server Release 2 9.0.3.0 and 9.0.3.1, 9.0.2.3 and earlier, and Release 1 1.0.2.2 and 1.0.2.2.2, and Database Server Release 2 9.2.0.1 and later) allows remote attackers to cause a denial of service with CPU and memory consumption via a SOAP message containing a crafted DTD.
Here is an example of a parser that is not following the specification and is instead referencing a DTD on a SOAP message [2].
Figure 1: SOAP billion laughs
This vulnerability also affects the Microsoft XML Core Services (MSXML), a service that allows applications to build Windows-native XML-based applications. If you paste the billion laughs attack code into Microsoft Word for Mac, the memory will start getting depleted until Word crashes. You can try it yourself: just copy, paste, and die laughing.
By continuing to use the site, you agree to the use of cookies. more information
The cookie settings on this website are set to "allow cookies" to give you the best browsing experience possible. If you continue to use this website without changing your cookie settings or you click "Accept" below then you are consenting to this.