SoftwareSecurity2012/Group 7/Verdict
Level 1B – Source Code Scan (Partial Automated Verification)
Based on OWASP ASVS 2009 Web Application std. we need to scan the code with automated tools to search through the application source code to find patterns that represent vulnerabilities
L1B.1 Perform source code scanning on the application according to the Level 1B requirements specified in the “Detailed Verification Requirements” section.
L1B.2 Verify all source code scan results using either manual application penetration testing or code review. Unverified automated results are not considered to provide any assurance and are not sufficient to qualify for Level 1.
Requirement | Description | L1B.1 result | L1B.2 result |
---|---|---|---|
V4.1 | Verify that users can only access protected functions for which they possess specific authorization. | Automated tools do not provide sufficient evidence that the positive requirement has been met (Indeed. Unclear to me why V4.1 is included in level 1B at all...) | Please refer to L2B.1 |
Level 2B - Code Review (Partial Manual Verification)
Based on the OWASP ASVS 2009 Web Application std. we need to review the code manually, with the help of Doxygen tool, we can determine all the data structure of the fluxBB, even though we are not sure the accuracy of Doxygen to generate all the instances, functions and variables.
L2B.1 Perform a manual code review on the application according to the Level 2B requirements specified in the “Detailed Verification Requirements” section. This is a new requirement at Level 2.
Requirement | Description | Verdict | Explanation | |
---|---|---|---|---|
V4.1 | Verify that users can only access protected functions for which they possess specific authorization. | Pass | We located satisfied access control condition in posts.php to prevent unauthorized posting functions to a certain restricted thread ( eg. if the thread can only be posted by admin or moderators).
<source lang="php">
if ((($tid && (($cur_posting['post_replies'] == && $pun_user['g_post_replies'] == '0') ||
$cur_posting['post_replies'] == '0')) ||
($fid && (($cur_posting['post_topics'] == && $pun_user['g_post_topics'] == '0') ||
$cur_posting['post_topics'] == '0')) ||
(isset($cur_posting['closed']) && $cur_posting['closed'] == '1')) && !$is_admmod)
message($lang_common['No permission'], false, '403 Forbidden');
</source>
$cur_post['closed'] == '1') && |
$is_admmod)
message($lang_common['No permission'], false, '403 Forbidden'); </source>
From the code above we know that the access control for delete_topic() and delete_post() is satisfied.
|
V4.2 | Verify that users can only access URLs for which they possess specific authorization. | Pass | Fluxbb provides admin and moderators functionality to govern every activity at the forum. To make sure the access control is implemented in URLs user’s privileges such as admin and moderators functionality, every page related to the access control to the higher privileges URLs (eg. admin_index.php, admin_permission.php, admin_loader.php, etc.) would have tell header.php to use the admin template and check the user’s privileges like code below: <source lang="php"> define('PUN_ROOT', dirname(__FILE__).'/'); require PUN_ROOT.'include/common.php'; require PUN_ROOT.'include/common_admin.php'; if ($pun_user['g_id'] != PUN_ADMIN) message($lang_common['No permission'], false, '403 Forbidden'); </source>
The granted access would then load the language file pack to display the associated admin/moderators functionality. We verdict that users can only have access URLs for which they possess specific authorization.
| |
V4.3 | Verify that users can only access data files for which they possess specific authorization. | Pass | Although there are some pages that are not user-friendly shielded off, it is still secure.
| |
V4.4 | Verify that direct object references are protected, such that only authorized objects are accessible to each user. | N/A | No direct object references are being stored on FluxBB bulletin board. The only possible object reference is using the avatar function where image files could be uploaded by the user. We tried several XSS image attacks on the avatar upload function and they seem to have passed because of the following validation code. message($lang_profile['Bad type']); // Make sure the file isn't too big if ($uploaded_file['size'] > $pun_config['o_avatars_size']) message($lang_profile['Too large'].' '.forum_number_format($pun_config['o_avatars_size']).' '.$lang_profile['bytes'].'.'); // Move the file to the avatar directory. We do this before checking the width/height to circumvent open_basedir restrictions if (!@move_uploaded_file($uploaded_file['tmp_name'], PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$id.'.tmp')) message($lang_profile['Move failed'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.'); list($width, $height, $type,) = @getimagesize(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$id.'.tmp'); // Determine type if ($type == IMAGETYPE_GIF) $extension = '.gif'; else if ($type == IMAGETYPE_JPEG) $extension = '.jpg'; else if ($type == IMAGETYPE_PNG) $extension = '.png'; else { // Invalid type @unlink(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$id.'.tmp'); message($lang_profile['Bad type']); } // Now check the width/height if (empty($width) || empty($height) || $width > $pun_config['o_avatars_width'] || $height > $pun_config['o_avatars_height']) { @unlink(PUN_ROOT.$pun_config['o_avatars_dir'].'/'.$id.'.tmp'); message($lang_profile['Too wide or high'].' '.$pun_config['o_avatars_width'].'x'.$pun_config['o_avatars_height'].' '.$lang_profile['pixels'].'.'); } </source> | |
V4.6 | Verify that users can only access services for which they possess specific authorization. | Pass | After carefully looking at all the php functions in the FluBB project, we found that the different services offered to a user are - deletion of post, posting an entry in the forum, viewing topics, viewing a particular post, editing a particular post, creating a profile, searching for a topic or post. We found that there is a php file corresponding to each aforementioned service which implements it. For example, the file "delete.php" implements the service of deleting topics or posts, "search.php" implements the service of searching the forum. The other mentioned services are also similarly implementing using a php fle each. After careful observation of all these php files responsible for implementing all these services, we conclude that access control mechanisms are adequately applied to each of these services. When any user tries to access any of these services, the code checks whether the current user has the necessary access permissions to perform that action before allowing it. An example of code which implements access control can be found in the file "delete.php" which is used to delete a post from the forum. Lines 38 to 43 are mentioned here:- <source lang="php"> if (($pun_user['g_delete_posts'] == '0' ||($pun_user['g_delete_topics'] == '0' && $is_topic_post) || $cur_post['poster_id'] != $pun_user['id'] || $cur_post['closed'] == '1') && !$is_admmod) message($lang_common['No permission']); </source> Looking at the above code, one can clearly observe that only administrator user or moderators are allowed to delete a particular post. It is also noteworthy here that a normal user can only delete posts created by himself. Similar lines of code can be found in the file "edit.php" which is used to implement the service which enables a user to edit a particular post. Lines 40-45 of the file "edit.php" have similar code which implements access control. Another basic service is posting in a forum. Access control is also implemented here. A code snippet from lines 46 to 50 of the file are as follows:- <source lang="php"> if ((($tid && (($cur_posting['post_replies'] == && $pun_user['g_post_replies'] == '0') || $cur_posting['post_replies'] == '0')) || ($fid && (($cur_posting['post_topics'] == && $pun_user['g_post_topics'] == '0') || $cur_posting['post_topics'] == '0')) || (isset($cur_posting['closed']) && $cur_posting['closed'] == '1')) && !$is_admmod) message($lang_common['No permission']); </source> The above lines in the file "post.php" check whether the current user has the privileges required to post in that particular forum. If the posting in the forum is not open, then only the administrator and moderator users are allowed to post. We could also find similar access control checks implemented in the other files such as "viewtopic.php" and "viewforum.php". We also found that all these above mentioned php files are calling functions which are defined in the php file "functions.php". But, as the access control code (an example of which was explained above) is implemented before the function call, we do not need access control checks in the file "function.php" and hence we could not find them as they would be redundant. (All this suggest that access control is done in a systematic way - some design decisions seem to have been made here. ) We could not find any counter example which portrays violation of access control mechanisms in any of the php files responsible for implementing any of the services of the FluxBB bulletin board. Thus, we conclude that access control is implemented for each service and this verification requirement is satisfied. Files Checked - viewtopic.php, viewforum.php, search.php, functions.php, delete.php, login.php, post.php, register.php, | |
V4.7 | Verify that users can only access data for which they possess specific authorization. | Pass | The data present in the bulletin board FluxBB are things like the forum topics and posts, the list of users and user credentials. This requirement asks whether these data possessed by the online forum are properly protected using access control mechanisms. We checked the code in the php files responsible for interfacing these data and implementing the functions which enable access to this data. We find that the data mentioned here is indeed protected by checking user privileges inside the PHP functions that are responsible for accessing these data. The php file which contains the code for obtaining a list of the users of the forum is "userlist.php". It implements access control with code present in lines 13 - 16 that is listed below : - <source lang="php"> if ($pun_user['g_read_board'] == '0') message($lang_common['No view']); else if ($pun_user['g_view_users'] == '0') message($lang_common['No permission']); </source> Similar user authentication code can be found in the PHP files "viewtopic.php" and "viewforum.php" which prevent unauthorized users from viewing a particular topic or a forum. The code found in both files, on lines 13 and 14 in both cases, is written below:- <source lang="php"> if ($pun_user['g_read_board'] == '0') message($lang_common['No view']); </source> The above code clearly prohibits unauthorized users. It keeps track of the current user with the "$pun_user" data item. Looking at the above instances, we conclude that all the data of the forum are properly protected by user authentication code present in the PHP functions responsible for accessing these data. Hence, we think that FluxBB passes this verification requirement as we were not able to find any instance where user authentication was not performed while accessing any forum data.
| |
V4.8 | Verify that access controls fail securely. | Pass | Failing securely means that the application should not divulge any sensitive information to the user if he is stopped by access control checks. For this requirement, we checked the error messages produced when access control checks force a failure to access a resource.
There are numerous examples of FluxBB code where error handling is performed. <source lang="php">
// Did someone just hit "Submit" or "Preview"?
if (isset($_POST['form_sent']))
{
// Flood protection
if (!isset($_POST['preview']) && $pun_user['last_post'] != && (time() - $pun_user['last_post']) < $pun_user['g_post_flood'])
$errors[] = $lang_post['Flood start'].' '.$pun_user['g_post_flood'].' '.$lang_post['flood end']; Taken from the file "common.php" : - <source lang="php">
// Make sure PHP reports all errors except E_NOTICE. FluxBB supports E_ALL, but a lot of scripts it may interact with.
error_reporting(E_ALL ^ E_NOTICE); Files checked - delete.php, index.php, login.php, post.php, veiw_forum.php, veiw_topic.php, admin_bans.php, admin_censoring.php, functions.php, common.php, common_admin.php, admin_reports.php
| |
V4.9 | Verify that the same access control rules implied by the presentation layer are enforced on the server side. | Pass | FluxBB 1.4 has access control rules on the server side.We have to check the functions in the fluxBB to check whether they are in the server side or not. As an example- time() function is on the server side. It updates the time from the server side. So where ever the time() function is used it is on server side . As verified in (V4.11) access control rules are on server side whereas FluxxBB 1.4 access control rules were not found on client side.
| |
V4.10 | Verify that all user and data attributes and policy information used by access controls cannot be manipulated by end users unless specifically authorized. | Not sure | To prevent unauthorized end users manipulating user and data attributes and policy information, fluxbb provides authenticate_user() function against the user database. We think that all the SQL queries are escaped properly and the requirement to prevent manipulation towards access control is rectified correctly, at least from our point of view.
| |
V4.11 | Verify that all access controls are enforced on the server side. | Pass | All access controls are enforced on the server side.
The following example shows that the authentication is being handled on the server and therefore passing the requirement. We focused on testing the login module because this module <source lang="php"> $result = $db->query('SELECT * FROM '.$db->prefix.'users WHERE '.$username_sql) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error()); $cur_user = $db->fetch_assoc($result); </source> This code on page 27-30 will put the search result of the filled username in the form on the login page with the server database into the "$cur_user". <source lang="php"> $authorized = ($cur_user['password'] == $form_password_hash); </source> The user will be authorized by the server if the password of the database with the corresponding user ($cur_user['password'] matches the hashed filled in password on the login page. The cookie is based on the following data: - user id (this is the id used in the user table in the database. Default guest = 1 and admin = 2) - hash of the password - expiration of the cookie The hash of the password gets hashed again with hmac. The SHA-1 password hash is being hashed with the cookie seed as a key with hmac.
At the end of this procedure the cookie looks something like this: 2%7C4a34448a1a92fa6c5679cfd0860aa33d7e37d1d8%7C1339872821%7Cc096b82c5a774cba02d6012a0449b6a21bea3ff5 The only non-hashed value is the first digit "2". This is the user id.
We have tried altering the cookie, but without knowing the password it was hard. Files checked: login.php and the main functions/methods that are included. (common.php, functions.php, ROOT/lang/ and the tables in the database). | |
V4.12 | Verify that there is a centralized mechanism (including libraries that call external authorization services) for protecting access to each type of protected resource. | Not Sure | We think there is specialized centralized mechanism for checking access control to any resources. All the access control checks are implemented within all the php files responsible for each resource as has been explained in V4.1 and V4.6. The access control mechanism for each service, such as deleting a forum topic or post, editing a forum topic or post, etc., is implemented in the files such as "delete.php" and "edit.php". However, these files are including the file "functions.php" and use its functions. An example can be found in the file "delete.php" which is used to delete topics or posts from the bulletin board. The access control checks are performed using the code in the file "delete.php" but it uses a global data item "$cur_user" and for the actual deletion process, it uses a function "delete_post($post_id, $topic_id)". The actual deletion from the database happens using this function but the access control check is implemented in the "delete.php" file. So we can see that the access control checks are performed in the individual php files but these checks are facilitated by global data items and inclusion of the file "functions.php". Thus, we are not quite able to ascertain if a centralized mechanism is present for implementing access control checks and hence we cannot conclude if this requirement is satisfied. Files Checked - delete.php, viewtopic.php, edit.php, viewforum.php, functions.php. | |
V4.13 | Verify that limitations on input and access imposed by the business on the application (such as daily transaction limits or sequencing of tasks) cannot be bypassed. | Pass | The user does not have privileges to bypass on limitations on input and access. The user has has to go through the administrater in order to get limitations on input. Only admin and moderates have the rights to access in the forums to setup rules. We mainly looked at post.php with its posting functions and have tested the flood protection function. If the blocked user tries to delete the post from the forum he cannot. Even though we tried to change the post id from the URL,we were not able to see the post nor delete the post.It blocked us giving the message you do not have rights. Since by looking at this it a good access control and is based on sever based(Verified by 4.11 & 4.9).
The flood protection code can be found in line 62-64 in post.php: <source lang="php">
// Flood protection if (!isset($_POST['preview']) && $pun_user['last_post'] != && (time() - $pun_user['last_post']) < $pun_user['g_post_flood']) $errors[] = $lang_post['Flood start'].' '.$pun_user['g_post_flood'].' '.$lang_post['flood end']; </source> However, it is not possible to bypass the server-sided limitations but we came across a possible exploitation of the 60-seconds interval restriction. Let's take as an example the ranking group "Elite" which one person needs 60000 posts and give extra permissions for the user.
In order to exploit this one could make a flood program. The fluxbb uses protection for this and is all server-side decided.
Thus it is possible to reach a high amount of posts. In our case that would take 60000 posts*60 seconds treshold = 1000 hours = ~42 days.
The spammer can get away unoticed because there are no logs about this event. Everytime a post is being added the ID column in the database gets incremented and the administrator could get suspicious by the gaps. This is hard to spot when you have a highly active forum where users post/edit/delete posts all the time. --- Banned account bug ---
We also found out that if we ban an account and change its nickname the user will be unbanned. The banned account-name is still in the banned table but not being updated. Files checked- functions.php, post.php , admin_bans, admin_censoring , post.php, edit.php , delete.php , login.php , admin_reports.php ,index.php | |
V4.14 | Verify that all access control decisions can be logged and all failed decisions are logged. | Fail | By looking at the below code from the functions.php the user being banned from the forum is not being logged. The attempts made to log in by the banned user is not being seen by the admin how many times the user tried to log in. The following code on line 405 in functions.php show us the banned_check with no logging: <source lang="php"> if ($is_banned) {
$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\.$db->escape($pun_user['username']).'\) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
message($lang_common['Ban message'].' '.(($cur_ban['expire'] != ) ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : ).(($cur_ban['message'] != ) ? $lang_common['Ban message 3'].
' </source>
if ($is_banned)
{
// If the decision is to decline acces to the banned user.
// ----
$db->query('DELETE FROM '.$db->prefix.'online WHERE ident=\.$db->escape($pun_user['username']).'\) or error('Unable to delete from online list', __FILE__, __LINE__, $db->error());
message($lang_common['Ban message'].' '.(($cur_ban['expire'] != ) ? $lang_common['Ban message 2'].' '.strtolower(format_time($cur_ban['expire'], true)).'. ' : ).(($cur_ban['message'] != ) ? $lang_common['Ban message 3'].
' </source>
Furthermore, there are no tables/ columns in the database which indicate that there is some sort of logging. The only logging that we came across was the logging of posted messages. Their user id, ip adress, etc. Files checked: functions.php and several other pages included like common.php and functions.php. |