Monday, 16 July 2012

Fun with the Vstarcam IP camera

Recently, I got myself a VStarCam IP camera, model H6837WI, relatively cheap for what you get - a H264 capable, wireless/wired IP camera with two way audio, SD card recording and few other nice features.

The software provided with the camera is Windows only, which is a system I don't use very often at home ;) I started with exploring the camera's web interface, by default run on port 81. It turned out that the quicktime plugin didn't seem to work in any browser and other than getting the direct H264 stream, this was the only way to get live video feed without the proprietary software.

Nothing about getting the H264 stream directly in the docs. Duh. :(

A bit frustrated, I run wireshark just to get an idea of what the camera is 'doing' when left idle. Hmmm...DNS requests to Looks like part of the default DDNS settings, which according to the documentation, let you use the vstarcam provided service to access your IP camera remotely using an external server...Call me paranoid, but that's definitely not something I would be happy with! By the way, urls found by google pointing to the vstarcam forum, redirect to, which is rather suspicious (did someone forgot to update their server software? oops). According to Virustotal, Sophos flags this domain as malicious, although it doesn't currently resolve to any IP... None of this made me anymore comfortable about using the default (or any) DDNS service and the security of it... Made a mental note to disable the DDNS and verify that the camera is not doing anything silly later on.

Right, all of this was a bit disappointing...but apart from traffic sniffing, there's one more thing you need to do with every device you connect to your network - port scan it of course! ;] So here we go, in the most simple way...

# nmap

Starting Nmap 6.01 ( ) at 2012-07-16 16:36 BST
Nmap scan report for
Host is up (0.029s latency).
Not shown: 997 closed ports
23/tcp open telnet
81/tcp open hosts2-ns
554/tcp open rtsp
MAC Address: 00:E0:4C:AA:BB:CC (Realtek Semiconductor)

Nmap done: 1 IP address (1 host up) scanned in 3.28 seconds

Telnet! Getting interesting...Ok, the web UI default credentials are...'admin' and no password ;] Let's see...

$ telnet
Connected to
Escape character is '^]'.

(none) login: admin
Login incorrect

Nah! How about root?

(none) login: root
warning: cannot change to home directory
/ #

Voila! Got shell and it's password free! ;] Let's do some exploring here...

/ # id
uid=0(root) gid=0(root)
/ # free
total used free shared buffers
Mem: 17344 15720 1624 0 2724
Swap: 0 0 0
Total: 17344 15720 1624
/ # uname -a
Linux (none) 2.6.24ssl #197 PREEMPT Thu Sep 22 14:07:30 CST 2011 armv5tejl unknown

Not the most recent kernel I'd say... ;) running on armv5, (not MIPS?)

/ # cat /proc/cpuinfo
Processor : ARM926EJ-S rev 5 (v5l)
BogoMIPS : 119.60
Features : swp half fastmult edsp java
CPU implementer : 0x41
CPU architecture: 5TEJ
CPU variant : 0x0
CPU part : 0x926
CPU revision : 5
Cache type : write-back
Cache clean : cp15 c7 ops
Cache lockdown : format C
Cache format : Harvard
I size : 8192
I assoc : 4
I line length : 32
I sets : 64
D size : 8192
D assoc : 4
D line length : 32
D sets : 64

Hardware : object h264 ipcam
Revision : 0000
Serial : 0000000000000000

Not the most capable hardware, but hey... ;)

Either way, I have to admit that being able to get a proper shell on your cheap IP camera is pretty cool :) (Still, no toaster yet ;)). There's quite a lot of interesting stuff there, for a geek of course (yes, including the /etc/shadow file of course, but I won't spoil the fun ;)). My camera even came with a snapshot picture taken in what looks like a warehouse...

A definite bonus is the fact that the web UI is located in /mnt/www so you can poke around and adjust few bits here and there ;) You can actually grab the update file from the vendor website which contains most of the filesystem anyway and have a look around that way, too... :)

There's also a service running on port 6801/udp and I have no idea what's it for, and the netstat doesn't reveal associated binary name:

# netstat -tualn
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0* LISTEN
tcp 0 0* LISTEN
tcp 0 0* LISTEN
udp 0 0*

