Raketenwilli: $_POST Variable auf Validität überprüfen

Beitrag lesen

Die Herkunft kannst du nicht überprüfen. Du kannst und solltest nur überprüfen,

  • ob $_POST die Keys enthält, die du erwartest
  • und ob deren Werte "gültig sind", also deinen Erwartungen entsprechen.
  • Optional: Prüfen, ob es weitere Nonsense-Keys gibt, die gar nicht ins Konzept passen.

So „optional“ ist die letzte Prüfung gar nicht. Insbesondere bei Nutzung externer, scheinbar gut dokumentierter und oft genutzer Libarys (oder meinetwegen Wordpress-Plugins) könnte ein Angreifer ungewollte / nicht erwartete Key:Value-Paare einschmuggeln, auf welche die Libs dann in einer „nicht dokumentierten Weise“ reagieren - und plötzlich hat ein Angreifer dadurch ungeahnte Möglichkeiten…

Außerdem kann man so Nessus-Benutzer & Co (warum macht das wohl jemand, den man nicht aufgefordert hat) auch ausbremsen.

Da das gleiche Problem auch andere Variablen betreffen kann (e.g. $_GET, $_COOKIE, $_REQUEST, Daten von API-Schleudern...) habe ich mal fix eine Funktion hierfür entworfen.

Freilich kann, darf und muss man diese für feinere Prüfungen anpassen…, kann z.B. einfach false zurückgeben und also außerhalb der Funktion reagieren.

<?php
error_reporting( E_ALL );
ini_set( 'display_errors', 1 );

/**
 * Function: simpleArrayCheck
 * will stop the skript if the array ist not complete or maybe tainted.

 * Params:
 * 1: One array with awaited keys.
 * 2: The suspected array.  
 * 3: Show for unexpexted keys (Array is tainted)?
 *    boolean, Default: true
 * 4: The name for the array in error-messages 
 *    string , Default: 'Array'
 * Return: true or die with error-message
*/


function simpleArrayCheck(
	$awaitedKeys,
	$arr,
	$strong = true,
	$arrName = 'Array'
) {
	# Has all keys?

	foreach ( $awaitedKeys as $key ) {
		if ( !  array_key_exists( $key, $arr )  ) {
			http_response_code( 400 );
			trigger_error( 
				'Key "' . $key . '" is not ' . $arrName . '.',
				E_USER_ERROR
			);
		}
	}

	# Maybe taintet?
    if ( $strong )  {
		foreach ( array_keys( $arr ) as $key ) {
			if ( ! in_array ( $key, $awaitedKeys ) ) {
				http_response_code( 400 );
				trigger_error(
					'Unknown Key "' . $key . '" in Array "' . $arrName . '". Attack?',
					E_USER_ERROR
				);
			}
		}
	}
	
	return true;
}

/** 
 * Tests
*/


$awaitedKeys = [
	'foo',
	'bar',
	'baz'
];


/*
### Fine:
$_POST['foo'] = 'Hallo1';
$_POST['bar'][] = 'Hallo2';
$_POST['bar'][] = 'Hallo3';
$_POST['baz'][] = 'Hallo4';
$_POST['baz'][] = 'Hallo5';
if ( simpleArrayCheck( $awaitedKeys, $_POST, true, '$_POST' ) ) {
    echo "fine." . PHP_EOL;
}
#*/

/*
### Key fehlt:
$_POST['foo'] = 'Hallo1';
simpleArrayCheck( $awaitedKeys, $_POST, true, '$_POST' );
#*/

/*
### Nicht erwarteter Key
$_POST['foo'] = 'Hallo1';
$_POST['bar'][] = 'Hallo2';
$_POST['bar'][] = 'Hallo3';
$_POST['baz'][] = 'Hallo4';
$_POST['baz'][] = 'Hallo5';
$_POST['tok'][] = 'Hallo5';

if  ( simpleArrayCheck( $awaitedKeys, $_POST, false, '$_POST' ) ) {
	echo "Not strong? fine!" . PHP_EOL;
}
simpleArrayCheck( $awaitedKeys, $_POST, true, '$_POST' );
#*/