Completed
Push — development ( 63cb21...942fb8 )
by Nils
08:57
created

upgrade_ajax.php ➔ addIndexIfNotExist()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 13
Code Lines 7

Duplication

Lines 13
Ratio 100 %

Importance

Changes 0
Metric Value
cc 2
eloc 7
nc 2
nop 3
dl 13
loc 13
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * @file          upgrade.ajax.php
4
 * @author        Nils Laumaillé
5
 * @version       2.1.27
6
 * @copyright     (c) 2009-2017 Nils Laumaillé
7
 * @licensing     GNU AFFERO GPL 3.0
8
 * @link          http://www.teampass.net
9
 *
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
 */
14
15
require_once('../sources/SecureHandler.php');
16
session_start();
17
error_reporting(E_ERROR | E_PARSE);
18
$_SESSION['db_encoding'] = "utf8";
19
$_SESSION['CPM'] = 1;
20
21
require_once '../includes/language/english.php';
22
require_once '../includes/config/include.php';
23
24
// manage settings.php file
25
if (!file_exists("../includes/config/settings.php")) {
26
    if (file_exists("../includes/settings.php")) {
27
        // since 2.1.27, this file has changed location
28
        if (copy("../includes/settings.php", "../includes/config/settings.php")) {
29
            unlink("../includes/settings.php");
30
        } else {
31
            echo 'document.getElementById("res_step1_error").innerHTML = '.
32
                '"Could not copy /includes/settings.php to /includes/config/settings.php! '.
33
                'Please do it manually and press button Launch.";';
34
            echo 'document.getElementById("loader").style.display = "none";';
35
            exit;
36
        }
37
    } else {
38
        echo 'document.getElementById("res_step1_error").innerHTML = '.
39
            '"File settings.php does not exist in folder includes/! '.
40
            'If it is an upgrade, it should be there, otherwise select install!";';
41
        echo 'document.getElementById("loader").style.display = "none";';
42
        exit;
43
    }
44
}
45
require_once '../includes/config/settings.php';
46
require_once '../sources/main.functions.php';
47
48
$_SESSION['settings']['loaded'] = "";
49
50
################
51
## Function permits to get the value from a line
52
################
53
/**
54
 * @param string $val
55
 */
56
function getSettingValue($val)
0 ignored issues
show
Best Practice introduced by
The function getSettingValue() has been defined more than once; this definition is ignored, only the first definition in api/functions.php (L147-157) is considered.

This check looks for functions that have already been defined in other files.

Some Codebases, like WordPress, make a practice of defining functions multiple times. This may lead to problems with the detection of function parameters and types. If you really need to do this, you can mark the duplicate definition with the @ignore annotation.

/**
 * @ignore
 */
function getUser() {

}

function getUser($id, $realm) {

}

See also the PhpDoc documentation for @ignore.

Loading history...
57
{
58
    $val = trim(strstr($val, "="));
59
    return trim(str_replace('"', '', substr($val, 1, strpos($val, ";") - 1)));
60
}
61
62
################
63
## Function permits to check if a column exists, and if not to add it
64
################
65
function addColumnIfNotExist($db, $column, $columnAttr = "VARCHAR(255) NULL")
66
{
67
    global $dbTmp;
68
    $exists = false;
69
    $columns = mysqli_query($dbTmp, "show columns from $db");
70
    while ($c = mysqli_fetch_assoc($columns)) {
71
        if ($c['Field'] == $column) {
72
            $exists = true;
73
            break;
74
        }
75
    }
76
    if (!$exists) {
77
        return mysqli_query($dbTmp, "ALTER TABLE `$db` ADD `$column`  $columnAttr");
78
    }
79
}
80
81 View Code Duplication
function addIndexIfNotExist($table, $index, $sql) {
0 ignored issues
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
82
    global $dbTmp;
83
84
    $mysqli_result = mysqli_query($dbTmp, "SHOW INDEX FROM $table WHERE key_name LIKE \"$index\"");
85
    $res = mysqli_fetch_row($mysqli_result);
86
87
    // if index does not exist, then add it
88
    if (!$res) {
89
        $res = mysqli_query($dbTmp, "ALTER TABLE `$table` ".$sql);
90
    }
91
92
    return $res;
93
}
94
95 View Code Duplication
function tableExists($tablename, $database = false)
0 ignored issues
show
Unused Code introduced by
The parameter $database is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
96
{
97
    global $dbTmp;
98
99
    $res = mysqli_query($dbTmp,
100
        "SELECT COUNT(*) as count
101
        FROM information_schema.tables
102
        WHERE table_schema = '".$_SESSION['database']."'
103
        AND table_name = '$tablename'"
104
    );
105
106
    if ($res > 0) {
107
        return true;
108
    } else {
109
        return false;
110
    }
111
    }
