Issues (204)

Security Analysis    13 potential vulnerabilities

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  Response Splitting (2)
Response Splitting can be used to send arbitrary responses.
  File Manipulation (6)
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Variable Injection (1)
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Cross-Site Scripting (1)
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

web/admin/inc/sendinvite.inc.php (2 issues)

1
<?php
2
3
/*
4
 * *****************************************************************************
5
 * Contributions to this work were made on behalf of the GÉANT project, a 
6
 * project that has received funding from the European Union’s Framework 
7
 * Programme 7 under Grant Agreements No. 238875 (GN3) and No. 605243 (GN3plus),
8
 * Horizon 2020 research and innovation programme under Grant Agreements No. 
9
 * 691567 (GN4-1) and No. 731122 (GN4-2).
10
 * On behalf of the aforementioned projects, GEANT Association is the sole owner
11
 * of the copyright in all material which was developed by a member of the GÉANT
12
 * project. GÉANT Vereniging (Association) is registered with the Chamber of 
13
 * Commerce in Amsterdam with registration number 40535155 and operates in the 
14
 * UK as a branch of GÉANT Vereniging.
15
 * 
16
 * Registered office: Hoekenrode 3, 1102BR Amsterdam, The Netherlands. 
17
 * UK branch address: City House, 126-130 Hills Road, Cambridge CB2 1PQ, UK
18
 *
19
 * License: see the web/copyright.inc.php file in the file structure or
20
 *          <base_url>/copyright.php after deploying the software
21
 */
22
23
require_once dirname(dirname(dirname(__DIR__))) . "/config/_config.php";
24
25
$auth = new \web\lib\admin\Authentication();
26
$auth->authenticate();
27
28
$catInstance = new \core\CAT();
29
$validator = new \web\lib\common\InputValidation();
30
$uiElements = new \web\lib\admin\UIElements();
31
$languageInstance = new \core\common\Language();
32
$languageInstance->setTextDomain("web_admin");
33
34
$mgmt = new \core\UserManagement;
35
$new_idp_authorized_fedadmin = FALSE;
36
37
// check if the user is authenticated, and we have a valid mail address
38
if (!isset($_SESSION['user']) || !isset($_POST['mailaddr'])) {
39
    throw new Exception("sendinvite: called either without authentication or without target mail address!");
40
}
41
42
$newmailaddress = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'mailaddr')));
43
$totalSegments = explode(",", $newmailaddress);
44
$validAddresses = core\common\OutsideComm::exfiltrateValidAddresses($newmailaddress);
45
$newcountry = "";
46
47
// fed admin stuff
48
// we are either inviting to co-manage an existing inst ...
49
50
$userObject = new \core\User($_SESSION['user']);
51
$federation = NULL;
52
53
const OPERATION_MODE_INVALID = 0;
54
const OPERATION_MODE_EDIT = 1;
55
const OPERATION_MODE_NEWFROMDB = 2;
56
const OPERATION_MODE_NEWUNLINKED = 3;
57
const OPERATION_MODE_SELF_ADMIN_ADD = 4;
58
const OPERATION_MODE_SELF_NEWFROMDB = 5;
59
60
61
$operationMode = OPERATION_MODE_INVALID;
62
63
// filter all input to make Scrutinizer unnecessarily happy
64
65
// what did we actually get?
66
if (isset($_GET['inst_id'])) {
67
    if (isset($_POST['self_registration'])) {
68
        \core\common\Logging::debug_s(4, "Self registration received\n");
69
        $operationMode = OPERATION_MODE_SELF_ADMIN_ADD;
70
        } else {
71
        $operationMode = OPERATION_MODE_EDIT;
72
    }
73
}
74
75
if (isset($_POST['creation'])) {
76
    $filteredCreation = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'creation')));
77
} else {
78
    $filteredCreation = NULL;
79
}
80
81
if (isset($_POST['name'])) {
82
    $filteredName = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'name')));
83
} else {
84
    $filteredName = NULL;
85
}
86
87
if (isset($_POST['country'])) {
88
    $filteredCountry = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'country')));
