The Medium Bagel

June 18, 2007

Vermont Dept of Taxes Releases Open Source Tax Software

Just a little note to let you all know that the Vermont Department of Taxes has released an application called the ‘gateway‘ as Free / Open Source Software under the Mozilla Public License v1.1. The gateway provides a web services framework for accepting Streamlined Sales Tax registrations and returns. It also includes a web interface for manually submitting transmissions and managing users.

The Source Forge project page is here, the project website is here, and a press release is available here.

April 11, 2007

être et durer

I’ve been watching parkour videos on YouTube for over an hour and I still can’t figure out what they’re running from.

April 9, 2007

showcase.ca, why have you forsaken me?

Showcase is a Canadian television network with wonderful programming like Kenny vs Spenny, Webdreams, and Trailer Park Boys. Trailer Park Boys is my favorite Canadian television show. I own all the DVDs… the first five seasons, the movie, and both releases of the Christmas special (the “original” and the “dope and liqueur” edition). I even own the conky finger puppet and movie soundtrack. Needless to say, I am a huge fan of the show.

While I was visiting Bridget in Canada this past weekend, I heard that the first episode of season 7 was available for viewing on the showcase website. I was really excited since I don’t get Trailer Park Boys at home in the USA. Since I don’t get to spend much time with Bridget, I decided that I’d spend more time with her and wait until I got home to watch the video. When I visited the showcase website after arriving home, I selected the video and got this shit…

Showcase.ca: Access Denied to US Visitors

Guh!

April 4, 2007

secure php programming series — final thoughts

Periodically Audit Your Code

Before you make a release (and periodically during development) you need to audit your code. What do I mean by audit? I mean go through it all line by line looking for potential problems. Study every line and use everything you’ve read in this series to spot potential problems. Then, start the process again and trace the execution from each input source to each output source. A second set of eyes is useful too. It is much harder to spot problems in your own code.

April 4, 2007

secure php programming series — part 6 — validation and filtering

Input Validation

Browsers are just regular software applications that can be written by anyone. They are all different and you cannot depend on their expected behavior. Your web server is exposed and any attacker can send you any input (form data, headers, etc) he or she wishes. Therefore, you must validate the input given to you. Javascript input validation and filtering is useless because it can easily be bypassed. You must do input validation in php.

When validating input, don’t try to think of every possible bad input you are trying to protect against. This methodology is dangerous because you could be missing something or a new evil input could come up in the future. The best methodology is to define what you want and if the input isn’t exactly what you want, reject it.

Database Output Validation

A database is another untrusted data source. Just because you pulled something out of the database does not mean that it is safe to use for subsequent queries. When you pull data from a database it could contain unescaped characters and/or malicious SQL that you might use in a future SQL statement. Always do some sort of validation on the data and remember to escape it if you use it in another SQL statement.

Configuration Validation

Don’t assume that the user has the program configured properly. A user can change the configuration options to whatever he pleases. Since we have no control over that, we have to check for sane settings before we use them. For example, in a search engine the number of search results on the default search results page is usually controlled by a configuration option. After fetching the setting, the search engine should check that it is indeed a number and that the value is greater than 0 and not more than a reasonably large number (say 1000).

Register Globals

The register_globals option for php is dangerous because it allows an attacker to set global variables. For example, ./index.php?authorized=1 would set the global variable $authorized to 1. In the event that you made a mistake and didn’t properly initialize $authorized, the attacked could gain unauthorized privileges. Since there isn’t a good reason to use register globals, it should always be turned off. You can check for it in your code with ini_get(’register_globals’) and refuse to run if it is turned on.

Output Filtering

Whenever you are outputting data that you’ve gotten from a user (from a database, form input, or whatever), you need to escape it with htmlspecialchars. Otherwise a user could submit javascript and have it executed by the client viewing the output. When writing an application that outputs potentially unsafe data in XML, you need to call htmlspecialchars twice. Once to encode it for XML and another time to encode it for the client viewing it.

Limit Disclosure

Users may try browsing to php files that they aren’t intended to browse. When they do this, the file gets executed. Any code not in a function or class will be run. To get around this potential pitfall in an application I wrote, I put each page in an includes directory. For each page I put everything besides the license notice inside a function called “show()”. This function has many purposes. For one, it hides things from the users. When they browse to that page they get a blank page. It also ensures that 1 and only 1 page gets sent to the user. Because index.php calls show(), including more than 1 page will be an error (redefining show()). It also enforces the use of show() because not having a show function will cause an error (undefined function show()).

April 4, 2007

secure php programming series — part 5 — sessions

Session Cookies

