This is a blog post Josh and I wrote when we were still students at Deep Dive Coders.
At Deep Dive Coders, we’ve been learning about secure web development since day one. But last Friday, during our Security Day War Games, we learned just how easy it was to attack insecure sites. How easy? Many of us had no exposure to hacking, but in just a couple of hours, we were able to pull off attacks such as SQL injection, shell injection, cross-site scripting and password cracking.
For our War Games, we were divided into two teams. Our instructor, Dylan McDonald built two sites containing common vulnerabilities. It was our job to quickly defend our site, while launching attacks on the other team’s site. Over two intense hours, we gained points by successfully launching attacks and by defending our site against the other team.
In preparation for the War Games, Dylan described the kinds of attacks we could do, but never taught us how to do them. This was a big part of the challenge for us was to figure how to pull off these attacks. We really only had one guide: recognizing where good coding practices weren’t being followed.
Before we get into how to defend sites, we should ask, why is security that important? Well, in our SQL injection attacks, we were able to access and destroy all the database information. In our shell injection attacks, we got command line access to the server. We were able to download usernames and passwords and crack the hash. Obviously, we were playing with dummy sites, but if these were business sites, companies could have lost time and money or had sensitive information stolen. Since privacy is the currency of the internet, we must do our best to reasonably protect our information.
Protecting Your Site
Thankfully, it is relatively easy to protect your site from the majority of attacks if you follow secure coding practices. PHP and mySQLi have many built-in functions to help you in this.
Input Sanitization
From day one, we have learned to sanitize inputs from malicious (and incompetent) users. User input is toxic and it must be cleansed. We know that input sanitization isn’t as sexy as cryptography, but it is the easiest and most powerful way to protect your site as a web developer.
Regular expressions have become one of our best friends in this. At first, these crazy combinations of characters confused and scared us, but now we are comfortable designing and testing them for all sorts of different inputs.
PHP’s htmlspecialchars() is also a great tactic in sanitizing inputs that later get displayed on a webpage, such as comments on a blog post. It takes out html tags, which prevents cross-site scripting attacks.
If you absolutely need to use a shell command (which we recommend you do are rarely as possible), escapeshellarg() and escapeshellcmd() do exactly what the names say, escape commands and arguments for shell. These are your best bet to prevent injection attacks. If you are running an external program, you need to use these or a simple “;” will turn your input into a command line for your server.
Taking the time to prepare statements and bind parameters are the best protection from SQL injection. This practice checks the query for obvious attacks, ensures that only one SQL statement is present and verifies the input types are what we expect. These two simple methods accomplish so much! Both of them are built-in features in mySQLi that are really easy to implement.
Now that we’ve covered server-side sanitization, what about client-side? jQuery form validation is a good practice, but it isn’t enough since all you need to do is turn off JavaScript on your browser to get around it.
The same goes for drop down menus and checkboxes. They are great protection against incompetent users, but they are completely ineffective against malicious users. Be aware that users can tools such as Inspect Element in Chrome to arbitrarily change these values. This is, in fact, how we launched some of our attacks in the War Games.
The best practice in input sanitization is to sanitize client side and server side multiple times.
What we learned
The only thing more surprising than how easy it was to launch all of these attacks was how easy it was to defend against them. There is no excuse not to do the simple work necessary to defend your site against malicious input. Protecting your site is more work, but like physical exercise, once you get in the habit, you do it automatically.
Dylan has been teaching us these safe coding practices all along, often without us knowing why they were secure at the time. He himself is very security minded and instrumental in laying down a strong security foundation for us. This foundation goes well beyond application security to using good password hashes and salt, proper encryption and more.
Taking the mindset of the attacker drove home how important security is for a good web developer, plus it was really fun.
Leave a Reply