As you develop on the Twitter platform, we want to remind you of the real and present danger of hackers, who aim to spread spam, install malware and generally promote mayhem across the web. To that end, this page is to inform you of many threats that exists, and good practices you can use to help keep your application as safe as possible.
If there’s anything you believe should be added to this page, please let us know. If you’ve discovered a security issue that directly affects Twitter, please contact Twitter Security. If your security issue is legitimate, we have a bug bounty program for Vulnerabilities.
The following threats are applicable no matter what your platform. Please keep them in mind as you build into the Twitter platform, and elsewhere across the internet.
In short, do not retain passwords. Instead, opt to use OAuth tokens where possible. Encrypt other sensitive data as needed.
Don’t assume that your users will provide you with valid, trustworthy data. Sanitize all data, checking for sane string lengths, valid file types, etc. Twitter attempts to sanitize data POSTed to our APIs, but a little client-side help goes a long way. Whitelist the types of input that are acceptable to your application and discard everything that isn’t on the whitelist.
Unencrypted Communication (no SSL)
Twitter provides all REST API methods over SSL. Whenever your code might be operating on an untrusted network (that is, if you’re developing a client application), please make use of SSL for all authenticated or sensitive requests. For example, posting a status, requesting recent direct messages, and updating profile attributes should all be performed over SSL in a Twitter client. It’s safe and suggested to use SSL in conjunction with OAuth. Service-to-service communication should also be encrypted wherever possible. Modern hardware eliminates most performance impact for encrypted traffic.
Tokens and Secrets
Twitter APIs rely on OAuth for authorizing each call. When working with an access token and token secret, be sure to encrypt them (and other sensitive data) as safely as possible. At Twitter, we use bcrypt-ruby as needed.
Exposed Debugging Information
Be sure that you’re not exposing sensitive information through debugging screens/logs. Some web frameworks make it easy to access debugging information if your application is not properly configured. For desktop and mobile developers, it’s easy to accidentally ship a build with debugging flags or symbols enabled. Build checks for these configurations into your deployment/build process.
Ensure that your tests (you do have tests, right?) check not just that you can do what should be able to do, but that bad guys can’t do what they shouldn’t be able to do. Put yourself in an attacker’s mindset and whip up some evil tests.
Not Letting People Help
Have you set up firstname.lastname@example.org? Do those emails go right to your phone? Make it easy for people to contact you about potential security issues with your application. If someone does report a security flaw to you, be nice to them; they’ve just done you a huge favor. Thank them for their time and fix the issue promptly. It’s fairly common for security researchers to write about vulnerabilities they’ve discovered once the hole has been closed, so don’t be upset if your application ends up in a blog post or research paper. Security is hard, and nobody is perfect. As long as you’re fixing the issues that are reported to you, you’re doing right.
Consider hiring security professionals to do an audit and/or penetration test. You can’t depend solely on the kindness of strangers; for every vulnerability that someone was nice enough to report to you, there’s ten more that malicious hackers have found. A good security firm will dig deep to uncover issues. Look for firms and individual consultants that do more than run a few automated tools.
If your application is (going to be) handling money, you may be required by law to adhere to certain security practices and regulations. Find out what’s applicable to you and make sure you’re up to code.
Web Application Security
Unfiltered Input, Unescaped Output
One easy-to-remember approach to input validation is FIEO: Filter Input, Escape Output. Filter anything from outside your application, including Twitter API data, cookie data, user-supplied form input, URL parameters, data from databases, etc. Escape all output being sent by your application, including SQL sent to your database server, HTML to you send to users’ browsers, JSON/XML output sent to other systems, and commands sent to shell programs.
Cross-Site Scripting (XSS)
Generally: if HTML isn’t needed from some user-facing form, filter it out; for example, there’s no reason to allow anything other than integers when storing a phone number. If HTML is needed, use a known-good whitelist filter. HTMLPurifier for PHP is one such solution. Different contexts may require different filtering approaches. See the OWASP XSS Prevention Cheat Sheet for more on filtering.
If your application makes use of a database, you need to be aware of SQL injection. Again, anywhere you accept input is a potential target for an attacker to break out of their input field and into your database. Use database libraries that protect against SQL injection in a systematic way. If you break out of that approach and write custom SQL, write aggressive tests to be sure you aren’t exposing yourself to this form of attack.
The two main approaches to defending against SQL injection are escaping before constructing your SQL statement and using parameterized input to create statements. The latter is recommended, as it’s less prone to programmer error.
Cross-Site Request Forgery (CSRF)
Are you sure that requests to your application are coming from your application? CSRF attacks exploit this lack of knowledge by forcing logged-in users of your site to silently open URLs that perform actions. In the case of a Twitter app, this could mean that attackers are using your app to force users to post unwanted tweets or follow spam accounts. You can learn more about this sort of attack on PHP security expert Chris Shiflett’s blog.
The most thorough way to deal with CSRF is to include a random token in every form that’s stored someplace trusted; if a form doesn’t have the right token, throw an error. Modern web frameworks have systematic ways of handling this, and might even be doing it by default if you’re lucky. A simple preventative step (but by no means the only step you should take) is to make any actions that create, modify, or destroy data require a POST request.
Lack of Rate Limiting
CAPTCHAs where appropriate to slow down potential spammers and attackers.
Lack of Information about Threats
If you think there’s an issue with your web application, how do you find out for sure? Have critical exceptions and errors emailed to you and keep good logs. You may want to put together a dashboard of critical statistics so that you can see at a glance if something is going wrong (or staying right).
Desktop Application Security
We could use suggestions from desktop developers about the security issues they’ve run into. Developers working in sufficiently high-level languages shouldn’t be dealing with buffer overflows and the usual security issues. What have you defended against?
Unencrypted Storage of Credentials
As aforementioned, for optimal security you should be using OAuth. But once you have a token with which to make requests on behalf of a user, where do you put it? Ideally, in an encrypted store managed by your operating system. On Mac OS X, this would be the Keychain. In the GNOME desktop environment, there’s the Keyring. In the KDE desktop environment, there’s KWallet.
The below links are great ways to learn more about security. Security is a deep topic, but don’t feel like you have to learn everything about it before taking proactive steps to lock down your application. A little security-mindedness goes a long way.