WordPress Plugin Development In Bangla Part-9: WordPress Plugins Security with Nonce

wordpress nonce
wordpress nonce

WordPress এ Nonce কি?

WordPress Plugins Security

WordPress এ Nonce (number used once) হচ্ছে মূলতঃ WordPress এ randomly generated security hash সিস্টেম, tokens বা একটা unique identifiers , যা দিয়ে আমরা form ,url অথবা ajax request কোথায় থেকে আসছে , তা চেক করতে পারি। এবং এর মাধ্যমে WordPress site এ যেকোনো ক্ষতিকর attack থেকে সুরক্ষা দিতে পারি।

WordPress এ Nonce security প্রধানের জন্য ফাঙ্কশন গুলো দুইভাগে বিভক্ত :

1. Creating a Nonce

  • wp_nonce_url() – সাইটে যেকোনো URL তৈরির সময় তার সাথে একটা nonce যুক্ত করার কাজে ব্যবহৃত হয়। এবং URL এ অবস্থিত & গুলোকে & তে escapes করে।
  • wp_nonce_field() – সাইটের মধ্যে যেকোনো form এ একটা nonce hidden field যুক্ত করার কাজে ব্যবহৃত হয়।
  • wp_create_nonce() – custom nonce তৈরির কাজে ব্যবহৃত হয়। বিশেষ করে ajax request এর সময় এটি বেশি ব্যবহৃত হয়।এছাড়া আপনি চাইলে এটাকে form, url এমনকি session এর জন্য ও ব্যবহার করতে পারেন।

2. Verifying a Nonce

  • check_admin_referer() –শুধু মাত্র এক admin screen থেকে অন্য admin screen এর জন্য pass হওয়া nonce কে ভেরিফাই করার কাজে ব্যবহৃত হয়।
  • check_ajax_referer() – ajax এর জন্য nonce চেক করে। অর্থাৎ ajax request টি যদি আপন সাইট থেকে আসে, তাহলে সাইটে একসেস এর সুযোগ দিবে। অন্যথায় script execution সাথে সাথে terminate করে দিবে।
  • wp_verify_nonce() – Time limit দিয়ে nonce চেক করার জন্য এটি ব্যবহৃত হয়।

wp_nonce_url() Function Syntax

wp_nonce_url( 
    string $actionurl, 
    int|string $action = -1, 
    string $name = '_wpnonce' 
)

Parameters#

  • $actionurl (string) (Required) যেই URL এ nonce action টি যুক্ত করবেন , তা এখানে দিতে হবে।
  • $action (int|string) (Optional) Nonce এর action টির নাম এখানে দিতে পারেন। Default value: -1
  • $name (string) (Optional) Nonce এর একটা নাম দিতে পারেন। Default value: ‘_wpnonce’

উদাহরণঃ

// Sample URL, note the & in there
$url = 'http://localhost/?arg1=value1&arg2=value2';
 
// This will show http://localhost/?arg1=value1&arg2=value2&_wpnonce=abcdef
echo wp_nonce_url( $url, 'action' );
 
// This will return http://localhost/?arg1=value1&arg2=value2&_wpnonce=abcdef
echo add_query_arg( '_wpnonce', wp_create_nonce( 'action' ), $url );

wp_verify_nonce() function syntax

wp_verify_nonce(
    string $nonce,
    string|int $action = -1
);

Parameters #

  • $nonce (string) (Required) যেই Nonce value কে verification করবেন, তা এখানে হবে, এটা সাধারণত form, url অথবা ajax রিকোয়েস্ট থেকে এসে থাকে।
  • $action (string|int) (Optional) nonce টি যেই স্ট্রিং বা টোকেনের বিপরীতে তৈরি করেছিলেন , তা এখানে হবে। Default value: -1

URL Nonce Verification Plugin

এখন আমরা URL দিয়ে আসা একটা nonce কে ভেরিফিকেশন কিভাবে করা যায়, তা একটা প্লাগিনের মাধ্যমে দেখব। নিচের প্লাগিন টি দেখুন :

<?php
/*
Plugin Name: W3 URL Nonce Checking Plugin
Plugin URI: https://github.com/w3programmers/w3-url-nonce/
Description: W3 URL Nonce Checking Plugin
Author: Masud Alam
Version: 1.0.0
Author URI: https://blog.w3programmers.com/
*/