Speaking about binaries - by the looks of things, the toolchain used for the camera is rather ancient - glibc 2.3.6 and gcc 3.4.6. One could still cross compile that and thanks to the ftp client provided on the camera (didn't I say it's hackers friendly? ;)), or using the 'update' method, put and run their own binaries on the camera...;] BTW, the wireless adapter is Ralink 3070 which in theory should run aircrack-ng just fine... ;]

Another discovery - the vendor provided Windows software communicates with the camera via the camera webserver and binary cgi files using some sort of a binary protocol...I was looking at the netzob tool not long ago, and maybe I've just found some good opportunity to play with it...Rewriting a simple client in Python would be cool, as well as a remote code execution via the cgi ;). Did I mention that the IE interface uses ActiveX component?

All in all, one must admit - the H6837WI is a hacker friendly camera! ;] I still need to get the H264 streaming to work at some point though...after all that was the main reason why I got the camera in the first place...:)

Happy hacking! :)

Thursday, 21 June 2012

Gentoo chroot on Nokia N900

While I was waiting for my Raspberry Pi to arrive, I decided to put my Nokia N900 for a better use and create a Gentoo chroot on the SD card to give the hardened ARM toolchain a go. For the record, I found these two links to be particularly useful when working on the chroot.

N900 is not the fastest arm board out there, but it was the only ARM board I had at hand...Anyway, creating Gentoo chroot on N900 is quite simple actually. First you need to create a spare partition, or two if you want to use swapping space, which is probably a good idea, given my plan to re-compile the toolchain natively. :)

I also decided to leave some space on the SD for the N900 itself, ( apparently it's also a good way of shutting it up as it tries to mount the card anyway ), so I ended up with three partitions:

Disk /dev/mmcblk1: 15.9 GB, 15931539456 bytes
255 heads, 63 sectors/track, 1936 cylinders
Units = cylinders of 16065 * 512 = 8225280 bytes

Device Boot Start End Blocks Id System
/dev/mmcblk1p1 1 974 7823623+ 83 Linux
/dev/mmcblk1p2 975 1097 987997+ 83 Linux
/dev/mmcblk1p3 1098 1936 6739267+ 83 Linux

The first partition is left for the N900 as a FAT filesystem, the second one will be our Gentoo chroot and the 3rd is swap space. ( I wonder how quickly the card will die by the way ;)). Now you need to decide where you are going to put your Gentoo chroot for instance in /home/user/MyDocs/Gentoo and create that folder so your new partition on the SD card can be mounted there (but we need to format it first).

mkdir /home/user/MyDocs/Gentoo
mkfs.ext2 /dev/mmcblk1p2
mkswap /dev/mmcblk1p3
mount /dev/mmcblk1p2 /home/user/MyDocs/Gentoo

With the correct card setup in place, the next thing is to get a Gentoo stage for the arm achitecture, which you can get from the site. The N900 is a ARMv7 board and you can use the hardfp stages. Untar it in your chroot folder:

tar -jxpf stage3-*.tar.bz2

After mounting few additional folders, we can jump in to our new Gentoo environment, so mount first:

mount -o bind /dev /home/user/MyDocs/Gentoo/dev
mount -o bind /dev/pts /home/user/MyDocs/Gentoo/dev/pts
mount -o bind /dev/shm /home/user/MyDocs/Gentoo/dev/shm
mount -o bind /proc /home/user/MyDocs/Gentoo/proc
mount -o bind /sys /home/user/MyDocs/Gentoo/sys
mount -o bind /tmp /home/user/MyDocs/Gentoo/tmp

Note that the mounting of /dev/pts will allow you to run the screen command within the chroot which will come handy later...

Now for the chroot itself:

chroot /home/user/MyDocs/Gentoo/ /bin/bash
source /etc/profile
export PS1="(chroot) $PS1"

Done! It's probably a good idea to put the 'mount' commands along with the 'chroot' into a shell script somewhere on the N900 so you can run it again quickly after restarting the phone.

