web-dev-qa-db-fra.com

Supprimer tous les éléments du tableau, sauf ce que je veux?

J'ai un contrôleur qui prend les paramètres de publication du formulaire HTML, il les enverra ensuite au modèle qui insérera le tableau dans la base de données Cassandra.

C'est une preuve SQLInjection, parce que c'est NoSQL. Cependant, ce qui me fait peur, c'est que l'utilisateur peut simuler 100 000 paramètres de post ou simplement ajouter ceux dont je n'ai pas besoin et il sera inséré dans la base de données. Comment puis-je m'assurer que seules les valeurs dont j'ai besoin resteront dans mon tableau?.

Exemple:

$post = ['parent_id', 'type', 'title', 'body', 'tags']; // Good
$post = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three'] // Bad

Comment puis-je m'assurer que mon tableau supprimera tous les éléments qui ne sont pas dans bon exemple?

44
stan

Vous recherchez array_intersect :

$good = ['parent_id', 'type', 'title', 'body', 'tags'];
$post = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three'];

print_r(array_intersect($good, $post));

Le voir en action.

Bien sûr, cet exemple spécifique n'a pas beaucoup de sens car il fonctionne sur le tableau valeurs, mais il existe aussi array_intersect_key qui fait la même chose avec les clés.

45
Jon

En mettant les entrées en liste blanche, vous faites attendez-vous.

<?php
$post = array( 
    'parent_id' => 1,
    'type' => 'foo', 
    'title' => 'bar', 
    'body' => 'foo bar', 
    'tags' => 'foo, bar', 
    'one' => 'foo',
    'two' => 'bar',
    'three' => 'qux'
);

$whitelist = array(
    'parent_id',
    'type',
    'title',
    'body',
    'tags'
);

$filtered = array_intersect_key( $post, array_flip( $whitelist ) );

var_dump( $filtered );

Quoi qu'il en soit, utiliser Cassandra comme magasin de données n'est bien sûr pas une raison pour ne pas valider les données que vous recevez.

76
Berry Langerak

Qu'en est-il du tableau multidimensionnel? J'ai recherché pendant quelques heures cette solution, mais je n'ai trouvé aucune solution optimale. alors je l'ai écrit moi-même

function allow_keys($arr, $keys)
    {
        $saved = [];

        foreach ($keys as $key => $value) {
            if (is_int($key) || is_int($value)) {
                $keysKey = $value;
            } else {
                $keysKey = $key;
            }
            if (isset($arr[$keysKey])) {

                $saved[$keysKey] = $arr[$keysKey];
                if (is_array($value)) {

                    $saved[$keysKey] = allow_keys($saved[$keysKey], $keys[$keysKey]);
                }
            }
        }
        return $saved;
    }

utiliser: exemple 

$array = [
        'key1' => 'kw',
        'loaa'=> ['looo'],
        'k'    => [
            'prope' => [
                'prop'  => ['proo', 'prot', 'loolooo', 'de'],
                'prop2' => ['hun' => 'lu'],
            ],
            'prop1' => [

            ],
        ],
    ];

appel: exemple

allow_keys($array, ['key1', 'k' => ['prope' => ['prop' => [0, 1], 'prop2']]])

sortie:

Array ( [key1] => kw [k] => Array ( [prope] => Array ( [prop] => Array ( [0] => proo [1] => prot ) [prop2] => Array ( [hun] => lu ) ) ) ) 

de sorte que vous n'obtenez que les clés nécessaires du tableau multidimensionnel. il n’est pas limité que pour "multidimensionnel", vous pouvez l’utiliser en passant un tableau comme

['key1', 'loaa']

sortie vous obtenez:

Array ( [key1] => kw [loaa] => Array ( [0] => looo ) )

à votre santé!

1
George Kolmer

Ceci s'appelle liste blanche, votre exemple est trompeur car le $_POST est un tableau d'association. 

$post = [
    'parent_id' => 'val',
    'type' => 'val',
    'title' => 'val',
    'body' => 'val',
    'tags' => 'val',
    'one' => 'val',
    'two' => 'val',
    'three'=>'val',
];

$whitelist = ['parent_id', 'type', 'title', 'body', 'tags'];

$sanitized_post = array_whitelist_assoc($post, $whitelist);

C’est une fonction de liste blanche que j’ai créée pour les tableaux associatifs. 

if(!function_exists('array_whitelist_assoc')){

    /**
     * Returns an associative array containing all the entries of array1 which have keys that are present in all the arguments when using their values as keys.
     *
     * @param array $array The array with master keys to check.
     * @param array $array2 An array to compare keys against its values.
     * @return array $array2,... A variable list of arrays to compare.
     * 
     */

    function array_whitelist_assoc(Array $array1, Array $array2) {

        if(func_num_args() > 2){
            $args = func_get_args();
            array_shift($args);
            $array2 = call_user_func_array('array_merge', $args);
        } 
        return array_intersect_key($array1, array_flip($array2)); 
    }
}
1
TarranJones

Cela produira la même chose que $ post_allowed. Cela permet uniquement les valeurs dans $ post_input qui sont également présentes dans $ post_allow.

$post_allowed = ['parent_id', 'type', 'title', 'body', 'tags'];
$post_input   = ['parent_id', 'type', 'title', 'body', 'tags', 'one', 'two', 'three'];
$post = array_intersect($post_input, $post_allowed);
1
Christian Riesen

Si vous utilisez des tableaux associatifs et que vous ne voulez pas utiliser array_intersect_key() pour une raison quelconque, vous pouvez également utiliser une approche plus simple pour construire manuellement un nouveau tableau en utilisant les valeurs de l’ancien.

$post = array(
    'parent_id' => 1,
    'type' => "post",
    'title' => "Post title",
    'body' => "Post body",
    'tags' => "Post tags",
    'malicious' => "Robert'); DROP TABLE students;--"
);
$good = array(
    'parent_id' => $post['parent_id'],
    'type' => $post['type'],
    'title' => $post['title'],
    'body' => $post['body'],
    'tags' => $post['tags']
);
1
danillonunes

Utilisez l'intersection du tableau. tableau intersecter , cela vous aidera.

0
ime.devdesks

Il est bon de se rappeler que, bien que array_intersect et array_intersect_key soient bons, ils risquent de devenir excessifs. Dans ma situation, je ne voulais plus que 1 élément. L'option la plus simple était donc simplement de reconstruire le tableau que je voulais en fonction des clés/valeurs dont j'avais besoin. Je me demande à quel point les array_intersect ne valent donc pas la peine et vous êtes tout simplement mieux avec $new = array('whatI'=>'want');. Je crois que dans le PO, cela en vaut la peine, mais dans des cas plus modestes, cela peut être exagéré.

Alternativement, en réponse à la question initiale, simplement utiliser unset aurait pu être une option moins chère - unset($post['one'],$post['two'],$post['three']). Encore une fois cependant, cela concerne le moment où cela devient trop inefficace et que les fonctions array_intersect sont meilleures.

0
Antony