The Kaya standard library and web application framework is designed to remove or minimise the risk of security vulnerabilities in web applications. However, no library that allows application authors sufficient flexibility to do what they need can completely protect them from the consequences of mistakes or laziness. This tutorial describes some of the common types of web vulnerability, how the Kaya frameworks help to prevent them, and what additional precautions you as an author must take.
General precautions
As a general precaution (and one that is not language-specific), any user session that involves authentication should be encrypted using HTTPS at the web server level starting at the login form and ending only when the user explicitly logs out. Do not be tempted to try to save processing time by not using HTTPS or only using it for the login pages themselves.
Kaya uses the standard CGI interface to communicate with web browsers. If you are not on a dedicated web server (and probably even if you are) the use of Apache's suexec to ensure that your CGI scripts, config files, and other web documents don't need to be readable by anyone other than yourself can give a significant increase to security. Kaya also supports the SCGI protocol if you prefer to use this.
In addition to the techniques here, you will also need to ensure that the server that your Kaya web applications are running on is properly secured - consult the documentation for your web server and operating system.
Remote code execution
Remote code execution is one of the most powerful security vulnerabilities, and automated worms may spread across the internet in minutes using this method, if a suitable vulnerability in a widely used application is found. This vulnerability is generally most widespread in interpreted languages using functions that allow a string of text to be directly (as in the eval construct present in many languages) or indirectly (by inclusion of other scripts, for example via PHP's include statement.
In Kaya, the risk of remote code execution in this form is when an unmarshalled string contains a function which is then executed. This can be avoided by not calling unmarshal on untrusted (i.e. user-supplied) data. The exception to this is data generated by Kaya's built-in state handling routines, which is cryptographically protected by the application secret key.
SQL Injection
SQL Injection occurs when an attacker is able to manipulate the content of a database statement to run their own statement, often by using the ' and " characters within strings. The Kaya database access functions do not allow multiple SQL statements to be placed within a single call to exec which may reduce the severity of the possible attacks. However, to avoid them entirely, you should use prepared statements (prepare and execPrepared) and ensure that user-supplied data is only added to a database query via the parameters rather than in String concatenation. If user-supplied data must be added via String concatenation, which is rarely necessary, then you must filter and validate it yourself.
Cross-site scripting
Cross-site scripting occurs when an attacker who does not have authorised access to your application is able to insert their own code into the web page displayed to the end user. This may be used to intercept a form, steal authentication cookies, or compromise the user's web browser. To protect against this, any user-supplied data displayed back to that user or to another user must be filtered.
The webapp model of development uses the HTMLDocument module to automatically carry out this filtering. You can use this module when developing using the CGI model, but if you do not, you must filter all output yourself (as is common in most web programming languages). There are two situations in which the filtering can either be bypassed or is not possible to do automatically, which you must guard against yourself:
- The readFromString and readFromTemplate functions convert a String to HTML. You should never call
readFromTemplateon untrusted data, and you should read the WhiteList documentation before usingreadFromString. - Certain HTML attribute values - for example hyperlink destinations or image sources - may use the
javascript:pseudo-protocol. The Kaya library cannot determine the difference between legitimate and illegitimate use of this protocol (although there are generally better ways to achieve the same result for legitimate users!) and so you must additionally do your own checks in this relatively rare case.
Cross-site request forgery
Cross-site request forgery occurs when an attacker is able to trick an authenticated user of your application into carrying out an action on that application. Depending on the attack itself, the user may not be aware that they have carried out this action!
While the Kaya application's internal secret key remains secure, any application that solely uses state passed around via URL parameters and form controls to track requests should be completely immune to cross-site request forgery, as the attacker will be unable to cause the user to construct the request.
If, however, you use cookies to retain some application state, an attacker may be able to cause the user to construct the request. You can guard against this by storing a state variable (the user's username is the easiest) in both the cookie and in any forms and links generated by users with that cookie, and refusing to process any actions if the state variable in the cookie does not match the one submitted with the form.
Insufficient input validation
Input validation bugs are largely language-independent. They are caused when user input is not in an expected format, but the program processes it as if it was in the expected format, or when the user is given the ability to submit information (often in hidden form fields) that can be recalculated.
For example, a shopping site might select the item ID and price from a database, and place them as hidden variables in a 'buy it now' form. A malicious or curious user might take advantage of this to adjust the price variable and buy the item very cheaply. The site should only place the item ID in the form (while obviously continuing to display the price), and recalculate the price from the item ID when the form is submitted.
Alternatively, a bookings site might allow users to book 1 to 4 tickets, and use a set of radio buttons to allow them to select which they prefer. A user might modify the form in their web browser (by various methods) to instead submit a request for 6 tickets, which the form must deal with.
Generally, this class of bugs is entirely your responsibility to avoid. However, as Kaya is a strongly-typed language, you may be able to avoid some of these bugs by converting the String that you receive from a user into a more meaningful type (for example, converting numeric values to Ints and Floats) before processing it. Proper use of Kaya's state management can also help, as variables contained within that application state cannot be modified by the user provided the application secret key remains secret.
Man-in-the-middle attacks
These attacks occur when an attacker is able to intercept communication between the application and either a user or a web service that you are communicating with, and either alter the communication, or save them to conduct a replay attack later.
The proper use of the HTTPS protocol will virtually eliminate this possibility. In addition to using HTTPS on your own web server, you should use HTTPS when connecting to other web servers, and use the certfiles parameter to functions in the HTTP module to specify the certification authority used by the other server.