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' );
#*/