Server-side security war games: Part 11

This is level 11. Your clue is that "XOR encryption" is not encryption. Let's look in the cookies to find out they have XOR-ed, so we can mess with it.
Read more »

Server-side security war games: Part 10

Welcome to level 10. "For security reasons, we now filter on certian characters" -- okay they've gotten wise to our little game. But let's check how good their countermeasures are.

Well, they don't allow us to use the semicolon or ampersand any longer. Well that's not a problem, I know other ways to manhandle that command into doing what I want.
Read more »

Server-side security war games: Part 9

In level 9, the "Input secret" form is replaced by one that looks like it is searching for words containing the string you provide. Give it a try, and then look at the code.

Well, this is just grepping through a wordlist, using the POSTed needle as a parameter. Since we control the value of that POSTed variable, we can control the command that gets executed. Now we need to figure out how to use that to our advantage.
Read more »

Server-side security war games: Part 8

Level 8 shows us another "Input secret" form. Let's examine the source again. This time, there is an "encoded" secret. Let's try to reverse engineer this. They're using bin2hex, strrev, and base64_encode -- those are all trivially reversible.
Read more »

Server-side security war games: Part 7

Level 7 is a simple webpage that doesn't seem to offer us any clues about a vulnerability. Let's click around those links a bit to see more.

Well, each of these links passes the name of the page to a PHP script, which seems to just stuff the contents of the file into the webpage. So, we should be able to change that URL parameter to whatever we want, in order to get the contents of the file containing the next password.
Read more »

Server-side security war games: Part 6

On level 6, there is a curious "Input secret" form. I wonder what it does? Well, there is also a "View sourcecode" link, which will presumably show us the source code for that form. Then, we can try to anaylze whether it has any weaknesses we can take advantage of.
Read more »

Server-side security war games: Part 5

"You are not logged in" -- I wonder what that means. Normally, websites use cookies to tell whether you're logged in. Let's check if that's the case here.

If you're using Google Chrome, press CTRL-J and switch to the "Resources" tab. Expand the "Cookies" item, and select the current domain: "natas5.natas..." and lo and behold there is a cookie there. Named loggedin. With value 0. Remember, the client controls what gets sent in the cookies. That's our attack vector.
Read more »

Server-side security war games: Part 4

We got an "access disallowed" error because we were visiting from "", while authorized users should come from "natas5.blah". Try the "Refresh page" link. Now the page says we came from "natas4.blah". This is the referring to the Referer[sic] header. But that's information provided by the client, and we control the client. We can put whatever we want in that header. So, let's put the natas5 domain, as they kindly suggested.
Read more »

Server-side security war games: Part 3

There is still nothing on this page, and now if we look at the source, they've removed that image. Now there's a taunt that not even Google will find it this time.

Well, Google is a good little robot puppy who always obeys his master, but we are evil attackers. What rules do robots have to follow that we don't? robots.txt. Let's look at what they don't want Google to see. robots.txt always lives at the root of the domain, so open

They've hidden /s3cr3t/ from crawlers, but we don't have to abide by that. Let's take a look. Another directory listing, which contains a file which contains our password.

Lessons learned

Remember that hiding things from search engines is very different from making them inaccessible. Even some web crawlers won't respect your robots.txt file, and attackers certainly won't. If you need to make something inaccessible, configure that in your webserver, not in robots.txt.

See you soon for level 4!

Server-side security war games: Part 2

Use the username "natas2" and the password you obtained in level 1.

There is nothing on the page, nor anything "in" the page, if you look in the source.

Maybe there's something in one of those external resources we can use. There's a CSS file, and an image. The CSS file was always there, but the image is new, so let's see if we can exploit that.

Copy the src for the image, and paste it into the address bar, after the domain part. The full URL is

The image itself is nothing helpful, but sometimes server misconfiguration can leak information about other files on the server. If you remove the pixel.png part, you'll see a directory listing. You can see there's a file containing the password. Open that, and use it to access the next level.

Lessons Learned