add_action('admin_menu', 'add_my_plugin_admin_screen');
function add_my_plugin_admin_screen () {
    add_options_page(
        __('My Plugin Settings', 'my-plugin-textdomain'),
        __('My Plugin', 'my-plugin-textdomain'),
        'manage_options',
        'my_plugin_settings',
        'my_plugin_do_something'
    );
}
 
function my_plugin_do_something () {
    if (!isset($_GET['my_nonce']) || !wp_verify_nonce($_GET['my_nonce'], 'doing_something')) {
?>
<h2><?php esc_html_e('My Plugin Admin Screen', 'my-plugin-textdomain');?></h2>
<p>
    <a href="<?php print wp_nonce_url(admin_url('options-general.php?page=my_plugin_settings'), 'doing_something', 'my_nonce');?>"
        class="button button-primary"><?php esc_html_e('Do Something!', 'my-plugin-textdomain');?></a>
    <span class="description"><?php esc_html_e('This button does something interesting.', 'my-plugin-textdomain');?></span>
</p>
<?php
    } else {
        // User pressed "Do Something!" button, so
        // do something interesting.
        $nonce=$_GET['my_nonce'];
        echo "Hey! Your Nonce is: ".$nonce,"<br>";
        $nonce = wp_verify_nonce( $nonce, 'doing_something' );
switch ( $nonce ) {
    case 1:
        echo 'Nonce is less than 12 hours old';
        break;
    case 2:
        echo 'Nonce is between 12 and 24 hours old';
        break;
    default:
        exit( 'Nonce is invalid' );
}
    }
}

এখন যদি, আপনি প্লাগিনটি activate করেন, তাহলে নিচের মতো আপনার nonce রেজাল্ট দেখতে পাবেন।

before click url button
before click url button

এখন যদি, আপনি বাটনটি ক্লিক করেন , তাহলে নিচের মতো nonce value দেখতে পাবেন।

after click button
after click button

wp_nonce_field() function syntax

wp_nonce_field(
    int|string $action = -1, 
    string $name = '_wpnonce', 
    bool $referer = true, 
    bool $echo = true 
)

Parameters #

  • $action (int|string) (Optional) চাইলে এখানে একটা Action এর নাম দিতে পারেন। Default value: -1
  • $name (string) (Optional) এখানে Nonce এর নামটি দিতে পারেন। Default value: ‘_wpnonce’
  • $referer (bool) (Optional) referer field টি validation করবে কিনা তার জন্য এখানে একটা বুলিয়ান ভ্যালু দিতে পারেন। Default value: true
  • $echo (bool) (Optional) hidden form field টি display নাকি return করবে , তা এখানে বলতে পারেন। Default value: true

উদাহরণঃ

<form method="post">
   <!-- some inputs here ... -->
   <?php wp_nonce_field( 'name_of_my_action', 'name_of_nonce_field' ); ?>
</form>

Form Nonce Verification Plugin

এখন আমরা wp_nonce_field() function এবং form ব্যবহার করে একটা প্লাগিন তৈরি করে ফেলব। চলুন শুরু করা যাক।

<?php
/*
Plugin Name: W3 Form Nonce Checking Plugin
Plugin URI: https://github.com/w3programmers/w3-nonce-form/
Description: W3 Form Nonce Checking Plugin
Author: Masud Alam
Version: 1.0.0
Author URI: https://blog.w3programmers.com/
*/

add_action('admin_menu', 'add_w3_nonce_form_admin_screen');
function add_w3_nonce_form_admin_screen () {
    add_options_page(
        __('W3 Nonce Form Plugin Settings', 'w3-nonce-form-plugin-textdomain'),
        __('W3 Nonce Form Plugin', 'w3-nonce-form-plugin-textdomain'),
        'manage_options',
        'w3_nonce_form_plugin_settings',
        'w3_nonce_form_plugin_do_something'
    );
}
 
