Issues (2473)

Branch: master

Security Analysis    no vulnerabilities found

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

  Cross-Site Scripting
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.
  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.
  File Manipulation
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.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  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.
  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.
  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.
  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.
  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.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  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.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
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.

engine/lib/input.php (1 issue)

Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Parameter input functions.
4
 * This file contains functions for getting input from get/post variables.
5
 *
6
 * @package Elgg.Core
7
 * @subpackage Input
8
 */
9
10
/**
11
 * Get some input from variables passed submitted through GET or POST.
12
 *
13
 * If using any data obtained from get_input() in a web page, please be aware that
14
 * it is a possible vector for a reflected XSS attack. If you are expecting an
15
 * integer, cast it to an int. If it is a string, escape quotes.
16
 *
17
 * Note: this function does not handle nested arrays (ex: form input of param[m][n])
18
 * because of the filtering done in htmlawed from the filter_tags call.
19
 * @todo Is this ^ still true?
20
 *
21
 * @param string $variable      The variable name we want.
22
 * @param mixed  $default       A default value for the variable if it is not found.
23
 * @param bool   $filter_result If true, then the result is filtered for bad tags.
24
 *
25
 * @return mixed
26
 */
27
function get_input($variable, $default = null, $filter_result = true) {
28 9
	return _elgg_services()->input->get($variable, $default, $filter_result);
29 1
}
30
31
/**
32
 * Sets an input value that may later be retrieved by get_input
33
 *
34
 * Note: this function does not handle nested arrays (ex: form input of param[m][n])
35
 *
36
 * @param string          $variable The name of the variable
37
 * @param string|string[] $value    The value of the variable
38
 *
39
 * @return void
40
 */
41
function set_input($variable, $value) {
42 1
	_elgg_services()->input->set($variable, $value);
43 1
}
44
45
/**
46
 * Filter tags from a given string based on registered hooks.
47
 *
48
 * @param mixed $var Anything that does not include an object (strings, ints, arrays)
49
 *					 This includes multi-dimensional arrays.
50
 *
51
 * @return mixed The filtered result - everything will be strings
52
 */
53
function filter_tags($var) {
54 1
	return elgg_trigger_plugin_hook('validate', 'input', null, $var);
55
}
56
57
/**
58
 * Returns the current page's complete URL.
59
 *
60
 * It uses the configured site URL for the hostname rather than depending on
61
 * what the server uses to populate $_SERVER.
62
 *
63
 * @return string The current page URL.
64
 */
65
function current_page_url() {
66 1
	$url = parse_url(elgg_get_site_url());
67
68 1
	$page = $url['scheme'] . "://" . $url['host'];
69
70 1
	if (isset($url['port']) && $url['port']) {
71
		$page .= ":" . $url['port'];
72
	}
73
74 1
	$page = trim($page, "/");
75
76 1
	$page .= _elgg_services()->request->getRequestUri();
77
78 1
	return $page;
79
}
80
81
/**
82
 * Validates an email address.
83
 *
84
 * @param string $address Email address.
85
 *
86
 * @return bool
87
 */
88
function is_email_address($address) {
89
	return filter_var($address, FILTER_VALIDATE_EMAIL) === $address;
90
}
91
92
/**
93
 * Save form submission data (all GET and POST vars) into a session cache
94
 *
95
 * Call this from an action when you want all your submitted variables
96
 * available if the submission fails validation and is sent back to the form
97
 *
98
 * @param string $form_name Name of the sticky form
99
 *
100
 * @return void
101
 * @since 1.8.0
102
 */
103
function elgg_make_sticky_form($form_name) {
104
	_elgg_services()->stickyForms->makeStickyForm($form_name);
105
}
106
107
/**
108
 * Remove form submission data from the session
109
 *
110
 * Call this if validation is successful in the action handler or
111
 * when they sticky values have been used to repopulate the form
112
 * after a validation error.
113
 *
114
 * @param string $form_name Form namespace
115
 *
116
 * @return void
117
 * @since 1.8.0
118
 */
119
function elgg_clear_sticky_form($form_name) {
120
	_elgg_services()->stickyForms->clearStickyForm($form_name);
121
}
122
123
/**
124
 * Does form submission data exist for this form?
125
 *
126
 * @param string $form_name Form namespace
127
 *
128
 * @return boolean
129
 * @since 1.8.0
130
 */
