Vulnerability: The MediaWiki "Report" extension has a Cross-Site Request Forgery (CSRF) vulnerability. Before fixed version, there was no protection against CSRF checks on Special:Report, so requests to report a revision could be forged. The problem has been fixed in commit f828dc6 by making use of MediaWiki edit tokens.
Vulnerability ID: CVE-2021-21275
CWE: CWE-352
Severity score: 2.9
Project: https://github.com/Kenny2github/Report
Published: 2021-01-25
File: SpecialReport.php
Commit message: Add CSRF check for Special:Report

Also clean up a little of the logic
Commit author: Kenny2github

Vulnerable version (before fix):
 public function execute( $par ) { 		} 		$request = $this->getRequest(); 		if ($request->wasPosted()) { 			return self::onPost( $par, $out, $request ); 		} 		$out->setIndexPolicy( 'noindex' ); 		$out->addHTML( public function execute( $par ) { 				'id' => 'mw-report-form-reason' 			] 		)); 		$out->addHTML(Html::rawElement( 			'input', 			[ public function execute( $par ) { 		$out->addHTML(Html::closeElement( 'form' )); 	}  	static public function onPost( $par, $out, $request ) { 		global $wgUser; 		if (!$request->getText('reason')) { 			$out->addHTML(Html::rawElement( 				'p', 				[ 'class' => 'error '], 				wfMessage( 'report-error-missing-reason' )->escaped() 			)); 		} else { 			$dbw = wfGetDB( DB_MASTER ); 			$dbw->startAtomic(__METHOD__); 			$dbw->insert( 'report_reports', [ 				'report_revid' => (int)$par, 				'report_reason' => $request->getText('reason'), 				'report_user' => $wgUser->getId(), 				'report_user_text' => $wgUser->getName(), 				'report_timestamp' => wfTimestampNow() 			], __METHOD__ ); 			$dbw->endAtomic(__METHOD__); 			$out->addWikiMsg( 'report-success' ); 			$out->addWikiMsg( 'returnto', '[[' . SpecialPage::getTitleFor('Diff', $par)->getPrefixedText() . ']]' ); 			return; 		} 	}  	public function getGroupName() {

Fixed version (after fix):
 public function execute( $par ) { 		} 		$request = $this->getRequest(); 		if ($request->wasPosted()) { 			return self::onPost( $par, $out, $request, $user ); 		} 		$out->setIndexPolicy( 'noindex' ); 		$out->addHTML( public function execute( $par ) { 				'id' => 'mw-report-form-reason' 			] 		)); 		$out->addHTML(Html::rawElement( 			'input', 			[ 				'type' => 'hidden', 				'name' => 'token', 				'value' => $user->getEditToken() 			] 		)); 		$out->addHTML(Html::rawElement( 			'input', 			[ public function execute( $par ) { 		$out->addHTML(Html::closeElement( 'form' )); 	}  	static public function onPost( $par, $out, $request, $user ) { 		if (!$user->matchEditToken($request->getText( 'token' ))) { 			$out->addWikiMsg( 'sessionfailure' ); 			return; 		} 		if (!$request->getText('reason')) { 			$out->addHTML(Html::rawElement( 				'p', 				[ 'class' => 'error '], 				wfMessage( 'report-error-missing-reason' )->escaped() 			)); 			return; 		} 		$dbw = wfGetDB( DB_MASTER ); 		$dbw->startAtomic(__METHOD__); 		$dbw->insert( 'report_reports', [ 			'report_revid' => (int)$par, 			'report_reason' => $request->getText('reason'), 			'report_user' => $user->getId(), 			'report_user_text' => $user->getName(), 			'report_timestamp' => wfTimestampNow() 		], __METHOD__ ); 		$dbw->endAtomic(__METHOD__); 		$out->addWikiMsg( 'report-success' ); 		$out->addWikiMsg( 'returnto', '[[' . SpecialPage::getTitleFor('Diff', $par)->getPrefixedText() . ']]' ); 	}  	public function getGroupName() {

Patch:
patch: @@ -55,7 +55,7 @@ public function execute( $par ) {
 		}
 		$request = $this->getRequest();
 		if ($request->wasPosted()) {
-			return self::onPost( $par, $out, $request );
+			return self::onPost( $par, $out, $request, $user );
 		}
 		$out->setIndexPolicy( 'noindex' );
 		$out->addHTML(
@@ -87,6 +87,14 @@ public function execute( $par ) {
 				'id' => 'mw-report-form-reason'
 			]
 		));
+		$out->addHTML(Html::rawElement(
+			'input',
+			[
+				'type' => 'hidden',
+				'name' => 'token',
+				'value' => $user->getEditToken()
+			]
+		));
 		$out->addHTML(Html::rawElement(
 			'input',
 			[
@@ -98,29 +106,31 @@ public function execute( $par ) {
 		$out->addHTML(Html::closeElement( 'form' ));
 	}
 
-	static public function onPost( $par, $out, $request ) {
-		global $wgUser;
+	static public function onPost( $par, $out, $request, $user ) {
+		if (!$user->matchEditToken($request->getText( 'token' ))) {
+			$out->addWikiMsg( 'sessionfailure' );
+			return;
+		}
 		if (!$request->getText('reason')) {
 			$out->addHTML(Html::rawElement(
 				'p',
 				[ 'class' => 'error '],
 				wfMessage( 'report-error-missing-reason' )->escaped()
 			));
-		} else {
-			$dbw = wfGetDB( DB_MASTER );
-			$dbw->startAtomic(__METHOD__);
-			$dbw->insert( 'report_reports', [
-				'report_revid' => (int)$par,
-				'report_reason' => $request->getText('reason'),
-				'report_user' => $wgUser->getId(),
-				'report_user_text' => $wgUser->getName(),
-				'report_timestamp' => wfTimestampNow()
-			], __METHOD__ );
-			$dbw->endAtomic(__METHOD__);
-			$out->addWikiMsg( 'report-success' );
-			$out->addWikiMsg( 'returnto', '[[' . SpecialPage::getTitleFor('Diff', $par)->getPrefixedText() . ']]' );
 			return;
 		}
+		$dbw = wfGetDB( DB_MASTER );
+		$dbw->startAtomic(__METHOD__);
+		$dbw->insert( 'report_reports', [
+			'report_revid' => (int)$par,
+			'report_reason' => $request->getText('reason'),
+			'report_user' => $user->getId(),
+			'report_user_text' => $user->getName(),
+			'report_timestamp' => wfTimestampNow()
+		], __METHOD__ );
+		$dbw->endAtomic(__METHOD__);
+		$out->addWikiMsg( 'report-success' );
+		$out->addWikiMsg( 'returnto', '[[' . SpecialPage::getTitleFor('Diff', $par)->getPrefixedText() . ']]' );
 	}
 
 	public function getGroupName() {
path: SpecialReport.php