Are You at Risk of an Injection Attack? These Types of Attacks Are Common, Primarily Because They Affect Ubiquitous SQL Databases
Total Page:16
File Type:pdf, Size:1020Kb
Are you at risk of an injection attack? These types of attacks are common, primarily because they affect ubiquitous SQL databases. If a user — internal or external — supplies information through a form, you may be at risk. Insufficient input validation may allow users to insert or inject their own parameters in your SQL call and gain access to some or all of your data. Injection flaws occur primarily when an application uses untrusted data when constructing an SQL call or when an application relies on older, vulnerable frameworks. An attacker can simply modify the ‗id‘ parameter in their browser to return all records. More savvy attackers can even, under the right circumstances, make changes to data. In addition to impacting SQL databases, injection flaws can also be found in queries from LDAP, XPath or NoSQL as well as OS commands, SMTP headers, XML parsers and the like. Injection flaws are most common in legacy code, but they are tough to find and eradicate during testing. You really need to examine the code manually to check for injection flaws. Injection attacks can be devastating to your business, both from a technical aspect and from the business side. Once an injection attack takes place, you can no longer trust your data. It may be corrupted or denial of access may occur. In rare cases, injection attacks can take down your entire DBMS or issue commands to your operating system. You lose the ability to guarantee confidentiality to your authorized users or customers, because sensitive information may have been made available to attackers. And if you‘re holding authorization information in your SQL database, an attacker may be able to change this to limit access. From a manager‘s perspective, how does losing the data or having it stolen impact your day-to-day operations? Depending on the sensitivity of the data, such a worst-case breach could be devastating to your company‘s ability to continue operations. It could also be terrible publicity for your company and cost you customers should the breach be made public. Eliminating any opportunities for an attacker to take advantage of injection flaws should be a top consideration for your business because of the high impact a savvy attack could have on critical business data. Injection flaws are common with applications written in PHP or ASP, because these tend to have older functional interfaces. They are much less common with J2EE and ASP.NET applications, which don‘t generally allow SQL injections. While you can‘t assume that applications written in the latter will be fine, you should be more concerned about your legacy apps in PHP and ASP. The first thing to do when investigating the vulnerability of your application to an injection attack is to make sure that any interpreter in use separates the query from any untrusted data. In SQL, you can simply avoid dynamic queries, or you can use bind variables in stored procedures and prepared statements so users are unable to insert text. You can use a code analysis tool to find out if an interpreter is in place and to see the way data flows through the application. Some penetration testers can create scenarios such as would be used by an attacker, and this can tell you if you‘re at risk. But in most cases, you‘ll have to check the code for yourself — that‘s the quickest and most accurate method for determining if the interpreter is present. Scanners can‘t always tell whether an attack could be successfully carried out. In order to keep an attacker from accessing your data, you need to ensure that untrusted data stays separated from commands and queries. That means that an attacker isn‘t able to call records by modifying the ‗id‘ parameter; the query will return nothing. The easiest way to do this? Don‘t use the interpreter at all. A safe API can avoid using the interpreter by creating a parameterized interface that only uses PreparedStatements instead of Statements. These stored procedures are compiled before the user adds any input, so it‘s not possible to modify the SQL statement. Even some stored procedures are vulnerable, so avoid dynamic queries and use parameterized queries. All your SQL statements should recognize user inputs as variables and validate them before passing data back to the user. In other words, statements should be precompiled before actual inputs are substituted for variables. In some cases, there‘s no API with a parameterized interface that is suitable for use. It is possible to escape special characters, but you must use specific escape syntax for whichever interpreter you are running. Check your code library for an escape routine that will work. This is the only way to make special characters safe if they need to be used in your application. While you can ―white list‖ approved characters for use, that may not be a perfect solution if your users need to be able to input many different special characters. You should also avoid disclosing any error information to the user. An uncaught SQL error may contain information like procedure names or table names and, in the hands of a knowledgeable attacker, can be used to access data. Injection flaws are relatively common and should be removed from legacy code. The good news is that most injection flaws are rather hard to exploit — they have to be set up in just the right way for an attacker to take advantage of them. However, if a vulnerability is exploited, it can be very damaging to your business. As part of an overall security review, it may be a good idea to re-examine your databases that allow user queries to ensure that queries or commands and unsecured data are completely separated. Weaknesses arise when form processing code constructs SQL queries on the fly. The naive approach is to construct a prototype statement and fill it out with data from the form fields. A couple of examples: Let‘s suppose that some web application requests a user name and a password to access a private area. The application will pick these values and it will collect a query to send to the database. The query might look like this: 1 select id 2 from users_table 3 where username='$username' and password='$password'; Where $username and $password are replaced by the values the user has entered on the screen. In this case, we allowed the user to write some texts that will be sent to the database without any verification. Given the case of a malicious user, he could write in the password field and in this case, the resulting query will be as follows: 1 select id 2 from users_table 3 where username='admin' and password=''or '1'='1'; This query will produce the same result as if the admin user had introduced their password correctly. So that the web application will allow access to the administration area to a user who doesn‘t know the proper password. Let‘s see another example: SELECT ADDRESS FROM CUSTOMERS WHERE LAST_NAME = ‘#1′ Excessively trusting code will accept whatever the user types into a ―Last Name‖ field and replace ―#1″ with it. This works fine as long as the user types a normal last name. But let‘s say this appears in the form field: Smith';DELETE FROM CUSTOMERS WHERE LAST_NAME = ‘Smith Note the quotation marks. After the SELECT statement, the next statement will delete all rows with the last name of Smith from the CUSTOMERS table. A more elaborate statement could change records or do anything else. Some injection attacks can even obtain information. Reading or modifying the database requires knowing or guessing something about its tables. Less sophisticated attackers can attempt a denial-of-service attack by blindly modifying the SQL to make it invalid. That approach might crash an application on the server or put the database into an invalid state. The backslash (\) character is as dangerous as the quote. A backslash followed by a single quote tells SQL to treat it as a literal quote character, not a string delimiter. Using it at the end of a string leaves the string unterminated, and whatever comes next will be part of the string. A backslash-based SQL injection is harder to construct that one using quote characters, but not impossible. The comment introducer, ―–‖ (two hyphens), will make the database engine ignore the rest of the line. The character sequence ―/*‖ will make it ignore everything until a matching ―*/‖ comment delimiter. These don‘t work within quoted strings, and not all SQL implementations support them, but they provide a venue for injection if the attacker can get outside a quoted string. The attacker can find more options by constructing post data directly rather than going through a Web form. The code needs to validate all post data fields, not just the ones that come from form fields. To get the best chances of success, an attacker needs to learn something about the database. For open-source code, this information may already be available. In other cases, the error-based approach can yield information. The attacker performs a trial injection and hopes to get back an error page. The error report will often consist of a stack dump and a display of the failed SQL statement. This lets the attacker see what injected text can perform harm. A variation on this is a page that displays the SQL output, even if it‘s an error message. The page will look normal, except where the error message appears instead of expected data. This approach also lets the attacker inject arbitrary SELECT statements and see the output on the page.