<<< Date Index >>>     <<< Thread Index >>>

ULtimate PHP Board <= 1.96 GOLD Code Execution (exploit code)



&#65279; Ultimate PHP Board v. 1.9.6 GOLD Current  Security Advisory

[Vulnerability List Affecting Ultimate PHP Board =>1.96 GOLD]
Multiple Issues Resulting In  Remote Code Execution
Private Key Collision Generator
Decryption/Encryption without brute force 
Insecure Session Management
NON-SQL database injection leading to the creation of an administrative account
NON-SQL database injection leading to full read access to database and code 
execution
directory traversal found in multiple calls to the chmod() function  
 PHP include() code execution 

[EXPLOIT] (in PHP)
http://www.kliconsulting.com/users/mbrooks/UPB_0-day.txt

Vendors site:
http://forum.myupb.com/
Download:
http://fileserv.myupb.com/download.php?url=upb196GOLD.zip
http://prdownloads.sourceforge.net/textmb/upb1.8.2.zip?download
Download Mirror:
http://www.kliconsulting.com/users/mbrooks/upb196GOLD.zip
http://www.kliconsulting.com/users/mbrooks/upb1.8.2.zip

[Introduction]
  Ultimate PHP Board is feature rich and it serves a purpose.   One UPB's best 
features is that its very simple to install.  UPB uses a unique implementation 
of three major features;  session management,  an encryption algorithm  and,  a 
flat file database.  Though it this web application is functional,  these three 
areas are very insecure.  The database implementation alone is vulnerable to 
two types of NON-SQL database injection resulting in the creation of new 
accounts,  remote code execution and the ability to gain  full read access to 
the database.  I really enjoyed doing security development for this project.  
So many features where done in house resulting in fairly unique attacks.   

[Install]
Ultimate PHP Board(UPB) is a easy to install easy to use web application.    
Uncompress the archive and set the permissions and its ready to run.  You do 
not need to configure a database as you would with mysql and phpbb.  You do 
however have to modify your permissions to allow UPB to function properly.  a 
`chmod 777 -R *` in the UPB folder will work.    The default administrative 
password is (Admin:admin [case sensitive]).    UPB will not work properly 
unless it can write to its flat file database system and configuration files,  
my exploit will not function properly unless UPB is functioning properly.   UPB 
can be exploited even if it has never been used!  This Zero Setup system helps 
the attacker as well.  In order to activate an account with UPB you must be 
able to receive a generated password via e-mail.  All working UPB servers 
should have e-mail addresses in there database and the ability to send mail. 
This makes UPB a prime target for illegal spamers.

[Cryptography  Issue]
The Cryptographic algorithm used in Ultimate PHP Board is unique.  This is a 
huge red flag, there are many public Cryptographic algorithms that are far more 
secure than this one.   The Cryptographic algorithm used is a symmetric key 
block cypher.  This block cypher is two way and has a key.   There are Two 
cryptography issues affecting  this application.  One is an implementation 
issue,  the other is a non-trivial attack against the block cypher its self. 

 The implementation issue is that the key used to encrypt and decrypt *should* 
have been private.  The fact that this key is a static value distributed with 
the web application,  allows for the non brute force decryption of passwords in 
a default installation of Ultimate PHP Board.   This fast decryption is 
provided in the exploit code.   A very simple patch for this implementation 
issue would be to generate a random key before using the block cypher.

