SoftwareSecurity2012/Group 7/Verdict

Uit Werkplaats
Ga naar: navigatie, zoeken


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.

V4 Access Control Requirements
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>
We also found how the application controls which users are eligible to use restricted functions such as delete_topic() and delete_post().
They used for deleting a topic and all of its posts and delete a single post respectively.
They are restricted function because to delete a topic and all of its posts or a post, users need to have authorization such as admin or moderator and it is regulated in delete.php <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'], false, '403 Forbidden');

</source> From the code above we know that the access control for delete_topic() and delete_post() is satisfied.
We located it also in edit.php, it controls who can edit which post. So for these functions, we verdict that users can only access protected functions for which they possess specific authorization.
However, we are not sure whether this condition is met with all the files of fluxBB application.
We checked these operations as a representative sample, with the assumption that if these are satisfied, then others protected functions will also be satisfied.

Files checked : functions.php, delete.php, posts.php, edit.php, common.php, moderate.php

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.
The reason why we chose these files is more like common sense in the forum that regular users should not have an access to privileged users’ URLs such as admin or moderators, in the same way, moderators should only have access to its moderators URLs and should not have access to Admin URLs.

Files checked: header.php, moderate.php, admin_index.php, admin_permissions.php, admin_bans.php, admin_loader.php, common_admin.php, admin_forums.php

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.


For more details see:Access_Control_Table

Files Checked:
-The entire root directory of FluxBB.
-The entire include directory.
-The entire cache directory.<br. Keep in mind that no subdirectories where selected during the file checking procedure.
This is mainly due to the cause that we are performing Level 2B analysis.
Data files that were left out were mainly the 3rd party libraries.(Level3)

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.
<source lang="php"> // Preliminary file check, adequate in most cases $allowed_types = array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/png', 'image/x-png'); if (!in_array($uploaded_file['type'], $allowed_types))

    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.


Files checked - userlist.php, viewtopic.php, viewforum.php. search.php.

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.
We provide an example in the code below which implements flood control. This code is from the file "functions.php". If a user tries to submit any post again, the code checks the time of the last post and compares it with the current post time. If the condition is not met, it displays an error message.

<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'];
</source>

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);
</source> Another example of error handling can be seen from the admin_report.php
// Delete old reports (which cannot be viewed anyway) <source lang="php"> $result = $db->query('SELECT zapped FROM '.$db->prefix.'reports WHERE zapped IS NOT NULL ORDER BY zapped DESC LIMIT 10,1') or error('Unable to fetch read reports to delete', __FILE__, __LINE__, $db->error()); if ($db->num_rows($result) > 0) { $zapped_threshold = $db->result($result); $db->query('DELETE FROM '.$db->prefix.'reports WHERE zapped <= '.$zapped_threshold) or error('Unable to delete old read reports', __FILE__, __LINE__, $db->error()); }
</source> After going through the files, we can safely say that error handling is performed quite well without revealing any vital system information.

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.


File checked - functions.php,login.php,common.php,index.php,install.php and the files from the db layer.

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.
However, we are not sure whether this operation is implemented properly for all user and data attributes and policy information in all the files of the application.

Files checked  : functions.php, login.php, register.php

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
looks at the most important authentication functions, namely the procedure of authenticating an user, making a cookie for the user and checking the validity of the cookie. This
is checks authentication and is being used in different approaches, like e.g. in post.php for posting a message. All these authentication function callings come back to the main
authentication functions. This is why we focused on the security of these functions and used login.php as our approach to these functions.
The example we show of the server-based acces control is the authentication on the login.php page:

<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.
This shows us that the access control is handled server based. However, we tried to take this a step further and test the client-side access control function, namely the cookie.
That leaves us with the possiblilty on manupulating the cookie since the cookie is stored client based. We did more research on the safety of the cookie storage and possible flaws. FluxBB have their own cookie creation function in functions.php which they call: "pun_setcookie()"

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.
Since we are not focussing on possible crypto hacks and keeping in the scope of this requirement which is being passed we left this out.

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.
We did not check other examples, because we found it important to look at the messaging input limits since we think that a forum is all about posting messages.

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).


--- Bypassing and explanation of the flood protection of posts --- We tested the input limitation of posting a message with an interval of 60 seconds and tried to find a way around.

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.
The fluxBB uses a ranking system for the users.

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.


The $pun_user['g_post_flood'] is set standard on 60 seconds. This value is stored in the database on the server. The time() function is a php function which determines the local time of the machine where the function is being executed.


This means that all computations are being made on the server side and not possible to bypass this by e.g. changing the local machine time of the exploiter.


On the other hand, there is a more exhausted way to bypass this server-side protection. If one would write an automated program to post a message every 60 seconds and automatically delete the post nobody will notice that you posted spam messages.


Normally when a post is deleted the post count of the user should also be lowered. This is NOT the case in the code of fluxBB.

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.
Looking up this bug showed us that it is being fixed in version 1.5. We did not take a look at how they fixed it, but we guess they built an extra ban_check when changing user information.

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']. '

'.pun_htmlspecialchars($cur_ban['message']).'

' : '

').$lang_common['Ban message 4'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true); }

</source>


Below we write an example of code which would indicate the behaviour of the function with a smiple built-in logging query to the database:


<source lang="php">

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']. '

'.pun_htmlspecialchars($cur_ban['message']).'

' : '

').$lang_common['Ban message 4'].' <a href="mailto:'.$pun_config['o_admin_email'].'">'.$pun_config['o_admin_email'].'</a>.', true); // Add information to the logging table in the db. $db->query('INSERT INTO '.$db->prefix.'logging VALUES ...); } else if ($is_banned == "false") { // If the decision is that the user is granted acces because he is not being banned. // ---- // Add information to the logging table in the db. $db->query('INSERT INTO '.$db->prefix.'logging VALUES ...); } }

</source>


By looking the above example this criteria is not met.

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.