simo-security-plugin
A WordPress firewall plugin that automatically detects and bans malicious IPs. Features brute force protection, directory scan detection, plugin enumeration monitoring, and a REST API honeypot.
by mohammed boutahir · github.com/mboutahir/simo-security-plugin · website
Install
No release zip yet. The repository archive installs, but the folder name will carry the branch suffix and updates will not flow:
wp plugin install https://github.com/mboutahir/simo-security-plugin/archive/refs/heads/main.zipWP-Sentinel
A lightweight WordPress security plugin that monitors, detects, and blocks malicious traffic in real time.
File Structure
wp-content/plugins/simo-security-plugin/
├── wp-sentinel.php # Main loader — registers everything
└── includes/
├── db-manager.php # Database table creation
├── hooks.php # All sensors, firewall, and ban logic
└── admin-ui.php # WordPress admin dashboard UI
How It Works
WP-Sentinel runs in four layers on every request:
Every Request
│
▼
1. FIREWALL — Is this IP already banned? → Block immediately
│
▼
2. SENSORS — Is this request suspicious? → Ban + Log
│
▼
3. BAN ACTION — Write to DB, add to ban list, kill request
│
▼
4. ADMIN UI — View logs, unban IPs from the dashboard
Features
Firewall
Runs on every single request before WordPress finishes loading. If the visitor's IP is in the ban list, they receive a 403 and execution stops immediately. No database queries, no theme loading, no wasted resources.
Sensor A — Brute Force Login Protection
Tracks failed login attempts per IP using WordPress transients. After 5 failed attempts within 5 minutes, the IP is permanently banned. The strike counter resets automatically after 5 minutes of no failures.
Sensor B — Path Probe & Rate Detection
Two-part sensor that runs on every page load:
- Instant ban for requests targeting critical files:
.env,.git,wp-config,/backup,phpmyadmin,etc/passwd. Any hit to these paths is an immediate ban with no threshold. - Rate-based ban for excessive 404 or 403 responses. If an IP triggers more than 10 error responses within 60 seconds, they are banned automatically.
Sensor C — Plugin Enumeration Detection
Monitors requests to the /wp-content/plugins/ directory. Tracks how many unique plugin directories an IP probes within 60 seconds. If they probe more than 10 distinct plugin folders, they are banned. Duplicate hits to the same plugin do not increment the count, preventing false positives from legitimate asset loading.
Sensor D — REST API Honeypot
Registers a fake REST API endpoint at /wp-json/wp/v2/sentinel-probe that has no legitimate purpose. Any request to this endpoint is automatically logged and banned. Bots find it by scraping WordPress's public route map at /wp-json/ and probing every listed endpoint.
Admin Dashboard
A full management interface under WP Admin → Sentinel:
- View the 50 most recent security events
- See each log entry's timestamp, IP address, target username, user agent, and reason
- See whether each IP is currently banned or just logged
- Unban individual IPs with one click
- Clear all bans at once (with confirmation dialog)
- All actions are protected with WordPress nonces to prevent CSRF attacks
Database
WP-Sentinel creates one custom table on activation: wp_sentinel_logs
| Column | Type | Description |
|---|---|---|
id |
mediumint | Auto-incrementing row ID |
time |
datetime | When the event occurred |
ip_address |
varchar(100) | The attacker's IP address |
user_agent |
text | Browser or bot identifier string |
attempted_user |
varchar(100) | Username targeted (if applicable) |
reason |
text | Human-readable description of the threat |
The ban list itself is stored in WordPress's wp_options table under the key sentinel_banned_list as a serialized array of IP strings.
Transient Keys
WP-Sentinel uses three separate transient namespaces in wp_options for temporary counters:
| Key Pattern | Sensor | Expires | Purpose |
|---|---|---|---|
sentinel_strikes_{md5(ip)} |
Sensor A | 300 seconds | Failed login strike count |
sentinel_404_rate_{md5(ip)} |
Sensor B | 60 seconds | 404/403 hit rate count |
sentinel_scan_{md5(ip)} |
Sensor C | 60 seconds | Plugin directory probe count + paths |
All transients are deleted automatically by WordPress when they expire, or immediately after a ban is triggered.
Installation
- Upload the
wp-sentinelfolder to/wp-content/plugins/ - Make sure the file structure matches exactly as shown above
- Go to WP Admin → Plugins
- Find WP-Sentinel and click Activate
- The database table is created automatically on activation
- The Sentinel menu item appears in your admin sidebar
Security Notes
- Logged-in administrators are exempt from all sensors. You cannot accidentally ban yourself.
- All unban and clear actions require a valid WordPress nonce, preventing Cross-Site Request Forgery (CSRF).
- All output in the admin dashboard is passed through
esc_html()to prevent XSS. - Database inserts use
$wpdb->insert()which uses prepared statements internally, preventing SQL injection. - The honeypot endpoint appears in WordPress's public
/wp-json/route map, making it discoverable to any scanner that reads it.
Thresholds Reference
| Sensor | Threshold | Window | Action |
|---|---|---|---|
| Brute Force | 5 failed logins | 5 minutes | Permanent ban |
| 404/403 Rate | 10 error responses | 60 seconds | Permanent ban |
| Plugin Enumeration | 10 unique plugin dirs | 60 seconds | Permanent ban |
| Critical Path Probe | 1 hit | Instant | Permanent ban |
| REST API Honeypot | 1 hit | Instant | Permanent ban |
Requirements
- WordPress 5.0 or higher
- PHP 7.4 or higher
- MySQL 5.6 or higher