89
} else {
90
    $filteredCountry = NULL;
91
}
92
93
if (isset($_POST['externals'])) {
94
    $filteredExternals = htmlspecialchars(strip_tags(filter_input(INPUT_POST, 'externals')));
95
} else {
96
    $filteredExternals = NULL;
97
}
98
99
if ($filteredCreation == "new" && $filteredName !== NULL && $filteredCountry !== NULL) {
100
    $operationMode = OPERATION_MODE_NEWUNLINKED;
101
}
102
103
if ($filteredCreation == "existing" && $filteredExternals !== NULL && $filteredExternals != "FREETEXT") {
104
    if (isset($_POST['self_registration'])) {
105
        \core\common\Logging::debug_s(4, "Self registration received\n");
106
        $operationMode = OPERATION_MODE_SELF_NEWFROMDB;
107
        } else {
108
        $operationMode = OPERATION_MODE_NEWFROMDB;
109
    }
110
}
111
$redirectDestination = '';
112
switch ($operationMode) {
113
    case OPERATION_MODE_EDIT:
114
        $idp = $validator->existingIdP($_GET['inst_id']);
115
        // editing IdPs is done from within the popup. When we're done, send the 
116
        // user back to the popup (append the result of the operation later)
117
        $redirectDestination = "manageAdmins.inc.php?inst_id=" . $idp->identifier . "&";
118
        if (count($validAddresses) == 0) {
119
            header("Location: $redirectDestination" . "invitation=INVALIDSYNTAX");
120
            exit(1);
121
        }
122
        // is the user primary admin of this IdP?
123
        $is_owner = $idp->isPrimaryOwner($_SESSION['user']);
124
        // check if he is (also) federation admin for the federation this IdP is in. His invitations have more blessing then.
125
        $fedadmin = $userObject->isFederationAdmin($idp->federation);
126
        // check if he is either one, if not, complain
127
        if (!$is_owner && !$fedadmin) {
128
            echo "<p>" . sprintf(_("Something's wrong... you are a %s admin, but not for the %s the requested %s belongs to!"), $uiElements->nomenclatureFed, $uiElements->nomenclatureFed, $uiElements->nomenclatureParticipant) . "</p>";
129
            exit(1);
130
        }
131
        $prettyprintname = $idp->name;
132
        $newtokens = $mgmt->createTokens($fedadmin, $validAddresses, $idp);
133
        \core\common\Logging::writeSQLAudit_s($_SESSION['user'], "NEW", "IdP " . $idp->identifier . " - Token created for " . implode(",", $validAddresses));
0 ignored issues
show
The call to core\common\Logging::writeSQLAudit_s() has too many arguments starting with 'NEW'. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

133
        \core\common\Logging::/** @scrutinizer ignore-call */ 
134
                              writeSQLAudit_s($_SESSION['user'], "NEW", "IdP " . $idp->identifier . " - Token created for " . implode(",", $validAddresses));

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
134
        $introtext = "CO-ADMIN";
135
        $participant_type = $idp->type;
136
        break;
137
    case OPERATION_MODE_SELF_ADMIN_ADD:
138
        $idp = $validator->existingIdP($_GET['inst_id']);
139
        $allowedIdPs = $_SESSION['resyncedIdPs'];
140
        if (!in_array($idp->identifier, $allowedIdPs)) {
141
            throw new Exception("sendinvite: requested IdP token for and IdP identifier which is not within the allowed list for this user");
142
        }
143
        $validAddresses = [$_SESSION['auth_email']];
144
        $prettyprintname = $idp->name;
145
        $newtokens = $mgmt->createTokens("FED", $validAddresses, $idp);
0 ignored issues
show
'FED' of type string is incompatible with the type boolean expected by parameter $isByFedadmin of core\UserManagement::createTokens(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

145
        $newtokens = $mgmt->createTokens(/** @scrutinizer ignore-type */ "FED", $validAddresses, $idp);
Loading history...
146
        \core\common\Logging::writeSQLAudit_s($_SESSION['user'], "NEW", "IdP (self)" . $idp->identifier . " - Token created for " . implode(",", $validAddresses));
147
        $participant_type = $idp->type;
148
        $introtext = "SELF-ADMIN";
149
        break;
150
    case OPERATION_MODE_NEWUNLINKED:
151
        $redirectDestination = "../overview_federation.php?";
152
        if (count($validAddresses) == 0) {
153
            header("Location: $redirectDestination"."invitation=INVALIDSYNTAX");
154
            exit(1);
155
        }
156
        // run an input check and conversion of the raw inputs... just in case
157
        $newinstname = $validator->string($_POST['name']);
158
        $newcountry = $validator->string($_POST['country']);
159
        $participant_type = $validator->partType($_POST['participant_type']);
160
        $new_idp_authorized_fedadmin = $userObject->isFederationAdmin($newcountry);
161
        if ($new_idp_authorized_fedadmin !== TRUE) {
162
            throw new Exception("Something's wrong... you want to create a new " . $uiElements->nomenclatureParticipant . ", but are not a " . $uiElements->nomenclatureFed . " admin for the " . $uiElements->nomenclatureFed . " it should be in!");
163
        }
164
        $federation = $validator->existingFederation($newcountry);
165
        $prettyprintname = $newinstname;
166
        $introtext = "NEW-FED";
167
        // send the user back to his federation overview page, append the result of the operation later
168
        // do the token creation magic
169
        $newtokens = $mgmt->createTokens(TRUE, $validAddresses, $newinstname, 0, $newcountry, $participant_type);
170
        \core\common\Logging::writeSQLAudit_s($_SESSION['user'], "NEW", "ORG FUTURE  - Token created for $participant_type " . implode(",", $validAddresses));
171
        break;
172
    case OPERATION_MODE_SELF_NEWFROMDB:
173
        $validAddresses = [$_SESSION['auth_email']];
174
        if (!isset($_SESSION['newIdPs']) || count($_SESSION['newIdPs']) !== 1) {
175
            throw new Exception("Tried eduroam DB based creation without ext identifiers");
176
        }
177
        $newIdPs = $_SESSION['newIdPs'];
178
        $externals = $validator->string($_POST['externals']);
179
        [$fedId, $newexternalid] = explode('-', $externals, 2);
180
        $found = [];
181
        foreach ($newIdPs as $allowed) {
182
            \core\common\Logging::debug_s(4, $allowed, "Allowed:\n", "\n");
183
            if (strtoupper($allowed[2]) === $fedId && $allowed[0] ===  $newexternalid) {
184
                $found = $allowed;
185
            }
186
        }
187
        if ($found == []) {
188
            throw new Exception("sendinvite: requested IdP token for and IdP identifier which is not within the allowed list for this user");
189
        }
190
        $federation = $validator->existingFederation($fedId);
191
        $newInstFlag = $federation->getAttributes('fed:autoregister-new-inst');
192
        if ($newInstFlag === []) {
193
            throw new Exception("sendinvite: You tried to register an IdP in self-service, but this federation does not allow self-service!");
194
        }
195
        $extinfo = $catInstance->getExternalDBEntityDetails($newexternalid, strtoupper($fedId).'01');
196
        // see if the inst name is defined in the currently set language; if not, pick its English name; if N/A, pick the last in the list
197
        $prettyprintname = "";
198
        foreach ($extinfo['names'] as $lang => $name) {
199
            if ($lang == $languageInstance->getLang()) {
200
                $prettyprintname = $name;
201
            }
202
        }
203
        if ($prettyprintname == "" && isset($extinfo['names']['en'])) {
204
            $prettyprintname = $extinfo['names']['en'];
205
        }
206
        if ($prettyprintname == "") {
207
            foreach ($extinfo['names'] as $name) {
208
                $prettyprintname = $name;
209
            }
210
        }
211
        if(\config\Master::FUNCTIONALITY_FLAGS['SINGLE_SERVICE'] === 'MSP') {
212
            $participant_type = \core\IdP::TYPE_SP;
213
        } else {
214
            $participant_type = $extinfo['type'];
215
        }
216
        // fill the rest of the text
217
        $introtext = "EXISTING-FED";
218
        // do the token creation magic
219
        $newtokens = $mgmt->createTokens(TRUE, $validAddresses, $prettyprintname, $newexternalid, $fedId);
220
        \core\common\Logging::writeSQLAudit_s($_SESSION['user'], "NEW", "IdP FUTURE (self) - Token created for " . implode(",", $validAddresses));        
221
        break; 
222
    case OPERATION_MODE_NEWFROMDB:
223
        $redirectDestination = "../overview_federation.php?";
224
        if (count($validAddresses) == 0) {
225
            header("Location: $redirectDestination"."invitation=INVALIDSYNTAX");
226
            exit(1);
227
        }
228
        // a real external DB entry was submitted and all the required parameters are there
229
        $externals = $validator->string($_POST['externals']);
230
        [$fedId, $newexternalid] = explode('-', $externals, 2);
231
        $extinfo = $catInstance->getExternalDBEntityDetails($newexternalid, strtoupper($fedId).'01');
232
        $new_idp_authorized_fedadmin = $userObject->isFederationAdmin($extinfo['country']);
233
        if ($new_idp_authorized_fedadmin !== TRUE) {
234
            throw new Exception("Something's wrong... you want to create a new " . $uiElements->nomenclatureParticipant . ", but are not a " . $uiElements->nomenclatureFed . " admin for the " . $uiElements->nomenclatureFed . " it should be in!");
235
        }
236
        $federation = $validator->existingFederation($extinfo['country']);
237
        $newcountry = $extinfo['country'];
238
        // see if the inst name is defined in the currently set language; if not, pick its English name; if N/A, pick the last in the list
239
        $prettyprintname = "";
240
        foreach ($extinfo['names'] as $lang => $name) {
241
            if ($lang == $languageInstance->getLang()) {
242
                $prettyprintname = $name;
243
            }
244
        }
245
        if ($prettyprintname == "" && isset($extinfo['names']['en'])) {
246
            $prettyprintname = $extinfo['names']['en'];
247
        }
248
        if ($prettyprintname == "") {
249
            foreach ($extinfo['names'] as $name) {
250
                $prettyprintname = $name;
251
            }
252
        }
253
        if(\config\Master::FUNCTIONALITY_FLAGS['SINGLE_SERVICE'] === 'MSP') {
254
            $participant_type = \core\IdP::TYPE_SP;
255
        } else {
256
            $participant_type = $extinfo['type'];
257
        }
258
        // fill the rest of the text
259
        $introtext = "EXISTING-FED";
260
        // do the token creation magic
261
        $newtokens = $mgmt->createTokens(TRUE, $validAddresses, $prettyprintname, $newexternalid, $fedId);
262
        \core\common\Logging::writeSQLAudit_s($_SESSION['user'], "NEW", "IdP FUTURE  - Token created for " . implode(",", $validAddresses));
263
        break;
264
    default: // includes OPERATION_MODE_INVALID
265
        // second param is TRUE, so the variable *will* contain a string
266
        // i.e. ignore Scrutinizer type warning later
267
        $wrongcontent = print_r($_POST, TRUE);
268
        echo "<pre>Wrong parameters in POST:
269
" . htmlspecialchars(/** @scrutinizer ignore-type */ $wrongcontent) . "
270
</pre>";
271
        exit(1);
272
}
273
274
// send, and invalidate the token immediately if the mail could not be sent!
275
276
$status = [];
277
$allEncrypted = TRUE;
278
$allClear = TRUE;
279
foreach ($newtokens as $onetoken => $oneDest) {
280
    $sent = \core\common\OutsideComm::adminInvitationMail($oneDest, $introtext, $onetoken, $prettyprintname, $federation, $participant_type);
281
    if ($sent["SENT"] === FALSE) {
282
        $mgmt->invalidateToken($onetoken);
283
    } else {
284
        $status[$onetoken] = $sent["TRANSPORT"];
285
        if (!$sent["TRANSPORT"]) {
286
            $allEncrypted = FALSE;
287
        } else {
288
            $allClear = FALSE;
289
        }
290
    }
291
}
292
293
if (count($status) == 0) {
294
    switch ($operationMode) {
295
        case OPERATION_MODE_SELF_ADMIN_ADD:
296
        case OPERATION_MODE_SELF_NEWFROMDB:
297
            print("FAILURE");
298
            break;
299
        default:
300
            header("Location: $redirectDestination" . "invitation=FAILURE");
301
            exit;
302
    }
303
}
304
$finalDestParams = "invitation=SUCCESS";
305
if (count($status) < count($totalSegments)) { // only a subset of mails was sent, update status
306
    $finalDestParams = "invitation=PARTIAL";
307
}
308
$finalDestParams .= "&successcount=" . count($status);
309
if ($allEncrypted === TRUE) {
310
    $finalDestParams .= "&transportsecurity=ENCRYPTED";
311
} elseif ($allClear === TRUE) {
312
    $finalDestParams .= "&transportsecurity=CLEAR";
313
} else {
314
    $finalDestParams .= "&transportsecurity=PARTIAL";
315
}
316
317
switch ($operationMode) {
318
    case OPERATION_MODE_SELF_ADMIN_ADD:
319
    case OPERATION_MODE_SELF_NEWFROMDB:
320
        print("SUCCESS");
321
        break;
322
    default:
323
        header("Location: $redirectDestination" . $finalDestParams);
324
}
325
326
327
328