Confirmed Twitter XSS Vulnerability

Just to confirm, my picture post guessing at a potential XSS vulnerability from over 3 hours ago proved itself to be exactly that.

The vulnerability is caused by URLs not being cleaned/escaped properly. By adding JavaScript to the end of a URL, you can effectively execute whatever you like as long as it’s within 140 chars (including pretty rainbow coloured tweets). Unfortunately, this is no limiter though; by calling upon the powers of JavaScript libraries you can reference external JS files that then cause more damage. Tweeting rainbows is harmless enough, but JavaScript is pretty powerful and can be used to obtain session tokens, follow people you don’t want to be following, send DMs and tweets, etc.

The safest thing to do at this point in time is to simply avoid the twitter.com website. Non-web/non-JavaScript clients are risk free, and may enable you to delete any RTs etc that you may have inadvertently spread. You can also use the Firefox NoScript extension to block twitter.com/twimg.com which is nice and safe, but basically breaks the twitter website.

You can now give me cookies for calling this first.

SQL Injection Flaw in FanUpdate

A security issue has come to light in FanUpdate (2.2.1 specifically but likely affects previous versions). This only affects those who are still running with register_globals turned on (a very bad idea).

The problem — for those interested — lies in show-cat.php relying on an unsanitised $listingid. In an ideal world, show-cat.php should only be called by the script from another page where you define $listingid first. However, because there’s nothing stopping direct loading of the file itself, show-cat.php can be accessed (on a server with register_globals on) with a malicious SQL query in the URL.

Quick Fix

Open show-cat.php and change: if (!isset($listingid)) { exit; }

to: if (!isset($listingid) && !is_numeric($listingid)) { exit; }

then change: $query = "SELECT * FROM ".$fu->getOpt('catoptions_table')." WHERE cat_id=$listingid LIMIT 1";

to: $query = "SELECT * FROM ".$fu->getOpt('catoptions_table')." WHERE cat_id=".(int)$listingid." LIMIT 1";

Important note: I am not responsible for any damage incurred by running this fix. I do not have any responsibility over FanUpdate. (Blah blah blah.) I’m only posting this because I know Jenny doesn’t maintain the script now.

PHP Security Tips

Because you can never know too much, and it’s about time I wrote a follow-up to my PHP Script Checklist article.

1. Never include sensitive data in a .inc

When I started my current job, one of the first things I did was move all of the database connection details (yes, that includes passwords) from .inc to .php files. It shocked me back then, but the more time and money I spend enhancing my PHP security knowledge, the more I realise why it’s not uncommon. Many of the most popular articles on PHP security don’t touch on it — instead favouring SQL injection, cross site scripting, etc. So, note to all: .inc files display their contents when viewed in the browser (unless configured by Apache not to do so, and this is rarely the case). That means that those passwords in the files I mentioned? Viewable to all and sundry. Not good.

2. Never trust the data in $_SERVER

There’s a popular misconception amongst PHP beginners that because the contents of the $_SERVER superglobal array are generally set by the web server, they are untouchable, trusted and secure. This is not the case. The contents of certain $_SERVER elements are manipulable like any variable, so be sure to sanitise them instead of using them blindly.

3. Never trust client-side validation

I have talked about not trusting user data before and yet people still write their scripts with little or no validation of data, instead relying on crap like the maxlength attribute and drop-down menus. Of course, to your average Joe Bloggs a drop-down menu means they can only pick the options in front of them. To a spam bot, or any sensible/knowledgeable user it’s another method of input and the drop-down part is irrelevant. Even the Firefox Web Developer toolbar can convert <select>s to <input />s (which means anything can be entered).

The other problem is reliance on JavaScript… consider the logic of checking and cleaning your data with something that the user can turn off!

4. Use mysql_real_escape_string over addslashes

Don’t take my word for it, Chris Shiflett (a leader in the PHP security industry) wrote about it: addslashes() Versus mysql_real_escape_string().

Despite the use of addslashes(), I’m able to log in successfully without knowing a valid username or password. I can simply exploit the SQL injection vulnerability.

Clean your data, check it with regular expressions etc and then prepare it with mysql_real_escape_string().

5. Read my blog

Where else can you get such a witty and intelligent outlook on life, coding, etc? Yeah, yeah, couldn’t think of a decent number five :)

Cutenews is Shite

I’ve added a short note about Cutenews on my Unsafe PHP Scripts page.

Passwords at Tesco Not The Issue

It seems almost ironic that just the other day I was ranting about Tesco’s seemingly mediocre approach to password security, and today we hear that Tesco online store ‘is infiltrated by insider card fraudster’.

Customers shopping at Britain’s biggest Internet store — Tesco Direct — are feared to have had their card details stolen by a company insider.

The security breach is allegedly linked to a worker who handled phone orders for items advertised on the Tesco Direct website and the related store catalogue.

Now, if a call centre worker has access to those details and enough information to use them for his or her own gain without the need for any criminal record checks or other vetting, why are we bothering with passwords at all? I might as well start handing out my card information on the street.

(Thank you Louise for sending this to me..)