Archive for the ‘Security’ Category

Breaking a CAPTCHA – rules for good design

Sunday, June 7th, 2009

A CAPTCHA is a challenge and response test used to verify that the end-user is a human and not a computer – CAPTCHA is an acronym standing for a Completely Automated Public Turing test to tell Computers and Humans Apart.

Captchas seem to have become increasingly popular as a method to prevent the submission of spam and automated responses. You can see a captcha generated by the popular reCAPTCHA service when you post a comment on this blog.

The main problem with the Captcha is that sometimes the people who implement them are lazy or have no knowledge about how create an image that a computer would find hard to decode. Captchas must be generated server side and over the last few months I have seen an increase in the number of client-side captchas generated by software such as Adobe Flex. If you generate a Captcha client side it is not secure.

When designing a Captcha its important to understand what computers find it hard to do.

Its hard for a computer to segment an image. Computers need to segment an image in order to classify each character of text. Anything you can do – such as running letters together – that makes the image harder to segment will make it much harder for a computer to segment your image.

Lets look at the following example to see how easy it is to segment the text from a badly designed captcha.

Image segmentation in 3 steps, (1) Capture the image, (2) Apply thresholding (3) Convolution Matrix

Image segmentation in 3 steps, (1) Acquire the image, (2) Apply thresholding (3) Apply a simple Convolution Matrix

Two very simple algorithms have been applied to the Captcha above. Firstly thresholding and secondly a convolution matrix to remove the vertical and horizontal lines. If we look at the captcha below we can see that some captchas can be segmented just by using thresholding alone.

Even worse - The background can easily be removed by just simple thresholding

Even worse - The background can easily be removed by just simple thresholding

Once the image has been segmented the computer then has to then classify each character. The more options there are for each character the higher the chance of the computer classifying the letter incorrectly – so when your designing your captcha it pays to use the entire alphabet and not restrict yourself to just numbers or letters – It follows that the longer your captcha the more chance there is of the computer making a mistake in classification. Google makes its captchas between 8 and 11 characters in length.

Both of the captchas we have seen so far are easy to segment – they are also easy to classify. This is due to the similarity of the characters within the image (both 4’s look the same in the second captcha) – if we want to make it tricky for the computer to classify each character we need to use different fonts for each character or warp each character by applying rotation or other image morphing operators. The following Captcha from Yahoo! is much harder to segment due to there being little space between each character, the captcha also uses both upper and lower case characters and has been morphed so that the string is harder to classify.

A set of captchas from Yahoo! that are very hard to segment

A set of captchas from Yahoo! that are hard to segment and classify

Sadly as captchas become harder for computers to read they also become harder for humans to read – there is a fine line between providing the necessary security and frustrating a user with a captcha that is impossible to read.

Google has an interesting solution to this using Markov Chains – here random strings that appear to be words are generated using a statistical method known as a Markov Chain. These words are much easier for a human to read because they seem to be a normal word, however they are not words and this is important. If dictionary words were use then a dictionary could be introduced to improve captcha classification rates.

Google captchas use markov chains to make them easier to read

Google captchas use Markov chains to make them easier to read

Its pretty easy to design and write a good captcha using PHP GD or something similar. If you cant be bothered to write a captcha then services such as reCAPTCHA exist which can provide you with an effective captcha solution (although this is vulnerable to the “penis flood attack“)

No captcha will ever be 100% secure, rumor has it that even google’s captcha has been broken with a classification rate of 20%; there are even stories of captcha sweatshops emerging around the world where people are paid  to solve Captchas – a kind of mechanical Turk.

As algorithms become more sophisticated an alternative to captchas need to be found but until these have been found you may as well make sure that your captchas are secure.

Creating secure web applications

Thursday, November 20th, 2008

So many companies tend to think of security as an afterthought. When it comes to developing Web Applications many companies and clients in particular seem to have their priorities wrong. In order of priority they seem to go something like this:-

  • Get it done cheap
  • Get it out quick
  • Make it look nice
  • Make it really easy to use
  • Sell it to lots of people

