As the year of 2005 was drawing to a close, a website known as Myspace was basking in popularity. With millions of users, the site was the most popular social networking site in the world. It was unique in that it let users use HTML code to customize their Myspace page. Most of us, c’mon…admit it….had a Myspace page. The coding part was fun! But not everything was changeable with code. You could only upload up to 12 images and the Relationship Status drop-down menu only had a few options to choose from. These limitations did not sit well with [Samy Kamkar], a 19 year old hacker out of Los Angeles.
It didn’t take [Samy] long to figure out how to trick the site to let him upload more images and change his relationship status to a customized “in a hot relationship”. After hoodwinking the Myspace site with some simple hacks, he realized he could do just about anything he wanted to with it. And this is where things get interesting. It took just over a week to develop a script that would force people who visited his page to add him as a friend. But that wasn’t enough. He then programmed the script to copy itself onto the visitor’s page. [Samy] had developed a self-propagating worm.
The script went live as [Samy] went to bed. He woke up the next morning with 200 friends requests. An hour later the number had doubled. [Samy] got worried and sent an anonymous email to the webmaster warning of the worm. It was ignored. By 1:30PM that day, he had over 6,000 friends request. And like any good hacker worth his weight in floppy drives, his sense of humor had him program the script to also add his name to each visitor’s Heroes List. This angered many people, who deleted him from their page, only to get reinfected moments later when they visited another (infected) page.
[Samy’s] script was raging out of control. As the evening closed in, his friends count had reached 919,664. It would top the 1 million mark just before Myspace took their servers offline to figure out what was going on. Two hours later, the site was back up. [Samy’s] profile page had been deleted.
[Samy] had used a technique known as cross-site scripting (XSS) to pull off his hack. We’ll touch on XSS in a later article. For now, we’re going to stick to the basics – proper passwords and SQL Injection.
To begin, we need to touch on some basics. All of the hacker protections you employ can be rendered useless with an ineffective password. In our last article, we talked about how a group of hackers known as Lulzsec were able to hack software security expert [Aaron Barr]’s corporate website. His main password was “kibafo33”. According to a password security checker, it would take about 11 minutes to crack. Adding a single special character and capitalizing a letter, such as Kiba#fo33, brings that time up to 275 days.
Cracking passwords consists of using common phrases and brute force attacks. With brute force attacks, all letter, number and special character combinations are tried in a sequential manner. Thus choosing longer passwords and a larger number of character types makes it harder to break. This is why many websites insist that you use at least one special character and capitalize a letter as it greatly increases the security of your password. It doesn’t take much effort to create what is essentially an unbreakable password. So before you go checking your site for vulnerabilities, start with your password.
SQL injection (SQLi) is a technique that allows an attacker to execute SQL statements in an entry field. This technique was used with great success by the Lulzsec hackers. One member who went by the name [Kayla] wrote an automated program that combed thousands of URLs and returned those that were vulnerable to the attack. Typically, a mischievous SQL statement is passed to the database along with a normal input. For instance, one could type into a password field of a username/password login prompt:
password’ OR 0=0
The resulting SQL query would look something like:
SELECT id FROM users WHERE username=’username’ AND password=’password’ OR 0=0
The statement “0=0” that was added is always true. If there are no checks in place, this will result in bypassing the authentication process and logging into the account of the first person on the database, which is usually the database administrator. Now, it’s highly unlikely that you would find a modern website that would have this kind of vulnerability, but it never hurts to check. It is often the simple hacks that are overlooked.
A more advanced form of SQLi is called union based SQL injection. It involves a similar process but uses the UNION SQL operator to gain access to data within the HTTP response. A security company has set up a phony testing website that is vulnerable to this type of attack that we will utilize for demonstration purposes.
Key in the following:
This is a completely normal query but vulnerable to SQL injection. You can tell by putting an apostrophe (‘) at the end of the string and observing the SQL error message. This is a just a test website, so go ahead and try it! We’re going to exploit it by asking for a nonexistent record, such as “artist = -1”. It can be any number that does not exist within the database. We’ll then use the UNION operator to join our malicious statement to the request. The malicious statement will be SELECT.
http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1, 2, 3
This proves that the database will return data if we ask it nicely. Now let’s get some useful data, like a (fake) credit card number.
http://testphp.vulnweb.com/artists.php?artist=-1 UNION SELECT 1,pass,cc FROM users WHERE uname='test'
Running rogue SQL statements on a test website is one thing, running them on a real website is another. You will have realized by now that you’ll need to brush up on your SQL skills to truly understand any real penetration testing. Finding real websites with vulnerabilities is the first step, but is not much different from our example. PHP sites tend to be targets as they are more likely to be vulnerable to SQLi attacks. A method called Google Dorking (pdf) is one method used to find these sites. Here’s just one example that can be typed into your favorite search engine:
This turns up about 1.6 Million results, and as before, appending the URL with an apostrophe is the simple test. If an SQL error is returned, the site is vulnerable to an SQL attack. From this point, an attacker would go on to use SQL statements to figure out how many columns are in the database, and then start exploiting it.
Preventing SQL Injection Attacks
You now have more than enough information to start testing your site to see if it’s vulnerable to an SQLi hack. In many cases, the hacker winds up with the MD5 hash of the database password. They’ll then use various crackers to get the password…another reason you should use secure passwords and not use the same password on various accounts.
Preventing SQLi can be done by sanitizing inputs on your webpage. This would prevent anyone from entering “0=0” in an input where numbers are not needed. The vast majority of pages out there will have their inputs sanitized. But it only taks one slip up to expose the entire site to attacks. If ever you happen to run across a site that is not sanitizing its inputs, please play nice and send the webmaster an email. Save your hacking skills for constructive endeavors.
41 thoughts on “The Dark Arts: SQL Injection And Secure Passwords”
SQl in seringes… Kids these days…
This is SKID stuff, cmon hackaday!
So what? It’s literally a “hack” in the modern sense of the word. Sure, it’s basic stuff that even your entry-level techie could figure out if he sat down and looked at how logins are parsed, but it’s still worth writing about.
Not to mention that story about myspace. Never knew that, and that’s really quite cool.
I’m glad I’m not the only one who thought so. This is not the kind of rubbish I’m used to seeing on HaD, If I wanted to read a skiddiot blog there’s plenty of other places I could go. I started reading this hoping it would be more along the lines of a retrotechtacular article, or the Hacking and Philosophy article where Lloyd Blankenship chimed in. I was interested until i got to the password security blurb. Then I had to choke back bile when I read “It doesn’t take much effort to create what is essentially an unbreakable password.”. Rainbow Tables and system/service exploits aside- the password security blurb is written as if Will is just learning about this and doesn’t really understand password hashing, entropy, collisions, or compute time. Since he’s posting XKCD comics anyway, Will should read xkcd #936- as it does make a very valid point about password security and what most end users and websites are doing wrong with password requirements. In the end, the simple truth is that sanitizing database inputs is like washing your hands after using the toilet; EVERYONE knows you should- but there are those whom- for whatever reason (usually lethargy/willful stupidity)- just don’t. (Or worse, they roll their own poor implementation, which while great for learning- is terrible for a production environment.) Heck, CISSP’s website was vulnerable to SQL injection for quite awhile- in a bad way (one was able to create additional administrative accounts on their website.) And that was only remedied back in late 2007, perhaps even early 2008. Clearly they knew better.
If I want security news there are better sites for that. If I want poorly informed security advice- well- there’s plenty of that going around anyway. (thankfully I’m seeing some sound advice and valid policy concerns further down in the comments.) HaD, can we get back to cool projects like dumping the firmware from a smart-watch through the pager motor, or reverse engineering protocols with bus-pirates, or hell even another arduino-driven nixie-tube clock or infinity mirror project build?
Anyway, I’m rambling, the point is this article had an interesting start and was quickly ruined by poorly written PSA content that everyone even remotely aware of standard practices knows about. This skiddiot garbage is not what HaD has ever been nor should ever be about.
The Dark Arts series is about how black hat hackers hack into websites. This series is meant to be easy to understand and light on the technicalities. There are many readers here who haven’t the slightest clue what SQLi is or how it works. After reading this article, they will have a basic idea. Comments from those with a more advanced knowledge in a specific area are welcome. Insulting those that do not gets you a pass to the troll office.
I had no idea how this stuff worked–so I’m grateful for the explanation. Thanks HaD!
Same here. Well said that man.
I agree……thanks for info, and keep up the good work. Being a micro-controller guy, I enjoy the intro articles a lot.
Whilst I, and presumably you, come from a SW background, there’s plenty of people here from a HW background who’d be unaware of this stuff. I’m sure the series will get more detailed.
Or start writing a more advanced article yourself, I’m sure theres plenty of folks who’d benefit from your knowledge.
“Running rouge SQL statements on a test website is one thing”
Whatever happened to the obligatory xkcd links ?
Little Bobby tables is in the article?
Unfortunately, a simple “sanitize your inputs”–looking for malicious strings–is about as effective as antivirus software only looking for patterns. It only works against attacks that you know of, and becomes an arms race against attackers. (Spoiler alert: the attackers win.)
The real solution to this is to use SQL prepared statements or an ORM. It will produce much cleaner code than mysql_real_escpae_string(). And in pretty much every language other than PHP, variable substitution features are available by default.
This stuff is surprisingly subtle, and if you try to roll your own, you will get bitten!
Stored Procedures can be poorly written and create sql injection problems too. I worked at a company where I was told that their sp’s were how they did security, within 5 minutes I had broken into my boss’ account and made some changes. After a couple of days of looking at their code I handed in my resignation as well as a detailed list of security problems that my boss had told me didn’t need to be fixed.
Instead of resigning, I would have talked to your boss’s boss and secured yourself a promotion. The point of having a job is that there is actually work to do… If everything was already perfect, then there’d be no need for you, right?
But what if the aforementioned boss was the owner and Jeff’s job was not to secure the IT infrastructure or security but some completely different project? – Obviously the boss did not see this as Jeff’s job.
Security is one of those things that it’s almost never a good idea to roll your own. If you really want to, contribute to a security project. The only time I’ve seen self-rolled security work better than non-self rolled is with anti-spam on forums. Even if it’s just a single question that never changes like “what color is this site’s logo” or “what game is this forum about”, it’s much more effective than a recaptcha. (unless you’re a very large website. Then it doesn’t work.)
Also, I’ve seen attempts to prevent SQL injection that actually made the website less secure- like requiring your password to be exactly 8 characters, so it would be more difficult to build an injection.
PDO in php parametrizes and escapes strings.
the proper and only way to prevent SQL injection are parametrized queries. sanitizing is not bulletproof
Agreed, I always write my own database abstraction as well to go from a data request object (not query) to a returned data object. The same abstraction also deals with authorization level.
The real problem with SQL injection is that php is often the first webserver language that people learn and by default the basic security of the inbuilt MySQL primitives is non-existent. MySQL has now been depreciated and they are using MySQLi instead but I don’t know if that forces parameterized queries. I haven’t done any php for some time now.
You should mention that some websites try to only sanitize with JS which is, in essence, asking the end-user not to transmit bad data. Silly admins, did you forget that JS is client-side?
Won’t enforced password rules eliminate whole swats of possible passwords thus reducing the total amount of brute force search space?
I think you’re caught in an error of thinking when it comes to combinametrics. The rules are precluding the easiest passwords to crack: less than 6 characters, all lower case with no numbers. Because the pool of possibilities is so small this is very easy to calculate all possible hashes and compare to the hash you’re trying to break.
Requiring at least 1 upper case letter and 1 number takes the possibilities for each character in the password from 26 up to 62. Add punctuation and it gets even bigger.
Sure! I’ll just inject into the username, or the email, or the password hint, or some search term, or…
Should have mentioned in the article that the license plate pictured was intended to exploit traffic cameras.
Did it work?
A little off-topic, but does other kind of injections count?
I’ll just live this here: https://hackaday.io/project/6621-hack-the-hack-a-day-editor/log/20782-give-yourself-a-skull
Especially interesting given that skulls are worth money at the moment.
This is really outdated stuff. PHP has had prepared statements for a good while through PDO. And “no one” hashes their passwords with MD5. The most common password hashing method in PHP today is:
This automatically hashes and salgs the password using blowfish.
You can also supply an optional password stretching parameter.
If any website is vulnerable to any of the methods written in this article, they are old.
PHP has come a long way, and is today a fully naturen OO language.
The mysql extension has been deprecated for a good while, and is completely removed from the newly releaed 7.0.
Today most developers use PDO, or they have upgraded their old projects to the new mysqli which keeps much of the legacy syntax, but supports prepared statements, and OO usage.
That’s cute. You think people actually use those tools instead of grabbing the first crappy answer off some old forum…
I mean no disrespect to any developers/programmers out there but the spread of SQL Injection attacks could have been
significantly reduced. While there are always expectations to any rule you can bet that %75 or more of the SQL Injection attacks out there can be traced back to the trivialization of the SQL/DB Side of some project. Far too often (within the world of programming, coders) the attitude towards SQL is either to find a No SQL way to do it or have one of the programmers take the “SQL in 24 Hours” 1 day training seesi0n and afterward they are designated the DBA master.
That’s not to say that properly trained DBA’s have not been hit with an SQL Injection attack only that the trivialization of the DB side of development projects has helped the spread of the SQL Injection attack. All one needs to do is visit any of the traditional/popular programing sites and you’ll find numerous discussions on how to do thing without using/knowing SQL.
Like everything else, SQL/databases are an important piece of a project and had best practices been applied/followed the rampant spread of SQL Injection attacks might not have spread to the level they did.
You should at least get his name right. It’s Kamkar…
Quite right. Fixed, thanks.
As a server-side developer, I can say that these mistakes still rage on even with ORMs and modern frameworks like Grails, Ruby on Rails, DropWizard, et c. In my experience, it’s often when someone gets frustrated with trying to get the ORM/DB abstraction to do something complicated and drops to `find_by_sql()` or equivalent.
Kinda makes your heart sink a little when you see a SQL statement error scroll by in the logs of a completely modern application because someone used a single quote in their password…
I’ll add to that, that I’ve seen a number of new hires whose primary experience is self-taught PHP, who are *very* quick to disregard the ORM or DB abstraction and drop to SQL for even trivial tasks. Aside from often introducing security vulnerabilities, being smarter than the query optimizer is usually the exception, not the default.
“Aside from often introducing security vulnerabilities, being smarter than the query optimizer is usually the exception, not the default”
Are you saying that the dev is more often then not smarter then the DB Engines query Optimizer? I mean no disrespect and I can’t speak about Oracle’s optimizer but as far as SQL Server goes its seldom the case that the developer is smarter then the DB engines query optimizer. From personal experience I can testify that the misuse of hints in queries by the code’s author have caused problems from dirty reads to poor performance all because the codes author believed they were smarter tehn the optimizer.
Calm Down Bitches!!!
Believe it or Not, not EVERYONE here is a Software guy.
But many of the folks here (that are mechanical hackers such as myself)
are having to learn the software side to enhance their physical builds.
I appreciate the authors efforts here.
If it hurts your massive intellect to read such simple things then pick
Another article to read.
Or get a girlfriend
Please be kind and respectful to help make the comments section excellent. (Comment Policy)