Tag: security

  • Bots Arrive Within 24 Hours — Security P0 Before Domain Disclosure

    Bots Arrive Within 24 Hours — Security P0 Before Domain Disclosure

    Bots Arrive Within 24 Hours — Security P0 Before Domain Disclosure

    Self-hosting guide, part 8. Essential 25 minutes to complete before launching the domain.


    TL;DR

    • Disclosing a WordPress domain = bots arrive within 24 hours for brute force attacks. A statistical fact.
    • A 25-minute task can block 99%: ① Avoid username admin ② Block xmlrpc ③ Change wp-login slug.
    • These three constitute security P0. Complete this before disclosing your domain.
    • Wordfence and 2FA are P1 (to be added after domain launch).

    1. The Truth of the First 24 Hours

    When a WordPress site is exposed to the internet, within the first 24 hours:

    Attack Frequency Target
    /wp-login.php brute force Thousands per hour Admin password
    /xmlrpc.php pingback amp Continuous DDoS amplification
    Scanning for known plugin vulnerabilities Continuous Outdated plugins
    SQL injection attempts Automatic bots ?id=1 OR 1=1 URL
    User enumeration (?author=1) Automatic bots Discovering usernames

    The goal here is not just to block but to eliminate the surface itself, which is P0.


    2. P0 — Three Security Setup

    

    3. ① Avoiding Username Admin

    When creating the first user with the WordPress installation wizard, do not enter admin. Bots primarily target this username for brute force attacks.

    Good examples: jamjam, sailor904, personal nicknames
    Bad examples: admin, administrator, root, wpadmin
    

    If you’ve already created an admin user, create a new user via wp-cli, then revoke admin rights or delete the old user:

    wp user create newname [email protected] --role=administrator --user_pass=$(openssl rand -base64 24) --allow-root
    wp user delete admin --reassign=newname --allow-root
    

    4. ② Blocking xmlrpc.php — mu-plugin

    /xmlrpc.php is an old API for WordPress, rarely used (only by Jetpack users). Bots exploit it for brute force amplification (attempting thousands of passwords with a single request).

    Create /var/www/html/wp-content/mu-plugins/disable-xmlrpc.php:

    <?php
    /**
     * Plugin Name: Disable XML-RPC
     * Description: Block xmlrpc.php to reduce attack surface.
     */
    if (!defined('ABSPATH')) exit;
    
    add_filter('xmlrpc_enabled', '__return_false');
    add_filter('wp_headers', function ($headers) {
        unset($headers['X-Pingback']);
        return $headers;
    });
    add_filter('xmlrpc_methods', function ($methods) {
        unset($methods['pingback.ping']);
        unset($methods['pingback.extensions.getPingbacks']);
        return $methods;
    });
    add_action('init', function () {
        $uri = $_SERVER['REQUEST_URI'] ?? '';
        if (stripos($uri, '/xmlrpc.php') !== false) {
            status_header(403);
            exit('xmlrpc disabled');
        }
    });
    

    Verification:

    curl -I http://localhost:8090/xmlrpc.php
    # HTTP/1.1 403  ← Success
    

    5. ③ Changing wp-login Slug

    /wp-login.php is the login URL common to all WordPress sites. Bots start automatically hitting this URL. It should be obscured with a different slug.

    Install the plugin wps-hide-login:

    wp plugin install wps-hide-login --activate --allow-root
    wp option update whl_page starport --allow-root
    

    starport is a secret slug chosen by I, difficult to guess yet easy to remember. For example: byeolgorae-gate, secret-door-2026, starport.

    Verification:

    curl -I -L http://localhost:8090/wp-login.php
    # 301 redirect → Fake URL (bot fails there)
    
    curl -I -L http://localhost:8090/wp-admin/
    # 404 (Admin page appears nonexistent when logged out)
    
    curl -I -L http://localhost:8090/starport/
    # 200 (Login page known only to I)
    

    If I forget the slug, I won’t be able to access it either. Bookmarking and note-taking are essential.


    6. Results — From the Bot’s Perspective

    Attack Response after Blocking
    GET /wp-login.php 301 → Fake URL → Bot attempts there → Forever fails
    POST /xmlrpc.php Blocked immediately with 403. Amplification not possible
    GET /wp-admin/ 404. The admin page pretends to be nonexistent
    Username brute force Attempting admin → Our site has no admin
    ?author=1 user enum Rank Math automatically blocks it (Disable Author Archives)

    Resources expended by bots = Gains from I’s site = 0.


    7. P0 vs P1 vs P2 — Prioritization

    Stage Task Timing
    P0 (Mandatory, before domain disclosure) Username, xmlrpc, wp-login slug This 25 minutes
    P1 (Immediately after domain launch) Wordfence wizard + 2FA GUI operations by I
    P2 (Monthly) Plugin security updates + WPA (vulnerability scan) Operational phase

    If I launch the domain without completing P0 — bots will arrive within 24 hours to start brute force attempts. Even without setup, it is impenetrable, yet logs will accumulate brute force attempts and consume mini-PC CPU. Preventing such occurrences is vital for mental well-being.


    8. Traps

    Trap 1. mu-plugin Auto Activation

    mu-plugins run forced above regular plugins. Consequently, security policies, like blocking xmlrpc, that must never be disabled, are suitable for mu-plugins.

    Trap 2. Forgetting WPS Hide Login Slug

    Since the whl_page option is directly written into the DB, if I forget the slug, I won’t be able to access it either. Recovery method: wp option get whl_page --allow-root (via mini-PC SSH) or temporarily deactivate the mu-plugin.

    Trap 3. Automatic Bypass After Authentication

    WPS Hide Login only blocks those who do not know the slug. A logged-in session continues to use /wp-admin/. Once I log in, I have free access to the admin page for the next 30 minutes.

    Trap 4. Entry with a New Slug Upon Logout

    After I log out, the next login will be at /starport. Updating bookmarks is essential.


    FAQ

    Q. What if I already disclosed the domain but haven’t set up P0?
    Immediately turn off cloudflared or disable the Tailscale Funnel → Set up P0 → Re-disclose. 5 minutes.

    Q. Why is the Wordfence wizard (P1) not P0?
    P0 removes the surface itself. Wordfence detects and blocks attacks while the surface is still present. It serves as a supplementary measure.

    Q. Can I change the slug to /admin?
    /admin is also a common slug targeted by bots. Not recommended. Choose a word that only I can think of, which is difficult to guess.

    Q. Is P0 sufficient without 2FA?
    Sufficient + entirely enough. 2FA acts as the final shield when passwords are compromised. P0 + 2FA = Effectively invulnerable.

    Q. If I block xmlrpc, can I still use Jetpack?
    Some Jetpack functionalities are disabled. It is irrelevant if Jetpack is not used at all. Our Star Whale does not utilize Jetpack.


    Next Episode Preview

    Part 9 — The Invisible Bridge: Cloudflare Tunnel. Finally connecting the domain to the mini-PC. No need to open router ports, without exposing the mini-PC IP, and employing a free WAF, DDoS protection, and CDN.


    Summary

    Disclosing a WordPress domain = Bots will arrive within 24 hours. A P0 setup (username, xmlrpc, wp-login slug) in 25 minutes can block 99%. Complete this before launching the domain.