N900 / # eselect profile list
Available profile symlink targets:
[1] default/linux/arm/10.0 *
[2] default/linux/arm/10.0/desktop
[3] default/linux/arm/10.0/desktop/gnome
[4] default/linux/arm/10.0/desktop/kde
[5] default/linux/arm/10.0/developer
[6] default/linux/arm/10.0/server
[7] default/linux/arm/10.0/armv4
[8] default/linux/arm/10.0/armv4/desktop
[9] default/linux/arm/10.0/armv4/desktop/gnome
[10] default/linux/arm/10.0/armv4/desktop/kde
[11] default/linux/arm/10.0/armv4/developer
[12] default/linux/arm/10.0/armv4/server
[13] default/linux/arm/10.0/armv4t
[14] default/linux/arm/10.0/armv4t/desktop
[15] default/linux/arm/10.0/armv4t/desktop/gnome
[16] default/linux/arm/10.0/armv4t/desktop/kde
[17] default/linux/arm/10.0/armv4t/developer
[18] default/linux/arm/10.0/armv4t/server
[19] default/linux/arm/10.0/armv5te
[20] default/linux/arm/10.0/armv5te/desktop
[21] default/linux/arm/10.0/armv5te/desktop/gnome
[22] default/linux/arm/10.0/armv5te/desktop/kde
[23] default/linux/arm/10.0/armv5te/developer
[24] default/linux/arm/10.0/armv5te/server
[25] default/linux/arm/10.0/armv6j
[26] default/linux/arm/10.0/armv6j/desktop
[27] default/linux/arm/10.0/armv6j/desktop/gnome
[28] default/linux/arm/10.0/armv6j/desktop/kde
[29] default/linux/arm/10.0/armv6j/developer
[30] default/linux/arm/10.0/armv6j/server
[31] default/linux/arm/10.0/armv7a
[32] default/linux/arm/10.0/armv7a/desktop
[33] default/linux/arm/10.0/armv7a/desktop/gnome
[34] default/linux/arm/10.0/armv7a/desktop/kde
[35] default/linux/arm/10.0/armv7a/developer
[36] default/linux/arm/10.0/armv7a/server
N900 / # uname -a
Linux N900 #1 PREEMPT Sun Mar 18 20:10:56 EET 2012 armv7l ARMv7 Processor rev 3 (v7l) Nokia RX-51 board GNU/Linux

Next step - making the chroot environment a Gentoo Hardened environment of course! ;] We will have to create a hardened toolchain first, but that's a story for the next post :)

Sunday, 17 June 2012

Raspberry Pi forever - getting the SD card(s) to work along with some numbers and graphs

I have finally got my hands on the awesome Raspberry Pi board with a vicious plan of running a hardened Gentoo on it of course ;] But before that could happen, I had to get a decent SD card for it, which turned out to be not that obvious. There's a wiki page with a list of SD cards that should and shouldn't work with your Raspberry. There's also a discussion thread on the Raspberry Pi forum about performance of various cards, which is vital to the overall performance of the system. I took an SD card from my camera - a 16GB SanDisk Extreme SD card, which is a Class 10 card and should do "up to 45MB/s". I also decided to buy a 16GB micro SDHC SanDisk Card with adapter. SanDisk claims this card can do "up to 30MB/s" and is marked as '200x' class 6 card. What what I could tell, there were at least some people who were able to get it to work with Pi and got a decent performance out of it.

So I had the following candidates:
  • 16GB SanDisk Extreme SD card, class 10, 45 MB/s
  • 16GB micro SDHC SanDisk Card with adapter, class 6, 30MB/s
For an easy start, I grabbed the debian image of the Raspberry Pi site, put on the cards and booted the Pi. None of the card let me boot the system. Ooops! My hope was that updating the kernel will make a difference...Fortunately, updating kernel image on the Pi is easy, you just need to grab the kernel files from here. All I've done was to replace the kernel.img, kernel_emergency.img and start.elf on the first partion of the card, with the files available in the /boot folder from the firmware repository. Next step was to update the /modules folder from the firmware repository, which can be found in /lib/ folder on the second partition on the card. Voila! With the new kernel both cards booted the Debian Pi successfully!

root@raspberrypi:~# uname -a Linux raspberrypi 3.1.9+ #122 PREEMPT Sun Jun 17 00:30:41 BST 2012 armv6l GNU/Linux

Now I was curious how well can each of the card perform. I've run the CrystalMark tool on both of them, but the results were fairly inconclusive - both cards scored pretty much the same results, with the random write speeds fluctuating between 1.0 - 1.3 MB/s. Not a bad result anyway! Regardless, I don't like running Windows...;) and I wanted to run something on the Pi itself, as I think it gives better comparable results between users, because it's done on the very same hardware - the Pi itself :) So hdparm went first, simply run as

hdparm -t /dev/mmcblk0

...and I got the following results for the Extreme 45 MB/s card:

