Gruyere Lessons On Secure Application Development

Notes from Gruyere (formerly Jarlsberg) testing

Learn how to make web apps more secure. Do the Gruyere codelab.

Cross-site Scripting (XSS)

There is no magic defense to getting rid of XSS vulnerabilities. Some steps you should take to prevent these types of bugs from appearing in your products:

  1. Make sure you understand the problem.
  2. Familiarize yourself with the security features of your template system. Reuse their knowledge.
  3. “Sanitize” user-supplied text; that is, ensure that it user-supplied text fits your assumptions. Validate user-supplied text. Do not substitute filtering-out known malicious character sequences for sanitization. Wherever possible, use template features to perform the sanitization. By using template features, all of your escaping will be done in one place. All of your escaping should be done correctly. Use known and proven routines. (Note that Adobe Cold Fusion 8.0, 8.0.1, 9.0 and earlier do not perform sanitization well; see Security Tracker. On the bright side, if you relied upon the sanitization features of Adobe Cold Fusion, a fix to Adobe Cold Fusion fixes vulnerabilities in your application.)
  4. “Escaping” is using escape characters to represent special characters found in user-supplied text. Escape input that is displayed in error messages; that is, do not trust user-supplied text to fit your assumption. User-supplied text can include a script, for example, and returning the original text to the user launches that script.
  5. Employ good testing practices with respect to XSS. See XSS (Cross Site Scripting) Cheat Sheet Esp. for filter evasion.
  6. Don’t write your own template library.

Approach HTML sanitization as follows:

  • Parse the input into an intermediate Document Object Model (DOM) structure, then rebuild the body as well-formed output.
  • Use whitelists for allowed tags and attributes.
  • If URL and CSS attributes are permitted, sanitize those as well.

Whenever possible it is preferable to use an already available known and proven HTML sanitizer.

A replacement for cgi.escape:

