Promise VTrak M500f

From fakedWiki
Revision as of 22:06, 3 August 2011 by Jan (talk | contribs)
Jump to: navigation, search

Getting Started

Thanks to Mathis Schmieder for the fsck.cramfs tip!

Analyzing the Firmware file

binwalk -v iv2p_all_20110303_16mb.img
Scan Time:    Aug 03, 2011 @ 20:13:21
Magic File:   /etc/binwalk/magic.binwalk
Signatures:   67
Target File:  iv2p_all_20110303_16mb.img
MD5 Checksum: b8dad677c907a53ca9b222f2103c13b3

DECIMAL         HEX             DESCRIPTION
-------------------------------------------------------------------------------------------------------
18204           0x471C          gzip compressed data, from Unix, last modified: Thu Apr 20 05:12:30 2006, max compression
871968          0xD4E20         Linux Compressed ROM filesystem data, little endian size 2584576 version #2 sorted_dirs           CRC 0xeeb623f0, edition 0, 1217 blocks,            7 files
3456544         0x34BE20        Linux Compressed ROM filesystem data, little endian size 3231744 version #2 sorted_dirs           CRC 0xf1e0771a, edition 0, 2870 blocks,            946 files
3528967         0x35D907        bzip2 compressed data
6688288         0x660E20        gzip compressed data, from Unix, last modified: Thu Mar  3 03:51:40 2011, max compression
11309493        0xAC91B5        Linux Compressed ROM filesystem data, little endian size 1277952 version #2 sorted_dirs           CRC 0x477edaab, edition 0, 802 blocks,            142 files
12882033        0xC49071        LZMA compressed data, properties: 0x5D, dictionary size: 335544320 bytes, uncompressed size: 30 bytes
13215338        0xC9A66A        LZMA compressed data, properties: 0x85, dictionary size: 740294656 bytes, uncompressed size: 16388 bytes
13216042        0xC9A92A        LZMA compressed data, properties: 0x86, dictionary size: 745537536 bytes, uncompressed size: 16388 bytes
13216734        0xC9ABDE        LZMA compressed data, properties: 0x89, dictionary size: 747110400 bytes, uncompressed size: 16388 bytes
13219257        0xC9B5B9        LZMA compressed data, properties: 0x5D, dictionary size: 335544320 bytes, uncompressed size: 30 bytes
13220658        0xC9BB32        LZMA compressed data, properties: 0x95, dictionary size: 272629760 bytes, uncompressed size: 16387 bytes
13221334        0xC9BDD6        LZMA compressed data, properties: 0x90, dictionary size: 65536 bytes, uncompressed size: 65536 bytes
13221354        0xC9BDEA        LZMA compressed data, properties: 0x90, dictionary size: 65536 bytes, uncompressed size: 65536 bytes

Extracting the Firmware parts

Part 1

dd if=iv2p_all_20110303_16mb.img bs=1 skip=18204 count=853764 of=part1.gz
gunzip part1.gz
file part1
part1: data

Part 2

dd if=iv2p_all_20110303_16mb.img bs=1 skip=871968 count=2584576 of=part2.cramfs
mkdir part2
mount -o loop parts2.cramfs part2/
ls -l part2/
total 4858
-rw-r--r-- 1 root root   18204 Jan  1  1970 iodrv.o
-rw-r--r-- 1 root root  233655 Jan  1  1970 Marvell.o
-rw-r--r-- 1 root root  470713 Jan  1  1970 qla4xxx.o
-rw-r--r-- 1 root root 3193368 Jan  1  1970 raid_core.o
-rw-r--r-- 1 root root  436560 Jan  1  1970 scsi.o
-rw-r--r-- 1 root root  619697 Jan  1  1970 xfc.o

Part 3

dd if=iv2p_all_20110303_16mb.img bs=1 skip=3456544 count=72423 of=part3.cramfs
mount -o loop part3.cramfs part3/
ls -lR part3/

Full contents of Part 3

fsck.cramfs part3.cramfs
fsck.cramfs: file length too short

Part 4

dd if=iv2p_all_20110303_16mb.img bs=1 skip=3528967 count=3159321 of=part4.bz2
bunzip2 part4.bz2
bunzip2: part4.bz2 is not a bzip2 file.

Part 5

dd if=iv2p_all_20110303_16mb.img bs=1 skip=6688288 count=4621205 of=part5.gz
gunzip part5.gz
file part5
part5: Linux rev 1.0 ext2 filesystem data, UUID=1e4f9d2b-b406-4a38-bbf8-8f1fcf52e5c7
mv part5 part5.ext2
mkdir part5
mount -o loop part5.ext2 part5/
ls -lR part5/

Full contents of Part 5

Part 6

dd if=iv2p_all_20110303_16mb.img bs=1 skip=11309493 count=1572540 of=part6.cramfs
mkdir part6/
mount -o loop part6.cramfs part6/
ls -lR part6/

Full contents of Part 6

Fixing Part 3

Part 3 is a broken CramFS, and Part 4 is "data"... smells fishy. Let's say Part 3 is actually Part 3.1 and Part 4 is Part 3.2:

dd if=iv2p_all_20110303_16mb.img bs=1 skip=3456544 count=3231744 of=part3.cramfs
fsck.cramfs -v part3.cramfs
cramfs endianness is little
part3.cramfs: OK

Bingo!

Oh, exploitable!

So here's the root of all problems: in line 23 and 24, PHP is told to get the language of the user's browser from a header that's sent on each request. No problem there, you probably won't ever see an error, as your browser provides this header.

If you're using a monitoring tool like Nagios to check if the webinterface is still alive, your Nagios check doesn't send that header and PHP will throw an error of the level NOTICE.

php -a
Interactive mode enabled

<?php
preg_match('/^([a-z\-]+)/i', $_SERVER['HTTP_ACCEPT_LANGUAGE'], $matches);
    $lang=$matches[1];
    switch(substr($lang,0,2))
    {
      case 'en':
   $language='en_US';
        break;
      // [...]
      default:
        $language='en_US';
        break;
    }
?>
PHP Notice:  Undefined index: HTTP_ACCEPT_LANGUAGE in - on line 2
PHP Notice:  Undefined offset: 1 in - on line 3

Being the good developer that you are, you hide those errors from the user and only write them to a logfile somewhere on your device's internal flash.

So, your Nagios checks the webserver every 5 minutes, every hour of the day, every day of the week, etc., and every time there are a couple of lines appended to the logfile.

Now what would you think will happen if that logfile gets so big that there is no space left on that flash?

I can tell you what happens next:

islavista>_