function w3_nonce_form_plugin_do_something () {
    if (!isset($_REQUEST['w3_nonce_field']) || !wp_verify_nonce($_REQUEST['w3_nonce_field'], 'doing_something')) {
?>
<h2><?php esc_html_e('W3 Nonce Form Plugin Admin Screen', 'w3-nonce-form-plugin-textdomain');?></h2>
<form method="post" action="<?php echo admin_url('options-general.php?page=w3_nonce_form_plugin_settings');?>">
   <!-- some inputs here ... -->
   <?php wp_nonce_field( 'doing_something', 'w3_nonce_field' ); ?>
   <input class="button button-primary" type="submit" value="Check Nonce Value" name="submit">
</form>

<?php
    } else {
        // User pressed "Do Something!" button, so
        // do something interesting.
        $nonce=$_REQUEST['w3_nonce_field'];
        echo "Hey! Your Nonce is: ".$nonce,"<br>";
        $nonce = wp_verify_nonce( $nonce, 'doing_something' );
switch ( $nonce ) {
    case 1:
        echo 'Nonce is less than 12 hours old';
        break;
    case 2:
        echo 'Nonce is between 12 and 24 hours old';
        break;
    default:
        exit( 'Nonce is invalid' );
}
    }
}

এখন যদি আপনি form টি সাবমিট করেন , তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন।

w3 nonce form output after submit
w3 nonce form output after submit

wp_create_nonce() Function Syntax

wp_create_nonce( 
string|int $action = -1 
)

Parameter #

  • $action (int|string) (Optional) চাইলে এখানে একটা Action এর নাম দিতে পারেন। Default value: -1

উদাহরণঃ

/*
 * Step A: Create an nonce for a link.
 * We pass it as a GET parameter.
 * The target page will perform some action based on the 'do_something' parameter.
 */
$nonce = wp_create_nonce( 'my-nonce' );
?>
<a href='myplugin.php?do_something=some_action&_wpnonce=<?php echo esc_attr( $nonce ); ?>'><?php esc_html_e( 'Do some action', 'textdomain' ); ?></a>
 
 
/*
 * Step B: This code would go in the target page.
 * We need to verify the nonce.
 */
$nonce = $_REQUEST['_wpnonce'];
if ( ! wp_verify_nonce( $nonce, 'my-nonce' ) ) {
    // This nonce is not valid.
    die( __( 'Security check', 'textdomain' ) ); 
} else {
    // The nonce was valid.
    // Do stuff here.
}

WordPress Plugins Security

তবে specific কিছু চেক করার জন্য ও আমরা চাইলে wp_create_nonce() function টি ব্যবহার করতে পারি। যেমন আপনি একটা ডিলিট রিকোয়েস্ট নিচের মতো করে nonce সহ পাঠাতে পারেন।

wp_create_nonce( 'delete_post-' . $post_id );

আর ডিলিট করার সময় , নিচের মতো করে ভেরিফাই করে নিতে পারবেন।

wp_verify_nonce( $nonce, "delete_post-{$_REQUEST['post_id']}" );

AJAX Request Nonce Verification Plugin

এখন আমরা wp_create_nonce() function এবং ajax ব্যবহার করে একটা প্লাগিন তৈরি করে ফেলব। চলুন শুরু করা যাক।

<?php
/*
Plugin Name: W3 Demo Ajax Plugin
Description: An Example of AJAX in WordPress Plugin
Plugin URI: https://github.com/w3programmers/w3-demo-ajax
Version: 1.0.0
Author: Masud Alam
Author URI: https://blog.w3programmers.com
Text Domain: w3-demo-ajax
*/

add_action( 'admin_enqueue_scripts', 'my_enqueue' );
function my_enqueue() {

    wp_register_script(
        'ajax-script', 
        plugins_url( '/js/script.js', __FILE__ ), 
        array('jquery') );    

	wp_enqueue_script('ajax-script');

    // in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.name
    $ajax_nonce = wp_create_nonce( "w3-security" );
    wp_localize_script( 
        'ajax-script', 
        'ajax_object',
        array( 
            'ajax_url' => admin_url( 'admin-ajax.php' ), 
            'nonce' =>  $ajax_nonce,
            'name' => "Masud Alam",
            'age'=>35,
        ));
    
}

add_action("wp_ajax_{$_REQUEST['action']}", 'receive_data' );

function receive_data() {
    $nonce = $_POST['nonce'];
   if (!wp_verify_nonce( $nonce, 'w3-security' ) ){
        die ( 'Busted!');
    } 
    $name= $_POST['name'];
    $age=  $_POST['age'];
    echo "Welcome! ".$name." You're ".$age." Years Old! Your Uniquue Security Code: $nonce";

	wp_die(); // this is required to terminate immediately and return a proper response
}

