Facebook SDK

Saturday, January 4, 2014

Programming Security - Part 7 (Python Security, cont.)

Since the Python Security.org website isn’t being updated anymore, I will do my best to give some general tips for Python programming. While these aren't necessarily expressly for Python, they were listed on the Python Security site so I thought I would put them here.
  • When validating input, use a whitelist for approved data rather than a blacklist. It is easier to deal with a limited data set than try to block every “bad thing” that may be out there. If you know what to expect then you know how to work with it; everything else is rejected by default.
    • If you use regular expressions (regex) for validation, make sure you are matching against the entire string by using start and end anchors.
    • Consider converting input data to a different datatype for further validation. If you receive numbers as a text string, convert them to integers to validate that they are “in range” of expected values. If you get a date string, convert it to a date object to ensure the date is real.
    • If you expect to receive numbers, determine beforehand whether they should be signed or unsigned and what the min/max values should be. This can help eliminate unexpected values and prevent buffer overrun or other attacks.
  • Web authentication can be handled a number of ways, however “basic authentication” is the worst. Basic authentication is supported by nearly every web browser and is not secure, at all. The username and password are sent, in the clear, within the HTTP header during every request. These credentials are stored in the browser cache the entire time the browser is open. Thus, until the browser is actually closed or the user manually clears the cache, the authentication information is available to malicious browser attacks.
  • If you're developing a web application, be cognizant of cross-site scripting (XSS) attacks. XSS allows attackers to inject client-side scripts into a web page that will be run by the client, bypassing the access controls established on the site. The easiest way (but not the only way) to mitigate this attack is through input validation and escaping. Escaping can be handled by your template engine.
  • Escaping is essentially ensuring your output data is treated as data and not characters that can be parsed by the interpreter and executed. Escaping can be as simple as using a simple “escape” character or more complex, depending on the needs of the system.
    • Escaping is not the same as converting (“encoding”) to Unicode. Unicode will still be interpreted and decoded automatically by the browser or sever and will not prevent an attack.
    • You will often see escaped characters in HTML when you see an ampersand (“&”) converted to “&”. These conversions prevent the system from switching to “execution mode” and attempting to run the following characters as a program or script.
  • Hashing data performs a one-way encoding of data, of any size, to a fixed-length text string. Any changes to the data, whether accidental or intentional, will change the resulting hash, thus indicating that the original data is corrupt.
    • MD5 and SHA-1, while very popular, are not considered secure anymore and should not be used. If you are implementing a hashing system in your program, use one of the functions from the SHA-2 family.
    • Salting is padding your data, typically a password, with random data to make it more difficult to determine the original data through certain attack vectors, such as rainbow tables. With the advent of GPU-powered hash attacks, salting doesn't have the same effect it once had but is still considered a safe practice and should be used.
    • If you are posting publicly downloadable software, consider also posting a hash value of the final product so downloaders can verify they have the correct software and that it wasn't corrupted during transfer or tampered with.

Friday, January 3, 2014

Programming Security-Part 6 (Python Security)

I’ve talked about a lot of general programming tactics in regards to security but now I’d like to focus on Python for a bit. Python eliminates a lot of security issues inherent in C, C++, and other languages. For example, it is very difficult, if not impossible, to create a buffer overflow in Python; the language will attempt to allocate the required memory, possibly slowing down the system as space is allocated but Python will automatically resize the buffer as needed or, worst case, throw an exception.

Now, this doesn’t mean that a suitably intelligent attacker won’t find some way to hack Python code and make a system fail. It just means that Python was written in such a way that the most common issues in programming are removed from the consciousness of the programmer; in short, you don’t have to think about vulnerabilities in the underlying language (as long as you upgrade to the latest versions). Obviously, vulnerabilities are found and patched, just like any other software. Maintaining your language (2.x or 3.x) at the most recent version ensures you have the latest security patches to the core language.

However, this doesn’t mean you won’t introduce vulnerabilities into your own programs just by choosing to use Python (or Java, Ruby, or any other “new” language). Sensible coding practices will help make your application resistant to attacks. Of course, you need to keep track of bug reports and provide updates to address any vulnerabilities that are found.

The Python Security website was established to make Python the “most secure programming language in the world” (according to the site). A lot of the material currently on the site (as of this writing) is for Python libraries and modules, like web frameworks, web servers, template engines, etc. The general security topics is somewhat limited. Being a wiki, the amount of information can be limited, and as of August 2013, the site is listed as no longer being updated.