root@raspberrypi:~# hdparm -t /dev/mmcblk0 /dev/mmcblk0: Timing buffered disk reads: 60 MB in 3.08 seconds = 19.47 MB/sec

the Ultra 30 MB/s card scored:

root@raspberrypi:/home/pi# hdparm -t /dev/mmcblk0 /dev/mmcblk0: Timing buffered disk reads: 60 MB in 3.08 seconds = 19.48 MB/sec

Again, pretty much the same results - a taste of things to come. Let's see...

I was interested how they would both perform with random reads and writes, to test in the similar manner that the CrystalMark tool does. I found that there's a great linux tool than can achieve this - fio. Fio is a very versatile tool and provide a lot of testing options. It can also log results to a file, which then can be plotted with gnuplot using a script that is also provided with fio. I created simple three cases:
  • random read
  • random write
  • random read/write
Each one of them was defined as follows (in three separate files, as otherwise fio would run them simultaneusly as a separate threads. Not something I wanted but an interesting feature for creating more complex tests):




All tests where done over ssh, other than the login shell, the system was idle.

Results below, first, the Extreme card, random read, 2 best and 2 worst results out of approximately 10 runs:

READ: io=102400KB, aggrb=3370KB/s, minb=3451KB/s, maxb=3451KB/s, mint=30377msec, maxt=30377msec
READ: io=102400KB, aggrb=2881KB/s, minb=2951KB/s, maxb=2951KB/s, mint=35531msec, maxt=35531msec
READ: io=102400KB, aggrb=2783KB/s, minb=2850KB/s, maxb=2850KB/s, mint=36789msec, maxt=36789msec
READ: io=102400KB, aggrb=2766KB/s, minb=2832KB/s, maxb=2832KB/s, mint=37018msec, maxt=37018msec

...and the Ultra card:

READ: io=102400KB, aggrb=3355KB/s, minb=3436KB/s, maxb=3436KB/s, mint=30513msec, maxt=30513msec
READ: io=102400KB, aggrb=3337KB/s, minb=3417KB/s, maxb=3417KB/s, mint=30682msec, maxt=30682msec
READ: io=102400KB, aggrb=3218KB/s, minb=3295KB/s, maxb=3295KB/s, mint=31814msec, maxt=31814msec
READ: io=102400KB, aggrb=3210KB/s, minb=3287KB/s, maxb=3287KB/s, mint=31891msec, maxt=31891msec

More or less, same results, the Ultra card seems actually more consistent than the Extreme card...

Now the random write results below, 2 best and 2 worst results out of approximately 10 runs, the Extreme card:

WRITE: io=102400KB, aggrb=1192KB/s, minb=1221KB/s, maxb=1221KB/s, mint=85842msec, maxt=85842msec
WRITE: io=102400KB, aggrb=1181KB/s, minb=1209KB/s, maxb=1209KB/s, mint=86696msec, maxt=86696msec
WRITE: io=102400KB, aggrb=1111KB/s, minb=1138KB/s, maxb=1138KB/s, mint=92104msec, maxt=92104msec
WRITE: io=102400KB, aggrb=956KB/s, minb=979KB/s, maxb=979KB/s, mint=107096msec, maxt=107096msec

...and the Ultra card:

WRITE: io=102400KB, aggrb=1244KB/s, minb=1274KB/s, maxb=1274KB/s, mint=82269msec, maxt=82269msec
WRITE: io=102400KB, aggrb=1221KB/s, minb=1250KB/s, maxb=1250KB/s, mint=83851msec, maxt=83851msec
WRITE: io=102400KB, aggrb=1027KB/s, minb=1051KB/s, maxb=1051KB/s, mint=99697msec, maxt=99697msec
WRITE: io=102400KB, aggrb=645KB/s, minb=660KB/s, maxb=660KB/s, mint=158708msec, maxt=158708msec

Interesting...apart from the one particularily slow run - the Ultra card is as quick as the Extreme card! And the best result for Ultra is better than for Extreme!
And potentially the most interesting one, random read and write results, again 2 best and 2 worst results out of approximately 10 runs:

READ: io=51484KB, aggrb=1059KB/s, minb=1084KB/s, maxb=1084KB/s, mint=48600msec, maxt=48600msec
WRITE: io=50916KB, aggrb=1047KB/s, minb=1072KB/s, maxb=1072KB/s, mint=48600msec, maxt=48600msec