The encryption and decryption can be found in:
./textdb.inc.php line 324:
function t_encrypt($text,$key){

There is another issue affecting this block cypher,  the generation of key 
collisions.  This is a NON-Trivial attack on this block cypher.   What is 
needed is a plain text value and its corresponding cypher text.    This can be 
obtained by  legitimately singing up for an account then singing in.  The 
password used to login is the plain text,  and the cypher text is the 
?pass_env? cookie value.   With the plain and cypher text data an offset can be 
generated.    This offset can be used to generate up to 256 key collisions.  
The offset alone can be used for encryption and decryption. 

the authors encryption algorithm can be expressed as:
cypher_text[x] = text[x] + key[x] -  key[x+1]
or
cypher_text[x] - text[x]  =  key[x] ? key[x+1] 
This creates an offset:
offset[x] = key[x] ? key[x+1] 
offset[x] = cypher_text[x] - text[x]  
which means that every key has an offset and  the offset alone can be used to 
encryption and decryption:
cypher_text[x] = text[x] + offset[x] 
text[x] = offset[x] - cypher_text[x]

All 256 possible key collisions can be generated from the key collision. 
Collision is possible because the starting character does not affect the 
algorithm,  what matters is the difference between characters.  The encoding is 
using the extended ascii set: http://www.lookuptables.com/ . The exploit code 
generates keys 0-255,  or 256 possible combinations.  If you give the function 
a number like 256,  the character will overflow resulting in the value of 0,  
257 is 1, 258 is 2,  and so on. 

Some examples using the key distributed with Ultimate PHP board 1.96 Gold
Key:120 = xeozzkjoggo
Cypher:D((4D72@9(
Plain :1234567890

This is the first eleven characters of the real key:
Key:119 = wdnyyjinffn  
Cypher:D((4D72@9(
Plain :1234567890

Key:118 = vcmxxihmeem
Cypher:D((4D72@9(
Plain :1234567890

The same keys in uppercase are also collisions:

Key:88 = XEOZZKJOGGO
Cypher:D((4D72@9(
Plain :1234567890

Key:87 = WDNYYJINFFN
Cypher:D((4D72@9(
Plain :1234567890

Key:86 = VCMXXIHMEEM
Cypher:D((4D72@9(
Plain :1234567890

Not all of the keys print out properly due to control characters in the ASCII 
set,  however all keys can be used for encryption and decryption,  which is 
shown in the exploit code. 

An attack is possible using this key collision weakness.  For the sake of 
argument lets say that the encryption algorithm is implemented correctly with a 
secure private key.   An attacker could change there password to a very long 
string then login using that long password.  If the attacker creates the 
longest password,  then the attacker will be able to decrypt every password  by 
access /db/users.dat using the exploit code.    I wonder how many people have 
the same password for there e-mail account as there Ultimate PHP Board 
account... 

First of all a block cypher should not be used for a password,  one should use 
a one way hash.  Second of all there are many many publicly available 
encryption algorithms that are in orders of magnitude more secure than this.  
Keep in mind SHA-0, SHA-1 and MD5 are broken, so please STOP USING THEM.  Even 
though MD5 is broken it is still more secure than this current system. 

[Session Issue]
Due to the way that sessions are handled decryption of the password is not 
needed to login.   Sessions are immortal; the web application does a string 
compare of the cookie with the value in the database.     On a default install 
of UPB the administrative login is user name: ?Admin?  password: ?admin?  This 
login has the most privileges on the board with the value of 3.  This is the 
first account with the id value of 1.
The cookie value for this account is:
Cookie: user_env=Admin; pass_env=tZbi%7D; power_env=3; id_env=1
This cookie should allow authentication on a default install of UPB.  This  
information session is immortal. when you login with your user name and 
password on the system your cookie is given a time stamp,  however this time 
stamp is not necessary for authentication.  

Session management has been done so well in PHP with session_start() and the 
$_SESSION supper global it seems a shame to try and replace it.  You should 
never use a login name and password for a session ID.  The value should be a 
securely randomly generated value that is only used for that session. 

[Database Issues]
UBP uses an in house developed database implementation called TextDB.   Text 
Database was written by Tim Hoeppner (aka Pilot) on the © Ultimiate PHP Board 
(UPB) Team .   I'm glad i had the privilege to find these NON-SQL database 
injection attacks.   This database currently suffers from two major vectors of 
injection.  One vector allow for the injection of an arbitrary login.  The 
other allows an attacker to write and over-write an arbitrary file on the 
remote system.   

In order to understand the attack the reader should get some background 
information about the database. 

One line in the database looks like this:
Admin<~>tZbi}<~>3<~><~><~>on<~><~>http://<~>db/users.dat<~><~><~><~><~>20<~><~>1

the corresponding users.def :
user_name<~>password<~>level<~>email<~>view_email<~>mail_list<~>location<~>url<~>avatar<~>icq<~>aim<~>msn<~>sig<~>posts<~>date_added<~>id

The database is a (FILO) First In Last Out Stack,  each cell is separated by an 
'<~>' and each  record is separated by a new line.  This storage system is not 
much more complex than Coma Separated Values(CSV) system of data storage.  

There are two values which could be described as special words:  [NL] and [NR]. 
    The database records a newline character '\n' as the [NL] key word.    The 
[NR] word is used to pass multiple records to the add() function, thus the [NR] 
is converted into a '\n'. 

file /UBP/textdb.inc line 21 in function add($record, $db, $new) :
        $every = explode("[NR]", $record);


Try navigating to register.php fill out the forum then enter this as the 
signature:
?s<~>0<~>2006-04-17[NR]NewAdmin<~>m<~>3<~><~><~><~><~>1<~><~><~><~><~>13<~><~>1<~>4000000000?
(note: there are no new lines or quote marks in the exploit string)

This will create and administrator login with the login name of:  NewAdmin  and 
the password is Z.   It is possible to inject an administrative account 
regardless of the status of magic_quotes  and does not rely on manipulating a 
global variable.  

The function add()  puts a unique ?id? at the end of the string and is stored 
in the  cell name ?id?.  The id needs to be known in order to reconstruct a 
valid cookie session data.   This exploit string is injecting a full record,  
add generates the sequential id and adds it to the end of the record which does 
not affect execution.  

The second type of database injection in this system allows an attacker to drop 
an arbitrary file.  This vulnerability leads to code execution.   In version 
1.8 and below the entire database folder /db/  was viewable by your web 
browser,  the patch uses an apache .htaccess file which does not allow access 
to anyone using apache.  With this database injection its possible to  
overwrite  the .htaccess  with a commented out junk data allowing an attacker 
full read access to the database. Over writing of files is important,  mysql's 
?into outfile? will NOT allow you to overwrite a file.  

This is possible regardless of the status of register_globals;  however 
magic_quotes does need to be off because a NULL byte must be injected to 
control the file extension.  

The reason why the register_globals doesn't matter is because the following 
code implements the same functionality as  register_globals:
func.inc.php line 19:
while (list ($key, $val) = each ($HTTP_GET_VARS)) {
    $$key = $val;
}
while (list ($key, $val) = each ($HTTP_POST_VARS)) {
    $$key = $val;
}
while (list ($key, $val) = each ($HTTP_COOKIE_VARS)) {
    $$key = $val;
}

Simple yet so effective,  elegant because of its power and size.   These nine 
lines of code result in the systematic failure of security.  Its effects 
cascade throughout the program allowing an attacker to assume total control.  
Smaller variations of this exist,  but each of them have there own beauty. 

An arbitrary file can be created on the remote system using directory traversal 
attack accessible from  newpost.php.  The file name is controlled by $id.   By 
injecting a ../ the attacker can control what directory to inject the file.  By 
injecting a hex encoded null byte %00 at the end of $id the attacker can 
control the extension type.  This is because PHP is built on C.  In the C 
programming language (as well as others)  a null byte signify the end of the 
data in an array.  The null byte is absolutely necessary in an array,  without 
it the C function will not know when to stop and could continue to read until 
it wonders into memory not owned by the process this will  cause a segmentation 
fault, trespassers will be shot. 

$id is only validated if it is sent as a GET;  as a result of registering 
globals we can send $id as a post or a cookie and still be able to hit the 
add() function.  UBP does  check for  '<' and '>',  this prevents the injection 
of javascript and php,  however by no means stops the injection of perl CGI.  
The add() function also introduces a lot of junk data,  however this junk can 
be commented out for some attacks.    Such as commenting out the .htaccess 
file. 

  $icon  needs to be controlled by the attacker because it  allows an attacker 
to control the first few characters of the file.  $icon must exist in the POST 
or the request is rejected. The $message which is sent via post contains the 
arbitrary perl cgi to be executed by the remote server:
[NR]use CGI qw(:standard);print header;print "one";print " two";print " three";#

[NR] is used again in this attack.  Instated of using it to inject an 
administrative account,  its used to get a vital new line for formating the 
dropped file.   There can't be any new lines in the perl payload itself and it 
needs to end with a '#' to comment out junk created by the database 
implementation.

Using this database injection an attacker can drop a perl cgi file,  however 
cgi must be made executable on a Unix type system.  These rights can be given 
to the file using chmod.  A user on a Unix type system can only chmod files 
that that user owns.  This means that if you are using chmod within PHP then 
apache's user must own the file.    A file created by PHP can be chmod'ed by 
PHP;  thus the payload can be chmod()'ed in this way. 

file UPB/close.php line: 12
chmod("./db/$id/$t_id.dat", 0555);
both $id and $t_id can be controlled by an attacker. Directory traversal is 
possible using '../../' and '%00' (null byte in hex) can be used to remove .dat.

chmod 555  give a file the following rights:
-r-xr-xr-x
That makes any file on the system an attacker chooses to be executable and 
readable.   Its ironic that this ?close?  feature  was created to prevent 
access but instead its a critical part in remote code execution process.    
Remote code execution using the database could have been foiled on most system 
by changing only ONE BIT.  That is decreasing the byte value of 5 by one bit,  
making it 554.  chmod 555 is most likely three bits off from what was intended 
which is chmod 444 which makes a file read only:
-r?r?r--

There is also open.php which suffer from the same directory traversal attack 
making a file chmod 666.  This allows an attacker to make an arbitrary file 
readable and writable.   chmod 666 gives a file the following access rights:
-rw-rw-rw-

Using this database to drop a Perl CGI is not a very realistic remote code 
execution attack.  The reason why is that not only does perl cgi have to be 
installed,  but the attacker has to know the location of perl.  This attack 
vector was created to show the security issue in this NON-SQL database 
implementation. 

 Attackers don't have to use such a theoretical attack to obtain code 
execution,  instead there is  fairly straight forward PHP execution available 
in the administrative area.  Its the best method for remote code execution on 
this system.  The php code is stored and then included during execution.   One 
could easily install a php-back-door into the main page.  This is also a great 
point of entree for a type 2 (heighest level) cross site scripting issue.  Type 
2 XSS is great for subjecting browsers to exploits.     This PHP remote code 
execution attack could be stopped by storing the configuration information in 
the database. 
  
With administrative access one is able to then access the vulnerable function 
calls in: 
admin_chatconfig.php admin_configcss.php admin_config.php admin_config2.php
The data is sent to corresponding file 'do' file :
admin_chatconfigdo.php admin_configcssdo.php admin_configdo.php 
admin_configdo2.php
Every item is vulnerable to code execution; in total there are 120  individual 
variables that allow for code execution.  Of course only one of which is 
necessary to gain control. 
For any of the configuration fields add this Prof of concept code to the end:
";phpinfo(); $crap="1
All functions add  the nectary  ?;  to complete the line and then the payload 
is written to a configuration file and then included during execution.   To 
remove the php injection go back to the injected config.php and and submit the 
configuration values without modification.   A fix for this hole is to store 
these configuration values in the database.

There are two separate methods of gaining administrative access and remote code 
execution.    The first method that is the easiest and the most sure fire.  
First one needs to inject an administrative login,  then use the php injection 
in the configuration files to execute code.   A second method  of gaining 
administrative access could  be used, by gaining access to /db/users.dat then 
decrypting an administrative password . The other method of code execution 
would be to sign up for an account then use the perl cgi upload attack which is 
available in the exploit code.  

Ultimate PHP Board is a huge target for botnet spammers.  For one all working 
Ultimate PHP Boards need to be able to e-mail new users there randomly 
generated password for there first login.  So all fully functional Ultimate PHP 
Boards can be used to send spam.  Also Ultimate PHP Board's database will 
contain a valid e-mail addresses for every user.    IRC is a popular method of 
controlling a botnet,  Ultimate PHP Board has a chat feature that could be used 
in the same way.  Lastly the Type 2 Cross Site Scripting could be used to 
further spread the botnet by  exploiting  code execution holes in visitor's web 
browsers.  

At the top of the vendors site it reads :
?All of the features you expect,  without the SQL mess?
How dare you insult SQL,  As a LAMP developer I find that very offensive.  SQL 
is an amazing system that I am grateful for.  You should be ashamed for saying 
that when what you have to offer is not even close to as functional or secure.  
There is no advantage in using these in house abominations of security.   It is 
not a waste of time to develop a rival technology to the main stream, after all 
thats how these systems get replaced.   But when you developed a rivaling 
technology with no intention of surpassing readily available Open Source 
solutions,  you are just wasting your time.   The Ultimate PHP Board 
Development team isn't bad, however  they wasted a lot of time developing 
functions  that have already been developed.  

This database implementation does make this web application easier to install, 
but at what cost?    Obviously this database implementation is vulnerable to 
injection,  even remote code execution!   A better solution is to utilize some 
kind of SQL database,  at the very least SQLite which has been built into php5. 
 UBP could use SQLite and still keep its zero configuration install.  
I suggest removing the use of global variables,  this has been shown to be a 
security train wreck.  Such a bad security issue that its being flat out 
removed in PHP6.  I also suggest using PHP's built in session handling 
functions which work very well.   The Cryptography issues should be solved by 
using  a mainstream one way hash function. In general UBP seem to be trying to 
reinvent the wheel.    Basic functionality such as the database, sessions, and 
encryption have been taken care of so that the average developer can work on 
the real problem at hand.  Doing your own  implementation of such heavily used 
tools will most likely result in inefficient and insecure code.