Application Security

Buffer overflow

The classic vulnerability in software is the buffer overflow. Programming languages like ‘C’ don’t deal ‘natively’ with strings, they have library functions that can be used to move strings of data from one memory location to another. If an attacker crafts a special string – typically much longer than the one intended and including malicious logic – and passes it into a program these library functions blindly copy the whole special string to a new memory location. Because the string is longer than expected, this tramples over other data and potentially program code and can lead to the malicious logic being executed at a later time.

A common technique is to include a “NOP-sled” in the special string. In x86 Intel processors the character 0x90 indicates no operation. The default behaviour on encountering NOP is to attempt to execute the next memory location. If it too is NOP, processing will slide on to the next piece of code at the end of the NOP sled – normally the malicious logic.

The key to defending against buffer overflows is to rigorously validate all input from outside the application – especially the length of input strings.

Advanced firewalls and intrusion prevention systems can search for and block strings of NOP characters in arriving data streams.

Injection attacks

Specially crafted user input is at the root of many vulnerabilities. Injection attacks inject technical code that modifies system behaviour into what is expected to be technically-neutral, user-supplied text.

The main injection attack is SQL Injection. SQL is the language used to interact with databases. In poorly structured code queries and updates can be created by concatenating technical commands (select, update) and user input (accountID = 1234). If the user supplies “1234 or 1 = 1”, the selection becomes “accountID = 1234 or 1 = 1” the second part of which is true for every record. This results in the coded action, be it query or update, unexpectedly being applied to every record on the database table.

To defend against SQL injection, SQL commands should never be created by concatenation that includes user input. “Parameterised Queries” should be used instead. These use place holders “accountID = ?” and replace the place holder with the user specified input which will never be interpreted as a technical command.

Injection attacks can be performed against any technical approach that can interpret text. For example XML injection and LDAP injection are both possible (The major Log4Shell vulnerability was an LDAP injection exploit). They can both carry out commands based on the content of input. Note the in general the initial developer has no expectation that text will be interpreted as commands. The attacker is taking advantage of dormant functions.

Directory Traversal

A similar issue is presented when the user is asked to specify a file for upload or download – or other input is used in constructing a filename. The user-supplied string can include strings such as “../../../some/unexpected/place” which triggers the application to go wandering into unexpected locations. This can be used by an attacker to read data, to update data or to remove key files and cause an outage. Extreme care and very strong validation is required if user-supplied filename elements are used. Ideally it should be avoided.

Web Applications

The web is based on the HTTP protocol which was originally designed for one-directional information retrieval. The basic HTTP protocol is not secure. There are no safeguards against impersonation and data is send in the clear. HTTPS should be used. Servers and web pages should be set to force HTTPS even if the client (in the hands of an attacker) attempts to return to basic HTTP.

HTTP headers & cookies

XSS (Cross Site Scripting)

In a similar manner to injection attacks, it is possible to place specially crafted user-input in a web page or form which is displayed in subsequent page views. This specially crafted user-input could include malicious Javascript code that executes in the viewers browser.

The user-input can be “reflected” (e.g. from an email link) or “stored” (e.g. placed in a forum user’s footer message and shown whenever a user’s postings are served).

The key to defending against XSS is to validate all user input and then encode it. The malicious code will typically include HTML tags such as “<script>”. Once encoded these become “&lt;script&gt;” which will not be interpreted as Javascript.

If a site uses functions like the html attribute “on-click”, care must be taken to ensure that no user input is ever used to construct the “on-click” value as this gives attackers a means of influencing behaviour that is not stopped by encoding.

XSRF (Cross Site Request Forgery)

To enhance usability (i.e. avoid the hassle of having to login every time you visit a web site) many sites store a long-lived user token in a cookie in the user’s browser. When the user visits the site, they are instantly identified and authenticated.

This becomes a problem then an attacker crafts a URL for that web site with malicious intent and somehow induces the user to invoke it on their browser. The invocation could be via a link in an email. It could be via Javascript embedded invisibly in another site using XSS. It could even be by placing the URL in an HTML “IMG” tag on another visited site. This would immediately attempt to download images (invoke the URL) when a page is requested.

When the URL is invoked, the user is identified and authenticated and performs the action in the malicious URL.

The most common defence is to use a XSRF tokens. These are large random numbers generated whenever a form page is prepared, held against HTTP session and included in the requested page as a hidden field. Any form request that arrives without a XSRF token matching the one held against the HTTP session will be ignored as invalid.

SSRF (Server side request forgeries)

Server side request forgeries are another form of injection attack. A user submits a request to a web server. The server uses the user input to construct a request to an 3rd party API and sends the request to the 3rd party server. After retrieving the response from the remote server, the results are interpreted and formatted for display to the user.

In an SSRF, the user constructs a request to produce unexpected behaviour from the 3rd party API. It may extract additional data or update data in an unwanted way. Once again the key is validating user input and restricting it to ensure only expected values are used in formatting the request to the 3rd party API.

Additional development considerations

  • External/visible detailed error messages (aids an attacker)
  • Internal operation and methods exposed
  • Race conditions (multi-threading)
  • Inadequate logging & monitoring
  • Insecure default configuration state (open ports, default passwords)