131
function elgg_is_sticky_form($form_name) {
132
	return _elgg_services()->stickyForms->isStickyForm($form_name);
133
}
134
135
/**
136
 * Get a specific value from cached form submission data
137
 *
138
 * @param string  $form_name     The name of the form
139
 * @param string  $variable      The name of the variable
140
 * @param mixed   $default       Default value if the variable does not exist in sticky cache
141
 * @param boolean $filter_result Filter for bad input if true
142
 *
143
 * @return mixed
144
 *
145
 * @todo should this filter the default value?
146
 * @since 1.8.0
147
 */
148
function elgg_get_sticky_value($form_name, $variable = '', $default = null, $filter_result = true) {
149
	return _elgg_services()->stickyForms->getStickyValue($form_name, $variable, $default, $filter_result);
150
}
151
152
/**
153
 * Get all submission data cached for a form
154
 *
155
 * @param string $form_name     The name of the form
156
 * @param bool   $filter_result Filter for bad input if true
157
 *
158
 * @return array
159
 * @since 1.8.0
160
 */
161
function elgg_get_sticky_values($form_name, $filter_result = true) {
162
	return _elgg_services()->stickyForms->getStickyValues($form_name, $filter_result);
163
}
164
165
/**
166
 * Remove one value of form submission data from the session
167
 *
168
 * @param string $form_name The name of the form
169
 * @param string $variable  The name of the variable to clear
170
 *
171
 * @return void
172
 * @since 1.8.0
173
 */
174
function elgg_clear_sticky_value($form_name, $variable) {
175
	_elgg_services()->stickyForms->clearStickyValue($form_name, $variable);
176
}
177
178
/**
179
 * Page handler for autocomplete endpoint.
180
 *
181
 * @todo split this into functions/objects, this is way too big
182
 *
183
 * /livesearch?q=<query>
184
 *
185
 * Other options include:
186
 *     match_on	   string all or array(groups|users|friends)
187
 *     match_owner int    0/1
188
 *     limit       int    default is 10
189
 *     name        string default "members"
190
 *
191
 * @param array $page
192
 * @return string JSON string is returned and then exit
193
 * @access private
194
 */
