Archive for October, 2008

22
Oct

Preventing SQL Injection in Cold Fusion

   Posted by: Joshbw    in Browser/Web Security

Well, the ASPROX worm has morphed to go after any page it finds ending with .cfm, which makes a good deal of sense. Much like .asp sites, a cold fusion site probably hasn’t been worked on in several years, was probably developed prior to SQL Injection being much of a worry, and is likely using SQL Server behind the scenes. The other day I stumbled across a website that was having problems connecting to their database, and as a result spit out a lovely exception trace to the screen, including the exact syntax of their SQL Query, which was not using prepared statements. Wanting to be the good little security monkey, I did some quick research into protecting against SQL Injection with cold fusion and sent the info on to them, as well as suggesting they don’t spill their debug info out onto the interwebs for everyone to see.

Adobe has a pretty good page on protecting against SQL Injection, which makes it a little embarrassing that one of their own sites fell victim, but that will hopefully serve as a warning to us all to worry about legacy apps. Anyway, you can enforce parameter typing withing your existing cfquery pretty easily by wrapping each parameter in a cfqueryparam . For example, the following query:

<cfquery name=”Recordset1″ datasource=”mydatasource”>
SELECT *
FROM myTable
WHERE myTableID =#URL.my_Table_ID#</cfquery>

would be turned into

<cfquery name=”Recordset1″ datasource=”mydatasource”>
SELECT *
FROM myTable
WHERE myTableID =<cfqueryparam value=”#URL.my_Table_ID#” cfsqltype=”cf_sql_numeric”></cfquery>

The cf_sql_numeric value ensures that the value passed will be considered as a number, rather than a string or function. This particular value should be of interest for everyone protecting against ASPROX since rather than targeting strings, it targets parts of your query that you assume are numbers. You can find a list of all potential cfsqltype values here. Also listed are other attributes that can be valuable doing rudimentary validation when using cfqueryparam, such as maxLength (it does what you think) and scale (number of decimal places in a number). If you know of any old cold fusion sites out there, let the devs know that they should probably go back and make sure they are using cfqueryparam with all of their SQL parameters. With how effective ASPROX is at finding and exploiting sites, chances are they will be victim if they do not.

~ Joshbw

In my last post, on threat modeling, I had mentioned that there would be a follow up post would talk about the issues to authenticating the communication from the server. My cohort and fellow Josh has been working with me on some side projects with local small and mid-size business to secure their applications (things like auto dealership websites that collect information for credit checks) to offset all that money our investment accounts have taken in the past 18 months with some extra income. In that process we have noticed several issues that keep coming up that make it harder to be confident we are talking to the application we think we are talking to.

In this day and age phishing is so easy because it is hard to authenticate the server to the client. There isn’t end to end trust. Ultimately the user only has a handful of verification methods- does the website visually look like the website they want to connect to, does the URL look like the correct domain, and is the communication over a secure channel, none of which is going to be obvious to non-technical users. The visual appearance is incredibly easy to spoof, to the point where only the most lazy phisher won’t put forth the effort. Short of sternography, the visual appearance can’t be trusted, and sternography isn’t a viable option. So, here are a couple of things you can do outside of the visual appearance.

- Don’t use multiple domain names. You can register multiple domains, but always have them redirect to one domain, and never advertise anything but that one domain. This prevents dilution of the domain name, and trains the user to only trust one domain. Don’t use BobsFordMazdaLincoln.com and BobsMazdaLincolnFord.com, because a phisher can set up bobsLincolnMazdaFord.com or similar name. This is obviously a contrived example, but plenty of companies have a variety of domains for different purposes (Microsoft is really bad about this, and with their live ID being an SSO for all of their domains it is easy for me to phish that credential to great payoff).

It is better to use sub-domains if you have separate sites associated with one company. It is also better to try and have a simple and short domain name, without too many words in it. bobscars.com is way better than BobsMazdaLincolnFord.com because it is much harder to create a variant that fools the users. Bob could then have ford.bobscars.com, mazda.bobscars.com, etc (and this scales if bob ever opens other dealerships). Also, users are more likely to remember your domain name and it will have fewer common mistype permutations (which you should buy, domains are cheap) if it is simple (something for which I am probably guilty with analyticalengine.net, a url that even I mistype occasionally).

