Issues (4122)

Security Analysis    not enabled

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.

includes/specials/SpecialUnblock.php (1 issue)

Labels
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
 * Implements Special:Unblock
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program 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. See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License along
16
 * with this program; if not, write to the Free Software Foundation, Inc.,
17
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18
 * http://www.gnu.org/copyleft/gpl.html
19
 *
20
 * @file
21
 * @ingroup SpecialPage
22
 */
23
24
/**
25
 * A special page for unblocking users
26
 *
27
 * @ingroup SpecialPage
28
 */
29
class SpecialUnblock extends SpecialPage {
30
31
	protected $target;
32
	protected $type;
33
	protected $block;
34
35
	public function __construct() {
36
		parent::__construct( 'Unblock', 'block' );
37
	}
38
39
	public function doesWrites() {
40
		return true;
41
	}
42
43
	public function execute( $par ) {
44
		$this->checkPermissions();
45
		$this->checkReadOnly();
46
47
		list( $this->target, $this->type ) = SpecialBlock::getTargetAndType( $par, $this->getRequest() );
48
		$this->block = Block::newFromTarget( $this->target );
49
		if ( $this->target instanceof User ) {
50
			# Set the 'relevant user' in the skin, so it displays links like Contributions,
51
			# User logs, UserRights, etc.
52
			$this->getSkin()->setRelevantUser( $this->target );
53
		}
54
55
		$this->setHeaders();
56
		$this->outputHeader();
57
58
		$out = $this->getOutput();
59
		$out->setPageTitle( $this->msg( 'unblockip' ) );
60
		$out->addModules( [ 'mediawiki.special', 'mediawiki.userSuggest' ] );
61
62
		$form = new HTMLForm( $this->getFields(), $this->getContext() );
63
		$form->setWrapperLegendMsg( 'unblockip' );
64
		$form->setSubmitCallback( [ __CLASS__, 'processUIUnblock' ] );
65
		$form->setSubmitTextMsg( 'ipusubmit' );
66
		$form->addPreText( $this->msg( 'unblockiptext' )->parseAsBlock() );
67
68
		if ( $form->show() ) {
69
			switch ( $this->type ) {
70
				case Block::TYPE_IP:
71
					$out->addWikiMsg( 'unblocked-ip', wfEscapeWikiText( $this->target ) );
72
					break;
73
				case Block::TYPE_USER:
74
					$out->addWikiMsg( 'unblocked', wfEscapeWikiText( $this->target ) );
75
					break;
76
				case Block::TYPE_RANGE:
77
					$out->addWikiMsg( 'unblocked-range', wfEscapeWikiText( $this->target ) );
78
					break;
79
				case Block::TYPE_ID:
80
				case Block::TYPE_AUTO:
81
					$out->addWikiMsg( 'unblocked-id', wfEscapeWikiText( $this->target ) );
82
					break;
83
			}
84
		}
85
	}
86
87
	protected function getFields() {
88
		$fields = [
89
			'Target' => [
90
				'type' => 'text',
91
				'label-message' => 'ipaddressorusername',
92
				'autofocus' => true,
93
				'size' => '45',
94
				'required' => true,
95
				'cssclass' => 'mw-autocomplete-user', // used by mediawiki.userSuggest
96
			],
97
			'Name' => [
98
				'type' => 'info',
99
				'label-message' => 'ipaddressorusername',
100
			],
101
			'Reason' => [
102
				'type' => 'text',
103
				'label-message' => 'ipbreason',
104
			]
105
		];
106
107
		if ( $this->block instanceof Block ) {
108
			list( $target, $type ) = $this->block->getTargetAndType();
109
110
			# Autoblocks are logged as "autoblock #123 because the IP was recently used by
111
			# User:Foo, and we've just got any block, auto or not, that applies to a target
112
			# the user has specified.  Someone could be fishing to connect IPs to autoblocks,
113
			# so don't show any distinction between unblocked IPs and autoblocked IPs
114
			if ( $type == Block::TYPE_AUTO && $this->type == Block::TYPE_IP ) {
115
				$fields['Target']['default'] = $this->target;
116
				unset( $fields['Name'] );
117
			} else {
118
				$fields['Target']['default'] = $target;
119
				$fields['Target']['type'] = 'hidden';
120
				switch ( $type ) {
121
					case Block::TYPE_IP:
122
						$fields['Name']['default'] = Linker::linkKnown(
123
							SpecialPage::getTitleFor( 'Contributions', $target->getName() ),
124
							$target->getName()
125
						);
126
						$fields['Name']['raw'] = true;
127
						break;
128
					case Block::TYPE_USER:
129
						$fields['Name']['default'] = Linker::link(
130
							$target->getUserPage(),
131
							$target->getName()
132
						);
133
						$fields['Name']['raw'] = true;
134
						break;
135
136
					case Block::TYPE_RANGE:
137
						$fields['Name']['default'] = $target;
138
						break;
139
140
					case Block::TYPE_AUTO:
141
						$fields['Name']['default'] = $this->block->getRedactedName();
142
						$fields['Name']['raw'] = true;
143
						# Don't expose the real target of the autoblock
144
						$fields['Target']['default'] = "#{$this->target}";
145
						break;
146
				}
147
				// target is hidden, so the reason is the first element
148
				$fields['Target']['autofocus'] = false;
149
				$fields['Reason']['autofocus'] = true;
150
			}
151
		} else {
152
			$fields['Target']['default'] = $this->target;
153
			unset( $fields['Name'] );
154
		}
155
156
		return $fields;
157
	}
158
159
	/**
160
	 * Submit callback for an HTMLForm object
161
	 * @param array $data
162
	 * @param HTMLForm $form
163
	 * @return array|bool Array(message key, parameters)
164
	 */
165
	public static function processUIUnblock( array $data, HTMLForm $form ) {
166
		return self::processUnblock( $data, $form->getContext() );
167
	}
168
169
	/**
170
	 * Process the form
171
	 *
172
	 * Change tags can be provided via $data['Tags'], but the calling function
173
	 * must check if the tags can be added by the user prior to this function.
174
	 *
175
	 * @param array $data
176
	 * @param IContextSource $context
177
	 * @throws ErrorPageError
178
	 * @return array|bool Array(message key, parameters) on failure, True on success
179
	 */
180
	public static function processUnblock( array $data, IContextSource $context ) {
181
		$performer = $context->getUser();
182
		$target = $data['Target'];
183
		$block = Block::newFromTarget( $data['Target'] );
184
185
		if ( !$block instanceof Block ) {
186
			return [ [ 'ipb_cant_unblock', $target ] ];
187
		}
188
189
		# bug 15810: blocked admins should have limited access here.  This
190
		# won't allow sysops to remove autoblocks on themselves, but they
191
		# should have ipblock-exempt anyway
192
		$status = SpecialBlock::checkUnblockSelf( $target, $performer );
193
		if ( $status !== true ) {
194
			throw new ErrorPageError( 'badaccess', $status );
0 ignored issues
show
It seems like $status defined by \SpecialBlock::checkUnbl...lf($target, $performer) on line 192 can also be of type boolean; however, ErrorPageError::__construct() does only seem to accept string|object<Message>, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
195
		}
196
197
		# If the specified IP is a single address, and the block is a range block, don't
198
		# unblock the whole range.
199
		list( $target, $type ) = SpecialBlock::getTargetAndType( $target );
200
		if ( $block->getType() == Block::TYPE_RANGE && $type == Block::TYPE_IP ) {
201
			$range = $block->getTarget();
202
203
			return [ [ 'ipb_blocked_as_range', $target, $range ] ];
204
		}
205
206
		# If the name was hidden and the blocking user cannot hide
207
		# names, then don't allow any block removals...
208
		if ( !$performer->isAllowed( 'hideuser' ) && $block->mHideName ) {
209
			return [ 'unblock-hideuser' ];
210
		}
211
212
		# Delete block
213
		if ( !$block->delete() ) {
214
			return [ 'ipb_cant_unblock', htmlspecialchars( $block->getTarget() ) ];
215
		}
216
217
		# Unset _deleted fields as needed
218
		if ( $block->mHideName ) {
219
			# Something is deeply FUBAR if this is not a User object, but who knows?
220
			$id = $block->getTarget() instanceof User
221
				? $block->getTarget()->getId()
222
				: User::idFromName( $block->getTarget() );
223
224
			RevisionDeleteUser::unsuppressUserName( $block->getTarget(), $id );
225
		}
226
227
		# Redact the name (IP address) for autoblocks
228
		if ( $block->getType() == Block::TYPE_AUTO ) {
229
			$page = Title::makeTitle( NS_USER, '#' . $block->getId() );
230
		} else {
231
			$page = $block->getTarget() instanceof User
232
				? $block->getTarget()->getUserPage()
233
				: Title::makeTitle( NS_USER, $block->getTarget() );
234
		}
235
236
		# Make log entry
237
		$logEntry = new ManualLogEntry( 'block', 'unblock' );
238
		$logEntry->setTarget( $page );
239
		$logEntry->setComment( $data['Reason'] );
240
		$logEntry->setPerformer( $performer );
241
		if ( isset( $data['Tags'] ) ) {
242
			$logEntry->setTags( $data['Tags'] );
243
		}
244
		$logId = $logEntry->insert();
245
		$logEntry->publish( $logId );
246
247
		return true;
248
	}
249
250
	/**
251
	 * Return an array of subpages beginning with $search that this special page will accept.
252
	 *
253
	 * @param string $search Prefix to search for
254
	 * @param int $limit Maximum number of results to return (usually 10)
255
	 * @param int $offset Number of results to skip (usually 0)
256
	 * @return string[] Matching subpages
257
	 */
258 View Code Duplication
	public function prefixSearchSubpages( $search, $limit, $offset ) {
259
		$user = User::newFromName( $search );
260
		if ( !$user ) {
261
			// No prefix suggestion for invalid user
262
			return [];
263
		}
264
		// Autocomplete subpage as user list - public to allow caching
265
		return UserNamePrefixSearch::search( 'public', $search, $limit, $offset );
266
	}
267
268
	protected function getGroupName() {
269
		return 'users';
270
	}
271
}
272