Misconfigured servers can be a problematic source of data leaks. Make sure you understand how the server you use can be configured to allow or deny access to sensitive files, or directory listings.

Server-side security war games: Part 1

Use the username "natas1" and the password you uncovered at level 0 to get in.

Let's try the same trick as before -- only now you can't right-click. Instead, use CTRL-U to view source,
and get the password for the next level.

Lessons learned

Again, this level was easy, but it's important to understand that people aren't required to behave the way you want when using your website. Doing validation in client-side javascript, or disabling right-click isn't going to be effective, so don't use it for anything security-sensitive.

See you at level 2 shortly.

Server-side security war games: Part 0 has a series of "war games" -- challenges that help you learn by doing. Natas is the webserver security series. Although there are walkthroughs already available, I am going to do my own series of posts. Some of the existing walkthroughs are overly complex, and none actually finished all the levels. The war games unfortunately don't have anything explaining why the example vulnerabilities can be important in real-world scenarios. I'll try to fill that void.

I'm going to post one every few days, beginning with levels zero and one today.
Read more »

Adding LUKS hard disk encryption on LVM after the fact

I have an external hard disk enclosure with two disks. I used Logical Volume Manager to create a single logical volume that spanned them, and slowly filled it to about 60% capacity. Lately, I've been trying to be more conscious of using encryption, and this was one area where I hadn't done so. At the time I felt like learning how to do LVM was enough, and LUKS could wait until later. Well, it's later. Here's how I added encryption after the fact (without a spare hard disk).

The warning

As these are potentially dangerous commands, you absolutely should back up your files prior to beginning. If you have sufficient spare media, you should consider not trying to do this conversion in-place. Instead just create a new filesystem and copy files over.

The plan

In my case, the volume of data was such that I didn't have the resources to do so, and the value of the files was fairly low, so I just went ahead without. The plan is to shrink the existing filesystem and logical volume, create a new logical volume in the freed space, with an encrypted filesystem inside. Then, move files from the old filesystem to the new one, while readjusting the allocation of disk space if needed.

The script

This was reconstructed from my bash history, and typed out by hand. Errors are certainly possible, so don't blindly reuse these exact commands. With that said, let's begin.

First, unmount the filesystem (FS), and shrink it to be as small as possible. Then, shrink the logical volume (LV) to match the FS's size:

umount /dev/vg0/usr-store
resize2fs -pM /dev/vg0/usr-store
lvreduce -L ? /dev/vg0/usr-store # from resize2fs

If resize2fs reports "2000 (4k) blocks" as the new filesystem size, then the size for lvreduce is in megabytes: 2000 * 4*1024 / 1024*1024.

Now, allocate the space you just freed up by shrinking usr-store to a new LV:

lvcreate -l 100%FREE -n new-store vg0

Now, we'll add the encryption layer:

cryptsetup --verify-passphrase luksFormat /dev/vg0/new-store
cryptsetup luksOpen /dev/vg0/new-store new-store

And create a new filesystem. I chose ext4, which has efficiencies when dealing with large files, but your workload might require something different.

mkfs -t ext4 -m2 -O dir_index,filetype,sparse_super -L new-store-fs /dev/mapper/new-store

At this point, you have a new filesystem that's LUKS-encrypted and ready to use. We can now begin transferring files from the old filesystem to the new one.

mkdir /mnt/new-store
mount -t ext4 /dev/mapper/new-store /mnt/new-store
mount -t ext4 /dev/vg0/usr-store /mnt/usr-store
mkdir /mnt/new-store/mike
chown mike:mike /mnt/new-store/mike
rsync -a --remove-source-files /mnt/usr-store/mike/Files /mnt/new-store/mike
# wait... wait... wait...
find /mnt/usr-store/mike/Files -type d -empty -delete

If you filled the new filesystem, then you'll need to readjust the disk space allocation by shrinking the old filesystem & LV, and growing the new filesystem & LV.