112
113
//define pbkdf2 iteration count
114
define('ITCOUNT', '2072');
115
116
if (isset($_POST['type'])) {
117
    switch ($_POST['type']) {
118
        case "step0":
119
            // erase session table
120
            $_SESSION = array();
121
            setcookie('pma_end_session');
122
            session_destroy();
123
124
            echo 'document.getElementById("res_step0").innerHTML = "";';
125
            require_once 'libs/aesctr.php';
126
            require_once "../includes/config/settings.php";
127
128
            // check if path in settings.php are consistent
129
            if (!is_dir(SECUREPATH)) {
130
                echo 'document.getElementById("but_next").disabled = "disabled";';
131
                echo 'document.getElementById("res_step0").innerHTML = "Error in settings.php file!<br>Check correctness of path indicated in file `includes/config/settings.php`.<br>Reload this page and retry.";';
132
                echo 'document.getElementById("loader").style.display = "none";';
133
                break;
134
            }
135
            if (!file_exists(SECUREPATH."/sk.php")) {
136
                echo 'document.getElementById("but_next").disabled = "disabled";';
137
                echo 'document.getElementById("res_step0").innerHTML = "Error in settings.php file!<br>Check that file `sk.php` exists as defined in `includes/config/settings.php`.<br>Reload this page and retry.";';
138
                echo 'document.getElementById("loader").style.display = "none";';
139
                break;
140
            }
141
142
            $_SESSION['settings']['cpassman_dir'] = "..";
143
            require_once '../includes/libraries/PasswordLib/Random/Generator.php';
144
            require_once '../includes/libraries/PasswordLib/Random/Source.php';
145
            require_once '../includes/libraries/PasswordLib/Random/Source/MTRand.php';
146
            require_once '../includes/libraries/PasswordLib/Random/Source/Rand.php';
147
            require_once '../includes/libraries/PasswordLib/Random/Source/UniqID.php';
148
            require_once '../includes/libraries/PasswordLib/Random/Source/URandom.php';
149
            require_once '../includes/libraries/PasswordLib/Random/Source/MicroTime.php';
150
            require_once '../includes/libraries/PasswordLib/Random/Source/CAPICOM.php';
151
            require_once '../includes/libraries/PasswordLib/Random/Mixer.php';
152
            require_once '../includes/libraries/PasswordLib/Random/AbstractMixer.php';
153
            require_once '../includes/libraries/PasswordLib/Random/Mixer/Hash.php';
154
            require_once '../includes/libraries/PasswordLib/Password/AbstractPassword.php';
155
            require_once '../includes/libraries/PasswordLib/Password/Implementation/Hash.php';
156
            require_once '../includes/libraries/PasswordLib/Password/Implementation/Crypt.php';
157
            require_once '../includes/libraries/PasswordLib/Password/Implementation/SHA256.php';
158
            require_once '../includes/libraries/PasswordLib/Password/Implementation/SHA512.php';
159
            require_once '../includes/libraries/PasswordLib/Password/Implementation/PHPASS.php';
160
            require_once '../includes/libraries/PasswordLib/Password/Implementation/PHPBB.php';
161
            require_once '../includes/libraries/PasswordLib/Password/Implementation/PBKDF.php';
162
            require_once '../includes/libraries/PasswordLib/Password/Implementation/MediaWiki.php';
163
            require_once '../includes/libraries/PasswordLib/Password/Implementation/MD5.php';
164
            require_once '../includes/libraries/PasswordLib/Password/Implementation/Joomla.php';
165
            require_once '../includes/libraries/PasswordLib/Password/Implementation/Drupal.php';
166
            require_once '../includes/libraries/PasswordLib/Password/Implementation/APR1.php';
167
            require_once '../includes/libraries/PasswordLib/PasswordLib.php';
168
            $pwdlib = new PasswordLib\PasswordLib();
169
170
            //connect to db and check user is granted
171
            $link = mysqli_connect(
172
                $server,
173
                $user,
174
                $pass,
175
                $database,
176
                $port
177
            );
178
179
            $user_info = mysqli_fetch_array(mysqli_query($link,
180
                "SELECT pw, admin FROM ".$pre."users
181
                WHERE login='".mysqli_escape_string($link, stripslashes($_POST['login']))."'")
182
            );
183
184
            if (empty($user_info['pw']) || $user_info['pw'] === null) {
185
                echo 'document.getElementById("but_next").disabled = "disabled";';
186
                echo 'document.getElementById("res_step0").innerHTML = "This user is not allowed!";';
187
                echo 'document.getElementById("user_granted").value = "0";';
188
                $_SESSION['user_granted'] = false;
189
            } else {
190
                if ($pwdlib->verifyPasswordHash(Encryption\Crypt\aesctr::decrypt(base64_decode($_POST['pwd']), "cpm", 128), $user_info['pw']) === true && $user_info['admin'] === "1") {
0 ignored issues
show
Documentation introduced by
base64_decode($_POST['pwd']) is of type string, but the function expects a object<Encryption\Crypt\source>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
'cpm' is of type string, but the function expects a object<Encryption\Crypt\the>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
191
                    echo 'document.getElementById("but_next").disabled = "";';
192
                    echo 'document.getElementById("res_step0").innerHTML = "User is granted.";';
193
                    echo 'document.getElementById("step").value = "1";';
194
                    echo 'document.getElementById("user_granted").value = "1";';
195
                    $_SESSION['user_granted'] = true;
196
                } else {
197
                    echo 'document.getElementById("but_next").disabled = "disabled";';
198
                    echo 'document.getElementById("res_step0").innerHTML = "This user is not allowed!";';
199
                    echo 'document.getElementById("user_granted").value = "0";';
200
                    $_SESSION['user_granted'] = false;
201
                }
202
            }
203
204
            echo 'document.getElementById("loader").style.display = "none";';
205
            break;
206
207
        case "step1":
208
209
            if ($_SESSION['user_granted'] !== "1") {
210
                echo 'document.getElementById("res_step1").innerHTML = "User not connected anymore!";';
211
                echo 'document.getElementById("loader").style.display = "none";';
212
                break;
213
            }
214
215
            $_SESSION['fullurl'] = $_POST['fullurl'];
216
            $abspath = str_replace('\\', '/', $_POST['abspath']);
217
            $_SESSION['abspath'] = $abspath;
218 View Code Duplication
            if (substr($abspath, strlen($abspath) - 1) == "/") {
219
                $abspath = substr($abspath, 0, strlen($abspath) - 1);
220
            }
221
            $okWritable = true;
222
            $okExtensions = true;
223
            $txt = "";
224
            $x = 1;
225
            $tab = array(
226
                $abspath."/includes/config/settings.php",
227
                $abspath."/includes/libraries/csrfp/libs/",
228
                $abspath."/install/",
229
                $abspath."/includes/",
230
                $abspath."/includes/config/",
231
                $abspath."/includes/avatars/",
232
                $abspath."/files/",
233
                $abspath."/upload/"
234
            );
235
            foreach ($tab as $elem) {
236
                // try to create it if not existing
237
                if (substr($elem, -1) === '/' && !is_dir($elem)) {
238
                    mkdir($elem);
239
                }
240
                // check if writable
241
                if (is_writable($elem)) {
242
                    $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">'.
243
                        $elem.'&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
244
                } else {
245
                    $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">'.
246
                        $elem.'&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
247
                    $okWritable = false;
248
                }
249
                $x++;
250
            }
251
252
            if (!extension_loaded('mcrypt')) {
253
                $okExtensions = false;
254
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"mcrypt\"'.
255
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
256
            } else {
257
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"mcrypt\"'.
258
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
259
            }
260
            if (!extension_loaded('openssl')) {
261
                //$okExtensions = false;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
262
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"openssl\"'.
263
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
264
            } else {
265
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"openssl\"'.
266
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
267
            }
268
            if (!extension_loaded('gd')) {
269
                //$okExtensions = false;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
270
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"gd\"'.
271
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
272
            } else {
273
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"gd\"'.
274
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
275
            }
276
            if (!extension_loaded('mbstring')) {
277
                //$okExtensions = false;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
278
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"mbstring\"'.
279
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
280
            } else {
281
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"mbstring\"'.
282
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
283
            }
284
            if (!extension_loaded('bcmath')) {
285
                //$okExtensions = false;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
286
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"bcmath\"'.
287
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
288
            } else {
289
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"bcmath\"'.
290
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
291
            }
292
            if (!extension_loaded('iconv')) {
293
                //$okExtensions = false;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
294
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"iconv\"'.
295
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
296
            } else {
297
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"iconv\"'.
298
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
299
            }
300 View Code Duplication
            if (!extension_loaded('xml')) {
301
                //$okExtensions = false;
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
302
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"xml\"'.
303
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
304
            } else {
305
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"xml\"'.
306
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
307
            }
308 View Code Duplication
            if (!extension_loaded('curl')) {
309
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"curl\"'.
310
                    '&nbsp;&nbsp;<img src=\"images/minus-circle.png\"></span><br />';
311
            } else {
312
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP extension \"curl\"'.
313
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
314
            }
315
            if (ini_get('max_execution_time') < 60) {
316
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP \"Maximum '.
317
                    'execution time\" is set to '.ini_get('max_execution_time').' seconds.'.
318
                    ' Please try to set to 60s at least until Upgrade is finished.&nbsp;'.
319
                    '&nbsp;<img src=\"images/minus-circle.png\"></span> <br />';
320
            } else {
321
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP \"Maximum '.
322
                    'execution time\" is set to '.ini_get('max_execution_time').' seconds'.
323
                    '&nbsp;&nbsp;<img src=\"images/tick-circle.png\"></span><br />';
324
            }
325
            if (version_compare(phpversion(), '5.5.0', '<')) {
326
                $okVersion = false;
327
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP version '.
328
                    phpversion().' is not OK (minimum is 5.5.0) &nbsp;&nbsp;'.
329
                    '<img src=\"images/minus-circle.png\"></span><br />';
330
            } else {
331
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">PHP version '.
332
                    phpversion().' is OK&nbsp;&nbsp;<img src=\"images/tick-circle.png\">'.
333
                    '</span><br />';
334
            }
335
336
            //get infos from SETTINGS.PHP file
337
            $filename = "../includes/config/settings.php";
338
            $events = "";
339 View Code Duplication
            if (file_exists($filename)) {
340
                //copy some constants from this existing file
341
                $settingsFile = file($filename);
342
                while (list($key, $val) = each($settingsFile)) {
343
                    if (substr_count($val, 'charset') > 0) {
344
                        $_SESSION['charset'] = getSettingValue($val);
345
                    } elseif (substr_count($val, '@define(') > 0 && substr_count($val, 'SALT') > 0) {
346
                        $_SESSION['encrypt_key'] = substr($val, 17, strpos($val, "')") - 17);
347
                    } elseif (substr_count($val, '$smtp_server') > 0) {
348
                        $_SESSION['smtp_server'] = getSettingValue($val);
349
                    } elseif (substr_count($val, '$smtp_auth') > 0) {
350
                        $_SESSION['smtp_auth'] = getSettingValue($val);
351
                    } elseif (substr_count($val, '$smtp_auth_username') > 0) {
352
                        $_SESSION['smtp_auth_username'] = getSettingValue($val);
353
                    } elseif (substr_count($val, '$smtp_auth_password') > 0) {
354
                        $_SESSION['smtp_auth_password'] = getSettingValue($val);
355
                    } elseif (substr_count($val, '$smtp_port') > 0) {
356
                        $_SESSION['smtp_port'] = getSettingValue($val);
357
                    } elseif (substr_count($val, '$smtp_security') > 0) {
358
                        $_SESSION['smtp_security'] = getSettingValue($val);
359
                    } elseif (substr_count($val, '$email_from') > 0) {
360
                        $_SESSION['email_from'] = getSettingValue($val);
361
                    } elseif (substr_count($val, '$email_from_name') > 0) {
362
                        $_SESSION['email_from_name'] = getSettingValue($val);
363
                    } elseif (substr_count($val, '$server') > 0) {
364
                        $_SESSION['server'] = getSettingValue($val);
365
                    } elseif (substr_count($val, '$user') > 0) {
366
                        $_SESSION['user'] = getSettingValue($val);
367
                    } elseif (substr_count($val, '$pass') > 0) {
368
                        $_SESSION['pass'] = getSettingValue($val);
369
                    } elseif (substr_count($val, '$port') > 0) {
370
                        $_SESSION['port'] = getSettingValue($val);
371
                    } elseif (substr_count($val, '$database') > 0) {
372
                        $_SESSION['database'] = getSettingValue($val);
373
                    } elseif (substr_count($val, '$pre') > 0) {
374
                        $_SESSION['pre'] = getSettingValue($val);
375
                    } elseif (substr_count($val, 'require_once "') > 0 && substr_count($val, 'sk.php') > 0) {
376
                        $_SESSION['sk_file'] = substr($val, 14, strpos($val, '";') - 14);
377
                    }
378
                }
379
            }
380
            if (
381
                isset($_SESSION['sk_file']) && !empty($_SESSION['sk_file'])
382
                && file_exists($_SESSION['sk_file'])
383
            ) {
384
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">sk.php file'.
385
                    ' found in \"'.addslashes($_SESSION['sk_file']).'\"&nbsp;&nbsp;<img src=\"images/tick-circle.png\">'.
386
                    '</span><br />';
387
                //copy some constants from this existing file
388
                $skFile = file(string($_SESSION['sk_file']));
389
                while (list($key, $val) = each($skFile)) {
390
                    if (substr_count($val, "@define('SALT'") > 0) {
391
                        $_SESSION['encrypt_key'] = substr($val, 17, strpos($val, "')") - 17);
392
                        echo '$("#session_salt").val("'.$_SESSION['encrypt_key'].'");';
0 ignored issues
show
Security Cross-Site Scripting introduced by
'$("#session_salt").val(...['encrypt_key'] . '");' can contain request data and is used in output context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: Read from $_POST, and $_SESSION is assigned in install/upgrade_ajax.php on line 215
  1. Read from $_POST, and $_SESSION is assigned
    in install/upgrade_ajax.php on line 215
  2. $_SESSION is assigned
    in install/upgrade_ajax.php on line 217
  3. $_SESSION is assigned
    in install/upgrade_ajax.php on line 391
  2. Path: Read from $_POST, and $_POST['abspath'] is passed through str_replace(), and $abspath is assigned in install/upgrade_ajax.php on line 216
  1. Read from $_POST, and $_POST['abspath'] is passed through str_replace(), and $abspath is assigned
    in install/upgrade_ajax.php on line 216
  2. $_SESSION is assigned
    in install/upgrade_ajax.php on line 217
  3. $_SESSION is assigned
    in install/upgrade_ajax.php on line 391

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
393
                    }
394
                }
395
            }
396
397
            if (!isset($_SESSION['encrypt_key']) || empty($_SESSION['encrypt_key'])) {
398
                // check if 2.1.27 already installed
399
                $defuse_file = substr($_SESSION['sk_file'], 0, strrpos($_SESSION['sk_file'], "/"))."/teampass-seckey.txt";
400
                if (file_exists($defuse_file)) {
401
                    $okEncryptKey = true;
402
                    $_SESSION['tp_defuse_installed'] = true;
403
                    $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">Defuse encryption key is defined&nbsp;&nbsp;<img src=\"images/tick-circle.png\">'.
404
                        '</span><br />';
405
                } else {
406
                    $okEncryptKey = false;
407
                    $_SESSION['tp_defuse_installed'] = false;
408
                    $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">Encryption Key (SALT) '.
409
                        ' could not be recovered &nbsp;&nbsp;'.
410
                        '<img src=\"images/minus-circle.png\"></span><br />';
411
                    }
412
            } else {
413
                $okEncryptKey = true;
414
                $txt .= '<span style=\"padding-left:30px;font-size:13pt;\">Encryption Key (SALT) is available&nbsp;&nbsp;<img src=\"images/tick-circle.png\">'.
415
                    '</span><br />';
416
            }
417
418
            if ($okWritable === true && $okExtensions === true && $okEncryptKey === true) {
419
                echo 'document.getElementById("but_next").disabled = "";';
420
                echo 'document.getElementById("res_step1").innerHTML = "Elements are OK.";';
421
            } else {
422
                echo 'document.getElementById("but_next").disabled = "disabled";';
423
                echo 'document.getElementById("res_step1").innerHTML = "Correct the shown '.
424
                    'errors and click on button Launch to refresh";';
425
            }
426
427
            echo 'document.getElementById("res_step1").innerHTML = "'.$txt.'";';
0 ignored issues
show
Security Cross-Site Scripting introduced by
'document.getElementById...HTML = "' . $txt . '";' can contain request data and is used in output context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: Read from $_POST, and $_SESSION is assigned in install/upgrade_ajax.php on line 215
  1. Read from $_POST, and $_SESSION is assigned
    in install/upgrade_ajax.php on line 215
  2. $_SESSION is assigned
    in install/upgrade_ajax.php on line 217
  3. $_SESSION['sk_file'] is escaped by addslashes() for sql, xpath context(s)
    in install/upgrade_ajax.php on line 385
  4. $txt is assigned
    in install/upgrade_ajax.php on line 384
  2. Path: Read from $_POST, and $_POST['abspath'] is passed through str_replace(), and $abspath is assigned in install/upgrade_ajax.php on line 216
  1. Read from $_POST, and $_POST['abspath'] is passed through str_replace(), and $abspath is assigned
    in install/upgrade_ajax.php on line 216
  2. $_SESSION is assigned
    in install/upgrade_ajax.php on line 217
  3. $_SESSION['sk_file'] is escaped by addslashes() for sql, xpath context(s)
    in install/upgrade_ajax.php on line 385
  4. $txt is assigned
    in install/upgrade_ajax.php on line 384

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
428
            echo 'document.getElementById("loader").style.display = "none";';
429
            break;
430
431
            #==========================
432
        case "step2":
433
            $res = "";
434
435
            if ($_SESSION['user_granted'] !== "1") {
436
                echo 'document.getElementById("res_step2").innerHTML = "User not connected anymore!";';
437
                echo 'document.getElementById("loader").style.display = "none";';
438
                break;
439
            }
440
            //decrypt the password
441
            // AES Counter Mode implementation
442
            require_once 'libs/aesctr.php';
443
444
            // connexion
445
            if (
446
                mysqli_connect(
447
                    $_SESSION['server'],
448
                    $_SESSION['user'],
449
                    $_SESSION['pass'],
450
                    $_SESSION['database'],
451
                    $_SESSION['port']
452
                )
453
            ) {
454
                $dbTmp = mysqli_connect(
455
                    $_SESSION['server'],
456
                    $_SESSION['user'],
457
                    $_SESSION['pass'],
458
                    $_SESSION['database'],
459
                    $_SESSION['port']
460
                );
461
                $res = "Connection is successful";
462
                echo 'document.getElementById("but_next").disabled = "";';
463
464
                // check in db if previous saltk exists
465
                if ($_POST['no_previous_sk'] === "false" || $_POST['no_previous_sk'] === "previous_sk_sel") {
466
                    $db_sk = mysqli_fetch_row(mysqli_query($dbTmp, "SELECT count(*) FROM ".$_SESSION['pre']."misc
467
                    WHERE type='admin' AND intitule = 'saltkey_ante_2127'"));
468
                    if (!empty($_POST['previous_sk']) || !empty($_POST['session_salt'])) {
469
                        // get sk
470
                        if (!empty($_POST['session_salt'])) {
471
                            $sk_val = filter_var($_POST['session_salt'], FILTER_SANITIZE_STRING);
472
                        } else {
473
                            $sk_val = filter_var($_POST['previous_sk'], FILTER_SANITIZE_STRING);
474
                        }
475
476
                        // upidate
477
                        if (!empty($db_sk[0])) {
478
                            mysqli_query($dbTmp,
479
                                "UPDATE `".$_SESSION['pre']."misc`
0 ignored issues
show
Security SQL Injection introduced by
'UPDATE `' . $_SESSION['... \'saltkey_ante_2127\'' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['session_salt'] is passed through filter_var(), and $sk_val is assigned in install/upgrade_ajax.php on line 471
  1. Read from $_POST, and $_POST['session_salt'] is passed through filter_var(), and $sk_val is assigned
    in install/upgrade_ajax.php on line 471
  2. Path: Read from $_POST, and $_POST['previous_sk'] is passed through filter_var(), and $sk_val is assigned in install/upgrade_ajax.php on line 473
  1. Read from $_POST, and $_POST['previous_sk'] is passed through filter_var(), and $sk_val is assigned
    in install/upgrade_ajax.php on line 473

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
480
                                SET `valeur` = '".$sk_val."'
481
                                WHERE type = 'admin' AND intitule = 'saltkey_ante_2127'"
482
                            );
483
                        } else {
484
                            mysqli_query($dbTmp,
485
                                "INSERT INTO `".$_SESSION['pre']."misc`
0 ignored issues
show
Security SQL Injection introduced by
'INSERT INTO `' . $_SESS...\'saltkey_ante_2127\')' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: Read from $_POST, and $_POST['session_salt'] is passed through filter_var(), and $sk_val is assigned in install/upgrade_ajax.php on line 471
  1. Read from $_POST, and $_POST['session_salt'] is passed through filter_var(), and $sk_val is assigned
    in install/upgrade_ajax.php on line 471
  2. Path: Read from $_POST, and $_POST['previous_sk'] is passed through filter_var(), and $sk_val is assigned in install/upgrade_ajax.php on line 473
  1. Read from $_POST, and $_POST['previous_sk'] is passed through filter_var(), and $sk_val is assigned
    in install/upgrade_ajax.php on line 473

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
486
                                (`valeur`, `type`, `intitule`)
487
                                VALUES ('".$sk_val."', 'admin', 'saltkey_ante_2127')"
488
                            );
489
                        }
490
                    } elseif (empty($db_sk[0])) {
491
                        $res = "Please provide Teampass instance history.";
492
                        echo 'document.getElementById("but_next").disabled = "disabled";';
493
                        echo 'document.getElementById("res_step2").innerHTML = "'.$res.'";';
494
                        echo 'document.getElementById("loader").style.display = "none";';
495
                        echo 'document.getElementById("no_encrypt_key").style.display = "";';
496
                    }
497
                } else {
498
                    // user said that database has not being used for an older version
499
                    // no old sk is available
500
                        $tmp = mysqli_num_rows(mysqli_query(
501
                            $dbTmp,
502
                            "SELECT * FROM `".$var['tbl_prefix']."misc` WHERE type = 'admin' AND intitule = 'saltkey_ante_2127'"
503
                        ));
504
                    if ($tmp == 0) {
505
                        mysqli_query($dbTmp,
506
                            "INSERT INTO `".$_SESSION['pre']."misc`
507
                            (`valeur`, `type`, `intitule`)
508
                            VALUES ('none', 'admin', 'saltkey_ante_2127')"
509
                        );
510
                    } else {
511
                        mysqli_query($dbTmp,
512
                            "INSERT INTO `".$_SESSION['pre']."misc`
513
                            (`valeur`, `type`, `intitule`)
514
                            VALUES ('none', 'admin', 'saltkey_ante_2127')"
515
                        );
516
                    }
517
                    $_SESSION['tp_defuse_installed'] = true;
518
                }
519
520
                //What CPM version
521
                if (mysqli_query($dbTmp,
522
                    "SELECT valeur FROM ".$_POST['tbl_prefix']."misc
0 ignored issues
show
Security SQL Injection introduced by
'SELECT valeur FROM ' . ...= \'cpassman_version\'' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in install/upgrade_ajax.php on line 522

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
523
                    WHERE type='admin' AND intitule = 'cpassman_version'"
524
                )) {
525
                    $tmpResult = mysqli_query($dbTmp,
526
                        "SELECT valeur FROM ".$_POST['tbl_prefix']."misc
0 ignored issues
show
Security SQL Injection introduced by
'SELECT valeur FROM ' . ...= \'cpassman_version\'' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in install/upgrade_ajax.php on line 526

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
527
                        WHERE type='admin' AND intitule = 'cpassman_version'"
528
                    );
529
                    $cpmVersion = mysqli_fetch_row($tmpResult);
530
                    echo 'document.getElementById("actual_cpm_version").value = "'.
0 ignored issues
show
Security Cross-Site Scripting introduced by
'document.getElementById.... $cpmVersion[0] . '";' can contain request data and is used in output context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST, and ``'SELECT valeur FROM ' . $_POST['tbl_prefix'] . 'misc WHERE type=\'admin\' AND intitule = \'cpassman_version\''`` is passed through mysqli_query()
    in install/upgrade_ajax.php on line 526
  2. $tmpResult is assigned
    in install/upgrade_ajax.php on line 525
  3. $tmpResult is passed through mysqli_fetch_row(), and $cpmVersion is assigned
    in install/upgrade_ajax.php on line 529

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
531
                        $cpmVersion[0].'";';
532
                } else {
533
                    echo 'document.getElementById("actual_cpm_version").value = "0";';
534
                }
535
536
                //Get some infos from DB
537
                if (@mysqli_fetch_row(
538
                        mysqli_query($dbTmp, "SELECT valeur FROM ".$_POST['tbl_prefix']."misc
0 ignored issues
show
Security SQL Injection introduced by
'SELECT valeur FROM ' . ...ule = \'utf8_enabled\'' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in install/upgrade_ajax.php on line 538

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
539
                    WHERE type='admin' AND intitule = 'utf8_enabled'")
540
                    )
541
                ) {
542
                    $cpmIsUTF8 = mysqli_fetch_row(mysqli_query($dbTmp,
543
                        "SELECT valeur FROM ".$_POST['tbl_prefix']."misc
0 ignored issues
show
Security SQL Injection introduced by
'SELECT valeur FROM ' . ...ule = \'utf8_enabled\'' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in install/upgrade_ajax.php on line 543

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
544
                        WHERE type='admin' AND intitule = 'utf8_enabled'")
545
                    );
546
                    echo 'document.getElementById("cpm_isUTF8").value = "'.$cpmIsUTF8[0].'";';
0 ignored issues
show
Security Cross-Site Scripting introduced by
'document.getElementById... . $cpmIsUTF8[0] . '";' can contain request data and is used in output context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST, and ``'SELECT valeur FROM ' . $_POST['tbl_prefix'] . 'misc WHERE type=\'admin\' AND intitule = \'utf8_enabled\''`` is passed through mysqli_query()
    in install/upgrade_ajax.php on line 543
  2. ``mysqli_query($dbTmp, 'SELECT valeur FROM ' . $_POST['tbl_prefix'] . 'misc WHERE type=\'admin\' AND intitule = \'utf8_enabled\'')`` is passed through mysqli_fetch_row(), and $cpmIsUTF8 is assigned
    in install/upgrade_ajax.php on line 542

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
547
                    $_SESSION['utf8_enabled'] = $cpmIsUTF8[0];
548
                } else {
549
                    echo 'document.getElementById("cpm_isUTF8").value = "0";';
550
                    $_SESSION['utf8_enabled'] = 0;
551
                }
552
553
                // put TP in maintenance mode or not
554
                @mysqli_query($dbTmp,
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
555
                "UPDATE `".$_SESSION['pre']."misc`
0 ignored issues
show
Security SQL Injection introduced by
'UPDATE `' . $_SESSION['...intenance_mode'] . '\'' can contain request data and is used in sql context(s) leading to a potential security vulnerability.

2 paths for user data to reach this point

  1. Path: Read from $_POST, and ``'SELECT valeur FROM ' . $_POST['tbl_prefix'] . 'misc WHERE type=\'admin\' AND intitule = \'utf8_enabled\''`` is passed through mysqli_query() in install/upgrade_ajax.php on line 543
  1. Read from $_POST, and ``'SELECT valeur FROM ' . $_POST['tbl_prefix'] . 'misc WHERE type=\'admin\' AND intitule = \'utf8_enabled\''`` is passed through mysqli_query()
    in install/upgrade_ajax.php on line 543
  2. ``mysqli_query($dbTmp, 'SELECT valeur FROM ' . $_POST['tbl_prefix'] . 'misc WHERE type=\'admin\' AND intitule = \'utf8_enabled\'')`` is passed through mysqli_fetch_row(), and $cpmIsUTF8 is assigned
    in install/upgrade_ajax.php on line 542
  3. $_SESSION is assigned
    in install/upgrade_ajax.php on line 547
  2. Path: Read from $_POST in install/upgrade_ajax.php on line 557
  1. Read from $_POST
    in install/upgrade_ajax.php on line 557

Preventing SQL Injection

There are two options to prevent SQL injection. Generally, it is recommended to use parameter binding:

$stmt = mysqli_prepare("SELECT * FROM users WHERE name = ?");
$stmt->bind_param("s", $taintedUserName);

An alternative – although generally not recommended – is to escape your data manually:

$mysqli = new mysqli('localhost', 'user', 'pass', 'dbname');

$escaped = $mysqli->real_escape_string($taintedUserName);
$mysqli->query("SELECT * FROM users WHERE name = '".$escaped."'");

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
556
                    SET `valeur` = 'maintenance_mode'
557
                    WHERE type = 'admin' AND intitule = '".$_POST['no_maintenance_mode']."'"
558
                );
559
560
                echo 'document.getElementById("dump").style.display = "";';
561
            } else {
562
                $res = "Impossible to get connected to server. Error is: ".addslashes(mysqli_connect_error());
563
                echo 'document.getElementById("but_next").disabled = "disabled";';
564
            }
565
566
            echo 'document.getElementById("res_step2").innerHTML = "'.$res.'";';
567
            echo 'document.getElementById("loader").style.display = "none";';
568
            break;
569
570
            #==========================
571
        case "step3":
572
573
            if ($_SESSION['user_granted'] !== "1") {
574
                echo 'document.getElementById("res_step3").innerHTML = "User not connected anymore!";';
575
                echo 'document.getElementById("loader").style.display = "none";';
576
                break;
577
            }
578
579
            mysqli_connect(
580
                $_SESSION['server'],
581
                $_SESSION['user'],
582
                $_SESSION['pass'],
583
                $_SESSION['database'],
584
                $_SESSION['port']
585
            );
586
            $dbTmp = mysqli_connect(
587
                $_SESSION['server'],
588
                $_SESSION['user'],
589
                $_SESSION['pass'],
590
                $_SESSION['database'],
591
                $_SESSION['port']
592
            );
593
            $status = "";
594
595
            //rename tables
596
            if (
597
                isset($_POST['prefix_before_convert']) && $_POST['prefix_before_convert'] == "true"
598
            ) {
599
                $tables = mysqli_query($dbTmp, 'SHOW TABLES');
600
                while ($table = mysqli_fetch_row($tables)) {
601
                    if (tableExists("old_".$table[0]) != 1 && substr($table[0], 0, 4) != "old_") {
602
                        mysqli_query($dbTmp, "CREATE TABLE old_".$table[0]." LIKE ".$table[0]);
603
                        mysqli_query($dbTmp, "INSERT INTO old_".$table[0]." SELECT * FROM ".$table[0]);
604
                    }
605
                }
606
            }
607
608
            //convert database
609
            mysqli_query($dbTmp,
610
                "ALTER DATABASE `".$_SESSION['database']."`
611
                DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"
612
            );
613
614
            //convert tables
615
            $res = mysqli_query($dbTmp, "SHOW TABLES FROM `".$_SESSION['database']."`");
616
            while ($table = mysqli_fetch_row($res)) {
617 View Code Duplication
                if (substr($table[0], 0, 4) != "old_") {
618
                    mysqli_query($dbTmp,
619
                        "ALTER TABLE ".$_SESSION['database'].".`{$table[0]}`
620
                        CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci"
621
                    );
622
                    mysqli_query($dbTmp,
623
                        "ALTER TABLE".$_SESSION['database'].".`{$table[0]}`
624
                        DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci"
625
                    );
626
                }
627
            }
628
629
            echo 'document.getElementById("res_step3").innerHTML = "Done!";';
630
            echo 'document.getElementById("loader").style.display = "none";';
631
            echo 'document.getElementById("but_next").disabled = "";';
632
            echo 'document.getElementById("but_launch").disabled = "disabled";';
633
634
            mysqli_close($dbTmp);
635
            break;
636
637
            #==========================
638
639
640
            //=============================
641
        case "step5":
642
643
            if ($_SESSION['user_granted'] !== "1") {
644
                echo 'document.getElementById("res_step5").innerHTML = "User not connected anymore!";';
645
                echo 'document.getElementById("loader").style.display = "none";';
646
                break;
647
            }
648
649
            $filename = "../includes/config/settings.php";
650
            $events = "";
651
            if (file_exists($filename)) {
652
                //Do a copy of the existing file
653
                if (!copy(
654
                    $filename,
655
                    $filename.'.'.date(
656
                        "Y_m_d",
657
                        mktime(0, 0, 0, date('m'), date('d'), date('y'))
658
                    )
659
                )) {
660
                    echo 'document.getElementById("res_step5").innerHTML = '.
661
                        '"Setting.php file already exists and cannot be renamed. '.
662
                        'Please do it by yourself and click on button Launch.";';
663
                    echo 'document.getElementById("loader").style.display = "none";';
664
                    break;
665
                } else {
666
                    $events .= "The file $filename already exist. A copy has been created.<br />";
667
                    unlink($filename);
668
                }
669
670
                //manage SK path
671
                if (isset($_POST['sk_path']) && !empty($_POST['sk_path'])) {
672
                    $skFile = str_replace('\\', '/', $_POST['sk_path'].'/sk.php');
673
                    $securePath = str_replace('\\', '/', $_POST['sk_path']);
674
                } else {
675
                    echo 'document.getElementById("res_step5").innerHTML = '.
676
                        '"<img src=\"images/exclamation-red.png\"> The SK path must be indicated.";
677
                        document.getElementById("loader").style.display = "none";';
678
                    break;
679
                }
680
681
                //Check if path is ok
682
                if (is_dir($securePath)) {
683
                    if (is_writable($securePath)) {
0 ignored issues
show
Unused Code introduced by
This if statement is empty and can be removed.

This check looks for the bodies of if statements that have no statements or where all statements have been commented out. This may be the result of changes for debugging or the code may simply be obsolete.

These if bodies can be removed. If you have an empty if but statements in the else branch, consider inverting the condition.

if (rand(1, 6) > 3) {
//print "Check failed";
} else {
    print "Check succeeded";
}

could be turned into

if (rand(1, 6) <= 3) {
    print "Check succeeded";
}

This is much more concise to read.

Loading history...
684
                        //Do nothing
685
                    } else {
686
                        echo 'document.getElementById("res_step5").innerHTML = '.
687
                            '"<img src=\"images/exclamation-red.png\"> The SK path must be writable!";
688
                            document.getElementById("loader").style.display = "none";';
689
                        break;
690
                    }
691
                } else {
692
                    echo 'document.getElementById("res_step5").innerHTML = '.
693
                        '"<img src=\"images/exclamation-red.png\"> '.
694
                        'Path for SK is not a Directory!";
695
                    document.getElementById("loader").style.display = "none";';
696
                    break;
697
                }
698
699
                $fh = fopen($filename, 'w');
700
701
                //prepare smtp_auth variable
702
                if (empty($_SESSION['smtp_auth'])) {
703
                    $_SESSION['smtp_auth'] = 'false';
704
                }
705
                if (empty($_SESSION['smtp_auth_username'])) {
706
                    $_SESSION['smtp_auth_username'] = 'false';
707
                }
708
                if (empty($_SESSION['smtp_auth_password'])) {
709
                    $_SESSION['smtp_auth_password'] = 'false';
710
                }
711
                if (empty($_SESSION['email_from_name'])) {
712
                    $_SESSION['email_from_name'] = 'false';
713
                }
714
715
                $result1 = fwrite(
716
                    $fh,
717
                    utf8_encode(
0 ignored issues
show
Security File Manipulation introduced by
utf8_encode('<?php globa.../ Don\'t change this.') can contain request data and is used in file manipulation context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST, and $_POST['sk_path'] . '/sk.php' is passed through str_replace(), and $skFile is assigned
    in install/upgrade_ajax.php on line 672
  2. ``'$lang, $txt, $k, $pathTeampas, $urlTeampass, $pwComplexity, $mngPages; global $server, $user, $pass, $database, $pre, $db, $port, $encoding; ### DATABASE connexion parameters ### $server = "' . filter_var($_SESSION['server'], FILTER_SANITIZE_STRING) . '"; $user = "' . filter_var($_SESSION['user'], FILTER_SANITIZE_STRING) . '"; $pass = "' . str_replace('$', '\\$', filter_var($_SESSION['pass'], FILTER_SANITIZE_STRING)) . '"; $database = "' . filter_var($_SESSION['database'], FILTER_SANITIZE_STRING) . '"; $port = ' . filter_var($filter_var['port'], FILTER_SANITIZE_STRING) . '; $pre = "' . filter_var($_SESSION['pre'], FILTER_SANITIZE_STRING) . '"; $encoding = "' . filter_var($_SESSION['db_encoding'], FILTER_SANITIZE_STRING) . '"; @date_default_timezone_set($_SESSION[\'settings\'][\'timezone\']); @define(\'SECUREPATH\', \'' . substr($skFile, 0, strlen($skFile) - 7) . '\'); if (!file_exists("' . $skFile . '")) { require_once "' . $skFile . '"; } @define(\'COST\', \'13\'); // Don\'t change this.'`` is passed through utf8_encode()
    in install/upgrade_ajax.php on line 718

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
718
"<?php
719
global \$lang, \$txt, \$k, \$pathTeampas, \$urlTeampass, \$pwComplexity, \$mngPages;
720
global \$server, \$user, \$pass, \$database, \$pre, \$db, \$port, \$encoding;
721
722
### DATABASE connexion parameters ###
723
\$server = \"".filter_var($_SESSION['server'], FILTER_SANITIZE_STRING)."\";
724
\$user = \"". filter_var($_SESSION['user'], FILTER_SANITIZE_STRING)."\";
725
\$pass = \"". str_replace("$", "\\$", filter_var($_SESSION['pass'], FILTER_SANITIZE_STRING))."\";
726
\$database = \"". filter_var($_SESSION['database'], FILTER_SANITIZE_STRING)."\";
727
\$port = ". filter_var($filter_var['port'], FILTER_SANITIZE_STRING).";
728
\$pre = \"". filter_var($_SESSION['pre'], FILTER_SANITIZE_STRING)."\";
729
\$encoding = \"".filter_var($_SESSION['db_encoding'], FILTER_SANITIZE_STRING)."\";
730
731
@date_default_timezone_set(\$_SESSION['settings']['timezone']);
732
@define('SECUREPATH', '".substr($skFile, 0, strlen($skFile) - 7)."');
733
if (!file_exists(\"".$skFile."\")) {
734
    require_once \"".$skFile."\";
735
}
736
@define('COST', '13'); // Don't change this."
737
                    )
738
                );
739
740
                fclose($fh);
741
                if ($result1 === false) {
742
                    echo 'document.getElementById("res_step5").innerHTML = '.
743
                        '"Setting.php file could not be created. '.
744
                        'Please check the path and the rights.";';
745
                } else {
746
                    echo 'document.getElementById("step5_settingFile").innerHTML = '.
747
                        '"<img src=\"images/tick.png\">";';
748
                }
749
750
                //Create sk.php file
751
                if (!file_exists($skFile)) {
752
                    $fh = fopen($skFile, 'w');
753
754
                    $result2 = fwrite(
755
                        $fh,
756
                        utf8_encode(
757
"<?php
758
@define('COST', '13'); // Don't change this.
759
@define('AKEY', '');
760
@define('IKEY', '');
761
@define('SKEY', '');
762
@define('HOST', '');
763
?>"
764
                        )
765
                    );
766
                    fclose($fh);
767
                }
768
769
                // update CSRFP TOKEN
770
                $csrfp_file_sample = "../includes/libraries/csrfp/libs/csrfp.config.sample.php";
771
                $csrfp_file = "../includes/libraries/csrfp/libs/csrfp.config.php";
772
                if (file_exists($csrfp_file)) {
773
                    if (!copy($filename, $filename.'.'.date("Y_m_d", mktime(0, 0, 0, date('m'), date('d'), date('y'))))) {
774
                        echo '[{"error" : "csrfp.config.php file already exists and cannot be renamed. Please do it by yourself and click on button Launch.", "result":"", "index" : "'.$_POST['index'].'", "multiple" : "'.$_POST['multiple'].'"}]';
0 ignored issues
show
Security Cross-Site Scripting introduced by
'[{"error" : "csrfp.conf...OST['multiple'] . '"}]' can contain request data and is used in output context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_POST
    in install/upgrade_ajax.php on line 774

Preventing Cross-Site-Scripting Attacks

Cross-Site-Scripting allows an attacker to inject malicious code into your website - in particular Javascript code, and have that code executed with the privileges of a visiting user. This can be used to obtain data, or perform actions on behalf of that visiting user.

In order to prevent this, make sure to escape all user-provided data:

// for HTML
$sanitized = htmlentities($tainted, ENT_QUOTES);

// for URLs
$sanitized = urlencode($tainted);

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
775
                        break;
776
                    } else {
777
                        $events .= "The file $csrfp_file already exist. A copy has been created.<br />";
778
                    }
779
                }
780
                unlink($csrfp_file); // delete existing csrfp.config file
781
                copy($csrfp_file_sample, $csrfp_file); // make a copy of csrfp.config.sample file
782
                $data = file_get_contents("../includes/libraries/csrfp/libs/csrfp.config.php");
783
                $newdata = str_replace('"CSRFP_TOKEN" => ""', '"CSRFP_TOKEN" => "'.bin2hex(openssl_random_pseudo_bytes(25)).'"', $data);
784
                $newdata = str_replace('"tokenLength" => "25"', '"tokenLength" => "50"', $newdata);
785
                $jsUrl = $_SESSION['fullurl'].'/includes/libraries/csrfp/js/csrfprotector.js';
786
                $newdata = str_replace('"jsUrl" => ""', '"jsUrl" => "'.$jsUrl.'"', $newdata);
787
                $newdata = str_replace('"verifyGetFor" => array()', '"verifyGetFor" => array("*page=items&type=duo_check*")', $newdata);
788
                file_put_contents("../includes/libraries/csrfp/libs/csrfp.config.php", $newdata);
789
790
791
                // finalize
792
                if (isset($result2) && $result2 === false) {
793
                    echo 'document.getElementById("res_step5").innerHTML = '.
794
                        '"$skFile could not be created. Please check the path and the rights.";';
795
                } else {
796
                    echo 'document.getElementById("step5_skFile").innerHTML = '.
797
                        '"<img src=\"images/tick.png\">";';
798
                }
799
800
                //Finished
801
                if (
802
                    $result1 !== false
803
                    && (!isset($result2) || (isset($result2) && $result2 !== false))
804
                ) {
805
                    echo 'document.getElementById("but_next").disabled = "";';
806
                    echo 'document.getElementById("res_step5").innerHTML = '.
807
                        '"Operations are successfully completed.";';
808
                    echo 'document.getElementById("loader").style.display = "none";';
809
                    echo 'document.getElementById("but_launch").disabled = "disabled";';
810
                }
811
            } else {
812
                //settings.php file doesn't exit => ERROR !!!!
813
                echo 'document.getElementById("res_step5").innerHTML = '.
814
                        '"<img src=\"images/error.png\">&nbsp;Setting.php '.
815
                        'file doesn\'t exist! Upgrade can\'t continue without this file.<br />'.
816
                        'Please copy your existing settings.php into the \"includes\" '.
817
                        'folder of your TeamPass installation ";';
818
                echo 'document.getElementById("loader").style.display = "none";';
819
            }
820
821
            break;
822
823
        case "perform_database_dump":
824
            $filename = "../includes/config/settings.php";
825
826
            $mtables = array();
827
828
            $mysqli = new mysqli($_SESSION['server'], $_SESSION['user'], $_SESSION['pass'], $_SESSION['database'], $_SESSION['port']);
829
            if ($mysqli->connect_error) {
830
                die('Error : ('.$mysqli->connect_errno.') '.$mysqli->connect_error);
831
            }
832
833
            $results = $mysqli->query("SHOW TABLES");
834
835
            while ($row = $results->fetch_array()) {
836
                $mtables[] = $row[0];
837
            }
838
839
            foreach ($mtables as $table) {
840
                $contents .= "-- Table `".$table."` --\n";
841
842
                $results = $mysqli->query("SHOW CREATE TABLE ".$table);
843
                while ($row = $results->fetch_array()) {
844
                    $contents .= $row[1].";\n\n";
845
                }
846
847
                $results = $mysqli->query("SELECT * FROM ".$table);
848
                $row_count = $results->num_rows;
849
                $fields = $results->fetch_fields();
850
                $fields_count = count($fields);
851
852
                $insert_head = "INSERT INTO `".$table."` (";
853
                for ($i = 0; $i < $fields_count; $i++) {
854
                    $insert_head .= "`".$fields[$i]->name."`";
855
                        if ($i < $fields_count - 1) {
856
                                $insert_head .= ', ';
857
                            }
858
                }
859
                $insert_head .= ")";
860
                $insert_head .= " VALUES\n";
861
862
                if ($row_count > 0) {
863
                    $r = 0;
864
                    while ($row = $results->fetch_array()) {
865
                        if (($r % 400) == 0) {
866
                            $contents .= $insert_head;
867
                        }
868
                        $contents .= "(";
869
                        for ($i = 0; $i < $fields_count; $i++) {
870
                            $row_content = str_replace("\n", "\\n", $mysqli->real_escape_string($row[$i]));
871
872
                            switch ($fields[$i]->type) {
873
                                case 8: case 3:
874
                                    $contents .= $row_content;
875
                                    break;
876
                                default:
877
                                    $contents .= "'".$row_content."'";
878
                            }
879
                            if ($i < $fields_count - 1) {
880
                                    $contents .= ', ';
881
                                }
882
                        }
883
                        if (($r + 1) == $row_count || ($r % 400) == 399) {
884
                            $contents .= ");\n\n";
885
                        } else {
886
                            $contents .= "),\n";
887
                        }
888
                        $r++;
889
                    }
890
                }
891
            }
892
893
            $backup_file_name = "sql-backup-".date("d-m-Y--h-i-s").".sql";
894
895
            $fp = fopen("../files/".$backup_file_name, 'w+');
896
            if (($result = fwrite($fp, $contents))) {
897
                echo '[{ "error" : "" , "file" : "files/'.$backup_file_name.'"}]';
898
            } else {
899
                echo '[{ "error" : "Backup fails - please do it manually."}]';
900
            }
901
            fclose($fp);
902
903
            break;
904
    }
905
}
906