Say you log into an online banking service called FooBank and they store your session ID in a cookie on your computer. While your browser is open you can visit another site, come back to FooBank, and still be logged in. It does this by getting the valid session ID from the cookie. If you visit a malicious site, it can use javascript to submit HTML forms to FooBank.com. Since your browser is authenticated with FooBank.com via the session cookie, FooBank will gladly accept any forms submitted from your browser. Suddenly you might find that your account has less money than you expected.

Browser security is getting better and this type of attack may be blocked by some browsers, but people using older browsers or less secure browsers are vulnerable. To protect against this, you shouldn’t use cookies to store session information. Use session IDs passed in the URL (example: index.php?sid=90ascj90ascj90). This too is a security risk because anyone who can get the session ID from the URL string could hijack the session. You can mitigate this risk by restricting a session ID to a single IP address, expiring stale sessions (15 minute timeout), and encouraging users to use https so that the “man in the middle” cannot steal your session ID.

Don’t accept form submissions from other Websites

In general, you should reject form submissions when the $_SERVER[’SERVER_NAME’] differs from the hostname in $_SERVER[’HTTP_REFERER’]. In most cases you don’t want other websites submitting data to your web application. This won’t protect against attackers who use fake referer information, but it might help to protect us against some XSS attacks.

April 4, 2007

secure php programming series — part 4 — version control

Be careful with CVS/Subversion/Git/…

A site called CIA displays commit messages and offers RSS feeds. Some projects also have a little bot which sends messages to an IRC channel. Attackers sometimes watch these channels for commit messages with specific words and/or phrases. For example, an attacker might watch for a message containing the phrase ‘buffer overflow’. If you just committed a fix for a buffer overflow that hasn’t been made public yet, you could alert an attacker who can now easily find where the security problem is. The best thing to do in this situation is to do the commit right before you make a release which contains a fix or just omit the commit message.

Another thing to look out for with version control systems is committing private information. For example, say a developer is testing some database code. He will likely have a config file with database connection information (username, password, hostname, etc). He must be careful not to inadvertently commit it because completely removing it is a pain in the butt. The best thing to do in this case is to use a config file that lives outside of the repository or use safe, non-specific, defaults (”dbuser”,”dbpass”,”localhost”, etc).

April 4, 2007

secure php programming series — part 3 — good programming habbits

Write code that is easy to read and Understand

In the open source world, many more people will be reading your code than if you kept it to yourself. People may be adding on their own features or sending you patches. This can sometimes cause very subtle security bugs to creep in. These bugs are sometimes due to a developer having certain expectations about certain parts of the code. If you write easy to read code, it reduces these types of bugs because the expectations are clear.

So how do you write easy to read code? Start by keeping a consistent coding style throughout your code. Don’t try to be “smart”. Usually the most straightforward way will be the easiest for other developers to read and understand. If you must do use some sort of trick or hack, comment it well. In the comments, you should also state any assumptions you make about the input or environment. All regular expressions and validations should be explained. Lastly, choose good names for classes, functions, and variables.

Understand what a function does before using it