195
function input_livesearch_page_handler($page) {
196
	$dbprefix = elgg_get_config('dbprefix');
197
198
	// only return results to logged in users.
199
	if (!$user = elgg_get_logged_in_user_entity()) {
200
		exit;
201
	}
202
203
	if (!$q = get_input('term', get_input('q'))) {
204
		exit;
205
	}
206
207
	$input_name = get_input('name', 'members');
208
209
	$q = sanitise_string($q);
210
211
	// replace mysql vars with escaped strings
212
	$q = str_replace(array('_', '%'), array('\_', '\%'), $q);
213
214
// for the group members search: group guid - should be numeric
215
	if (!$g = get_input('term', get_input('g'))){
216
		$g=0;
217
	}
218
	else {
219
		$g = sanitise_string($g);
220
221
		// replace mysql vars with escaped strings
222
		$g = str_replace(array('_', '%'), array('\_', '\%'), $g);
223
	}
224
225
	$match_on = get_input('match_on', 'all');
226
227
	if (!is_array($match_on)) {
228
		$match_on = array($match_on);
229
	}
230
231
	// all = users and groups
232
	if (in_array('all', $match_on)) {
233
		$match_on = array('users', 'groups');
234
	}
235
236
	$owner_guid = ELGG_ENTITIES_ANY_VALUE;
237
	if (get_input('match_owner', false)) {
238
		$owner_guid = $user->getGUID();
239
	}
240
241
	$limit = sanitise_int(get_input('limit', elgg_get_config('default_limit')));
242
243
	// grab a list of entities and send them in json.
244
	$results = array();
245
	foreach ($match_on as $match_type) {
246
		switch ($match_type) {
247
			case 'users':
248
				$options = array(
249
					'type' => 'user',
250
					'limit' => $limit,
251
					'joins' => array("JOIN {$dbprefix}users_entity ue ON e.guid = ue.guid"),
252
					'wheres' => array(
253
						"ue.banned = 'no'",
254
						"(ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%')"
255
					)
256
				);
257
258
				$entities = elgg_get_entities($options);
259
				if (!empty($entities)) {
260
					foreach ($entities as $entity) {
261
262
						if (in_array('groups', $match_on)) {
263
							$value = $entity->guid;
264
						} else {
265
							$value = $entity->username;
266
						}
267
268
						$output = elgg_view_list_item($entity, array(
269
							'use_hover' => false,
270
							'use_link' => false,
271
							'class' => 'elgg-autocomplete-item',
272
							'title' => $entity->name, // Default title would be a link
273
						));
274
275
						$icon = elgg_view_entity_icon($entity, 'tiny', array(
276
							'use_hover' => false,
277
						));
278
279
						$result = array(
280
							'type' => 'user',
281
							'name' => $entity->name,
282
							'desc' => $entity->username,
283
							'guid' => $entity->guid,
284
							'label' => $output,
285
							'value' => $value,
286
							'icon' => $icon,
287
							'url' => $entity->getURL(),
288
							'html' => elgg_view('input/userpicker/item', array(
289
								'entity' => $entity,
290
								'input_name' => $input_name,
291
							)),
292
						);
293
						$results[$entity->name . rand(1, 100)] = $result;
294
					}
295
				}
296
				break;
297
298
			case 'groups':
299
				// don't return results if groups aren't enabled.
300
				if (!elgg_is_active_plugin('groups')) {
301
					continue;
302
				}
303
304
				$options = array(
305
					'type' => 'group',
306
					'limit' => $limit,
307
					'owner_guid' => $owner_guid,
308
					'joins' => array("JOIN {$dbprefix}groups_entity ge ON e.guid = ge.guid"),
309
					'wheres' => array(
310
						"(ge.name LIKE '$q%' OR ge.name LIKE '% $q%' OR ge.description LIKE '% $q%')"
311
					)
312
				);
313
314
				$entities = elgg_get_entities($options);
315
				if (!empty($entities)) {
316
					foreach ($entities as $entity) {
317
						$output = elgg_view_list_item($entity, array(
318
							'use_hover' => false,
319
							'class' => 'elgg-autocomplete-item',
320
							'full_view' => false,
321
							'href' => false,
322
							'title' => $entity->name, // Default title would be a link
323
						));
324
325
						$icon = elgg_view_entity_icon($entity, 'tiny', array(
326
							'use_hover' => false,
327
						));
328
329
						$result = array(
330
							'type' => 'group',
331
							'name' => $entity->name,
332
							'desc' => strip_tags($entity->description),
333
							'guid' => $entity->guid,
334
							'label' => $output,
335
							'value' => $entity->guid,
336
							'icon' => $icon,
337
							'url' => $entity->getURL(),
338
						);
339
340
						$results[$entity->name . rand(1, 100)] = $result;
341
					}
342
				}
343
				break;
344
345 View Code Duplication
			case 'friends':
346
				$options = array(
347
					'type' => 'user',
348
					'limit' => $limit,
349
					'relationship' => 'friend',
350
					'relationship_guid' => $user->getGUID(),
351
					'joins' => array("JOIN {$dbprefix}users_entity ue ON e.guid = ue.guid"),
352
					'wheres' => array(
353
						"ue.banned = 'no'",
354
						"(ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%')"
355
					)
356
				);
357
358
				$entities = elgg_get_entities_from_relationship($options);
359
				if (!empty($entities)) {
360
					foreach ($entities as $entity) {
361
362
						$output = elgg_view_list_item($entity, array(
363
							'use_hover' => false,
364
							'use_link' => false,
365
							'class' => 'elgg-autocomplete-item',
366
							'title' => $entity->name, // Default title would be a link
367
						));
368
369
						$icon = elgg_view_entity_icon($entity, 'tiny', array(
370
							'use_hover' => false,
371
						));
372
373
						$result = array(
374
							'type' => 'user',
375
							'name' => $entity->name,
376
							'desc' => $entity->username,
377
							'guid' => $entity->guid,
378
							'label' => $output,
379
							'value' => $entity->username,
380
							'icon' => $icon,
381
							'url' => $entity->getURL(),
382
							'html' => elgg_view('input/userpicker/item', array(
383
								'entity' => $entity,
384
								'input_name' => $input_name,
385
							)),
386
						);
387
						$results[$entity->name . rand(1, 100)] = $result;
388
					}
389
				}
390
				break;
391
392 View Code Duplication
			case 'groupmems':
393
				$options = array(
394
					'type' => 'user',
395
					'limit' => $limit,
396
					'relationship' => 'member',
397
					'relationship_guid' => $g,
398
					'inverse_relationship' => true,
399
					'joins' => array("JOIN {$dbprefix}users_entity ue ON e.guid = ue.guid"),
400
					'wheres' => array(
401
						"ue.banned = 'no'",
402
						"(ue.name LIKE '$q%' OR ue.name LIKE '% $q%' OR ue.username LIKE '$q%')"
403
					)
404
				);
405
406
				$entities = elgg_get_entities_from_relationship($options);
407
				if (!empty($entities)) {
408
					foreach ($entities as $entity) {
409
410
						$output = elgg_view_list_item($entity, array(
411
							'use_hover' => false,
412
							'use_link' => false,
413
							'class' => 'elgg-autocomplete-item',
414
							'title' => $entity->name, // Default title would be a link
415
						));
416
417
						$icon = elgg_view_entity_icon($entity, 'tiny', array(
418
							'use_hover' => false,
419
						));
420
421
						$result = array(
422
							'type' => 'user',
423
							'name' => $entity->name,
424
							'desc' => $entity->username,
425
							'guid' => $entity->guid,
426
							'label' => $output,
427
							'value' => $entity->username,
428
							'icon' => $icon,
429
							'url' => $entity->getURL(),
430
							'html' => elgg_view('input/userpicker/item', array(
431
								'entity' => $entity,
432
								'input_name' => $input_name,
433
							)),
434
						);
435
						$results[$entity->name . rand(1, 100)] = $result;
436
					}
437
				}
438
				break;
439
440
			default:
441
				header("HTTP/1.0 400 Bad Request", true);
442
				echo "livesearch: unknown match_on of $match_type";
443
				exit;
444
				break;
0 ignored issues
show
break; does not seem to be reachable.

This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed.

Unreachable code is most often the result of return, die or exit statements that have been added for debug purposes.

function fx() {
    try {
        doSomething();
        return true;
    }
    catch (\Exception $e) {
        return false;
    }

    return false;
}

In the above example, the last return false will never be executed, because a return statement has already been met in every possible execution path.

Loading history...
445
		}
446
	}
447
448
	ksort($results);
449
	header("Content-Type: application/json;charset=utf-8");
450
	echo json_encode(array_values($results));
451
	exit;
452
}
453
454
/**
455
 * Strip slashes from array keys
456
 *
457
 * @param array $array Array of values
458
 *
459
 * @return array Sanitized array
460
 * @access private
461
 */
