ULtimate PHP Board <= 1.96 GOLD Code Execution (exploit code)
 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.