Writing Secure HTML Applications
HTML Insecurities and Prevention – Part 3
Foreword: In this part of the series, I talk about HTML vulnerabilities and prevention in general.
By: Chrysanthus Date Published: 1 Jan 2001
Introduction
Not Validating User Input
Form inputs should be validated at the server, (by a script like Perl). In the absence of validation, a user can send wrong (or trick) data to the site.
Validation can also be done at the client browser. However, validation at the client is not reliable because the hostile user can still redesign the form (page) without the validation and use to send his wrong data.
I suggest you (author- programmer) do both client and server validation - client, for assurance to the innocent user, and server, for better security.
Two Types of Validation
Validation (filter) can be whitelist-based, allowing known-safe constructs and disallowing all other inputs; or Blacklist-based, disallowing known-bad inputs and allow everything else. Blacklist-based are not secure, as not everything that is bad is yet known (for example, because it might be invented in the future).
Cross-Site Request Forgery (CSRF)
It is possible to send Form of one origin to a different origin. To make sure the Form is of same origin, verify the origin at the server. You can do this using the Perl language script.
It is not only Form data that has to be validated. Data (values) in query string of URLs also have to be validated. Consider the following HTML code segment:
<ul>
<li><a href="http://example.com/message.cgi?say=Hello">Say Hello</a>
</ul>
Assume that the script, message.cgi, just takes the value, “Hello” and displays as text in another web page (of its site). URLs to navigate a site can be of cross origins. In this case, a hostile user can send a script as query string value, to the site as follows:
http://example.com/message.cgi?say=%3Cscript%3Ealert%28%27Oh%20no%21%27%29%3C/script%3E
This URL is actually equivalent to,
http://example.com/message.cgi?say=<script>alert('Oh no!')</script>
where the script as value to the name, say, is
<script>
alert('Oh no!')
</script>
%3C means <; %E means >, %28 means ', etc.
A script can do anything at the site, such as corrupting site information, stealing information or making false purchases. To prevent this, validate the values of the query string of URLs.
There are many constructs that can be used to try to trick a site into executing code. Here are some that authors are encouraged to consider and do validation:
- http and https are not the only schemes for URLs. When allowing URLs to be provided by users (e.g. for links in a social network), the scheme of each URL also needs to be explicitly whitelisted, as there are many schemes that can be abused. The most prominent example is "javascript:".
- Allowing a base element to be inserted means any script elements in the page with relative links can be hijacked, and similarly that any form submissions can get redirected to a hostile site.
Clickjacking
This is the quotation from the specification:
“A page that provides users with an interface to perform actions that the user might not wish to perform needs to be designed so as to avoid the possibility that users can be tricked into activating the interface.
One way that a user could be so tricked is if a hostile site places the victim site in a small iframe and then convinces the user to click, for instance by having the user play a reaction game. Once the user is playing the game, the hostile site can quickly position the iframe under the mouse cursor just as the user is about to click, thus tricking the user into clicking the victim site's interface.
To avoid this, sites that do not expect to be used in frames are encouraged to only enable their interface if they detect that they are not in a frame (e.g. by comparing the window object to the value of the top attribute).”
It is possible to write software that would submit a form. To prevent such software from submitting data to your site, use random features based on time, such as CAPTCHA images or addition of numbers.
SQL injection
This is to do with the API that sends SQL statements to a database.
Never build up a string of SQL that includes user data, either by concatenation:
$sql = "SELECT * FROM users WHERE username = '" . $username . "';";
or interpolation, which is essentially the same:
$sql = "SELECT * FROM users WHERE username = '$username';";
If '$username' has come from an untrusted source (and you must assume it has, since you cannot easily see that in source code), it could contain characters such as ' that will allow an attacker to execute very different queries than the one intended, including deleting your entire database, etc.
To prevent this, use prepared statements and bound parameters. If you are using the PurePerl MySQL API, then use statements as follows:
#Prepare a statement; e.g.
my $ins = "INSERT INTO pet (name, owner, species, sex, birth, death) VALUES (?,?,'cat','f','2009-03-30',NULL)";
Mysql::prepare($ins)
Mysql::stmt_reset()
#Can be used to reset the prepared statement.
Mysql::execute($values)
#to execute a statement; e.g.
Mysql::execute("'Catty','Mary'")
Mysql::send_long_value("the long value")
#If there is only one ? and the value is long, use this function, instead of execute($values).
Mysql::stmt_close()
#This closes the prepared statement and frees resources at the server.
That is it for this part of the series.
Chrys
Related Links
Basics of HTML 5Basics of ECMAScript
HTML DOM Basics
CSS Basics
Text Elements in HTML
Grouping Content
Microsyntax Dates and Times in HTML
Sectioning Content
Common Idioms without Dedicated Elements
HTML Embedded Content
HTML Insecurities and Prevention
Presentation Mathematical Markup Language
More Related Links
PurePerl MySQL API
Major in Website Design
Perl Course - Optimized
Web Development Course
BACK