Tag Archive for 'security'

Granting just enough power, but no more

Sometimes you have a group of users who need to run certain commands on a server, and no others. It’s not necessarily that you don’t trust them. The point is simply that they don’t need a full-blown shell account, and you’re understandably reluctant to give it to them.

There are countless ways to set up a restricted account that can use only certain commands, but most of them are either extremely special-purpose, or rather difficult to set up. (Locking down SSH sessions inside a chroot jail, for example, requires almost as work as just setting up a dedicated virtual machine for your untrusted users.)

Furthermore, none of the existing solutions were written by me, to address exactly the needs I have for such a “sandbox” environment. Most notably, I don’t want users to even have to remember which commands are available to them. In many cases, they may only be using these tools every few months, and remembering cryptic UNIX-y command paths and syntax is hard enough even when you use something every day.

And so, I give you menush, a simple shell replacement which presents users with a list of available commands from which the user may choose. It loops until the user exits via the menu (or uses Ctrl-C/Ctrl-D to end the session).

To set it up on your own server, you’ll need to copy the file into a known location (say, /usr/local/sbin), then add a line to your /etc/shells file pointing to it. For each user you want to lock into a sandbox, edit their password entry using vipw (or your passwd editing method of choice) and change the last field from /bin/bash or similar to the full path to menush.

Then, create the directory /etc/menush, and write your default menu file (/etc/menush/__default__). On startup, menush will look in that directory for a file with the same name as the user being logged in; if that file is absent, the default will be loaded instead. The format for the menu files is documented in the README, but it’s just a YAML file. (Also, bonus points for the first person to correctly identify the gaping security hole in the provided example.)

The code is written in a fairly portable, POSIX-y style, so it should work on Linux, BSD, or OS X. Feel free to send me suggestions, pull requests, or rants about the horrible security holes I left because I banged this whole thing out in like two hours and then spent a bunch of time blogging about it instead of reviewing my own code.

Randomized primary keys in ActiveRecord

One of the easiest means of cracking a naively-implemented Rails application (or any RDBMS-backed application with auto-incremented primary keys) is to simply alter site URLs and request parameters with the assumption that their IDs will be sequential.

For example, if a user sees a URL like the following in their location bar:

http://example.com/post/2705/comments

They could easily replace the number 2705 with, say, 2706, and see comments for that post. Of course, you’ve already added explicit permissions checks to every controller method that insure such access will never happen, but we all know how easy it can be to forget to audit each and every method for ID-traversal attempts.

Furthermore, using simple sequential IDs exposes other potentially-useful information to would-be attackers. They can see, for example, how many users, data objects, etc., are in active use on your site, and perhaps even reverse-engineer more of your database schema in order to plan SQL-injection or XSS attacks.

Actually using randomized keys does mean overriding the default ActiveRecord behavior, and may be tough to accomplish simply using ActiveRecord migrations. If your database is of a reasonable size, though, or you’re just getting started, it’s easy enough to do. First, you’ll need to decide on a random ID-generation algorithm.

The best way to generate “random” keys isn’t actually random at all. If you want to insure that no one can guess your keys, you’ll want to use a full-strength cryptographic hash. (See my FOSCON slides from last year for more info on that topic.)

If your primary keys are going to be exposed in your URLs at all, though, there are advantages to keeping them simple. Strong hashes generate long, difficult-to-type identifiers, so you’ll want to either slice them to get only a substring, or use a weaker algorithm which generates less randomness.

Regardless, you’ll need a helper method to generate the IDs, as well as some support in your models and migrations to glue it all together. Here’s a simple example, based on an “account invitation” implementation from an application I’m working on now:

# app/models/invite.rb
class Invite < ActiveRecord::Base
  include GenIdHelper

  def before_create
    self.id = gen_id
  end
end

# db/migrate/001_create_invites.rb
class CreateInvites < ActiveRecord::Migration
  def self.up
    create_table :invites do |t|
      t.column :id, :string, :limit => 8
      t.column :email, :string
      # ...
      t.timestamps
    end
  end

  def self.down
    drop_table :invites
  end
end

# lib/gen-id.rb
module GenIdHelper
  # Generates a pseudo-random string in hex format (0..9+A..F)
  # which contains chunk*16 bits of randomness.
  def gen_id(chunks=2)
    ("%04x"*chunks % ([nil]*chunks).map { rand(2**16) }).upcase
  end
end

The end result will be that newly-created instances of the Invite class will have an ID generated by gen_id, and will be much harder for anyone to guess by simply replacing URL components or POST values.

These random IDs can also be considered another form of identification for users. Basically, if they have received the random ID by some trusted channel, (say, SMS message, or snail-mail) it can be treated as a secondary authentication mechanism when creating a new account, performing a password reset, or proving their real world identity.