এবার আপনার plugin ফোল্ডারের মধ্যে , js/script.js ফাইলে নিচের কোডগুলো লিখুন।

jQuery(document).ready(function($) {
	var data = {
        'action': 'send_data',
        'name': ajax_object.name,      // We pass php values differently!
        'age' :ajax_object.age,
        'nonce':ajax_object.nonce,
	};
	// We can also pass the url value separately from ajaxurl for front end AJAX implementations
	jQuery.post(ajax_object.ajax_url, data, function(response) {
		alert(response);
	});
});

WordPress Plugins Security

এখন যদি আপনি প্লাগিনটি activate করেন, তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন:

ajax with nonce
ajax with nonce

check_ajax_referer() Function Syntax

check_ajax_referer(
    int|string $action = -1, 
    false|string $query_arg = false, 
    bool $die = true 
)

Parameters #

  • $action (int|string) (Optional) চাইলে এখানে action nonce অর্থাৎ যেই string এর nonce তৈরী করেছেন , তা এখানে দিতে পারেন। Default value: -1
  • $query_arg (false|string) (Optional) $_REQUEST দিয়ে যেই নামে receive করবেন, চাইলে সেটি এখানে দিতে পারেন। যদি false থাকে তাহেল বাই ডিফল্ট এখানে ভ্যালু হিসেবে নিবে ‘_ajax_nonce’, এবং ‘_wpnonce’ . Default value: false
  • $die (bool) (Optional) AJAX nonce না মিললে সাথে সাথে script execution অফ হবে কিনা , তা এখানে চাইলে দিতে পারেন Default value: true

উদাহরণঃ

এখন চাইলে আপনি আমাদের উপরের “W3 Demo Ajax Plugin” এ wp_verify_nonce() ফাঙ্কশনটি ব্যবহারের পরিবর্তে check_ajax_referer() ফাঙ্কশনটি ব্যবহার করতে পারেন। নিচে লক্ষ্য করুন :

<?php
/*
Plugin Name: W3 Demo Ajax Plugin
Description: An Example of AJAX in WordPress Plugin
Plugin URI: https://github.com/w3programmers/w3-demo-ajax
Version: 1.0.0
Author: Masud Alam
Author URI: https://blog.w3programmers.com
Text Domain: w3-demo-ajax
*/

add_action( 'admin_enqueue_scripts', 'my_enqueue' );
function my_enqueue() {

    wp_register_script(
        'ajax-script', 
        plugins_url( '/js/script.js', __FILE__ ), 
        array('jquery') );    

	wp_enqueue_script('ajax-script');

    // in JavaScript, object properties are accessed as ajax_object.ajax_url, ajax_object.name
    $ajax_nonce = wp_create_nonce( "w3-security" );
    wp_localize_script( 
        'ajax-script', 
        'ajax_object',
        array( 
            'ajax_url' => admin_url( 'admin-ajax.php' ), 
            'nonce' =>  $ajax_nonce,
            'name' => "Masud Alam",
            'age'=>35,
        ));
    
}

add_action("wp_ajax_{$_REQUEST['action']}", 'receive_data' );

function receive_data() {
    $nonce = $_POST['nonce'];
  /*  if (!wp_verify_nonce( $nonce, 'w3-security' ) ){
        die ( 'Busted!');
    }  */
    check_ajax_referer( 'w3-security', 'nonce', true );
    $name= $_POST['name'];
    $age=  $_POST['age'];
    echo "Welcome! ".$name." You're ".$age." Years Old! Your Uniquue Security Code: $nonce";

	wp_die(); // this is required to terminate immediately and return a proper response
}

check_admin_referer() Function Syntax

check_admin_referer(
    int|string $action = -1, 
    string $query_arg = '_wpnonce' 
);

Parameters #

  • $action (int|string) (Optional) nonce action টির নাম এখানে হবে। Default value: -1
  • $query_arg (string) (Optional) nonce field এর নামটি এখানে হবে। অর্থাৎ যেই key দিয়ে আপনি $_REQUEST দিয়ে nonce value রিসিভ করবেন। Default value: ‘_wpnonce’