Unfortunately, this means you are pretty much on your own when it comes to finding out how to secure your Python programs. You can use many of the general programming tips I have provided on this blog or you find in books or other web sites. The main thing to consider is that, if you are using external libraries or frameworks, you need to make sure that they are patched just like every other program.

If you are disturbing software, make a mailing list for users to subscribe to so they can receive security update information as you patch your software. If you use external libraries, make sure those get updated when you distribute new patches, or at least provide notifications for users so they can get their own updates. Just remember that, generally speaking, people are lazy when it comes to updating software so the less work they have to do, the more likely they will do something. Hence, if you include all the necessary updates in one package, there is a better chance they will update everything; if they have to find, download, and install eight different things, it probably won’t happen.

Thursday, January 2, 2014

Programming Security-Part 5 (Web Development, cont.)

One thing to remember about web apps and input validation is that, if your app accepts comments or other user-supplied content, you need to ensure that your validation scheme strips any HTML or JavaScript before the content is posted to the site. While basic HTML is okay, e.g. text formatting like bold or italics, you need to be wary of links. Cross-site scripting (XSS) attacks can be used by someone posting comment section; anytime a user loads the page, that malicious code will be ran by the browser, making that user, or your site, susceptible to attacks.

While discussed in the context of web development, configuration management applies to nearly any programming task. In this case, you need to ensure your administrator interfaces are locked down, only accessible to authorized admins. Currently, the best authorization method is through certificates, such as smart cards.

Make sure remote access is limited or completely removed. If it is allowed, ensure encryption is enabled and consider using a VPN (virtual private network) due to the information and permissions available to administrators, and the possibility that a privilege escalation attack can occur during a remote session.

Anything that you would consider sensitive, such as passwords, credit card numbers, or even company secrets, should be handled accordingly. Don’t put them on an Internet-accessible server if possible. If you do need to use a sensitive item, e.g. for authentication, don’t use the raw data; store the data separately and generate a hash that will be stored locally, then use the hash for verification. That way the sensitive data won’t be directly accessible.

I remember reading an article about Intel that stated company secrets and other sensitive items could only be printed on colored paper. That way, someone could tell at a glance whether a document was needed to be handled in a special manner. Content management systems can be configured in a similar manner to minimize sensitive material leaks of electronic material.

If necessary, ensure the data is encrypted or hashed, depending on its use. (Hashes are one-way algorithms and can’t be “unhashed” while encrypted data can be decrypted). Don’t maintain sensitive material in a cache or in a persistent cookie; only access it as needed. Once in the cache, it will be in a decrypted format since it has to be available for use. If unencrypted, cookies can be viewed and modified by the end user; if encrypted, it makes it difficult to deal with the encryption key management as keys expire.

Be aware of session management issues. Use HTTPS when possible; Google, Facebook, and other companies are starting to set up HTTPS sessions by default to minimize vulnerabilities and reduce attacks on users. Be sure to protect any authentication cookies you use; if someone hijacks the authentication cookie or otherwise gains access to the session, they can impersonate a legitimate user.

Finally, consider program exceptions when errors occur. Exceptions can provide a lot of information to an attacker, such as the OS being used, the type of web server, database info, or file names. If an error occurs, ensure it is caught internally and not presented to the client; generic error messages can be presented that have a custom error ID for troubleshooting. Exception handling is also important because it can keep the program running even if an exception is thrown, if caught and handled correctly.

Programming Security-Part 4 (Web Development)

Web applications are huge nowadays. While making desktop applications is still big business, it is more likely that software will be developed to be used within a web browser. Web development comprises a number of different technologies, often requiring different skill sets to create. Back-end programmers rarely deal with the front-end HTML, database admins are responsible for their little section of the system, and so on. It is a rare individual who can do all of these things (especially do them well); while one or two people can make a SOHO application, especially if it is self-hosted, anything that is going to handle a large number of clients will have to have teams of people working on them.

Obviously, with all these people, ensuring security in the design is paramount (or it should be). If any one part of the application is insecure, the entire system if vulnerable. Each person has to ensure that they think about security when they are doing their part.

Though the site is outdated, Microsoft has a good page of web development topics. It lists 10 vulnerabilities that occur in web apps due to bad design. While I won’t go into detail about all of these, I’ll touch on some of the more significant areas.

1.       Input validation

