Category Archives: security testing

Ruby on Rails bottom up security – authentication and session management check

Reading Time: 1 minute

TL;DR

This post is about checking “The Gates” of your Rails application.

Every web application is a set of urls. Some of them are publically available and some are available only to you (e.g. your bank account page should be available only to you and your spouse).

Modern web application authentication works as follows:

  • there is log in page where you enter your username/password
  • backend checks that combination
  • if this combination is valid, backend returns in Set-Cookie header long, unique, hard to guess string of characters. This is session string.
  • Browser takes that value and sends it in Cookie header in all following requests.
  • Backend checks cookie value and it needs to be same as one assigned to username/password combination
  • there should be logout endpoint that removes session string form username/password combination.

More about Ruby on Rails session security can be found here.

If you want to start your own session management, this could go wrong in infinity number of combinations.

So what can you do? Use Devise gem with following options:

  • store session in database
  • session must expire after some user inactivity time
  • log out feature must be implemented.
  • rotate devise key value (most frequently means more security).

In future security audits you only need to check devise configuration, that devise if updated with (possible) latest security patches and that devise security key rotation is active.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Ruby on Rails bottom up security – sql injection check

Reading Time: 2 minutes

TL;DR

This post will explain how to check your Ruby on Rails code base against sql injections [Wikipedia].

After you have read Wikipedia source link about sql injections, you are ready to proceed. It is important to state that Ruby on Rails offers one of the best (if not the best framework) out of the box sql injection protection.

But sometimes, developer needs to be able to override this protection for some “Twin Peaks” feature requests. In that case, even experienced Rails developer could make sql injection attack possible. On the other spectrum, if your company can only afford junior Rails developers, this check is a must.

Here is how you should hunt such protection overrides. First, head to Rails SQL Injection site. This page lists many query methods and options in ActiveRecord which do not sanitize raw SQL arguments and are not intended to be called with unsafe user input. You will use this site as a reference.

Open your terminal, go to root folder of Rails project repository, and use this cmd:

grep -H -r 'search for activerecord method' * | less

You need to replace search term with active record method name. Here you need to be creative in order to filter out results that do not represent active record method.

Here is the punch line:

Never, ever, trust the user input!

Which means that user input must not be directly used in active record methods. Again, refer to Rails SQL injection site in order to learn how to recognize code that is prone to sql injection.

Wait, but I am using Windows that do not have grep! Well, Google is your friend, there is a number of open source tools that will help you.

We also need to check all custom SQL queries using command:

grep -H -r 'execute' * | less

grep -H -r 'params\[' * | less

Same as for the active record methods, user input must not be directly used in custom SQL queries.

p.s. Twin Peaks feature request makes developer to have experience  very similar to experience of watching Twin Peaks: “The Return” [source].

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Ruby on Rails bottom up security – other servers

Reading Time: 1 minute

TL;DR

In previous post I described how to do security hardening for your Ruby on Rails web server. In this post I will talk about other servers: database, openvpn, cache and job.

Database server holds web application data so hacker will definitely try to get direct access to it.

You first need to do basic server hardening explained in my previous post. After that you need to be sure:

  1. that other servers port is not publically available
  2. access to other server is properly securely configured

One is resolved by putting your servers behind firewall. Second depends which server do you use. Here is example for postgres database server. Here is you strategy. When you know you database server, Google for its security settings and apply official guidelines that you will found.

How to securely connect directly to your servers? You can publically expose ssh port, but this is not good strategy. You need to use vpn connection.

OpenVPN

Simply explained, openvpn is ssh that uses certificate (public/private) authentication.  It will make hacker job much harder. You need one dedicate box with openvpn server.  Also, you will need openvpn client. So after VPN is set up, here is how you connect to your servers:

  • establish open vpn connection
  • connect using ssh to your servers that now have ip address from VPN network range

In next post I will explain how to do daily security check for servers and their software components.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Ruby on Rails bottom up security – hardening the servers

Reading Time: 3 minutes

TL;DR

Next series of blog posts is about Ruby on Rails bottom up security. I will cover all aspects of web application written in Ruby on Rails framework. Described security concepts could be applied to any other modern web framework because we will describe which security problem particular concept resolves. I will start with hardening the server that runs the web application.

