When playing with Thinking Sphinx (the Ruby on Rails wrapper for the open source Sphinx search server), I decided to try to see if I could perform an injection attack on the server.

Here’s the bad news:

Yes, I could modify searches by changing the parameters

Here’s the good news:

It doesn’t matter. The Sphinx system is only an indexing system – and quite a good one at that. It doesn’t have any write access to the database server from which it is obtaining the indexing information.

Here’s the not quite so excellent news:

Anything you index can be obtained by modifying the search.

Executive Summary:

Be aware of what’s possible, but don’t stay up at night worrying about it.

How to do it

Personally, I had a clue – I can watch the searchd.query.log file, which shows me the queries and results of everything sent through our Sphinx server, which means that I can play with formats etc.; but just because the bad guys can’t, doesn’t mean that they still can’t (eventually) work it out.

On our search form is a field for Title. Anything in there is sent as a search string against the ‘title’ field.

So, if I enter

Ferrari

as the search term, I should get all records where the title contains the word ‘Ferrari’. The search log shows me the following results;

[Fri Jun 10 10:30:58.707 2011] 0.048 sec [ext/2/rel 348 (0,10)]
[car_core,car_delta] @mytitle => '*Ferrari*'

(column names have been changed to protect the innocent).

This search term returned to me 348 records with the word Ferrari somewhere in the title.

If I change the search term to, for example,

'  @author => '*John

The search sent to Sphinx will now show every record where the authors name contains the string ‘John’.

[Fri Jun 10 10:31:15.590 2011] 0.070 sec [ext/2/rel 540 (0,10)]
[car_core,car_delta] @mytitle => '*'  @author => '*John*'

So, whats the risk?

Very little; the only thing you can do with these injection attacks is to retrieve more data. It’s incredibly unlikely that you’ve indexed usernames and passwords into Sphinx (please don’t. Especially if you’re Sony…). You can’t write anything to a database – Sphinx doesn’t talk directly to the main database except when it’s actively updating it’s index, and even then its permissions are restricted to read-only. You *might* be able to unleash a small Denial of Service (DoS) attack, but Sphinx is so efficient that it isn’t worth it; there are so many other ways of attacking a server.

If you wanted to remove the threat, a small regex on the input data to remove any * and @ characters (unless email addresses are valid) would be all that’s required.

puts target_string.sub(/\*|@|(?:=>)/, "")

This will ensure that any input string will be sanitized such that anything invalid (as above) will be reduced to a single valid search string.