J'ai configuré plusieurs scripts WordPress Admin AJAX (qui ne fonctionnent que dans le panneau d'administration) qui utilisent actuellement tous les séparés actions, fonctions et nonce.
La seule "vraie" différence entre ces scripts réside dans leurs fonctions PHP. Ainsi, dans le but de rationaliser le système, j’ai écrit 1 fonction JS et 1 fonction principale PHP pour toutes les gérer.
Une valeur $ _POST est envoyée avec un chemin d'accès à l'inclusion. Par conséquent, lorsque wp_ajax_custom_func()
exécute le fichier PHP, il est inclus et intégré dans locate_template()
Cela fonctionne très bien, mais je crains que cela ne crée une faille de sécurité?
Je suis conscient que des attaquants peuvent essayer de simuler un nonce, envoyer des données factices POST à admin-ajax.php
, des attaques XSS/cross-scripting, etc.
Je présume que, parce que j'ai encapsulé l'inclusion dans locate_template()
, cela contribuera à protéger le système. (côté long un SSL, wp_verify_nonce et current_user_can bien sûr)
Voici le concept de base, simplifié.
Installer
wp_enqueue_script( 'ajax_js_class',
get_template_directory_uri() . '/theme/ajax_js_class.js'
);
wp_localize_script( 'ajax_js_class', 'custom_settings', array(
'my_ajaxurl' => admin_url( 'admin-ajax.php' )
// nonce and action are attached at the form level
) );
Une fonction
add_action( 'wp_ajax_run_ajax_class_func', 'run_ajax_class_func' );
// wp_ajax_nopriv_run_ajax_class_func is not used
function run_ajax_class_func() {
if(isset($_POST['nonce'])) {
$nonce= $_POST['nonce']; // the nonce from the form
$action = $_POST['action_hash']."-special-string"; // changes on each form
$verify_nonce = wp_verify_nonce($nonce, $action);
if( $verify_nonce !== false ) {
if(isset($_POST['path']) && current_user_can('administrator') ) {
$path = $_POST['path']; // <= this is my concern...
include locate_template($_POST['path']);
} else {
$output = json_encode( array( "success" => "false", "message" => "fail") );
}
} else {
$output = json_encode( array( "success" => "false", "message" => "fail") );
}
} else {
$output = json_encode( array( "success" => "false", "message" => "fail") );
}
echo $output; // this is handled in the include above
// always die
die();
}
HTML Essentials
<?php $nonce = wp_create_nonce( $random_hash."-special-string" ); ?>
<form>
<input type="hidden" name="path" value="in/theme/run_this.php" >
<input type="hidden" name="nonce" value="<?php echo $nonce; ?>" >
<input type="hidden" name="action_hash" value="<?php echo $random_hash; ?>" >
Js Essentials localisés
$.post(custom_settings.my_ajaxurl, data, function(response) {
J'ai essayé d'attaquer le formulaire (en utilisant Fiddler2 pour modifier les en-têtes et publier des données), mais je suspecte un biais de confirmation.
J'aimerais consulter la communauté pour voir si cette idée est mauvaise ou bonne. (les mauvaises idées valent bien sûr la critique)
Questions:
En conclusion, si la création de chaque nonce, mise en file d'attente, formulaire et action sous forme de scripts complètement séparés est plus sûre, veuillez expliquer pourquoi.
Référence et recherche:
Si vous utilisez correctement les nonces, il ne sera pas possible de faire en sorte que le site traite les demandes factices ... Cette partie doit donc être sécurisée, mais ... Il y a toujours un défaut de sécurité dans votre approche ...
Et si je peux vous obliger à exécuter mon script JS dans votre navigateur, alors que vous êtes connecté en tant qu'administrateur? C'est possible.
De cette façon, nonce ne causera pas d'erreur de validation et votre code s'exécutera comme je le veux - parce que vous ne vérifiez pas l'entrée de l'utilisateur ...
Donc, toute votre sécurité est basée sur la possibilité d'injecter du JS sur votre site - et c'est assez commun - jetez un coup d'œil à l'historique des malwares dans WP ...
Ce serait beaucoup plus sécurisé si le modèle était chargé sur la base de données vérifiées. Donc, ne le chargez pas directement, mais dressez une liste de modèles corrects et sécurisés et chargez-les en fonction de la variable envoyée dans POST.
Revenons donc à vos 3 questions:
Non, il n'est jamais acceptable de charger un fichier en fonction du chemin envoyé par l'utilisateur. C'est beaucoup plus sécurisé si vous passez une variable puis que vous traduisez cette variable en chemin d'un fichier en PHP.
Vous ne simplifiez pas vraiment les choses, mais oui, il sera possible d’attaquer de tels codes.
Oui, ça l'est. Mais vous n'avez pas à écrire plusieurs fonctions. Il vous suffit de sécuriser celui-ci correctement et de vous rappeler que vous ne devez jamais faire confiance à tout ce qui vient de l'utilisateur.