Web Application Defense Mechanisms
Despite much differences across web applications, many employ very similar core security mechanisms. These mechanisms are a significant part of an application’s defense against attackers, and hence represent a considerable attack surface. Mechanisms such as handling user access and user input are key when attacking an application, to which defects can compromise the entire application.
The fundamental problem in web application security is the fact that all user input cannot be trusted. This gives rises to some ways to defend from attacks. Conceptually, many of them are quite similar such as:
Preventing unauthorized access by handling user access to application data and functionality
Preventing crafted input from causing undesired behavior of the application
Taking suitable offense/defense mechanisms by frustrating attackers when attacking the application
Enabling administrators to monitor the application’s activities and functionalities by managing the application itself
Many attacks revolve around these concepts, and understanding how they work is key to being able to defend against them.
Most web apps handle user access using 3 common mechanisms, each representing a considerable attack surface of an application:
Ensuring that the application establishes that the logged in user is who they say they are
Most apps employ username password, which they check for validity
At higher levels, additional credentials can be used with multistage login process
At even higher levels, other authentication models can be used (i.e.client certificates, smartcards, challenge-response tokens).
Alongside, many apps have supporting functionality such as self-registration, account recovery, password change.
Seemingly simple, many authentication mechanisms are quite flawed
Weak passwords, or exploiting defects in application logic.
Once logged in, need to manage user’s session
Most apps create a session for each user and issue a token identifying that session
The token is a unique string mapping the user to the session
With each http request from user application, the token is attached with the request, associating the request with the user.
Ideally if a user does not make a request after some time, the session expires.
Session management mechanism is dependent on token security - if tokens are exploited, then the application can be exploited by an attacker identifying as another user.
The application needs to be able to make correct decisions about what a user can and cannot do on the application
Needs good logical controls with different use cases considered.
Can often get quite complicated, or developers making flawed assumptions or oversights, which an attacker can exploit to get unauthorized access.
Required in any input form, but there is no single protective mechanism
It’s tough because there is so many possibilities and often arbitrary input is required.
Many attack vectors such as via browser interface, cookies, hidden form fields
Blacklisting a set of literal string or patterns often known to be used in attacks.
Often seen as LEAST EFFECTIVE approach
Variety of ways to exploit with a wide variety of input which can be formed in various ways.
For example if block 0, try 1-1, or if alert(”xss”) blocked, try prompt(”xss”).
Filters can also be bypassed by inserting expressions into attack inputs to disrupt tokenizing by the application:
Many filters can be vulnerable to NULL byte attacks, inserting a NULL character can stop filter processing of the next following inputs.
Whitelisting a set of literal stings or patterns or criteria known to match only good input, blocking everything else.
When this approach is feasible, it is regarded as effective and can prevent many attackers from crafting input.
However, many situations require being flexible with what is considered “good”.
E.g. some people’s name have special characters like apostrophes
This cannot be an all encompassing solution
Instead of rejecting potentially bad input altogether, sanitize it before processing it.
Recognizing that sometimes data needs to be accepted which cannot be 100% safe.
Often highly effective approach
For example, sanitizing script tags to prevent XSS attacks.
Making sure user-supplied data is processed in safe ways
Can address attacks like SQL injection by correct use of parametrized queries.
Unsafe ways would be to parse user input into operating system command interpreter.
Cannot be applied to all kinds of attacks, but effective when applicable
Sometimes the input supplied by attackers is pretty much the same as a normal user’s input.
The key difference is the circumstances under which it is submitted.
An attacker might try to gain access to another user’s bank account by changing an account number transmitted in a hidden form field.
Syntactic validation can’t do much because it appears a legitimate entry
Need to consider the circumstances, i.e. matching the account number with user submitting it.
Although many input validation checks on client side are some ways to filter input and improve performance, no guarantee is given to the input that reaches the server.
The point at which data is received at server side is a big trust boundary and application needs to take measures to defend itself.
Chucking all validation checks on one side is too tough and has its technical challenges
Boundary validation is validation check as data passes through different components. Validation checks implemented at various stages.
Multi-step validation and canonicalization
When user input validated across several steps, it is possible a careful attacker could slip a crafted input through.
For example lets say abc is deemed malicious and is filtered out. An attacker could craft the input ababcc, which when sanitized, would give abc passing through.
Data canonicalization is when input sent from user’s browser could be encoded in various ways so that unusual characters and binary data cna be safely transmitted over HTTP.
Canonicalization is the process of decoding data into a common character set. Attackers can slip by validation mechanisms if canonicalization is done after input filters applied.
Can do recursive sanitization or just reject bad input altogether
Applications must assume that attackers are dedicated and skilled and must be able to handle them. Some measures are
Unanticipated errors will always occur regardless of how careful developers are
Applications need to be able to handle unexpected errors gracefully, with suitable error messages, or recover from them
No system generated messages should be sent through, otherwise can assist attackers in exploiting application.
Many languages provide good error-handling support with try-catch blocks and checked exceptions.
Used when investigating intrusion attempts against application
Effective logs should let application owners understand what has taken place, which vulnerabilities exploited, and whether attackers could gain access to data or perform unauthorized actions
Ideally provide evidence of intruder identity
Key events should be logged with application use, such as:
events with authentication functionality
access attempts that are blocked
requests containing attack strings
Effective audit logs will typically record time of each event, IP address, user account, etc.
Logs need ot be protected from read/write access and hidden from attackers.
Audit logs can give good evidence post attack, but sometimes need to react more promptly, such as blog attacker IP before making damage.
Must balance genuine attacks and false alarms reliably.
Deviations from normal usage, like large number of requests from single IP
Deviations from normal business, like large number of fund transfers
Requests containing attack strings
Requests where data is hidden from ordinary users has been modified.
Many web firewalls and intrusion detection products can be good layer of defense, but many attacks can go more subtly. Such software cannot be entirely relied on.
Most effective way is to integrate real time alerting with application’s input validation mechanism and other controls.
Many applications have defensive systems in place against attackers. If attackers bypass filters, can resort to frustrating the heck out of them and slowing down their progress considerably. Costs vs rewards, although will not deter a very patient attacker.
Applications need effective management and administration over user accounts, roles, access monitoring, audit functions, diagnostic tasks, and configuring aspects of application functionality.
Many applications have administrative functionality in the application itself, accessed through same web interface as core non-security functionality.
This can represent a critical part of the application’s attack surface such as attacker gaining privilege escalations
Often target for attackers because:
Compromising an administrator account means compromising the entire applications.
Many apps do not effectively implement access controls of some administrative functions. A new account could be created with powerful privileges.
Administrative functionality often involves displaying data originated from ordinary users. Cross site scripting attacks can compromise user sessions.
Administrative functionality often less scrutinized over security, because users deemed trusted, or because pen-testers not given high access.
The Web Application Hacker’s Handbook: Finding and Exploiting Security Flaws (2nd edition) - Chapter 2