def _EscapeTextToHtml(var):  """Escape HTML metacharacters.

  This function escapes characters that are dangerous to insert into  HTML. It prevents XSS via quotes or script injected in attribute values.

  It is safer than cgi.escape, which escapes only <, >, & by default.  cgi.escape can be told to escape double quotes, but it will never  escape single quotes.  """  meta_chars = {      '"': '"',      '\'': ''',  # Not '      '&': '&',      '<': '<',      '>': '>',      }  escaped_var = ""  for i in var:    if i in meta_chars:      escaped_var = escaped_var + meta_chars[i]    else:      escaped_var = escaped_var + i  return escaped_var

The JSON parser is available at json.org.

Javascript’s eval should rarely be used.

To escape quotes, use \x27 and \x22 for single and double quote respectively. (NOT the HTML escapes &#27; and &quot;.)

To escape < and >, use \x3c and \x3e (NOT the HTML escapes &lt; and &gt;.)

Even though browsers don’t always respect content type and content encoding, it should be specified. E.g., for HTML:


Serve JSON results as application/javascript.

Automated testing tools can help unearth problems quickly, but will not affirm that an application is without error.

Microsoft Fiddler with the x5s plugin found many instances of XSS vulnerabilities in Jarlsberg. Translating from a CodePoint to a transaction to a code change is not straightforward. Many of these vulnerabilities would have been avoided through a template library’s sanitization routines.

Debugging with Fiddler: The complete reference from the creator of the Fiddler Web Debugger by Eric Lawrence

The Firefox add-on “XSS Me” (from Security Compass) did not report failures but did report a few warnings when creating a new snippet. The “Sign Up” process passed with no errors or warnings. (Other Firefox add-ons: “SQL Inject Me” and the Collection “Web Application Security Penetration Testing.”)

Client-State Manipulation

Check authorization on the server side before committing changes.

Python’s hash function is not cryptographically secure.

Be careful of things that don’t work: using POST instead of GET is advisable but not sufficient by itself, checking Referer headers is insufficient, and copying cookies into hidden form fields can make your cookies less secure.

Path Traversal

Serve only specific resource files. Either hard code a list or, when your application starts, crawl the resource directory and build a list of files. Accept requests for only those files.

Alternately, prevent access to files outside the resources directory. File path validation (sanitization) is challenging due to the many ways path elements such as “../” and “~” can be escaped. Do file path validation on the final path, not on the URL, since there are numerous ways to represent the same characters in URLs.

Note: Changing file permissions will NOT work. Jarlsberg has to be able to read this file.

Denial of Service

Denial of service describes a wide class of attacks. This might mean bringing your service down or flooding your inbox so you can’t receive legitimate mail. Some things to consider:

  • If you were evil and greedy, how quickly could you take down your application or starve all of its resources? For example, is it possible for a user to upload their hard drive to your application? Entering the attacker’s mindset can help identify DoS points in your application. Additionally, think about where the computationally and memory intensive tasks are in your application and put safeguards in place. Do sanity checks on input values.
  • Put monitoring in place so you can detect when you are under attack and enforce per user quotas and rate limiting to ensure that a small subset of users cannot starve the rest. Abusive patterns could include increased memory usage, higher latency, or more requests or connections than usual.

Code Execution

Even though there is no single or simple defense to remote code execution, here is a short list of some preventative measures:

  • Least Privilege: Always run your application with the least privileges it needs.
  • Application Level Checks: Avoid passing user input directly into commands that evaluate arbitrary code, like eval() or system(). Instead, use the user input as a switch to choose from a set of developer controlled commands.
  • Bounds Checks: Implement proper bounds checks for non-safe languages like C++. Avoid unsafe string functions. Keep in mind that even safe languages like Python and Java use native libraries.

Configuration Vulnerabilities

Make sure debug features are not installed. If a debug feature is necessary, then it needs to be carefully locked down: only admin users should have access and only requests from debug IP addresses should be accepted.

Passwords should never be stored in cleartext. Instead, you should use password hashing. The idea is that to authenticate a user, you don’t need to know their password, only be convinced that the user knows their password. When the user sets their password, you store only a cryptographic hash of the password and a salt value. When the user re-enters their password later, you recompute the hash and if it matches you conclude the password is correct. If an attacker obtains the hash value, it’s very difficult for them to reverse that to find the original password. (Which is a good thing, since despite lots of advice to the contrary, users frequently use the same weak passwords for multiple sites.)

Hosting arbitrary content on the server is a major security risk whether it’s HTML, JavaScript, Flash or something else. Allowing a file with an unknown file type may lead to a security hole in the future.

  1. Only files that are part of the application should be treated as templates.
  2. Don’t store user uploaded files in the same place as application files. Use a separate domain.
  3. Consider limiting the types of files that can be uploaded (via a whitelist).

Jarlsberg implements a template language which allows arbitrary database access. It would be safer if the templates were only allowed to access data specifically provided to them. For example, a template could have an associated database query and only the data matched by that query would be passed to the template. This would limit the scope of a bug like this to data that the user was already allowed to access.

AJAX Vulnerabilities

AJAX code needs to make sure that the data only goes where it’s supposed to go. The flaw here is that the JSON structure is not robust. The JSON structure

[<private_snippet>, {<user> : <snippet>,...}]

is better than

{'private_snippet' : <user's private snippet>, ..., 'private_snippet' : <attacker's snippet>}

When user values are used in as DOM element identifiers, ensure that there can’t be a conflict. Prohibit user values which resemble application values (such as  id="user_"). Even better, use your own identifiers rather than user values.

Buffer Overflow and Integer Overflow

A buffer overflow vulnerability exists when an application does not properly guard its buffers and allow user data to write past the end of a buffer. This excess data can modify other variables, including pointers and function return addresses, leading to arbitrary code execution. Historically, buffer overflow vulnerabilities have been responsible for some of the most widespread internet attacks including SQL Slammer, Blaster and Code Red computer worms. The PS2, Xbox and Wii have all been hacked using buffer overflow exploits.

While not as well known, integer overflow vulnerabilities can be just as dangerous. Any time an integer computation silently returns an incorrect result, the application will operate incorrectly. In the best case, the application fails. In the worst case, there is a security bug. For example, if an application checks that length + 1 < limit then this will succeed if length is the largest positive integer value, which can then expose a buffer overflow vulnerability.

This codelab doesn’t cover overflow vulnerabilities because Jarlsberg is written in Python, and therefore not vulnerable to typical buffer and integer overflow problems. Python won’t allow you to read or write outside the bounds of an array and integers can’t overflow. While C and C++ programs are most commonly known to expose these vulnerabilities, other languages are not immune. For example, while Java was designed to prevent buffer overflows, it silently ignores integer overflow.

SQL Injection

Just as XSS vulnerabilities allow attackers to inject script into web pages, SQL injection vulnerabilities allow attackers to inject arbitrary scripts into SQL queries. When a SQL query is executed it can either read or write data, so an attacker can use SQL injection to read your entire database as well as overwrite it, as described in the classic Bobby Tables XKCD comic. If you use SQL, the most important advice is to avoid building queries by string concatenation. Sanitize the user input using well-tested API calls (don’t write your own data validation routines), store the sanitized result in a parameter and use parameterized queries instead of concatenating strings to create the SQL query.. This codelab doesn’t cover SQL injection because Jarlsberg doesn’t use SQL.

NTO SQL Invader gives the ability to quickly and easily exploit or demonstrate SQL Injection vulnerabilities in Web applications. With a few simple clicks, you will be able to exploit a vulnerability to view the list of records, tables and user accounts of the back-end database.


Comments are closed.