We have reached the point in the product cycle where clients are requesting that we can pass certain security standards. There was no specific request as to what these standards should be. It was a rather general guideline regarding a penetration test . For those who have never heard of this before I should say that this is not as painful as it sounds. A penetration test is a systematic scan of your system in order to highlight any weaknesses. A quick example: Lets say you have a linux box with port 22 (usually reserved for SSH) open (i.e. when someone tries to connect to it they get a response). This is potential vulnerability since it is pretty trivial to try a 'brute force attack' on the server and gain access (provided you have been lazy enough to have allowed password access). That is the kind of stuff a penetration should pick up and highlight for you.
Before everyone jumps down my throat about the definition of pen test vs a vulnerability test, let me just say that YES there is a difference. I will not go into that difference and if it seems that I am covering a bit of both, then apologies.
How to run a test yourself
First thing you need to do is figure out what is a pentest and how to run one yourself. There are tools out there which cost a lot of money and as per usual there is a free alternative which appears to also be amongst the best and most up do date solutions: metasploit. There is a paid version, but you will get a pretty good idea of how things work even with the free version. You also get a 14 day trial of the full version, which in my case was enough.
Since the test reflects both on your application and on your network setup you probably do not want to run everything locally. In my case I setup 2 servers on aws. The first server was a production setup of the application whereas the second server was the penetration tester. Take care to notify amazon that you will be performing a test. If you do not (besides the legal ramifications) there is a chance that aws may pickup the test and assume that this is an attack. I am not sure what are their countermeasures in this case, but it is certain that your pentest results will be distorted.
This does vary depending on your application setup. A basic setup would be to install your EC2 application server inside a VPC. This way you will have pretty good control of what is accessible to the outside world (more on that later).
You will need a server from which to run your tests. I used an Ubuntu box and I followed the instructions from rapid7, the company that is behind metasploit. Install this server on different VPC than your application. You are after all trying to simulate the scenario of an attack, which will definitely originate from outside your network.
I don't believe that you need a very powerful machine, but since you will run the test and then shut it down you may as well go for something that will get the job done quickly. An m3.medium is more than enough.
You may also want to know that metasploit has been recently featuring on an interesting WIRED article.
How to prepare
You need to take care of two aspects: the network setup and the application. As far as the application is concerned you are limited to what your framework has to offer. Here is a list of things that ideally you want your framework to take care of out of the box:
- Cross-site request forgery. You don't want you application to allow POST requests from any other client except the one that your user us using for accessing the site.
- Various cookie - session good practices. For example, you want to make sure that after you logout the session is invalidated. You can test that by recording the values of the cookies that deal with authentication, loging out and then trying to create the cookies again and accessing the page. You can use a chrome plugin for manipulating cookies such as editthiscookie.
- SQL injection. Provided you use an SQL type database (Postgres , Oracle , mysql ) you may be valnurable to sql commands that the user has managed to pass to your backend. If for some bizarre reason you decided that you will execute whatever your users post in a textbox, then
drop table userswill probably cause a fair amount of pain. Any ORM (e.g. activerecord for ruby, SQLAlchemy for python, hibernate for java) should take care of this.
Most people use a decent (modern) framework like Rails so they never have to worry about any of the above. They get regular updates and belong to an active community which quickly responds to threats. Legacy systems may not be that well prepared and if you are called to support them, then you definitely need to be aware of some of the main issues.
A comprehensive list of all the vulnerabilities as well as how critical they are, is maintained by OWASP. Here is the list of the top ten issues according to OWASP (for 2013).
You may be using the latest and greatest framework but you could easily have allowed access to you database on port 5432 (you know who that is) with a weak password (12345678). I am 100% sure that there are plenty of these out there (waiting for somebody to wreak havoc). Or how about a Redis server on port 6379 which is designed to accept zillions of calls, and therefore is a perfect target for a brute force attack? Any decent software engineer (call him system admin or whatever pleases you) would have hidden all the nuts and bolts somewhere in a dark corner of the network away from prying eyes. That is exactly what you need to do.
I use aws for all infrastructure. Same goes for my network. I think that aws forces you to use VPCs (Virtual Private Networks), but even if it does not then you should. I will get to details of the VPC on different message, but for now keep in mind just a couple of pieces of advice:
- Close all ports (using security groups) except what is absolutely necessary (e.g. 22 for ssh, 80 for web server).
- Make sure that any other service you are using is not accessible. They may reside on different servers within your VPC or even on the same server as your application. Whatever the case you should not allow direct access to them.
Which brings us to the next question of how will you actually access them should you have to. SSH tunnels to the rescue! Tunnel to your box (port 22) and then access anything you want. Here is a very quick example of how to establish an SSH tunnel to your database server:
ssh -N -p 22 -c 3des firstname.lastname@example.org -L 1111/my.very.well.hidden.databaseserver.com/5432
Run the above command on your terminal (*nix people only. Don't know how this is done in windows - see putty or something weird - or just install Ubuntu ) and then you will have established a connection locally on port 1111 which corresponds to your database server. When you are done, then CTLR-C on your terminal and the tunnel will be broken.