Application Security and Redefining User Input
One of the cardinal rules of the web application security is "Do not trust the user input" but it's loosely defined. We should've said "Do not trust any input!"
Which input is coming from the user?
Web applications are more complicated than they were. Now we have got office applications and shiny Web 2.0 stuff all over the web. Complexity comes with a price tag and lots of hidden layers.
A perfect example of a hidden layer is the second order injections where the injection goes into a back-end storage, then directly pulled out from there and used in an SQL Query, printing out to the HTML without filtering or something similar. In this level developers believe that data was secure, because it was coming from a back-end, which was supposed to be secure. Guess what, it's not!
The fact is you can't keep track of your inputs, your input can come from an API that you exposed to your users, an old form which is adding records your db etc.
First defence would be centralising the input as much as possible, duplicated code is a big threat for security, but this is not enough. You need think "defence in depth" and you should not trust any input. It can be coming from the functions of your programming language, your database internal variables or from your web server, Do not trust any input!
Recently a CSRF vulnerability spotted in twitter. Twitter has two post screens, one of them for mobile and one of them for normal web browsers. Even though they put a CSRF protection to the normal page, they forgot to put this to the mobile interface. A perfect example of how code duplication can hurt your application's security.
About couple of months ago I was working on an application and observed that an ASPX file actually doing an HTTP request to itself and then it was printing the response in the page. First question was “How the script would know where is it running from? Which host? Which exact URL?”
The answer was quite obvious: Request.Url, Follow up question was “How ASP.NET would figure out what's in the Request.Url?”. The answer was: "Host Header" of the request. Which means if the target application configured to response all requests for that IP address then you can change the host header to anything you want to accomplish following actions:
- Using this system as a proxy to browse internal network by sending HTTP requests around,
- Abusing trust relationships in the internal network and in the very same computer, A perfect example of this accessing ASP.NET error messages and trace.axd file which are only available to local IP address by default.
It's quite common to see rookie developers blindly trusts HTTP Headers such as HTTP_REFERRER or Cookies, Thus you can carry out SQL Injection attacks, XSS attacks via these channels easily. Experienced developers or more security minded developers are not so naive and they know one can easily modify these. Still it's quite common to rely on system functions or server functions to be secure, because they are coming somewhere you trust, right?
As shown in the previous example even the functions such as Request.Uri might be controlled by the attacker. Therefore you should not trust anything coming from anywhere...