Skip to content

Latest commit

 

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Wordpot2

A WordPress honeypot that detects probes for plugins, themes, timthumb and other common files used to fingerprint a WordPress installation.

Wordpot2 mimics a WordPress 6.4.3 site using the Twenty Twenty-Four theme (default). It logs all probing attempts including login bruteforce, plugin/theme enumeration, and author discovery.

Originally forked from Wordpot by Brindisi (Python 2 / Flask 0.x), fully rewritten for Python 3.10+ / Flask 3.x.

Quick Start

pip install -r requirements.txt
python wordpot2.py --host=127.0.0.1 --port=5000

Then visit http://127.0.0.1:5000 -- you should see a WordPress-looking site.

Configuration

Edit wordpot.conf or use command line arguments:

python wordpot2.py --help
Option Description Default
--host Host address 127.0.0.1
--port Port number 80
--title Blog title Here the Title
--theme Theme name twentytwentyfour
--plugins Fake plugins (comma-separated) all allowed
--themes Fake themes (comma-separated) all allowed
--ver WordPress version to mimic 6.4.3
--server Custom Server header Apache/2.4.57 (Ubuntu)

What gets logged

All activity is logged to logs/wordpot.log:

  • Login attempts (username + password captured)
  • Admin panel probes
  • Plugin and theme enumeration
  • Author discovery (?author=N)
  • Common file probes (readme.html, xmlrpc.php)
  • TimThumb/Uploadify probes

JSON event format

Every probe also produces a structured JSON event in the same log file, ready for ingestion into ELK or a similar pipeline:

{
  "plugin": "badlogin",
  "username": "admin",
  "password": "hunter2",
  "timestamp": "2026-08-09T08:40:41.627868+00:00",
  "src_ip": "203.0.113.7",
  "src_port": "54122",
  "dest_ip": "example.com",
  "dest_port": "80",
  "user_agent": "WPScan v3.8.28 (https://wpscan.com/wordpress-security-scanner)",
  "url": "http://example.com/wp-login.php",
  "browser_family": "Other",
  "browser_version": "",
  "os_family": "Other",
  "os_version": "",
  "device_family": "Spider"
}

The raw user_agent string is always kept alongside the parsed browser_* / os_* / device_family fields -- scanners send malformed and hand-crafted User-Agents, and that raw string is often the most useful signal.

Breaking change: as of this version, source_ip / source_port are renamed src_ip / src_port, and a timestamp field is added. This aligns the schema with T-Pot's expected field names. Update any parser built against the old format.

Optional: enable hpfeeds in wordpot.conf to forward the same JSON events to a centralized collector. JSON events are written locally either way.

Theme support

Themes live in wordpot/static/wp-content/themes/. Each theme needs a matching HTML template in wordpot/templates/ named after the theme (e.g. twentytwentyfour.html).

Available themes:

  • twentytwentyfour -- WordPress 6.4 default (recommended)
  • twentyeleven -- Legacy theme (in templates/v2.8/)

Note: Flask serves static files with static_url_path='' so assets are served under /wp-content/ (not /static/wp-content/) just like a real WordPress site.

Templates use the Jinja2 template engine.

Plugins (beta)

Wordpot2 is expandable with plugins to simulate specific WordPress vulnerabilities.

Built-in plugins:

  • badlogin -- Captures login credentials
  • commonfiles -- Serves readme.html, xmlrpc.php
  • userenumeration -- Responds to ?author=N probes
  • timthumb -- Detects TimThumb/Uploadify probes

See the wiki for writing custom plugins.

WPScan validation

Tested with WPScan 3.8.28:

  • WordPress 6.4.3 detected (via Meta Generator + readme.html)
  • Theme Twenty Twenty-Four identified
  • User enumeration working
  • Proper /wp-content/ paths (no /static/ leak)
  • Plugin fingerprints not yet detectable
  • User enumeration needs WordPress-style /author/ redirects

Docker deployment

Wordpot2 runs standalone with python wordpot2.py, but for production you'll want gunicorn behind a reverse proxy. Here's how:

Dockerfile example

FROM python:3.12-slim
WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends curl \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
RUN pip install --no-cache-dir gunicorn

# Important: suppress gunicorn's Server header so Flask can spoof Apache
RUN printf 'import gunicorn.http.wsgi\n\
_orig = gunicorn.http.wsgi.Response.default_headers\n\
def _no_server(self):\n\
    return [h for h in _orig(self) if not h.lower().startswith("server:")]\n\
gunicorn.http.wsgi.Response.default_headers = _no_server\n' > /opt/gunicorn.conf.py

COPY . .
EXPOSE 8000
CMD ["gunicorn", "wordpot2:app", "-c", "/opt/gunicorn.conf.py", "--bind", "0.0.0.0:8000", "--workers", "2"]

Key tips for realism

  • Server header: gunicorn overrides Flask's spoofed Server header by default. The config above fixes that so wordpot.conf's SERVER value is used instead.
  • Reverse proxy: put Nginx in front to add realistic logging and block suspicious paths (.git, .env, etc.).
  • Test with WPScan: always validate your setup with wpscan --url http://your-honeypot --enumerate u,vp,vt to check what leaks.

Links

License

ISC License.

Copyright (c) 2012, Gianluca Brindisi < g@brindi.si >

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.

About

WordPress 6.4 honeypot — mimics a real WP site to capture attacker probes, login bruteforce & plugin enumeration. Wordpot2 – WordPress honeypot (Python 3 + Flask) – port de gbrindisi/wordpot . WPScan validated.

Topics

Resources

Stars

2 stars

Watchers

2 watching

Forks

Releases

Packages

Used by

Contributors

Languages