And somewhere way down the line after 10 more seemingly insignificant priorities

  • Security

Don’t get me wrong; I can see why people order their priorities like this – if you want to make money fast then it makes sense but if you want to make money in the long term then it would probably pay to take a good look at your system security before you dive straight into designing the application.

Developing your application security as an after thought is not only a terrible idea in terms of security it’ll also cost you a lot more. Having to go back through all of your code and retrofit the security is a seriously labor intensive task. Security testing and design should always be the top of your list of priorities – especially with a web application – and its something that should continue to be tested and revised as you develop your application.

Coming up with a good security model and sticking with it will save you a lot of time and will result in a more secure application. It might be that software companies don’t see any immediate incentive in developing good security models or it might be that the client isn’t concerned about the security risks – both reasons are simply not good enough for ignoring application security.

If your company’s application gets hacked it not only reflects badly on the client but badly on the software developer. If security is an afterthought its also going to cost you as the developer to find and patch the vulnerability.

The bottom line is that security must never be an afterthought.

Using MySQL triggers to encrypt passwords

Tuesday, November 18th, 2008

Sometimes it’s helpful to take the handling of the passwords away from PHP and let the database do all the hard work. With the help of triggers and a simple MySQL function its possible to generate a salt and a hash from a plain text string. Doing password security this way makes it harder for the PHP programmers to make a mistake and ensures that passwords encoded as plain text will never appear in the database.

Lets start by creating a table to store users email addresses, passwords and salts.

CREATE TABLE `users` (
`email` VARCHAR( 255 ) NOT NULL ,
`salt` VARCHAR( 40 ) NOT NULL ,
`password` VARCHAR( 32 ) NOT NULL ,
PRIMARY KEY ( `email` )
) ENGINE = InnoDB

Now lets create a function to generate a random string for us – this will be our salt

CREATE FUNCTION `make_salt`(len TINYINT UNSIGNED) RETURNS varchar(255) CHARSET latin1
BEGIN

DECLARE salt varchar(255);
DECLARE i TINYINT UNSIGNED;

SET i = 0;
SET salt = ”;

WHILE i < len DO
SET salt = CONCAT(salt, CHAR(FLOOR(40 + (RAND() * 210)+1)));
SET i = i + 1;
END WHILE;

RETURN salt;

END//

Finally lets insert 2 triggers, one for the insert, one for the update. This will encrypt all passwords sent to the MySQL table and also generate salts for them.

CREATE TRIGGER encrypt_password_insert BEFORE INSERT ON users
FOR EACH ROW BEGIN

SET NEW.salt = make_salt(40);
SET NEW.password = SHA1(CONCAT(NEW.salt, NEW.password, NEW.email));

END;

The update trigger will re-encrypt the password and re-generate the salt when the table is updated

CREATE TRIGGER encrypt_password_update BEFORE UPDATE ON users
FOR EACH ROW BEGIN

SET NEW.salt = make_salt(40);
SET NEW.password = SHA1(CONCAT(NEW.salt, NEW.password, NEW.email));

END;

Simple eh? You might well wonder why I’ve hashed their email along with the password, this forces the programmer to ask the user to re-specify their password when they change their email address. The salt function ensures that every time they update their password or email that the salt will also change. Lets look at the results of the following insert on the table

INSERT INTO users SET email=’john@malcom.com”, password=”hello world”;

If you now look in at the user john@malcom.com you’ll see that their password has been turned into the SHA1 hash of the salt field (which is now populated) and the password and email. It should look something like this:

82b6f04c63640a2dd5da7650d36001b4a5f10707

Now if you want to verify that the password / username you can simple do the following

SELECT * FROM users WHERE email=’john@malcom.com’ AND SHA1(CONCAT(salt, ‘hello world’, email))

If the number of returned rows is 1 then you can grant the user access.

This approach to password security is fine as long as the connection between PHP and MySQL is secure. If your connecting to a remote MySQL server over an un-secure connection then you’ll want to hash your passwords before they are sent out. Its also worth mentioning that the password may be visible on the server when viewing processes.

When SSL isnt safe

Sunday, November 16th, 2008