READ: io=51660KB, aggrb=812KB/s, minb=831KB/s, maxb=831KB/s, mint=63605msec, maxt=63605msec
WRITE: io=50740KB, aggrb=797KB/s, minb=816KB/s, maxb=816KB/s, mint=63605msec, maxt=63605msec

READ: io=50528KB, aggrb=748KB/s, minb=766KB/s, maxb=766KB/s, mint=67502msec, maxt=67502msec
WRITE: io=51872KB, aggrb=768KB/s, minb=786KB/s, maxb=786KB/s, mint=67502msec, maxt=67502msec

READ: io=50456KB, aggrb=723KB/s, minb=740KB/s, maxb=740KB/s, mint=69733msec, maxt=69733msec
WRITE: io=51944KB, aggrb=744KB/s, minb=762KB/s, maxb=762KB/s, mint=69733msec, maxt=69733msec

...and the Ultra card:

READ: io=51028KB, aggrb=894KB/s, minb=915KB/s, maxb=915KB/s, mint=57071msec, maxt=57071msec
WRITE: io=51372KB, aggrb=900KB/s, minb=921KB/s, maxb=921KB/s, mint=57071msec, maxt=57071msec

READ: io=50664KB, aggrb=897KB/s, minb=918KB/s, maxb=918KB/s, mint=56471msec, maxt=56471msec
WRITE: io=51736KB, aggrb=916KB/s, minb=938KB/s, maxb=938KB/s, mint=56471msec, maxt=56471msec

READ: io=51112KB, aggrb=777KB/s, minb=795KB/s, maxb=795KB/s, mint=65773msec, maxt=65773msec
WRITE: io=51288KB, aggrb=779KB/s, minb=798KB/s, maxb=798KB/s, mint=65773msec, maxt=65773msec

READ: io=51308KB, aggrb=741KB/s, minb=759KB/s, maxb=759KB/s, mint=69182msec, maxt=69182msec
WRITE: io=51092KB, aggrb=738KB/s, minb=756KB/s, maxb=756KB/s, mint=69182msec, maxt=69182msec

As I mentioned, fio comes with fio_generate_plots script, that lets you plot collected data. Below are the results for the Extreme card.

Extreme - Random read bandwidth

Extreme - Random read latency

That spike in latency and resulting downward spike in bandwidth is interesting...

Extreme - Random write bandwidth

Extreme - Random write latency

Extreme - Random read/write bandwidth

Extreme - Random read/write latency

...and we can also combine them on one graph:
Extreme - bandwidth - combined

Extreme - latency - combined

And now the graphs for the Ultra card:

Ultra - Random read bandwidth

Ultra - Random read latency

Interesting...the very same spike as for the Extreme card!

Ultra - Random write bandwidth

Ultra - Random write latency

Ultra - Random read/write bandwidth

Ultra - Random read/write latency

...and when combined on one graph:

Ultra - bandwidth - combined

Ultra - latency - combined

Now, using the very same script, I have combined the respective graphs for both cards. Please bear in mind, that these graphs do not contain the best results for each card - hence should not be treated as a definitive point of reference. What you can see though, is that the cards share very similar patterns, even if the actual values are slightly different (again, these are from random runs, rather than the best ones)...

Combined results - Random read bandwidth

Combined results - Random read latency

Combined results - Random write bandwidth

Combined results - Random write latency

Combined results - Random read and write bandwidth

Combined results - Random read and write latency

Conclusion seems that the Extreme card does not perform much better, if at all, than the Ultra card. The fastest results for the random read/write test were significantly better than the highest result for the Ultra card; however, on average, they did perform more or less the same...Whether this testing was enough to give any conclusive results is a different matter...;)

The choice is yours...!

Next step - Gentoo on Pi, but for now...Enjoy the Pi! ;]

Tuesday, 5 June 2012

Default MPROTECT restriction for Firefox and Thunderbird on Gentoo Hardened

Good news! The Firefox and Thunderbird ebuilds in the portage tree disable JIT by default, using the two configuration options I've posted about before. Instead of using the pax_kernel USE flag, they incorporate the jit flag, which is by default disabled on the hardened profile. So, to make the long story short - if you have selected the hardened profile, your Firefox and Thunderbird will work without use of RWX memory pages and with correctly enforced mprotect() default! Happy days :)

From the firefox-13.0.ebuild:

# Both methodjit and tracejit conflict with PaX
mozconfig_use_enable jit methodjit
mozconfig_use_enable jit tracejit

You can quickly check that you are using hardened profile by running:

# eselect profile list
Available profile symlink targets:
[1] default/linux/amd64/10.0
[2] default/linux/amd64/10.0/selinux
[3] default/linux/amd64/10.0/desktop
[4] default/linux/amd64/10.0/desktop/gnome
[5] default/linux/amd64/10.0/desktop/kde
[6] default/linux/amd64/10.0/developer
[7] default/linux/amd64/10.0/no-multilib
[8] default/linux/amd64/10.0/server
[9] hardened/linux/amd64
[10] hardened/linux/amd64/selinux
[11] hardened/linux/amd64/no-multilib *
[12] hardened/linux/amd64/no-multilib/selinux

Bear in mind, that using video plugins, flash or java, will very likely crash your browser. An answer to that could be to use Flash/Java in a different web browser, such as Chromium, which requires RWX pages anyway. Alternatively, one could use a browser that cannot benefit from other hardening options during compilation, simply because its source code is not available, for instance - Opera.

If you experience random Firefox or Thunderbird crashes, make sure that you have all of the aforementioned plugins disabled first, and then try again.

Wednesday, 15 February 2012

Firefox 10.0.1 - MPROTECT strikes again!

It's been a while and Firefox has moved from version 5 to version 10.0.1, now that's a pace! ;) But the important bits are...enforcing MPROTECT has never been easier...well, almost. ;)

Thanks to this attachment in this bug, the latest version of Firefox compiles fine on hardened profiles (or simply on grsec kernels).

In order to enable MPROTECT restrictions, edit the ebuild and at the top add pax_kernel flag to IUSE so it reads like this:

IUSE="bindist +crashreporter +ipc +minimal pgo selinux system-sqlite +webm pax_kernel"

also, add the following snippet in src_configure() before the # Finalize and report settings line:

if use pax_kernel; then
   mozconfig_annotate '' --disable-methodjit
   mozconfig_annotate '' --disable-tracejit

...and get rid of the following lines in src_install():

# Pax mark xpcshell for hardened support, only used for startupcache creation.
pax-mark m "${S}/${obj_dir}"/dist/bin/xpcshell

and this:

# Required in order to use plugins and even run firefox on hardened.
pax-mark m "${ED}"${MOZILLA_FIVE_HOME}/{firefox,firefox-bin,plugin-container}

NOTE:You wan't be able to run Java or Flash as they require RWX mappings which will be not allowed when MPROTECT is enforced. If you need to use them, you can use different browser for it, for instance Chromium.

Now digest your local ebuild:

# ebuild /usr/local/portage/www-client/firefox/firefox-10.0.1.ebuild digest
>>> Creating Manifest for /usr/local/portage/www-client/firefox

...and you're ready to emerge! ;] Once done, start Firefox. If you're starting it from the command line, you'll see the following (expected) error:

LLVM ERROR: Allocation failed when allocating new memory in the JIT
Can't allocate RWX Memory: Operation not permitted

which is exactly what we wanted :) ...and to verify that it works as expected:

$ for pid in $(ps -ef | grep [f]irefox | awk '{print $2}'); do cat /proc/$pid/status | grep PaX; done
PaX: PeMRs

Note the capital 'M' - you're mprotected! ;]

Saturday, 25 June 2011

Firefox 5 with MPROTECT on...of course!

While the Firefox 4 ebuild is still warm, here comes Firefox 5! And yes - we want MPROTECT enabled on it too of course...! ;)

BTW, if you've ever wondered why I'm so preoccupied about the whole mrprotect story, I recommend reading my year old research on the topic which can be found here.

Well, it turns out to be, that with the release of the new Firefox things got much easier actually! There is no need to patch the source anymore, we just need to disable the 'jit' during source configuration. Not only this allows us to actually compile Firefox 5 on Gentoo hardened (sic!) but actually allows to run it with mprotect enabled too! But first things first...

An attempt to install Firefox 5 on Gentoo Hardened system is likely to end up with emerge failing and entry in kern.log similar to this:

grsec: denied RWX mmap of by /var/tmp/portage/www-client/firefox-5.0/work/mozilla-release/obj-x86_64-unknown-linux-gnu/dist/bin/xpcshell[xpcshell:10891] uid/euid:0/0 gid/egid:0/0, parent /bin/bash[sh:10882] uid/euid:0/0 gid/egid:0/0
xpcshell[10891]: segfault at 41ea0ddc ip 00006b9475051ed4 sp 000078b37e81b6f0 error 4 in[6b9474031000+1823000]