462
function _elgg_stripslashes_arraykeys($array) {
463
	if (is_array($array)) {
464
		$array2 = array();
465
		foreach ($array as $key => $data) {
466
			if ($key != stripslashes($key)) {
467
				$array2[stripslashes($key)] = $data;
468
			} else {
469
				$array2[$key] = $data;
470
			}
471
		}
472
		return $array2;
473
	} else {
474
		return $array;
475
	}
476
}
477
478
/**
479
 * Strip slashes
480
 *
481
 * @param mixed $value The value to remove slashes from
482
 *
483
 * @return mixed
484
 * @access private
485
 */
486
function _elgg_stripslashes_deep($value) {
487
	if (is_array($value)) {
488
		$value = _elgg_stripslashes_arraykeys($value);
489
		$value = array_map('_elgg_stripslashes_deep', $value);
490
	} else {
491
		$value = stripslashes($value);
492
	}
493
	return $value;
494
}
495
496
/**
497
 * Initialize the input library
498
 *
499
 * @return void
500
 * @access private
501
 */
502
function _elgg_input_init() {
503
	// register an endpoint for live search / autocomplete.
504
	elgg_register_page_handler('livesearch', 'input_livesearch_page_handler');
505
506
	// backward compatible for plugins directly accessing globals
507
	if (get_magic_quotes_gpc()) {
508
		$_POST = array_map('_elgg_stripslashes_deep', $_POST);
509
		$_GET = array_map('_elgg_stripslashes_deep', $_GET);
510
		$_COOKIE = array_map('_elgg_stripslashes_deep', $_COOKIE);
511
		$_REQUEST = array_map('_elgg_stripslashes_deep', $_REQUEST);
512
		if (!empty($_SERVER['REQUEST_URI'])) {
513
			$_SERVER['REQUEST_URI'] = stripslashes($_SERVER['REQUEST_URI']);
514
		}
515
		if (!empty($_SERVER['QUERY_STRING'])) {
516
			$_SERVER['QUERY_STRING'] = stripslashes($_SERVER['QUERY_STRING']);
517
		}
518
		if (!empty($_SERVER['HTTP_REFERER'])) {
519
			$_SERVER['HTTP_REFERER'] = stripslashes($_SERVER['HTTP_REFERER']);
520
		}
521
		if (!empty($_SERVER['PATH_INFO'])) {
522
			$_SERVER['PATH_INFO'] = stripslashes($_SERVER['PATH_INFO']);
523
		}
524
		if (!empty($_SERVER['PHP_SELF'])) {
525
			$_SERVER['PHP_SELF'] = stripslashes($_SERVER['PHP_SELF']);
526
		}
527
		if (!empty($_SERVER['PATH_TRANSLATED'])) {
528
			$_SERVER['PATH_TRANSLATED'] = stripslashes($_SERVER['PATH_TRANSLATED']);
529
		}
530
	}
531
}
532
533
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
534
	$events->registerHandler('init', 'system', '_elgg_input_init');
535
};
536