Cake Php 3 Уязвимость манипулирования файлами с checkmarx - PullRequest
0 голосов
/ 17 февраля 2020

Я продолжаю получать отчет о манипулировании файлами и раскрытии файлов, когда запускаю свое приложение через checkmarx. В отчете говорится, что:

Ввод, полученный с помощью add в файле src / Controller / UploadsController. php в строке 67 используется для определения местоположения файла, в который необходимо записать, путем добавления в файл src / Controller / UploadsController. php в строке 67, потенциально позволяющий злоумышленнику изменить или повредить содержимое этого файла или создать новый файл в целом.

Фрагмент кода:

....
78. $filtered = filter_var_array($this->request->getData('bulk_name'), $args);
....
94. if(escapeshellcmd(escapeshellarg(move_uploaded_file($tmp_name, $destination)))) {
....
150. public function sanitizeData($input){ 
....
211. public function sanitize($string, $forceLowerCase = true, $anal = false) {

Это то, что я пытался сделать, но у меня продолжают появляться те же проблемы в отчете. Что еще я могу сделать, чтобы обойти это? Идеи / Решения приветствуются.

public function add() {
        $upload = $this->Uploads->newEntity();
        if (escapeshellcmd(escapeshellarg($this->request->is('post')))) {
            $args = array(
                'tmp_name' => FILTER_SANITIZE_URL,
                'error' => FILTER_VALIDATE_INT,
                'name' => FILTER_SANITIZE_ENCODED,
                'type' => FILTER_SANITIZE_SPECIAL_CHARS,
                'size' => FILTER_SANITIZE_ENCODED,
            );

            $filtered = filter_var_array($this->request->getData('bulk_name'), $args);

            if (!empty($filtered)) {
                $file = $this->sanitizeData($filtered);
                if (isset($file['flashMessage'])) {
                    $flashMessage = $file['flashMessage'];
                    $this->Flash->error($flashMessage, ['key' => 'error']);
                } else {
                    $uploadDirectory = getcwd() . DS . 'files' . DS;

                    $fileName = $file['name'];
                    $upload = $this->Uploads->patchEntity($upload, $this->request->getData());
                    $upload->file_name = $fileName;
                    $tmp_name = $file['tmp_name'];
                    $destination = $uploadDirectory . $fileName;

                    if (escapeshellcmd(escapeshellarg(move_uploaded_file($tmp_name, $destination)))) {
                        $datasource = ConnectionManager::get("default");
                        $datasource->begin();
                        $saveUpload = $this->Uploads->save($upload);
                        if ($saveUpload) {
                            $session = $this->getRequest()->getSession();
                            $clientID = $session->read('Auth.User.client_id');
                            $userID = $session->read('Auth.User.id');
                            $lastSavedId = $saveUpload->id;

                            $baseName = basename($fileName);
                            $uploadedCSVFile = $uploadDirectory . $baseName;

                            $csvFile = fopen($uploadedCSVFile, "r");

                            $totalAmount = 0;

                            while (($row = fgetcsv($csvFile)) !== false) {
                                if ($row[1] < 1) continue;
                                $totalAmount += trim($row[1]);
                            }

                            fclose($csvFile);

                            $uploadEntry = $this->Uploads->UploadEntries->newEntity();
                            $entryData = array();
                            $entryData['upload_id'] = $lastSavedId;
                            $entryData['client_id'] = $clientID;
                            $entryData['user_id'] = $userID;
                            $entryData['amount'] = $totalAmount;
                            $entryData['status'] = 0;
                            $uploadEntry = $this->Uploads->UploadEntries->patchEntity($UploadEntry, $entryData);

                            $saveUploadEntries = $this->Uploads->UploadEntries->save($uploadEntry);

                            if ($saveUploadEntries) {
                                $datasource->commit();
                                $this->Flash->success('The upload has been saved.', ['key' => 'success']);
                                return $this->redirect('/');
                            }
                            $this->Flash->error(__('The  upload could not be saved. Please, try again.'));
                        }

                        $this->Flash->error(__('The  upload could not be saved. Please, try again.'));
                    }
                    $this->Flash->error(__('The  upload could not be saved. Please, try again.'));
                }
            } else {
                $this->Flash->error(__('Empty Upload', ['key' => 'error']));
            }
        }
    $this->set(compact('upload'));
}


public function sanitizeData($input){
        $args = array(
            'tmp_name' => FILTER_SANITIZE_URL,
            'error' => FILTER_VALIDATE_INT,
            'name' => FILTER_SANITIZE_ENCODED,
            'type' => FILTER_SANITIZE_SPECIAL_CHARS,
            'size' => FILTER_SANITIZE_ENCODED,
        );

        $filtered = filter_var_array($input, $args);


        $fileExtensionsAllowed = ['csv']; // These will be the only file extensions allowed
        $mimes = array('application/vnd.ms-excel', 'text/plain', 'text/csv', 'text/tsv');


        $fileName = $filtered['name'];
        $fileSize = $filtered['size'];
        $fileTmpName = $filtered['tmp_name'];
        $fileType = $filtered['type'];
        $fileError = $filtered['error'];

        $file = explode('.', $fileName);//Split file name with extension
        $ext = end($file); //get extension name
        $fileExtension = strtolower($ext); //if change extension to lowercase

        $output = array();

        if (!is_readable($fileTmpName)) {
            $output['flashMessage'] = 'File is not readable';
        } elseif (!in_array($fileExtension, $fileExtensionsAllowed) && !in_array($fileType, $mimes)) {
            $output['flashMessage'] = 'Unsupported File Type';
        } elseif ($fileSize > 50000) {
            $output['flashMessage'] = 'File is too large for upload';
        } elseif (!$fileError == 0) {
            $output['flashMessage'] = 'An error occurred';
        }

        $csvName = $file[0];
        $newfilename = $csvName . date("YmdHis") . '.' . $ext; //new file name


        $output['name'] = $this->sanitize($newfilename); //sanitize file name
        $output['error'] = $fileError;
        $output['tmp_name'] = $fileTmpName;
        $output['type'] = $fileType;
        $output['size'] = $fileSize;
        return $output;

}


public function sanitize($string, $forceLowerCase = true, $anal = false) {
    if($this->Auth->user()) {
        $strip = array(".","~", "`", "!", "@", "#", "$", "%", "^", "&", "*", "(", ")", "_", "=", "+", "[", "{", "]", "}", "\\", "|", ";", ":", "\"", "'", "&#8216;", "&#8217;", "&#8220;", "&#8221;", "&#8211;", "&#8212;", "—", "–", ",", "<", ">", "/", "?");
        $clean = trim(str_replace($strip, "", strip_tags($string)));
        $clean = preg_replace('/\s+/', "-", $clean);
        $clean = ($anal) ? preg_replace("/[^a-zA-Z0-9]/", "", $clean) : $clean;
        return ($forceLowerCase) ?
            (function_exists('mb_strtolower')) ?
                mb_strtolower($clean, 'UTF-8') :
                strtolower($clean) :
            $clean;
    }
}
...