উদাহরণঃ

এখন আমরা আমাদের ইতিমধ্যে ডেভেলপ করা “W3 Form Nonce Checking Plugin” এ wp_verify_nonce() ফাঙ্কশনের পরিবর্তে check_admin_referer() function দিয়ে নতুন করে সাজাবো। নিম্নে লক্ষ্য করুন :

<?php
/*
Plugin Name: W3 Form Nonce Checking Plugin
Plugin URI: https://github.com/w3programmers/w3-nonce-form/
Description: W3 Form Nonce Checking Plugin
Author: Masud Alam
Version: 1.0.0
Author URI: https://blog.w3programmers.com/
*/

add_action('admin_menu', 'add_w3_nonce_form_admin_screen');
function add_w3_nonce_form_admin_screen () {
    add_options_page(
        __('W3 Nonce Form Plugin Settings', 'w3-nonce-form-plugin-textdomain'),
        __('W3 Nonce Form Plugin', 'w3-nonce-form-plugin-textdomain'),
        'manage_options',
        'w3_nonce_form_plugin_settings',
        'w3_nonce_form_plugin_do_something'
    );
}
 
function w3_nonce_form_plugin_do_something () {
?>
<h2><?php esc_html_e('W3 Nonce Form Plugin Admin Screen', 'w3-nonce-form-plugin-textdomain');?></h2>

<?php
  if ( ! empty( $_POST ) && check_admin_referer( 'doing_something', 'w3_nonce_field' ) ){
        // User pressed "Do Something!" button, so
        // do something interesting.
        $nonce=$_REQUEST['w3_nonce_field'];
        echo "Hey! Your Nonce is: ".$nonce,"<br>";
    }
    ?>
    <form method="post" action="<?php echo admin_url('options-general.php?page=w3_nonce_form_plugin_settings');?>">
    <!-- some inputs here ... -->
    <?php wp_nonce_field( 'doing_something', 'w3_nonce_field' ); ?>
    <input class="button button-primary" type="submit" value="Check Nonce Value" name="submit">
 </form>
 <?php
}

WordPress Plugins Security

এখন যদি আপনি Plugin টি Activate করেন , তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন।

আর যদি আপনি form টি submit করেন , তাহলে নিচের মতো রেজাল্ট দেখতে পাবেন।

WordPress Nonce Verification
WordPress Nonce Verification

আবার যদি nonce ঠিক না থাকে , তাহলে check_admin_referer() function ইমিডিয়েট নিচের মতো রেজাল্ট দিবে।

lilligal nonce example
lilligal nonce example

আমি মাসুদ আলম, বাংলাদেশের ৩৬ তম Zend Certified Engineer । ২০০৯ সালে কম্পিউটার সাইন্স থেকে বেচেলর ডিগ্রী অর্জন করি। দীর্ঘ ১৫ বছর আমি Winux Soft, SSL Wireless, IBCS-PRIMAX, Max Group, Canadian International Development Agency (CIDA), Care Bangladesh, World Vision, Hellen Keller, Amarbebsha Ltd সহ বিভিন্ন দেশি বিদেশী কোম্পানিতে ডেটা সাইন্স, মেশিন লার্নিং, বিগ ডেটা, ওয়েব ডেভেলপমেন্ট এবং সফটওয়্যার ডেভেলপমেন্ট এর উপর বিভিন্ন লিডিং পজিশন এ চাকরি এবং প্রজেক্ট লিড করি। এছাড়াও বাংলাদেশের ১৮৫ জন জেন্ড সার্টিফাইড ইঞ্জিনিয়ার এর মধ্যে ১২০ এরও অধিক ছাত্র আমার হাতে জেন্ড সার্টিফাইড ইঞ্জিনিয়ার হয়েছেন। বর্তমানে w3programmers ট্রেনিং ইনস্টিটিউট এ PHP এর উপর Professional এবং Advance Zend Certified PHP -8.2 Engineering, Laravel Mastering Course with ReactJS, Python Beginning To Advance with Blockchain, Machine Learning and Data Science, Professional WordPress Plugin Development Beginning to Advance কোর্স করাই। আর অবসর সময়ে w3programmers.com এ ওয়েব টেকনোলজি নিয়ে লেখালেখি করি।

Leave a Reply