Knowing exactly what a function does and how to use it effectively is key not only to security, but to writing good code in general. Far too often I’ve seen people misuse functions in important areas. One example I want to highlight is that of the header() function. It can be used to send the browser information. Using header(”Location: http://fsf.org“) you could redirect the user to the Free Software Foundation. However, one thing some people don’t realize is that sending the location header doesn’t force the browser to redirect (its just a hint telling the browser where we’d like the user to go) and execution of the php code continues after the header() function.

Use risky functions only when necessary and with Constants

There are a lot of sexy functions like eval(), ini_set(), exec(), passthru(), shell_exec(), system(), and a bunch of file related functions. These allow you to do a lot of cool stuff, but they are also the most likely to do harm if an attacker can manipulate their input. Its like a double edged sword. One edge is a cool dynamic website and the other edge is a crazed cracker. Only use these functions when you have to and do your best to call them with constant input. If you have to use one of these functions with a variable or user submitted data, be very careful. Only call these functions with input that has been verified.

Do not use files on the Filesystem

Storing any information in files is a bad idea. Properly dealing with concurrency (locking) and permissions is not a trivial task. Additionally, finding a place to store the file is hard since it must be read/write by the web server and not remotely accessible. The file must also not be accessible to any system users on the server itself or any other web applications because the attacker could steal information from the file or inject his own data. A much better solution is to use a database. Databases already handle permissions and concurrency well without you having to do a lot of extra coding.

Force Installation File Removal

If your program has an install script, then you need to add checks to make sure that it cannot be run again by an attacker to cause data loss or change configurations. The easiest way to do this is to add a check to make sure the user removes the install scripts after installing your application. It might also be a good idea (and good programming practice) to code checks into the installer to ensure that the user doesn’t blow away an existing installation.

April 4, 2007

secure php programming series — part 2 — 3rd party code

Avoid using 3rd party code unless it is from a reputable source and carefully Reviewed

This part is about a personal experience I had with SourceForge in December 2006, but I’m sure that this could have happened at just about any place where one could obtain re-usable php code. You see, SourceForge allows anyone to create any project they wish. These people could be professional web application developers, grandmothers, children, etc. SourceForge also keeps projects around long after development interest is gone. Projects aren’t removed even when they have long standing security issues. Users can easily search and download code. This is a recipe for disaster.

One night I setup a little challenge for myself. Find a security hole in a PHP application that could be remotely exploited to gain full admin privileges. SourceForge made that easy. I just did a search and picked a PHP powered blog that hadn’t been updated in over 2 years and which had a short development lifetime (I think the last release date and project creation date were less than a month apart). I was able to find the software, download it, and find a remotely exploitable hole in under 1/2 an hour. I checked the download stats for the project and they were averaging over 10 downloads a week. New people were getting, and presumably using, the flawed code everyday.

What does this mean other than I’m an Uber 1337 h4×0r? It shows that you shouldn’t download and use code from other projects unless you really know what you’re doing because there is a lot of poorly written insecure php code available on the wild wild web. If you don’t have time to really look through the code or the knowledge to spot security problems, stay away from 3rd party code.

April 4, 2007

secure php programming series — part 1 — passwords

Do not store passwords in Plain Text

This isn’t always obvious to novice programmers or users, but it should be. Anyone who can view the database can view the passwords as one would type them in. It gets worse because many people re-use passwords. So one compromised password could give an attacker access to not only your application but potentially many others.

What is not very obvious is how to do authentication without a plain text password. You need a method that will make the password unreadable to the attacker if he looks in the database, but you need to be able to check if the user entered the correct password. The solution is to use a one way hash function (like sha1) on the password before storing it in the database. For example, the password ‘demo’ would be come ‘89e495e7941cf9e40e6980d14a16bf023ccd4c91′. Assuming the one way hash function is indeed one way, the attacker could not reverse the hash to get ‘demo’. It is best if you call the hash function in php rather than calling the hash function in MySQL (or some other database). That way the password won’t be sent “over the wire” to a remote MySQL server. Then, when the user wishes to authenticate, just hash her password and compare the value with what you have in the database.

Salt your Passwords

Salting a password refers to changing the password before it is hashed. This can be accomplished by appending and/or prepending a string to the original password. The string should be unique and randomly generated for each user.

This helps us in the event that an attacker or user gets a copy of our database. Without salting, if two users have the same password, their hashes will be the same. If a user found out that his hashed password matched another user’s hashed password, he could use the other user’s account. That sounded confusing, let’s use an example. The hash of Alice’s password is: “c3218af382ebc0a”. Bob’s password also hashes to “c3218af382ebc0a”. Bob looks in the database and sees that Alice’s password hashes to “c3218af382ebc0a”, just like his. Bob tries his password with Alice’s user name and is able to log in as her.

By using salts, we also make the life of an attacker more difficult. Sometimes attackers build dictionaries. They take thousands of common passwords, compute their hashes, and store both in a table. They take the hash they stole from you and look it (and the corresponding password) up in their dictionary. If we have added a constant value before and/or after the password before we hash it, the attacker would have to build dictionaries for every account he’s trying to break into.

Check Password Strength

Most authentication systems allow users to pick their own passwords. The user is usually free to pick anything. Some users aren’t the smartest when it comes to choosing passwords. They might pick a common dictionary word, their user name, or they might even leave the password field blank. Depending on your security requirements, you may want to set some restrictions on the types of passwords users can choose. A good rule set is: 8 characters minimum, mixed case, alpha numeric, at least 2 upper case, at least 2 lower case, at least 2 numbers, no dictionary words, no sequences (123abcDE), must not contain a user name.

No default Passwords

So many web applications install themselves with default user names and passwords (like admin:admin). This requires the user to take the initiative to change the password. In the best case, it leaves a very small window when an attacker could use the default login to gain access. In the worst case (i.e. the user never changes the default password), the site is wide open for anyone to find. The best thing to do is have a user pick their own admin user name and password when the installation scripts run. Another choice is to generate a random password during installation.

Transmitting Plain Text Passwords

This is more of an end user configuration issue, however, I’m going to address it anyway. Usernames and passwords should not be transmitted in plain text. Anyone between you and the server could ’sniff’ your password and use it to impersonate you. As a developer there are several options. You can be passive and suggest always using SSL (https) in your documentation or you could be more proactive and refuse to work without SSL by checking that the requested url begins with ‘https’. Another option is to do client side encryption in javascript.

© 2007 Thomas Cort | Entries (RSS) and Comments (RSS)

Global Positioning System Gazettewordpress logo