Issue Details (XML | Word | Printable)

Key: MDL-19354
Type: Sub-task Sub-task
Status: Open Open
Priority: Blocker Blocker
Assignee: Penny Leach
Reporter: Petr Skoda
Votes: 0
Watchers: 1
Operations

Add/Edit UI Mockup to this issue
If you were logged in you would be able to see more operations.
Moodle
MDL-19353

use of portfolio callbackfile and callbackclass parameters in portfolio/add.php is unaccepable

Created: 01/Jun/09 02:17 AM   Updated: 02/Jun/09 01:07 AM
Return to search
Component/s: Portfolio API
Affects Version/s: 2.0
Fix Version/s: 2.0

Participants: Penny Leach and Petr Skoda
Security Level: None
Affected Branches: MOODLE_20_STABLE
Fixed Branches: MOODLE_20_STABLE


 Description  « Hide
Following code from portfolio/add.php is a security nightmare - allowing anybody (including guests) to include ANY moodle file from dirroot and instantiate ANY class with ANY parameters is unacceptable, please note that there is also no sesskey CSRF protection!

$callbackfile = optional_param('callbackfile', null, PARAM_PATH); // callback file eg /mod/forum/lib.php - the location of the exporting content
$callbackclass = optional_param('callbackclass', null, PARAM_ALPHAEXT); // callback class eg forum_portfolio_caller - the class to handle the exporting content.

    $callbackargs = array();
    foreach (array_keys(array_merge($_GET, $_POST)) as $key) {
        if (strpos($key, 'ca_') === 0) {
            if (!$value = optional_param($key, false, PARAM_ALPHAEXT)) {
                if (!$value = optional_param($key, false, PARAM_NUMBER)) {
                    $value = optional_param($key, false, PARAM_PATH);
                }
            }
            // strip off ca_ for niceness
            $callbackargs[substr($key, 3)] = $value;
        }
    }
    // righto, now we have the callback args set up
    // load up the caller file and class and tell it to set up all the data
    // it needs
    require_once($CFG->dirroot . $callbackfile);
    $caller = new $callbackclass($callbackargs);


 All   Comments   Change History   Version Control      Sort Order: Ascending order - Click to sort in descending order
Penny Leach added a comment - 02/Jun/09 12:32 AM
Hi Petr,

Adding sesskey protection is trivial and a simple oversight, thank you for catching it. All the portfolio add buttons are handled through the portfolio_add_button's to_html method, so adding sesskey there and a check in portfolio/add.php will change all cases.

Regarding your other concern, do you have any better solution? I followed Martin's original spec for this, please see http://docs.moodle.org/en/index.php?title=Development:Portfolio_API&oldid=23088.

Also, it's not "ANY" class, those classes are all subclasses of portfolio_caller (this can easily be checked in portfolio/add.php).


Petr Skoda added a comment - 02/Jun/09 12:38 AM
I suppose you can pass in something that can be easily verified - then derive class name and expected php file from it.

Penny Leach added a comment - 02/Jun/09 12:48 AM
I don't think that the class name can be derived, as even now certain modules implement different portfolio_caller subclasses for different cases, see for example glossary, which behaves differently depending on whether it's a single entry or complete database export.

(grep for portfolio_module_caller)

The other option is to create a registry of all portfolio-exportable content but I dont think there's a good way to do it. This is not limited to activity modules, whole courses could be exportable.

There isn't an easy way to provide a mapping between portfolio exporters and their file/classes, other than:

1. Keep a database table of all classnames and files - I think this is a bit unmaintanable, as it's an additional "install time" question to ask modules/blocks/questiontypes/all plugins and we have it in code anyway

2. Everytime we draw the portfolio add icon on the screen, insert a possible export location into a database table. This is also not a good idea, because just because the icon gets drawn on the page doesn't mean that the user will ever click it , and it could result in multiple inserts per page load for a case that is never triggered.

I don't think the current situation is too terrible, if we have the following:

1. added sesskey protection as per my last comment, this is np to add
2. added check that the class to call is a subclass of portfolio_caller

Also bear in mind that the data that gets passed through as callback parameters to the constructor are pretty limited in regards to their datatype, it's limited to param_alphaext, param_number and param_path. That's pretty restrictive!


Penny Leach added a comment - 02/Jun/09 01:07 AM
Just committed 1 and 2 from above. Leaving open in case of any further discussion about the registry, but I think this is sufficient.