umount /dev/vg0/usr-store
resize2fs -pM /dev/vg0/usr-store
lvreduce -L ? /dev/vg0/usr-store
mount -t ext4 /dev/vg0/usr-store /mnt/usr-store
lvextend -l +100%FREE /dev/vg0/new-store
cryptsetup resize new-store
resize2fs -p /dev/mapper/new-store

Now you can continue moving files.

Once the old filesystem is empty, simply remove the logical volume that contains it, and rename the new encrypted volume and LV. You can optionally extend the FS & LV to fill the rest of the space now as well. I chose to use the space for a new LV I'll be using for backups instead.

umount /dev/vg0/usr-store
lvremove /dev/vg0/usr-store
lvrename vg0 new-store usr-store
dmsetup rename new-store usr-store
rmdir /mnt/new-store
mount -t ext4 /dev/mapper/usr-store /mnt/usr-store

Introducing mvr: like mv, but clever

I wanted to move a large number of files from one directory to another, but the target directory already had many of the filenames already used. This is a common enough problem -- digital cameras use DSC#, video downloaders often append numbers to get a unique filename, and so on. In both those examples, the sequence restarts if you empty the program's work directory. So, you'll end up with DSC0001.jpg every time you empty your camera's memory card. If you're trying to move such files into a single directory, you'll get conflicts every time.

Instead of manually renaming the files before transferring them, I wrote a simple script to give each file a unique name in the destination directory.
Read more »

Introducing Noose: just enough OO to hang yourself

Moose led to Mouse led to Moo led to Mo led finally to M, which gives you the least object-orientation possible, which is none at all. I quipped that Perl desperately needed a new OO module called Noose - just enough object orientation to hang yourself. Read more »

Planning a Content-Security-Policy with Dancer

The same-origin policy is a fundamental part of the security infrastructure of the web. It prevents a web site's scripts from accessing and interacting with scripts used on other sites. This helps keep your data safe because if your bank's website gives you some data, it can only be accessed by your bank's website, and not by scripts from other websites.

That's a nice theory, it'd be a shame if some evidence happened to it.

In the real world, attackers have found ways to get around the same-origin policy to gain access to data they're not supposed to be able to access. For example, a web programmer might mistakenly include some user-provided input verbatim in the HTML of a webpage -- perhaps a username. Well, if your username is <script type="text/javascript" src=""></script>, then how is the web browser supposed to know if that was intentionally put in the HTML of the page? Same-origin policies are insufficient in the face of programmer error. Enter Content Security Policy.
Read more »

Book review: "Coding Freedom" by Gabriella Coleman

I've just finished reading Gabriella Coleman's new book "Coding Freedom: The ethics and aesthetics of hacking" (2013, Princeton University Press) which culminates over a decade of field research, in-depth interviews, observation, and participation in the hacker scene globally. In this case, "hacker" refers to the free/open-source software (FOSS) hacker, and in particular the Debian project.
Read more »

Automating server build-out with Module::Build

At Pythian, we have one application that is composed of several components, the deployment of which needs to conform to our slightly peculiar server setup. Until recently, this required manually deploying each component. I did this a couple weeks ago, and it took me something like 40 hours to figure out and complete. As I went, I started reading up on Module::Build, trying to figure out how to automate as much as possible. It turns out that this core module gives us a surprisingly powerful tool for customized deployment. First, it will help to understand a few aspects of how our code is deployed. Read more »

Problems with in-memory buffers

Perl does lots of things that make life easier, from postfix conditional and looping constructs, to DWIM-infused language design. One of interesting things I discovered when learning to open a file was that Perl can treat a scalar as an in-memory file:

my $string = "many\nlines\nof\ntext";
open my $in, '<', \$string;
while (<$in>) { print }

Read more »

Computing isn't everything

The technology world has many problems: sexism, homophobia and/or heterosexism, classism, ageism, trolls, and more - often reflecting the imperfections of broader society. One of the more pernicious problems is our denigration of the non-technical. Yes, science and technology are important, and computing in particular is important - but it is not everything. Science and technology are nothing without public understanding and engagement - a computer does nothing without an operator. Read more »