Added basic support for Wietse Venema's taint feature. Fixed a few instances of shodd...
authorTim Starling <tstarling@users.mediawiki.org>
Wed, 4 Feb 2009 09:10:32 +0000 (09:10 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Wed, 4 Feb 2009 09:10:32 +0000 (09:10 +0000)
includes/GlobalFunctions.php
includes/User.php
includes/UserMailer.php
includes/WebRequest.php
includes/db/Database.php
includes/parser/Preprocessor_DOM.php
includes/parser/Preprocessor_Hash.php
includes/templates/NoLocalSettings.php

index 8af83ac..42e1e46 100644 (file)
@@ -89,6 +89,19 @@ if ( !function_exists( 'array_diff_key' ) ) {
        }
 }
 
+// Support for Wietse Venema's taint feature
+if ( !function_exists( 'istainted' ) ) {
+       function istainted( $var ) {
+               return 0;
+       }
+       function taint( $var, $level = 0 ) {}
+       function untaint( $var, $level = 0 ) {}
+       define( 'TC_HTML', 1 );
+       define( 'TC_SHELL', 1 );
+       define( 'TC_MYSQL', 1 );
+       define( 'TC_PCRE', 1 );
+       define( 'TC_SELF', 1 );
+}
 /// @endcond
 
 
index eb8c5fe..e0289f8 100644 (file)
@@ -915,7 +915,7 @@ class User {
                $this->mDataLoaded = true;
 
                if ( isset( $row->user_id ) ) {
-                       $this->mId = $row->user_id;
+                       $this->mId = intval( $row->user_id );
                }
                $this->mName = $row->user_name;
                $this->mRealName = $row->user_real_name;
index a2d4bae..7728abf 100644 (file)
@@ -363,7 +363,7 @@ class EmailNotification {
 
                        if ( $wgEnotifWatchlist ) {
                                // Send updates to watchers other than the current editor
-                               $userCondition = 'wl_user != ' . $editor->getID();
+                               $userCondition = 'wl_user != ' . intval( $editor->getID() );
                                if ( $userTalkId !== false ) {
                                        // Already sent an email to this person
                                        $userCondition .= ' AND wl_user != ' . intval( $userTalkId );
@@ -415,7 +415,7 @@ class EmailNotification {
                                        'wl_title' => $title->getDBkey(),
                                        'wl_namespace' => $title->getNamespace(),
                                        'wl_notificationtimestamp IS NULL', // store oldest unseen change time
-                                       'wl_user != ' . $editor->getID()
+                                       'wl_user != ' . intval( $editor->getID() )
                                ), __METHOD__
                        );
                        $dbw->commit();
index 4674712..0928e4d 100644 (file)
@@ -231,6 +231,7 @@ class WebRequest {
                        $data = $this->normalizeUnicode( $data );
                        return $data;
                } else {
+                       taint( $default );
                        return $default;
                }
        }
@@ -251,7 +252,7 @@ class WebRequest {
                        $val = $default;
                }
                if( is_null( $val ) ) {
-                       return null;
+                       return $val;
                } else {
                        return (string)$val;
                }
index 82db7da..3839918 100644 (file)
@@ -566,6 +566,10 @@ class Database {
                        }
                }
 
+               if ( istainted( $sql ) & TC_MYSQL ) {
+                       throw new MWException( 'Tainted query found' );
+               }
+
                # Do the query and handle errors
                $ret = $this->doQuery( $commentedSql );
 
index af591b6..502d81f 100644 (file)
@@ -304,7 +304,9 @@ class Preprocessor_DOM implements Preprocessor {
                                } else {
                                        $attrEnd = $tagEndPos;
                                        // Find closing tag
-                                       if ( preg_match( "/<\/$name\s*>/i", $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) ) {
+                                       if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i", 
+                                                       $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) ) 
+                                       {
                                                $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
                                                $i = $matches[0][1] + strlen( $matches[0][0] );
                                                $close = '<close>' . htmlspecialchars( $matches[0][0] ) . '</close>';
index 6202829..0e0fb57 100644 (file)
@@ -288,7 +288,9 @@ class Preprocessor_Hash implements Preprocessor {
                                } else {
                                        $attrEnd = $tagEndPos;
                                        // Find closing tag
-                                       if ( preg_match( "/<\/$name\s*>/i", $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) ) {
+                                       if ( preg_match( "/<\/" . preg_quote( $name, '/' ) . "\s*>/i", 
+                                                       $text, $matches, PREG_OFFSET_CAPTURE, $tagEndPos + 1 ) ) 
+                                       {
                                                $inner = substr( $text, $tagEndPos + 1, $matches[0][1] - $tagEndPos - 1 );
                                                $i = $matches[0][1] + strlen( $matches[0][0] );
                                                $close = $matches[0][0];
index 107f792..6a56614 100644 (file)
@@ -4,10 +4,7 @@
  * @ingroup Templates
  */
 
-# Prevent XSS
-if ( isset( $wgVersion ) ) {
-       $wgVersion = htmlspecialchars( $wgVersion );
-} else {
+if ( !isset( $wgVersion ) ) {
        $wgVersion = 'VERSION';
 }
 
@@ -40,7 +37,7 @@ foreach( $topdirs as $dir ){
 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns='http://www.w3.org/1999/xhtml' xml:lang='en' lang='en'>
        <head>
-               <title>MediaWiki <?php echo $wgVersion ?></title>
+               <title>MediaWiki <?php echo htmlspecialchars( $wgVersion ) ?></title>
                <meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
                <style type='text/css' media='screen, projection'>
                        html, body {
@@ -56,15 +53,15 @@ foreach( $topdirs as $dir ){
                </style>
        </head>
        <body>
-               <img src="<?php echo $path ?>skins/common/images/mediawiki.png" alt='The MediaWiki logo' />
+               <img src="<?php echo htmlspecialchars( $path ) ?>skins/common/images/mediawiki.png" alt='The MediaWiki logo' />
 
-               <h1>MediaWiki <?php echo $wgVersion ?></h1>
+               <h1>MediaWiki <?php echo htmlspecialchars( $wgVersion ) ?></h1>
                <div class='error'>
                <?php
                if ( file_exists( 'config/LocalSettings.php' ) ) {
                        echo( 'To complete the installation, move <tt>config/LocalSettings.php</tt> to the parent directory.' );
                } else {
-                       echo( "Please <a href=\"${path}config/index.{$ext}\" title='setup'> set up the wiki</a> first." );
+                       echo( "Please <a href=\"" . htmlspecialchars( $path ) . "config/index." . htmlspecialchars( $ext ) . "\" title='setup'> set up the wiki</a> first." );
                }
                ?>