I recently wrote this story on a forum I frequent, but I thought I’d share it here as well and include some additional details.
A little more than a month ago at my work we were dealing with a website that was constantly being hacked. The website itself ran just fine; the hack was unnoticeable to majority of users. The attackers were injecting hidden code into the website that was only appearing to bots like the Google bot. When people googled the website the listing on Google would show ads for other things (usually undesirable) rather than the website’s description or any intended content. Needless to say the client did not want this.
The client’s website had been a victim of hacking several times in the past over the course of several months. They were running a very outdated version of Joomla! that we determined to be the most likely way the attackers were getting in. Due to the amount of customization to the website and the age of it, we recommended rebuilding the site in WordPress or dropping the CMS capability altogether and just create a static website. The client declined to do either to save money. They continued to get hacked though and we continued to clean it up as best we could.
Eventually someone noticed the undesirable text on the Google (and other search engines) listings and alerted the client, who subsequently alerted us and asked us to fix it. We eventually convinced them to rebuild the website in WordPress; however, the attacks continued. At this point the client was getting increasingly annoyed with us thinking we were incompetent at what we did. To be clear: we’re not a security company. We make websites. This doesn’t mean we don’t know stuff, but we’re not experts at cleaning infections. There are some basic things that pretty much any programmer or techie would know to do or look for but we don’t specialize in this kind of work. We already went through the normal motions of changing passwords, folder/file permissions, etc.
The client pretty much threatened to drop us. This was our oldest client, and was very important to us in both monetary terms but also on a relationship basis. We wanted to make them happy and fix their problem but as just mentioned, this isn’t what we do. In any case, we stopped everything and decided to take a “scorched Earth” approach.
We deleted everything from their FTP and we systematically went through our code (line by line in many cases) looking for anything that was suspicious and scrutinized it with extreme prejudice. Once we were satisfied that our code had no infections we were ready to reupload the files.
During this process I was also going through changing all the passwords to their various systems, including the control panel password. We have a password scheme but I made the call that it was not sufficient in this case and decided to use KeePass’ password generation tool to generate 40 character passwords comprised of random letters, numbers, and symbols; these passwords were stored securely so there was no worry of having to remember them or even typing them in.
I changed the control panel password and it came back with a success message telling me it was changed. Great. I recorded the new password and went to log back in. The log in failed. I tried again. And again. I tried the old password as well. No dice. I tried on a different browser, a different computer. I tried everything. I couldn’t get back in.
We were in a critical moment as well because the client declared 5pm as the deadline to have everything back up and working again or they were no longer going to do business with us. It was 4:45pm. Myself and my boss were very stressed and almost freaking out. We contacted the hosting company but they were unable to do much for us. We weren’t “on the account” and therefore there wasn’t anything they could do except send out the password to the email addresses that were already on the account. One of the emails was the person we were dealing with directly (who had set the deadline).
That was the last person we wanted to interact with at this point, but my boss got on the phone and talked to him. He twisted some facts to take some of the heat off us but managed to get the password email forwarded to us. I took a look at the password and it was exactly what I generated. I copied and pasted it into the log in form and voila – I was in. But I was very perplexed because it was the same password! In any case, due to the time crunch I finished my work and we got everything settled with literally minutes to spare.
I went back to take a look at the password because I knew something was wrong. After putting both the generated password and the password from the retrieval email into Notepad I noticed the one from the retrieval email was only 39 characters. It was shorter. I studied both of them carefully to see what was missing and the password from the retrieval email was missing a backslash!
The control panel form accepted the password, but it stripped the backslash from it without ever telling me! There were no indications of any restrictions on passwords, and without giving any kind of feedback to the me, I was completely oblivious to what they had done. I told my boss about what happened because I wanted to make it clear that this wasn’t my mistake, and that this is very frowned upon when it comes to security practices.
We were both quite surprised because we have used the host quite a bit in the past and are still using them for several current projects as well and we have never had a problem at all. They seemed like they really knew what they were doing. I guess not. I sent a strongly worded email to them letting them know that this was poor practice and the trouble it caused me. I never heard from them.
Stripping random characters isn’t the only offence. I’ve seen people apply trim(), addslashes(), strip_tags(), strtoupper(), etc. to passwords. These are all bad, and most of all, completely unnecessary.
Just an additional tidbit of information: WordPress doesn’t accept backslashes in their users’ passwords either, but at least they display a message to tell you!
Regardless though, there’s no reason to restrict a user’s password. Not like this, anyway. Passwords are just strings that should be getting fed directly into some kind of hashing algorithm or other security function. By the time they reach something like a SQL query, they should no longer resemble anything a human would be able to understand, or anything that would be able to mess with a query. Period. Don’t do this. This is bad. Even if you reject the password and tell the user.