2.       Authentication

3.       Authorization

4.       Configuration Management

5.       Sensitive Data

6.       Session Management

7.       Cryptography

8.       Parameter Manipulation

9.       Exception Management

10.   Auditing and Logging

I’ve talked about input validation before but I’ll talk on it again. Input validation is the front-line in secure programming. If the attacker can’t get through the front door, hopefully he’ll move on to an easier target. Input validation attempts to block cross-site scripting, SQL injections, buffer overflows, and other, related attacks.

If you assume that all input from an external source has a malicious intent, it will help your mindset when it comes to defensive programming. Develop a central repository of validation and filtering code that can be used by other programs; this ensures that the same code is being used throughout all projects. This makes it easy to patch or upgrade while ensuring consistency among programs.

While it’s fine to have client-side validation, such as through JavaScript, ensure you have server-side validation too. What happens if the client-side software is bypassed somehow? An example of this is news media paywalls. By simply disabling JavaScript on the browser, a user can bypass a paywall and access the content anyways. With no server-side checking, the paywall might as well be non-existent.

As part of input validation, you need to accept known good data (based on type, length, format, and range), reject known bad data, and sanitize what’s left. Sanitizing includes stripping extraneous characters (like spaces or null characters), escaping out values to create literal text, and encoding URLs or HTML to make literal text rather than executable scripts.

When working with data over a network, assume that it will be intercepted. How would you deal with this? If you are sending data such as passwords and user names unencrypted, it’s only a matter of time before they are captured and used to break into your system. Therefore, use a secure transmission channel, like SSH or TLS/SSL, instead of unsecure protocols like TFTP or Telnet.

If you have a database of valuable information, like credit card data, addresses, etc., make sure the database is encrypted with a good encryption scheme. When storing passwords, don’t store in plain text; use a strong hashing algorithm and salt the passwords first.

Again, if the programming language you’re using has built-in libraries that will do what you want, use them. Don’t make your own and don’t rely on an unknown third-party’s library, as you’ll only create new vectors for attack.

Programming Security-Part 3 (Defensive Programming)

When writing the code to a program with a view to security, taking a defensive stature, much like “defensive driving” can be helpful. In defensive driving, you assume the other drivers on the road, bicyclists, and pedestrians will do something to harm you, make you crash, or otherwise interfere with you. With defensive programming, you assume that someone will attempt to misuse your code or it will crash in some fashion, thus you do your utmost to make your code easy to use but fault-tolerant.

The main concepts of defensive programming are: reduce bugs, make code easy to understand, and make it behave predictably despite unexpected input or user actions. One example is input checking to ensure a buffer isn’t overfilled and that the input is valid. While programming for security can mean more work initially (you have to consider a large number of possible errors and account for them), it means your program is more robust and, potentially, easier to maintain.

Something to remember is that, regardless of how well you think you know your code, after you haven’t worked on the software for several months, you may forget why you did something in a particular way or even how something works, if it is a method or function that you rarely use. This often occurs with programmers that have multiple projects back-to-back or if you tried something new you found online or in a book. While Python and other languages are “self-documenting” (the code is relatively easy to understand), adding comments to clarify sections makes a huge difference later on, especially if someone else is looking at your code.

While some people pride themselves on their ability to obfuscate their code, it doesn’t make it any easier when it comes to troubleshooting, patching, or upgrading. In addition, some people think that “security through obscurity” is a reasonable approach to secure programming and that code obfuscation will help. While it can slow down many malicious people, determined programmers will figure it out. Obfuscation is not encryption and should not be considered a form of security. All it means is that it will take slightly longer for someone to break it. It also means that it will take longer to fix any bugs in the software.

One method to ensuring secure code is to reuse proven software, rather than making it yourself. C++ has the Standard Template Library, Python has modules and libraries, and other languages have established code for you to use. Use it; it has been vetted by many developers over many years and is about as bullet-proof as you can get. While it’s perfectly okay to roll-your-own as a learning technique, don’t rely on your home-brew if an official template is available.

Of course, if you find something on the web that isn’t from an official site, it’s okay to be hesitant and cautious before using it. You never know what someone has done to it or what it will truly do. This applies especially to APIs; you can only access the APIs but not the underlying code. Once you pass data to the API, who knows what will happen to it. On the other hand, not trusting other sources means you may not be able to get your program to work. Ultimately, you have to judge how cautious you want to be.