You probably think that hardening (reducing the surface of vulnerability) the server is impossible task. But I will prove you wrong. I found this excellent blog post that is foundation for hardening the server.

It has all instructions for Ubuntu linux how to harden the server. And you could be done with this task in 5 minutes!

Precondition is that server is up and running, and you know root password. You should first login as root.

  1. Select linux distribution

As you probably know, there are various linux distributions. I suggest latest CentOS for two reasons:

  1. it has excellent database about security patches
  2. it is tailored for servers that run server side services (e.g. web application)

2. Change root password

Unix command is

passwd

Tip. We suggest that you use LastPass password manager for creating and storing that password.

2. Update the system

You want to have latest software version as starting point.

yum -y -d 0 -e 0 update yum
yum -y -e 0 -d 0 update

3. Install fail2ban

yum install fail2ban

fail2ban is daemon written in Python that monitors suspicious activities and if detected, automatically bans client ip addresses for some time.

4. create new user

useradd deploy

mkdir /home/deploy

mkdir /home/deploy/.ssh

chmod 700 /home/deploy/.ssh

You will use only that user to connect to your server! Never use root user for establishing ssh connection. Note important command, chmod and number 700. At first, this look very cryptic. Read this for more info, and for now, remember that 700 gives all access ONLY to deploy user to .ssh folder (1+2+4 = 7).

5. ssh using public/private key authentication

In order to connect to your server, you will use ssh without password. How to set up that type of access? I recommend github tutorial:

Check for existing ssh keys is not needed, since you have new fresh server.

Generate new ssh key pair. You should set up password phrase (which is by default optional). Also, add private key  to ssh agent, so you will not need to enter password phrase. Be sure to store password phrase to lastpass!

Test your ssh connection.

Add your public key to the server. Previous link contains instructions how to copy your public key. The you have to paste it:

vim /home/deploy/.ssh/authorized_keys

Save file and run:

chmod 400 /home/deploy/.ssh/authorized_keys chown deploy:deploy /home/deploy -R

Mode 400 is read only. This is highest security, and without that mode, you will get cryptic error when you will try to establish ssh connection.

6. Test The New User

Keep existing terminal open, and from new terminal type:

ssh deploy@server_ip_address

7. Enable sudo

In your first terminal as root, first set deploy user password:

passwd deploy

Save deploy user password in LastPass!

visudo

You are now in vi editor. Comment all lines and add at the bottom:

root ALL=(ALL) ALL

deploy ALL=(ALL) ALL

That means when you will run sudo as deploy user, you WILL BE ASKED TO ENTER PASSWORD!

8. Lock Down SSH

Via ssh, you will not be able to:

  • connect as as root user
  • connect using password
  • connect from any client, but only from clients that you will list in setting.
vim /etc/ssh/sshd_config

Enter this, and be sure that original entries ARE DELETED:

PermitRootLogin no
PasswordAuthentication no
AllowUsers deploy@(your-ip) deploy@(another-ip-if-any)
systemctl sshd restart

9. What about firewall ?

I strongly do not recommend that your server is directly exposed to the Internet. It must be BEHIND dedicated FIREWALL. Ask your IAAS provider about details.

10. Enable Automatic Security Updates

This should be set, at least for security update. Set it in cron to run automatically on daily basis.

vi /etc/cron.daily/yumupdate.sh

#!/bin/bash
 YUM=/usr/bin/yum
 $YUM -y -d 0 -e 0 update yum
 $YUM -y -e 0 -d 0 update

11. Install Logwatch To Keep An Eye On Things

Logwatch is tool that automatically monitors server logs and its logs can give you a hint about server intrusion.

yum install logwatch

vi /etc/cron.daily/logwatch_daily.sh

/usr/sbin/logwatch --output mail --mailto test@gmail.com --detail high

You are done with basic server hardening. In next post, I will explain how to harden servers based on their purpose. Web server, database server, cache server, job server have a slightly different security configuration.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Do not keep your credit card and PIN together in your wallet heuristic

Reading Time: 1 minute

TL;DR

This post is about testing heuristic : “Do not keep your credit card and PIN together in your wallet”.

Heuristic is commonsense rule (or set of rules) intended to increase the probability of solving some problem [WolframAlpha]. Heuristic is fallible.

Captcha is [WolframAlpha]

