|
Title: Invision Power Board <= 2.3.5=0D
Multiple Vulnerabilities and Security Bypass=0D
=0D
Vendor: http://www.invisionpower.com/community/board/=0D
=0D
Advisory: http://acid-root.new.fr/?0:18=0D
Author: DarkFig < gmdarkfig (at) gmail (dot) com >=0D
=0D
Released on: 2008/08/29=0D
Changelog: 2008/08/29=0D
=0D
Summary: Introduction=0D
Blind SQL Injection=0D
Insecure SQL Password Usage=0D
Admin Session Hijacking=0D
Deep Recursion Protection Bypass=0D
Code Execution=0D
Miscellanious=0D
=0D
Risk level: Medium / High=0D
CVE: ----------=0D
=0D
=0D
=0D
=0D
I - INTRODUCTION=0D
=0D
Before continuing, you need to know some stuff about how=0D
user's inputs are handled. All superglobal arrays which=0D
can be partially modified by the user, are passed to the =0D
function "parse_clean_globals()". Let's see the content=0D
of the file "sources/ipsclass.php":=0D
=0D
4847| $this->clean_globals( $_GET );=0D
4848| $this->clean_globals( $_POST );=0D
4849| $this->clean_globals( $_COOKIE );=0D
4850| $this->clean_globals( $_REQUEST );=0D
=0D
This function will replace special characters such as=0D
the null byte one and "../" (this replacement can be =0D
easily bypassed, we'll see that later), by their=0D
entities. Good idea, but bad implementation:=0D
=0D
4979| function clean_globals( &$data, $iteration = 0 )=0D
....|=0D
4991| foreach( $data as $k => $v )=0D
4992| {=0D
....|=0D
4999| # Null byte characters=0D
5000| $v = preg_replace( '/\\\0/' , '\0', $v );=0D
5001| $v = preg_replace( '/\\x00/', '\x00', $v );=0D
5002| $v = str_replace( '%00' , '%00', $v );=0D
5003| =0D
5004| # File traversal=0D
5005| $v = str_replace( '../' , '../', $v )=0D
5006|=0D
5007| $data[ $k ] = $v;=0D
=0D
Then, variables which are sent through the GET and=0D
POST methods are passed to another function. Note =0D
that POST variables overwrite the ones sent with the=0D
GET method:=0D
=0D
4852| # GET first=0D
4853| $input = $this->parse_incoming_recursively( $_GET, array() );=0D
4854| =0D
4855| # Then overwrite with POST=0D
4856| $input = $this->parse_incoming_recursively( $_POST, $input );=0D
4857|=0D
4858| $this->input = $input;=0D
=0D
Then POST and GET inputs are passed to the function =0D
"parse_incoming_recursively()". Each input are passed to=0D
two functions. Names are passed to the "parse_clean_key()"=0D
function, values to "parse_clean_value()":=0D
=0D
4940| function parse_incoming_recursively(&$data,$input=array()...=0D
4941| {=0D
....|=0D
4952| foreach( $data as $k => $v )=0D
4953| { =0D
....|=0D
4961| $k = $this->parse_clean_key( $k );=0D
4962| $v = $this->parse_clean_value( $v );=0D
4963| =0D
4964| $input[ $k ] = $v;=0D
4965| }=0D
....|=0D
4969| return $input;=0D
=0D
The "parse_clean_key()" function uses the "urldecode()"=0D
function, this means you can encode each variable names. =0D
=0D
For example, the parameter "act=Members" is the same =0D
as "%2561%2563%2574=Members". We don't really care=0D
about it, cause it will not cause a problem for the=0D
attacker:=0D
=0D
5024| function parse_clean_key($key)=0D
5025| {=0D
5026| if ($key == "")=0D
5027| {=0D
5028| return "";=0D
5029| }=0D
5030| =0D
5031| $key = htmlspecialchars(urldecode($key));=0D
5032| $key = str_replace( ".." , "" , $key );=0D
5033| $key = preg_replace( "/\_\_(.+?)\_\_/" , "" , $key );=0D
5034| $key = preg_replace( "/^([\w\.\-\_]+)$/", "$1", $key );=0D
5035| =0D
5036| return $key;=0D
5037| }=0D
=0D
This one will replace malicious tags by their entities.=0D
The most efficient replacement, is the one which protect=0D
against SQL Injections, (single/double quotes).=0D
=0D
Replacements concerning strings wich contains more than=0D
1 characters can be bypassed with the CR (Carriage Return)=0D
character (eg: bypassing the replacement of ../ by using =0D
..%0D/).=0D
=0D
We can also use that trick to encode links. For example the=0D
parameter "act=Members", is the same as "%2561%2563%2574==0D
M%0De%0Dm%0Db%0De%0Dr%0Ds":=0D
=0D
5077| function parse_clean_value($val)=0D
5078| {=0D
....|=0D
5084| $val = str_replace( " ", " ", $this->txt_stripslashes($val));=0D
....|=0D
5093| $val = str_replace( "", '' , $val );=0D
5094| =0D
5095| $val = str_replace( "&", "&" , $val );=0D
5096| $val = str_replace( "", "-->" , $val );=0D
5098| $val = preg_replace( "/