- Don’t go crazy with sub domains. You should probably only go one (or very rarely two) deep. mazda.bobscars.com is pretty simple to visually parse as being part of bobscars.com, but year2009.newcars.mazda.fordcorp.bobscars.com is going to be very easy to visually spoof to end users. We need to train customers to look at the domain name, and in order to do that it needs to be as apparent as possible. IE 8 does a good job calling this out, and there is a similar firefox plugin to highlight the domain name, but with many people still using IE 6 we need to focus on getting them to visually parse and recognize the domain (it would also be nice to get them to upgrade to a new browser). If we go overboard with subdomains we make the domain non-obvious and thus make it easy to spoof.

- Use SSL liberally, and use EV certs. The use of EV certs provides visual evidence in the location bar of the browser that this really is the corporation I intend to communicate with. It is one more protection that allows the user to visual identify the site. It offers more than that though, as it can attest to the integrity of the communication back and forth between the site. Afore mentioned cohort Josh has a post on his blog about using Ettercap to intercept communication and alter it in flight. The specific scenario he targeted was javascript based logins, where the page is served over http to improve performance but the login field uses javascript to submit over https; using ettercap he can show how he can modify the javascript while the page is being delivered so that it submits credentials elsewhere.

He recommends that to maintain performance you specifically force users to go to a separate page that is served start to finish over SSL. The problem is that 1) you don’t get the EV Cert based visual confirmation on the landing page if you do this and 2) if your landing page is sent in the clear you can use Ettercap to modify the url to the login page so the user goes offsite to submit credentials. Once a user is logged in you need to either have a ridiculously short session limit or make sure you continue to communicate over SSL, otherwise the sessionid will be sent in the clear which is almost as valuable as the user credentials.

I think it is much better to ALWAYS use SSL with EV certs, forced on every page. That way you get the visual validation of the cert on the landing page, the customer sees the little lock through the whole communication, and the entire conversation is resistant (not immune, but resistant) to tampering. This will impact performance (though I think it might have the advantageous effect of forcing cleaner website design) on dial up (I doubt it is human noticable on broadband) but if you want to provide some level of certainty to the user it is the way to go. Obviously, this should be weighed based on the risk of the site; paypal and banks should obviously do this, engadget probably can do without. As a final piece of advice, make sure that you set the cookie flag so that session information is only sent over secure channels.

These aren’t bullet proof assurances. It is all based on visually notifying the user that this is the site the really mean to be on. It is very reliant on training user behavior, a generally unreliable approach, and then on the user consistently being wary, which is even more unreliable. However, at this point we don’t have much else we can really do. Sandbags may not be an ideal replace for building on high ground, but it beats letting the water in. End to end trust is an unsolved problem but we do what we can.

~ Joshbw

14
Oct

Threat Modeling, quick recommendations

   Posted by: Joshbw    in Secure Development

A paper by Adam Shostack is circulating the blogosphere, and it is worth a read. I’d already left MS before Adam took over as the gatekeeper of threat modeling for SWI but it is nice to see that he basically agrees with the stripped down version that we regularly did in WinCE and that I still evangilize. Mainly-

1) Draw a data flow diagram (DFD) of how data moves around for your application/feature (depending on scope of the model), and where trust boundries are crossed

2) Enumerate threats. The paper has a nice little matrix of what threats are pertinent to what elements of the DFD and while he applies the necessary conditionals about it being specific to MS and perhaps not being universally applicable, I think it is a pretty good reference in general.

3) Determine Mitigations (or decide to let a threat slide)

4) Validate mitigations that are put in place

We lived by those simple steps, rather than getting into the horrid threat trees and DREAD risk modeling and all of that other overhead. I say this having been the security guy for my area in MS, supposedly the expert, and I ignored them. I can’t imagine the average non-security guy going to that trouble. Granted, being a security guy I probably find it a bit easier to subjectively (wait, am I supposed to say qualititavely now that I am a CISSP?) determine risk from a threat than put a number on it, which is what the overhead in threat modeling was supposed to do, but I think most non-experts can still make an educated guess.