a type of computer-administered test, usually in the form of distorted text or images, aimed at determining whether the respondant is a human or computer; used as a security measure on many websites to block automatically generated spam, since computers should be unable to respond correctly

Here is how we can apply this heuristic on capcha problem. Developer finished his captcha code. You hit Chrome developer tool Inspect feature on Captcha element, and you see this:

There is captcha question “odaberi kokice”, and three answers, radio values 1, 2 and 3 with appropriate image.

Can you apply credit card and PIN heuristic here?

Credit card is question, and PIN is radio image name. Image name contains PIN value. So it is possible, using simple algorithm, to automated answer to this captcha. In this example:

if captch_question is odaberi kokice the select img/captch-kokice.png.

In proper captcha, img src must not contain easy decodable captcha answer.

<img src="0efc2e4ab9e04bc9dc66833dbb98505438c26f5557713e53c69090b586e62c4ceff814a5def8174f5c6d417aec5c2d2d1829fafaa9d12b461b3b0fff0ab894a4.png">

Also, having more than three captcha answers helps in your fight against crawlers, spiders and robots.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

How to smart test minor version Ruby on Rails upgrade?

Reading Time: 1 minute

TL;DR

In this post I will explain what should be checked after Ruby on Rails minor version upgrade. Minor version upgrades are usually connected with security releases.

As I am subscribed to Ruby on Rails security Google group, when I receive information about latest security issue, I need to act very fast. Update must be pushed to production almost immediately, so there is no time for extensive regression testing.

How can we do quick test and be sure that everything still works as before upgrade?

Heuristic 1. Rails upgrade was extensively regression tested.

That heuristic proved itself to be always true.

Heuristic 2. Inspect Gemfile.lock to be sure that only Rails gem is upgraded.

How do we actually upgrade Ruby on Rails?

Edit gemfile:gem 'rails', '4.2.5.2'
bundle update rails

Investigate Gemfile.lock changes using git diff to see what else was updated beside Rails. If some other gem (not part of Rails) was also updated, check, using Google search, possible issues for that gem that are connected with Rails upgrade.

Heuristic 3. Search Google for Ruby on rails upgrade to n.n.n.n version issues (bugs, problems)

Conclusion.

For minor Ruby on Rails upgrades, using those three heuristics, you can do regression test in smart and quick way.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

How to set regression test scope for HTTPS only access?

Reading Time: 2 minutes

TL;DR

In this post I will provide an example how to set the scope of system regression test in order to achieve coverage of features that need to be tested.

Context

The trigger for regression system test was HTTPS only access to client Ruby on Rails application. Prior to that feature, it was possible to use both HTTP and HTTPS protocols. Developers use TDD concept, and prior to my test, all developer tests passed on CircleCI environment.

There was also set of selenium-webdriver tests, but those tests do not cover all application features.

My strategy was to include them in the regression test. All test passed. But I had not finished regression test yet.

I did not know all application features at that time. So I started risk analysis, which features could fail if HTTPS only protocol was introduced to web application. Let’s call OWASP for help.

There is transport layer cheat sheet. Reading through the rules, I pinpointed rules that were potential risk for application functionality:

  • Do Not Mix TLS and Non-TLS Content – because browser (modern browsers) will AUTOMATICALLY prohibit access to non HTTPS urls.
  • Use a Certificate That Supports Required Domain Names – if this is not the case for your application, browser will present to user a security error

First risk could be mitigated by using the application in Chrome and observing javascript console for mixed content errors. Could I automate that task? First thought would be: write selenium-webdriver test suite that covers all the features! But I do not have that time. Was there a simpler way?

My heuristic was to search all the code base for keywords HTTP and IFRAME.

grep -H -r ‘iframe’ * | grep http:// | grep -v elements.txt | grep -v ‘README.md’ | less

That piped command searched through the all code base in terminal and returned code that uses mixing content.

And we discovered additional issue, it was not possible to immediately set all HTTP urls to HTTPS protocol. Those urls were referencing external applications, like blog. For example, in order to set this blog to HTTPS protocol, I need to buy another plan that costs more money. And I need to have a certificate for tentamen.eu domain. Which brings us to second risk.

Use a certificate that supports required domain names. And this is environment dependant test. This risk was mitigated on my testing environment, but I should also check it on production environment (production is hosted on different domain).

