ℹ️ Many blog posts do not include full scripts. If you require a complete version, please use the Support section in the menu.
Disclaimer: I do not accept responsibility for any issues arising from scripts being run without adequate understanding. It is the user's responsibility to review and assess any code before execution. More information

Evolving Website Protection: From Fullscreen Overlay to Subtle Redirect Popup

The protection script has evolved from a fullscreen password overlay that blocked content immediately to a more subtle approach - a small popup that appears after a random delay, giving legitimate users time to browse before being challenged.

Visuals

This is the popup after a random 10 seconds:


Then if you click the password option you will then need to enter the password:


If you do nothing or get the password wrong you end up on this website (at the time of posting):


The New Approach: Delayed Popup with Countdown

Instead of immediately confronting visitors with a fullscreen overlay, the script now waits between 1-10 seconds (randomly determined) before showing a small popup at the top of the page. This popup contains a simple 6-second countdown and a key icon:

function initializeProtection() {
    if (initialDelayTimeout) {
        clearTimeout(initialDelayTimeout);
    }
    
    // Random delay between 1-10 seconds
    const randomDelay = Math.floor(Math.random() * 9000) + 1000;
    
    initialDelayTimeout = setTimeout(() => {
        showPopup();
    }, randomDelay);
}

The popup itself is minimal and non-intrusive:

popup.innerHTML = `
    <div class="popup-content">
        <div class="redirect-notice">
            <div id="countdown-timer">Redirecting in <span id="countdown-seconds">6</span> seconds</div>
            <span class="key-icon" onclick="showPasswordField()" title="Enter password">🔑</span>
        </div>
        <div class="password-form">
            <input type="password" id="pwd" placeholder="Enter password">
            <button onclick="checkPassword()">Submit</button>
        </div>
    </div>
`;

Two-Stage Authentication Flow

The script implements a two-stage authentication process. Initially, visitors see only the countdown and key icon. If they know they need to authenticate, clicking the key icon reveals the password field and restarts the 6-second countdown:

function showPasswordField() {
    // Stop current countdown
    stopCountdown();
    
    // Hide redirect notice, show password form
    document.querySelector('.redirect-notice').style.display = 'none';
    document.querySelector('.password-form').style.display = 'block';
    
    // Focus on password field
    document.getElementById('pwd').focus();
    
    // Restart countdown with 6 seconds
    startCountdown();
}

This gives authorized users a total of 12 seconds if needed - 6 seconds to notice and click the key, then another 6 seconds to enter their password.

Targeted Protection via IP and ASN Filtering

The script only activates for specific IP addresses and ASN (Autonomous System Number) ranges. This targeting happens before any UI elements appear:

async function checkVisitorIP() {
    const response = await fetch('https://ipapi.co/json/');
    const data = await response.json();
    const visitorIP = data.ip;
    const visitorASN = data.asn;
    
    const blockedIPs = ['86.165.185.215', '20.191.47.168', ...];
    const blockedASNs = ['22616', '32921', '40384', ...];
    
    const visitorASNNumber = visitorASN.replace('AS', '');
    return blockedIPs.includes(visitorIP) || blockedASNs.includes(visitorASNNumber);
}

If the visitor's IP or ASN doesn't match the blocklist, the script never activates and the website functions normally.

Password Validation with SHA-256 Hashing

The script uses SHA-256 hashing encoding to validate passwords. Passwords are never stored in plaintext:

const ALLOWED_PASSWORD_HASHES = [
    "245b6a74ddf05716b6013-hash-redacted-be4445b480c9db12f3e65215eca410f",
    "71b6a61380b21d67903-hash-redacted-c966aa31db7f2c84dd4f16d554d"
]; async function hashPasswordUTF16LE(password) { password = password.trim(); let byteArray = []; for (let i = 0; i < password.length; i++) { let charCode = password.charCodeAt(i); byteArray.push(charCode & 0xFF); byteArray.push(charCode >> 8 & 0xFF); } let hashBuffer = await crypto.subtle.digest("SHA-256", new Uint8Array(byteArray)); let hashArray = Array.from(new Uint8Array(hashBuffer)); return hashArray.map(b => b.toString(16).padStart(2, '0')).join(''); }

Valid passwords grant 8 hours of access stored in localStorage, preventing repeated challenges.

The Back Button Problem and Solution

The original implementation had a critical flaw - after being redirected, users could simply press the back button to return to the protected page. The countdown would be broken, and the protection wouldn't reinitialize properly.

The script now uses window.location.replace() instead of window.location.href, which replaces the current history entry rather than adding a new one:

function performRedirect() {
    sessionStorage.setItem('redirected', 'true');
    window.location.replace('https://nonono.a6n.co.uk');
}

Additionally, the script monitors for back navigation attempts using multiple event listeners:

window.addEventListener('pageshow', function(event) {
    if (event.persisted || performance.navigation.type === 2) {
        // Check if we've been redirected before
        if (sessionStorage.getItem('redirected')) {
            performRedirect();  // Immediately redirect again
            return;
        }
        stopCountdown();
        initializeProtection();
    }
});

window.addEventListener('popstate', function() {
    if (sessionStorage.getItem('redirected')) {
        performRedirect();
        return;
    }
    // Normal reinitialization if not previously redirected
});

The script sets a sessionStorage flag when redirecting. If users attempt to navigate back after being redirected, the script detects this flag and immediately redirects them again.

User Experience

Legitimate visitors get 1-10 seconds of normal browsing before any interruption

  1. Subtlety: The small popup is less aggressive than a fullscreen block
  2. Reliability: Session storage tracking prevents back button exploitation
  3. Performance: Random delay reduces server load from simultaneous protection checks

The combination of location.replace() for history manipulation and sessionStorage for state tracking creates a robust defense against back navigation, while the two-stage authentication flow balances security with usability for authorized users.

Previous Post Next Post

نموذج الاتصال