Category Archives: OWASP

Ruby on Rails bottom up security – sensitive data exposure

Reading Time: 1 minute

TL;DR

This post is about risk sensitive data exposure in your Ruby on Rails application. It will cover unauthorized access and cross site request forgery check (CSRF).

Unauthorized access risk is simple. User can access data that it is not supposed to access. Here you need to check source code of every controller. Your job is easier if developer named controllers by their purpose. For example:

z.rb

and

doctor.rb

make a big difference.

Rails application is using controller filters, for example:

before_action

If controller is public, then there would not be any before_action filter authorization method. If authorization is required, then there would be  before_action filter, for example, auth_user or auth_admin, depending on controller context.

And this is perfect candidate for automatization code. Developer should write simple tests with call for every controller, and result checks of HTTP status code that should be 403 for authorized controllers, and 200 for public one.

If there is role access, check authorization controllers with appropriate role credentials.

Cross site request forgery is when hacker tricks user to execute in his browser http request that modifies data (PUT, POST, DELETE). Ruby has out of the box CSRF protection, that adds additional hidden token parameter in all such requests. Of course, that protection could be turned off.

You should search your code base for:

grep -H -r 'protect_from_forgery except:' * | less

and you should discuss with developer do you really need that exception.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Ruby on Rails bottom up security – mass assignment

Reading Time: 2 minutes

TL;DR

Mass assignment is security risk where user can create/update data attributes that is not allowed to update.

Here is an example. Imagine application that registers your employees working hours. When user logs in it sets start time, and when it logs out it sets end time. Pretty simple feature.

User login form has username/password input fields. Imagine that user can temper its login timestamp using login request. How? Your employee friend is skilfull tester, and he knows how to send POST request using Postman tool. Using Chrome developer tools he/she finds out the login attributes and now he tries to guess login timestamp attribute:

  • createtime
  • logintime
  • login_time
  • create_time, …

Those names set with date values in the past (he/she wants his friend to work less) are sent using curl (no need to know cookie!). Heuristic to know when correct time attribute is guessed is very simple. There is another url endpoint, or even login response, that will return login time.

How is that possible!? Ruby on Rails got its popularity because is has a lot of default features that made developer work much easier. One of those features is to automatically accept all http request input parameters that match to available ORM (object relational model) object attributes.

Creation timestamp is an example of attribute that should be set by application, not the user input.

Remember, never trust the user input. And hacker loves default framework features.

Ruby on Rails in current version does not allow mass assignment. Every input parameter must be listed in

permit

method in order to be accepted by ORM.

Using super power tool grep, you should search your Rails codebase for this:

grep -H -r 'permit' * | less

Using your knowledge about the application, you need to conclude (look ma, no automation here!) are those parameter allowed to be listed in permit method in the first place.

I also strongly advise communication with your developers 🙂 in order to make the decision.

 

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Ruby on Rails bottom up security – daily server check

Reading Time: 2 minutes

TL;DR

This is next post in series about Ruby on Rails security. In previous post I explained how to harden other servers. This time I will explain daily security check for CentOS servers.

After you securely set up your Ruby on Rails servers, you need to take care about their security on daily basis. Because time is the ultimate attack vector for all web applications.

Monitor Common Vulnerabilities and Exposures (CVE)

You need to create a collection of web pages that announce CVE advisories for components of your web application. Here is one typical Ruby On Rails application stack.

Next, check security logs that you had set up during the hardening phase.

Logwatch
logwatch | less
Fail2ban
fail2ban-client status
Selinux
less /var/log/audit/audit.log | grep AVC | less
Nginx log
log/nginx.access.log-YYYYMMDD*

This is where your application knowledge is important. In that file, I look for hacker patterns. First, I filter out regular application url paths, so what is left are robot scripts that are probing for known security issues for various applications.

For example:

zless /home/deploy/apps/betterdoc/current/log/nginx.access.log-YYYYMMDD* | egrep -v  'assets|images|favicon.ico|robots.txt|fonts

Note that I use zless, which is less for compressed files.

Do I need to restart servers?

There is a myth that you do not need to restart Linux servers after application update. Linux will not force you to do that, because running application would happily run with previous version. Which is bad if previous version has security issue. Remember, you set up automatic daily update for all server components. With command:

lsof -n | grep DEL | less

you will get a list of applications that still use in memory libraries that had been deleted from the server. If that command returns any list(DEL), you need to restart whole server (easier) or just the application that is listed.

In next post, I will describe security audit for Ruby on Rails application code.

 

 

Facebooktwittergoogle_plusredditpinterestlinkedinmailby feather

Ruby on Rails bottom up security – web server

Reading Time: 2 minutes

TL;DR

In previous post I explained security hardening for linux server. This post will describe hardening based on server purpose.

Modern web application typically consists from following components:

  • web server
  • database server
  • job server
  • cache server

Security hardening for those servers is different.

Web server

Here are detailed instructions how to harden nginx web server.

  1. SELinux

SELinux is security kernel feature. If some component on your server is not patched, or there is Zero Day Vulnerability, SELinux will help you to protect other server components. For example, logging component has zero day vulnerability and hacker would use it to try to get access to your web server. SELinux adds additional level of kernel security to make that attack much harder.

2. Allow Minimal Privileges Via Mount Options

This is applied to partition that holds your web application files.

nosuid means that it will be not possible to change user and group permissions for that partition

noexec it will be not possible to run any program from that partition

nodev means do not interpret character or block special devices on
the file system

One of hacker attack vector is to serve his own malicious program using your web application. Those settings will make his attack much harder.

3. Linux /etc/sysctl.conf Hardening

These are low level linux networking and kernel parameters. First attack vector is try to login remotely to your server. These settings will make that job much harder.

4. Remove All Unwanted Nginx Modules

You need to run your nginx with modules that you need. Otherwise, your attack vector surface becomes larger.

nginx -V

will list current nginx modules. Here are instructions how to configure modules.

5. Change Nginx Version Header

This basically makes your nginx server more hidden. It will make hacker job much harder.

server_tokens off

How to change Server header. For centOS use

yum install

6. Install SELinux Policy To Harden The Nginx Webserver

These are selinux policies that will make your web server more secure.

7. Controlling Buffer Overflow Attacks

Buffer overflow attack is one of the first attack that will hacker try. There are special tools that help them (like Metasploit) to automate that attack. Basically, hacer will try to feed more data to web server connection. Setting explicit boundary values, you will make that task much harder. But be aware that those boundaries could influence your web application operations.

8. Control Simultaneous Connections

Set maximal number of simultaneous connections from same IP address. This will help you to fight web spiders and ddos attacks.

10. Limit Available Methods

You probably know about HTTP GET and POST methods, but do you know about OPTIONS? Restrict HTTP methods that are not used by your web application.

11. Nginx SSL Configuration

You need to run on SSL. For that you will need to buy signed ssl certificate.

12. Firewall

Your web server needs to be behind dedicated firewall appliance. Period.

That it is, security hardening for web server. In next post, I will talk about hardening for database server.

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

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