Users are generally told that when they see the little padlock at the bottom of a website that the data that they send is safe. All the padlock shows is that the data is secure – it is encrypted via SSL and is more or less guaranteed to arrive at the destination without being tampered with. It doesn’t directly show any of the identity information of the server that the data is being sent to. It would seem like a better idea to show who the certificate belongs to along side the padlock. Many browsers don’t and this means many users never know who the site they are using belongs to.

The browser padlock bar

The browser padlock bar

There is little or no checking when someone registers for their certificate signing request – occasionally someone will call you to verify your phone number. Attackers are now taking advantage of this by registering for SSL certificates in order to help convince users that their fake website is genuine when carrying out phishing attacks.

What can you do? Well extended validation (EV) certificates are becoming more and more popular. To obtain one of these its much more difficult – you have to physically prove your identity – the benefit of such a certificate is that you gain the little green bar next to your URL string identifying the owner of the site. This additional validation comes at a price – a normal non EV certificate costs about $30 for a year – the cheapest EV certificate costs $600 for the year, a 20 fold increase in price.

Is it worth it? Maybe – but only if you can educate users into questioning the identity of the websites that they use.

Cross Site Request Forgery attacks

Thursday, November 6th, 2008

Cross site request forgery attacks in one of their simplest forms are a hidden iframe in which an html form is hidden and who’s submit action is triggered on-load. CSRF attacks have been becoming increasingly common – they have the distinct advantage over other attacks (such as SQL injection – it is possible to combine both types of attack for devastating consequences) as they leave virtually no trace of the real attacker.

A CSRF attack works by secretly tricking your browser into posting data to another site via HTML/JavaScript. The user is often unaware of this and the the content of the post and its actions can vary. Some CSRF attacks simply abuse affiliate schemes in the hope that you will eventually visit the website you unknowingly posted to and purchase one of their products. Others can be far more malicious stealing personal information, posting entries in a blog or granting users additional access rights to your CMS.

Even if your website is password protected it could still be vulnerable to a CSRF attack. Since session data is shared amongst all windows a hidden iframe that posts data would be no exception. This would give an attacker the potential to POST to the password protected section of your website (such as a CMS or Control Panel). You might be totally unaware of this until someone mentioned a strange post that you had made. That’s right – the CSRF attack would appear to come from your account. Below is some HTML and JavaScript demonstrating how easy it is to craft a CSRF attack.

exploit.html

<iframe src=”postme.html” style=”display: none;” border=”0″ height=”0″ width=”0″></iframe>

postme.html

<form id=”send_me” name=”send_me” method=”post” action=”http://www.example.com/post_form.php”>
<input name=”title” value=”Teehee” type=”hidden”>
<input name=”content” value=”Woot” type=”hidden”>
<script>
document.send_me.submit();
</script>
</form>

In the above example the code in exploit.html would be pasted into a page, it would then post to example.com/post-form.php when you visited the page. If the website used GET instead of POST it would be possible to craft an even simpler attack

<img src=”http://www.example.com/post_form.php?title=Teehee&content=Woot>


CSRF + DDOS

If the script that you post to is vulnerable to SQL injection you could further compound the CSRF attack and create a Distributed Denial of Service attack on your given domain – every time someone visited your website with the embedded CSRF code in you could cause them to inject an additional SQL statement into an SQL query. If this was a command like BENCHMARK it could very well cripple the target server. Once again it would be very hard to trace the initial perpetrator of this type of attack.

Defending against CSRF

Tokens tend to be the most common way to defend against such attacks. Here the server sets a variable which is stored in a HTTP session. It then inserts a hidden item in the form which contains this value. When the form is posted to the server it checks the HTTP session value against the value sent by the form. If they don’t match, you reject the post.

A potential attacker would be unable to guess this token and as a result it would be very hard if not impossible to craft a CSRF attack.

As you can probably see CSRF attacks are certainly something you need to defend against – in case you don’t believe me here are some examples of CSRF in the news, the latter by David Airey makes very good reading.

http://www.webappsec.org/

http://www.davidairey.co.uk/