Doing risk analysis is fun. You will learn something new and the most importantly, you will properly set scope for your regression test.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Selenium RemoteWebDriver over http

Reading Time: 1 minute

TLDR

In this post I will explain how I connected knowledge from two testing domains, security and UI automation, in order to achieve proper UI automation stack configuration.

 In order to be able to use various browser/os combinations for ui automation, I am using SauceLabs, cloud based testing provider for web and mobile. SauceLabs is running Selenium Server instances to which you are connecting using RemoteWebDriver.

Here is how to do that in Ruby:

What bothered me is that UI test would open http connection and testing infrastructure would be vulnerable to man in the middle attack. By investigating the Selenium documentation, it is not possible to run Selenium Server with https.

What is next? SauceLabs has its own product, Sauce Connect.

“Sauce Connect is a secure tunneling app which allows you to execute tests securely when testing behind firewalls via a secure connection between Sauce Labs’ client cloud and your environment.”

That means you are still using http towards Selenium sever, but over secure tunnel.

“Data transmitted by Sauce Connect is encrypted through industry-standard TLS, using the AES-256 cipher.”

What is interesting is SauceLabs official statement:

“You should use Sauce Connect whenever you’re testing an app behind a firewall. Sauce Connect is not required to execute scripts on Sauce.”

This should be paraphrased:

You should use Sauce Connect when your testing scripts are using sensitive corporate data.

Never put aside your testing domain knowledge, you should always combine them, especially when clients security is at stake.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

When you should restart any server instance?

Reading Time: 2 minutes
image credit: findicons.com

TLDR

In order to know when you should restart your server process (web server, database server, or any other type of server), you need to understand how program works. In this post I will explain basics of program and used libraries and how to detect on linux when you must restart your server.

I am very frustrated with Windows operating system. You need to restart it almost for everything, important security issues, regular updates. Pain is even greater when there is some security product which just pop ups notification: your system will reboot immediately!

And in the beginning, there were stories that unix, and later linux is much better, because you do not need to restart it. As I was learning and using unix/linux, I found that this was true. There were notifications that new updates are installed, but there was no need for machine restart. As I learned about linux, I found out that this was not true.

If you are running linux instances as part of publicly available web application, you must walk extra mile. You will probably set silent automatic updates for you linux instance. But, you will have to do extra check to see do you need to restart your server processes.

Every server process is a program. It consists of executable part and a number of libraries. When you start your server process, executable and all required libraries (on linux those are files with .so extension) are loaded into memory assigned to that process. So if there was an update of libraries used by your server process, and those libraries are loaded into process memory space, you will need to restart your server instance in order to load new version of those libraries.

For linux, there is utility that can help. lsof lists all opened files. It has useful option, DEL, which list all opened files that are marked for deletion.

This example shows that postgres still uses deleted version of libcrypto library.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Heroku ACTION REQUIRED: Potential security vulnerability in Ruby and YAML parsing

Reading Time: 1 minute

I received email from security@heroku.com with that subject on April 3rd, 2014 at 22.55 local time. I was expecting that email. How many of you who have Rails application deployed on Heroku, patched your application by following instructions in security heroku email?
I followed instructions by typing them in my Mac terminal, and found out that instructions are wrong.
First command from email:

heroku run “ruby -rpsych -e ”p Psych.libyaml_version.join(‘.’)”” -a application_name   


should be replace with:

heroku run `ruby -rpsych -e ‘p Psych.libyaml_version.join(“.”)’ -a application_name


I do not explicitly use Psych gem so I found out that cmd:


git commit –allow-empty -m “upgrade ruby version”


should be replaced with:


git commit –allow-empty -m ‘upgrade ruby version’


I had to upgrade my Ruby from ruby-2.0.0-p247 to ruby-2.0.0-p451. For ruby-2.0.0-p247, libyaml version was 1.4.0 and by upgrading Ruby, I only managed to upgrade libyaml to version 1.5.0. I do not want to upgrade Ruby to ruby-2.1.1 because of following issue.

If you do not parse user yaml input in your application, then this issue does not affect you.
This blog post shows what security risks you should consider when you deploy your application at 3rd party cloud application platform. You can learn more about risk based testing in lecture 2 of BBST test design course.

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather