Javascript : Full Page Password (based on IP/ASN)

I have already covered the full screen block message that is scripted in JavaScript in a previous post, Which did work very well because it means you could not access blog posts, but you could access static pages.

Full screen block - not helpful

However, the downside was if you were using the Same external blocking factors in a corporation, you had no way of getting to it as the owner or member so I thought it would be a good idea to fix this.

Password stored in AES256

The password is stored in this script in AES256 that means no clear text passwords in the code.

Password override required

I have therefore had to think about this, and I have redevelop the original code to get rid of all the blocked messages and warnings, now what happens if you get prompted for a password.

Password removal logic

When this password is entered and it is correct, you get 60 minutes to use the blog and when the timer runs out, you get another 60 minutes upon reenter the password again - this does not apply to all traffic, but only the traffic listed in the IP or ASN section of the code.

If you get the password wrong, you simply get a message saying “ Incorrect password” and the message stops you from viewing or interacting with any blog posts.

This is what the block looks like in action:


Obviously, you didn’t enter the correct password in the box and you have access to the blog for 60 minutes, where you will need to enter the password again for an additional 60 minutes:


Script : PasswordPopup.html

<style>
.fullscreen-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.97);
    display: flex;
    justify-content: center;
    align-items: center;
    z-index: 2147483647;
    animation: fadeIn 0.5s ease-in;
    user-select: none;
}    

.fullscreen-content {
    text-align: center;
    color: white;
    padding: 2rem;
    max-width: 900px;
}  

.password-form {
    margin-top: 20px;
}

.password-form input {
    padding: 10px;
    width: 200px;
    margin: 10px 0;
    font-size: 16px;
    background-color: #333;
    color: white;
    border: 1px solid #666;
    border-radius: 4px;
}

.password-form button {
    padding: 10px 20px;
    background: #007bff;
    color: white;
    border: none;
    border-radius: 4px;
    font-size: 16px;
    cursor: pointer;
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}   
</style>
<script>
async function checkVisitorIP() {
    try {
        const response = await fetch('https://ipapi.co/json/');
        const data = await response.json();
        const visitorIP = data.ip;
        const visitorASN = data.asn;            

        const blockedIPs = [
            '10.19.5.2',
            '20.191.47.168',
            '40.127.243.162',
            '52.137.61.118',
            '194.73.107.231',
            '194.73.107.129',
            '52.142.120.109'
        ];            
        const blockedASNs = ['22616', '32921', '40384', '53444', '53813', '55242', '62044'];           

        const visitorASNNumber = visitorASN.replace('AS', '');
        return blockedIPs.includes(visitorIP) || blockedASNs.includes(visitorASNNumber);
    } catch (error) {
        console.error('Error checking IP/ASN:', error);
        return false;
    }
}

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('');
}

async function showPasswordPrompt() {
    const needsPassword = await checkVisitorIP();
    if (!needsPassword) return;

    if (localStorage.getItem('passExp') && Date.now() < parseInt(localStorage.getItem('passExp'))) {
        return;
    }

    const overlay = document.createElement('div');
    overlay.className = 'fullscreen-overlay';           
    overlay.innerHTML = `
        <div class="fullscreen-content">
            <h1>Enter Password</h1>
            <p>60 minutes of access</p>
            <div class="password-form">
                <input type="password" id="pwd">
                <br>
                <button onclick="checkPassword()">Submit</button>
            </div>
        </div>
    `;          

    document.body.appendChild(overlay);
}

async function checkPassword() {
    const inputPassword = document.getElementById("pwd").value;
    const inputHash = await hashPasswordUTF16LE(inputPassword);
    const storedHash = "245b6a74ddf05716b6013b0a3f04bf920be4445b480c9db12f3e65215eca410f".toLowerCase();
    
    if (inputHash.toLowerCase() === storedHash) {
        document.querySelector('.fullscreen-overlay').style.display = 'none';
        localStorage.setItem('passExp', Date.now() + (60 * 60 * 1000));
    } else {
        alert('Wrong password');
    }
}

document.addEventListener('DOMContentLoaded', showPasswordPrompt);

document.addEventListener('keydown', function(e) {
    if (
        (e.key === 'F12') ||
        (e.ctrlKey && e.shiftKey && e.key === 'I') ||
        (e.ctrlKey && e.key === 'u') ||
        (e.key === 'Escape') ||
        (e.key === 'F11')
    ) {
        e.preventDefault();
    }
}, true);

document.addEventListener('contextmenu', function(e) {
    e.preventDefault();
}, true);
</script>

How about if I need a new password?

Well as this is AES256 encrypted you will need to generate this and provide the hash file to the script as it is not stored in the code in ASCII, I have therefore created this tool to update the password:


The code of thie applet is shown below:

Script : NewPassword.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SHA-256 Generator (UTF-16LE)</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
            background-color: #f4f4f4;
        }
        .container {
            background: white;
            padding: 20px;
            border-radius: 8px;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            text-align: center;
        }
        input, button {
            margin: 10px;
            padding: 10px;
            font-size: 16px;
        }
        #hashOutput {
            word-break: break-all;
            font-size: 14px;
            padding: 10px;
            background: #eee;
            border-radius: 4px;
            margin-top: 10px;
        }
    </style>
</head>
<body>
    <div class="container">
        <h2>SHA-256 Generator (UTF-16LE)</h2>
        <input type="password" id="password" placeholder="Enter Password">
        <button onclick="generateHash()">Generate Hash</button>
        <div id="hashOutput">Your SHA-256 hash will appear here.</div>
        <button onclick="copyHash()">Copy to Clipboard</button>
    </div>

    <script>
        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('');
        }
        
        async function generateHash() {
            const password = document.getElementById("password").value;
            if (!password) {
                alert("Please enter a password.");
                return;
            }
            const hash = await hashPasswordUTF16LE(password);
            document.getElementById("hashOutput").textContent = hash;
        }
        
        function copyHash() {
            const hashText = document.getElementById("hashOutput").textContent;
            navigator.clipboard.writeText(hashText).then(() => {
                alert("Hash copied to clipboard.");
            }).catch(err => console.error("Failed to copy: ", err));
        }
    </script>
</body>
</html>
Previous Post Next Post

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