While jit seems to like RWX memory pages a lot, Gentoo hardened users do not...;)

But fear not! The trustworthy hack for Firefox 4 works here too, and we don't need to hack the source, it's just enough to add --disable-methodjit the configure script. (For more information on how to create your local overlay have a look at my previous post or refer to your favourite search engine ;) . So basically you could add this to the ebuild, somewhere in the src_configure() section:

if ! use jit ; then
mozconfig_annotate '' --disable-methodjit

..recompile...and off you go! At the moment the firefox binary (/usr/lib/firefox/firefox-bin) is quite likely to have mprotect automatically disabled so you might need to enable it by hand by running:

paxctl -M /usr/lib/firefox/firefox-bin

Bear in mind that Firefox now runs plugins in a separate process - plugin-container. It can also be mprotect enabled or disabled, so you might want to check it's worth noting that enabling mprotect on plugin-container will make Firefox crash probably on every use of Flash or Java, but hey, it's secure then, is it not...? ;)

Gentoo bug tracking all this can be found here.

Monday, 13 June 2011

Enabling MPROTECT on Firefox 4 after nearly a year (sic!), here's the solution to get MPROTECT working with Firefox - browsing the Interwebs can be secure again! ;) Thanks to zakalwe on #grsecurity@OFTC for the patch and help! :)

So the problem of course is JIT - we need to disable it at all cost! (You'll be probably losing some JS performance, ya've been warned!). Well, it's not the most elegant solution, but it does work...The elegant solution would be of course to have an compilation option available to completely disable JIT...

Anyway - let's get our hands dirty, shall we?

The easiest way to do it, would be to create your local overlay (unless you've already got one). Assuming that you don't here's what needs to be done. Choose a folder where you will store you local ebuild - say /usr/local/portage. Next create there required folder structure:

mkdir /usr/local/portage
mkdir -p /usr/local/portage/net-libs/xulrunner

Yes, we actually need to amend the xulrunner ebuild and not the firefox one.

Now we need to copy the "original" ebuild along with the patches which will serve as a baseline:

cp /usr/portage/net-libs/xulrunner/xulrunner-2.0.1-r1.ebuild /usr/local/portage/net-libs/xulrunner/
cp -r /usr/portage/net-libs/xulrunner/files/ /usr/local/portage/net-libs/xulrunner/

Now open the copied ebuild in your favourite editor and locate the following code:

mozconfig_annotate '' --with-default-mozilla-five-home="${MOZLIBDIR}"
mozconfig_annotate '' --enable-extensions="${MEXTENSIONS}"
mozconfig_annotate '' --disable-mailnews
mozconfig_annotate '' --enable-canvas
mozconfig_annotate '' --enable-safe-browsing
mozconfig_annotate '' --with-system-png
mozconfig_annotate '' --enable-system-ffi
mozconfig_use_enable system-sqlite
mozconfig_use_enable gconf

Add after the last mozconfig_annotate line the following code:

mozconfig_annotate '' --disable-jit
mozconfig_annotate '' --disable-methodjit the whole chunk looks like this:

mozconfig_annotate '' --with-default-mozilla-five-home="${MOZLIBDIR}"
mozconfig_annotate '' --enable-extensions="${MEXTENSIONS}"
mozconfig_annotate '' --disable-mailnews
mozconfig_annotate '' --enable-canvas
mozconfig_annotate '' --enable-safe-browsing
mozconfig_annotate '' --with-system-png
mozconfig_annotate '' --enable-system-ffi
mozconfig_annotate '' --disable-jit
mozconfig_annotate '' --disable-methodjit
mozconfig_use_enable system-sqlite
mozconfig_use_enable gconf

Halfway through! Now, unfortunately that is not enough - we'll have to patch xulrunners source here we go!

First, create folder where we can save our patch to be automatically picked up during compilation. It could be added explicitly to the ebuild but this way is just easier and less scary for some perhaps ;)

mkdir -p /etc/portage/patches/net-libs/xulrunner

...and save in that folder file (under whatever name) with the content below:

