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<~><~><~><~><~>2
0<~><~>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.