Anyway, the reason I am bringing all of this up is to illuminate one aspect that isn’t touched on much in most threat modeling discussion- Don’t just focus on your process/components. When people create a data flow diagram and start thinking about threats and mitigations they tend to focus on threats specific to their own code and how to mitigate stuff entering that code. However if we look at a vulnerability like XSS, it isn’t a threat to your own code, it is a threat to external entities (in this case, client browsers), and the best mitigation is to sanitize (HTML encode) data as it leaves your application rather than validate it as it enters (now you still need to validate it as it enters to make sure it isn’t malicious to your code, but don’t worry about flat out stopping xss with input validation if you can output encode).

Similarly, in the above web app example, a threat model would have us worry about how to authenticate the client for repudiation and information disclosure purposes, but I haven’t been to many threat modeling sessions where the team originaly considered the data flow the other direction (establishing to the client that this is the server you can trust- more on that in a post in the near future).

So as you are developing your threat model be sure to consider threats to each of the entities in the DFD. Don’t focus only on the flow into your components, and don’t consider threats to just your components, but rather look at the full ecology represented in your DFD.

~ Joshbw

Well, you announce that you are going to post a whole bunch of information, including technical details, in a whitepaper through I Hack Charities so that a whole slew of AppSec folks and web hackers go register. Then you notice that the registration is page is in the clear.

Now granted, the whole payment solution is through paypal, so other than your credentials there isn’t much to steal, but seriously Johnny, couldn’t you get Verisign to donate SSL certs for charity?

~ Joshbw

The HTML 5 spec lays out the details for cross domain XHR. I’ve written about my dislike of the idea before (details of the access control spec can be found here; I like how they justify sending cookies via XHR because you send them with img requests. In other news, if you don’t need seatbelts on a motorcycle you don’t need them in a car because obviously they are exactly the same scenarios), specifically why passing cookies is a VERY BAD IDEA.

Today I am going to focus on the other side of things, not from the user’s perspective, but from the perspective of the third party host (3PH) that is now getting requests from the client. To allow a 3PH to make discriminating decisions the source origin of the request (not the client, but the originator host of the call, though because of POORLY WRITTEN AND LAID OUT SPECS I am unable to tell if a page loaded from somesite.com that loads a script from someothersite.com that makes the actual call would consider the source origin somesite or someothersite) is passed in the origin field of the request. This origin is based off of what the browser thinks is the origin, rather than the actual origin. Thus any tricks that would fool a browser into loading a malicious site under a safe url would also fool the 3PH. ARP spoofing (for various reasons I have been exposed to techniques to do this with Ettercap recently, and it makes this very easy), DNS poisoning, and other similar techniques could be employed quite effectively for even bigger payout (not only do you fool the user into disclosing credentials or other sensitive information for website A, you also get all sorts of sensitive information from 3PH via cross domain XHR).

To some extent they could mitigate this. The origin field could also contain the DNS and ARP information the client *thinks* belongs to the origin, and this could be independently verified by the 3PH. Granted, the spec doesn’t call for this, but it *could* be made safer. From the perspective of the 3PH though, even if you can verify that the origin really is the website you expect, there is NO assurance of the integrity of the website. How many sites have XSS or SQL injection? Are you confident that the origin does not? Security is only as strong as the weakest link, and by exposing your customer’s data to the origin through cross domain XHR, that weakest link may be the origin rather than your.

Any data exposed through cross domain XHR should be considered public as soon as it is exposed, regardless of the origin field, since you can’t really verify who really is reading it. Because of that, does it really matter what the origin field says? I think the best bet for cross domain XHR is to explicitly let each user opt in to making certain information available to the world through scripting, with no assurance that only “trusted parties” would be able to script against it (since you can’t make that assurance in good conscience). All data exposed this way may be user specific in nature, but should be of trivial value since it will be effectively unprotected. 3PH should also recognize that this is the easy way of exposing data, but by no means the safe or right way. This whole proposal was introduced by scripters that wanted one more snazzy feature regardless of security implication, because having a federated webservice strategy smacks of effort.

Oh, one last thing to consider 3PH, you need to kill that timeout you put on your session to get all of this to work, which is considered BAD PRACTICE. You open yourself up to all sorts of concerns if your sessions don’t time out, and just because Google follows that bad practice doesn’t mean you should. It is good to make users log in periodically.

~ Joshbw