diff -Nurp ./mozilla-2.0/js/src/assembler/wtf/Platform.h
--- ./mozilla-2.0/js/src/assembler/wtf/Platform.h 2011-05-12
22:06:56.000000000 +0100
+++ ./ 2011-05-12
22:12:35.000000000 +0100
@@ -918,15 +918,7 @@ on MinGW. See
 #if !defined(ENABLE_YARR_JIT)

 /* YARR supports x86 & x86-64, and has been tested on Mac and Windows. */
-#if (WTF_CPU_X86 \
- || WTF_CPU_X86_64 \
- || WTF_CPU_X86)
-#define ENABLE_YARR_JIT 1
 #define ENABLE_YARR_JIT 0

 #endif /* !defined(ENABLE_YARR_JIT) */

Nearly there! Now, we need to create digest for our newly created ebuild,so:

# ebuild /usr/local/portage/net-libs/xulrunner/xulrunner-2.0.1-r1.ebuild digest
>>> Creating Manifest for /usr/local/portage/net-libs/xulrunner

...and tell portage to use our local ebuild:

echo PORTDIR_OVERLAY="/usr/local/portage" >> /etc/make.conf

Ready to compile! Emerging xulrunner should give you output similar to this:

# emerge -av xulrunner

These are the packages that would be merged, in order:

Calculating dependencies... done!
[ebuild R ~] net-libs/xulrunner-2.0.1-r1 USE="alsa crashreporter dbus ipc webm wifi -custom-optimization -debug -gconf -libnotify -startup-notification -system-sqlite" 0 kB [0=>1]

Total: 1 package (1 reinstall), Size of downloads: 0 kB
Portage tree and overlays:
[0] /usr/portage
[1] /usr/local/portage

As can be seen, our new ebuild is just about to be emerged!

Make sure that you see the code being patched (I named the patch jit.patch)

* 5009_use_system_libffi.patch ... [ ok ]
* Done with patching
* Applying mozilla-2.0_support_64bit_big_endian.patch ... [ ok ]
* Applying user patches from /etc/portage/patches//net-libs/xulrunner ...
* jit.patch ... [ ok ]

* Done with patching

...and then when the summary of config options is displayed (seconds later), you will see this:

--with-system-png default
--enable-system-ffi default
--disable-jit default
--disable-methodjit default

--disable-system-sqlite -system-sqlite
--disable-gconf -gconf

Looks good! So after short while...perfect for a cup of coffee or a pint of your favourite lager, xulrunner is ready! Now we need to recompile firefox itself against it...

emerge firefox

The ebuild will still disable mprotect on Firefox as we haven't touched it. Just before we enable it using paxutils, we need to disable all the JIT options in Firefox itself. So start it up, type "about:config" in the address bar and hit enter. Don't be worry about loosing warranty ;) Type jit in the filter and disable any option that is set to 'true' (click twice on it to change its value). Close Firefox and we can enable mprotect now!

# paxctl -v /usr/lib/firefox/firefox
PaX control v0.5
Copyright 2004,2005,2006,2007 PaX Team

- PaX flags: -----m-x-e-- [/usr/lib/firefox/firefox]
MPROTECT is disabled
RANDEXEC is disabled
EMUTRAMP is disabled

But that's not what we want! So:

# paxctl -M /usr/lib/firefox/firefox
# paxctl -v /usr/lib/firefox/firefox
PaX control v0.5
Copyright 2004,2005,2006,2007 PaX Team

- PaX flags: ----M--x-e-- [/usr/lib/firefox/firefox]
MPROTECT is enabled
RANDEXEC is disabled
EMUTRAMP is disabled

Start Firefox and...voila - it works! :)

It is worth noting, that plugins now run in a separate process: plugin-container which is normally located in /usr/lib/xulrunner-2.0/. To achieve best security, it should have the mprotect flag enabled as well. (Un)fortunatelly - flash will not work! So if you don't care about youtube and alike:

paxctl -M /usr/lib64/xulrunner-2.0/plugin-container

To verify that it is actually working you can find the PID of firefox running the ps command and then cat /proc/PID/status and at the bottom there will be something like this:

Cpus_allowed: f
Cpus_allowed_list: 0-3
Mems_allowed: 00000000,00000001
Mems_allowed_list: 0
voluntary_ctxt_switches: 21023
nonvoluntary_ctxt_switches: 1664
PaX: PeMRs

...where the capital 'M' stands for enabled MPROTECT. How cool is that? ;) Enjoy!