Merge branch 'feature/enable-restAPI' of https://github.com/mh4x0f/WiFi-PumpkiCLI into beta

This commit is contained in:
mh4x0f 2022-02-09 21:41:27 -03:00
commit c0fb50ad6d
13 changed files with 91 additions and 140 deletions

View File

@ -28,7 +28,7 @@
- Credentials harvesting
- Transparent Proxies
- LLMNR, NBT-NS and MDNS poisoner ([Responder3](https://github.com/skelsec/Responder3))
- RestFulAPI (disabled)
- RestFulAPI (new)
- and **more**!
### Donation

View File

@ -15,12 +15,11 @@ loguru>=0.4.0
scapy==2.4.3
isc_dhcp_leases==0.9.1
dnspython==1.16.0
Flask>=1.1.1
Flask==1.1.2
requests>=2.18.4
beautifulsoup4>=4.9.1
black
coverage==5.1
# jwt>=1.0.0
# Flask-RESTful==0.3.7
# Werkzeug==1.0.1
PyJWT==2.1.0
flask-restx>=0.5.1

View File

@ -14,10 +14,9 @@ loguru>=0.4.0
scapy>=2.4.4
isc_dhcp_leases>=0.9.1
dnspython==1.16.0
Flask==1.1.1
Flask==1.1.2
requests>=2.18.4
beautifulsoup4>=4.9.1
asn1crypto>=1.0.0
#jwt>=1.0.0
#Flask-RESTful==0.3.7
#Werkzeug==1.0.1
PyJWT==2.1.0
flask-restx>=0.5.1

View File

@ -19,7 +19,7 @@ import wifipumpkin3.core.utility.constants as C
from os import getuid
# disable RestAPI
# from wifipumpkin3.core.servers.rest.application import RestControllerAPI
from wifipumpkin3.core.servers.rest.application import RestControllerAPI
import threading
@ -38,27 +38,27 @@ def parser_args_func(parse_args, config):
info=True,
)
)
# if parse_args.restmode:
# if not (parse_args.password):
# print(
# display_messages(
# "{} \n rest mode require a valid password.".format(
# setcolor("password invalid", color="red")
# ),
# info=True,
# )
# )
# exit(0)
if parse_args.restmode:
if not (parse_args.password):
print(
display_messages(
"{} \n rest mode require a valid password.".format(
setcolor("password invalid", color="red")
),
info=True,
)
)
exit(0)
# set_nocolors()
# config.set_one("ap_mode", "restapi", True)
# config.set("rest_api_settings", "PASSWORD", parse_args.password)
# config.set("rest_api_settings", "USERNAME", parse_args.username)
# config.set("rest_api_settings", "port", parse_args.restport)
# server_restapi = RestControllerAPI("wp3API", config)
# thead = threading.Thread(target=server_restapi.run)
# thead.setDaemon(True)
# thead.start()
set_nocolors()
config.set_one("ap_mode", "restapi", True)
config.set("rest_api_settings", "PASSWORD", parse_args.password)
config.set("rest_api_settings", "USERNAME", parse_args.username)
config.set("rest_api_settings", "port", parse_args.restport)
server_restapi = RestControllerAPI("wp3API", config)
thead = threading.Thread(target=server_restapi.run)
thead.setDaemon(True)
thead.start()
def wp3_header():
@ -116,31 +116,31 @@ def main():
action="store_true",
default=False,
)
# parser.add_argument(
# "--rest",
# dest="restmode",
# help="Run the Wp3 RESTful API.",
# action="store_true",
# default=False,
# )
# parser.add_argument(
# "--restport",
# dest="restport",
# help="Port to run the Wp3 RESTful API on. default is 1337",
# default=1337,
# )
# parser.add_argument(
# "--username",
# dest="username",
# help="Start the RESTful API with the specified username instead of pulling from wp3.db",
# default="wp3admin",
# )
# parser.add_argument(
# "--password",
# dest="password",
# help="Start the RESTful API with the specified password instead of pulling from wp3.db",
# default=None,
# )
parser.add_argument(
"--rest",
dest="restmode",
help="Run the Wp3 RESTful API.",
action="store_true",
default=False,
)
parser.add_argument(
"--restport",
dest="restport",
help="Port to run the Wp3 RESTful API on. default is 1337",
default=1337,
)
parser.add_argument(
"--username",
dest="username",
help="Start the RESTful API with the specified username instead of pulling from wp3.db",
default="wp3admin",
)
parser.add_argument(
"--password",
dest="password",
help="Start the RESTful API with the specified password instead of pulling from wp3.db",
default=None,
)
parser.add_argument(
"-v",
"--version",

View File

@ -220,24 +220,24 @@ class PumpkinShell(Qt.QObject, ConsoleUI):
self.threads["RogueAP"].extend(self.proxy_controller.ActiveReactor)
self.threads["RogueAP"].extend(self.mitm_controller.ActiveReactor)
self.wireless_controller.ActiveReactor.start()
self.wireless_controller.ActiveReactor.signalApIsRuning.connect(
self.signalHostApdProcessIsRunning
)
# if not self.parse_args.restmode:
# self.wireless_controller.ActiveReactor.start()
# self.wireless_controller.ActiveReactor.signalApIsRuning.connect(
# self.signalHostApdProcessIsRunning
# )
# return
# self.wireless_controller.ActiveReactor.start()
# for thread in self.threads["RogueAP"]:
# if thread is not None:
# QtCore.QThread.sleep(1)
# if not (isinstance(thread, list)):
# thread.start()
# self.wireless_controller.ActiveReactor.signalApIsRuning.connect(
# self.signalHostApdProcessIsRunning
# )
if not self.parse_args.restmode:
self.wireless_controller.ActiveReactor.start()
self.wireless_controller.ActiveReactor.signalApIsRuning.connect(
self.signalHostApdProcessIsRunning
)
return
self.wireless_controller.ActiveReactor.start()
for thread in self.threads["RogueAP"]:
if thread is not None:
QtCore.QThread.sleep(1)
if not (isinstance(thread, list)):
thread.start()
def signalHostApdProcessIsRunning(self, status):
if status:

View File

@ -1,5 +1,5 @@
from flask import Blueprint
from flask_restful import Api
from flask_restx import Api
import wifipumpkin3.core.servers.rest.blueprints.restapi.accesspoint as res_ap
import wifipumpkin3.core.servers.rest.blueprints.restapi.authenticate as res_auth
import wifipumpkin3.core.servers.rest.blueprints.restapi.logger as res_logger
@ -48,8 +48,6 @@ def init_app(app):
res_ap.SettingsAPmodeResource, "/apmode", "/apmode/<string:attribute>"
)
api.add_resource(res_ap.ClientsResource, "/clients")
api.add_resource(
res_plugins.SettingsPluginResource, "/plugins", "/plugins/<string:attribute>"
)

View File

@ -3,7 +3,7 @@ import wifipumpkin3.core.utility.constants as C
from wifipumpkin3 import PumpkinShell
from wifipumpkin3.core.common.platforms import Linux as Refactor
from netaddr import EUI
from flask_restful import Resource
from flask_restx import Resource
from flask import jsonify, request
from wifipumpkin3.core.servers.rest.ext.auth import token_required
from wifipumpkin3.core.servers.rest.ext.exceptions import exception
@ -25,34 +25,6 @@ from wifipumpkin3.core.servers.rest.ext.exceptions import exception
# See the License for the specific language governing permissions and
# limitations under the License.
class ClientsResource(Resource):
def __init__(self):
self.root = PumpkinShell.getInstance()
super(ClientsResource, self).__init__()
def get_mac_vendor(self, mac):
""" discovery mac vendor by mac address """
try:
d_vendor = EUI(mac)
d_vendor = d_vendor.oui.registration().org
except:
d_vendor = "unknown vendor"
return d_vendor
@token_required
def get(self):
proxy_plugins = self.root.proxy_controller.getInfo()
connected_clints = Refactor.readFileDataToJson(C.CLIENTS_CONNECTED)
list_clients_connted = []
for item in connected_clints:
connected_clints[item]["VENDOR"] = self.get_mac_vendor(
connected_clints[item]["MAC"]
)
list_clients_connted.append(connected_clints[item])
return jsonify({"clients": list_clients_connted})
class SettingsAPmodeResource(Resource):
config = SettingsINI.getInstance()
key_name = "ap_mode"
@ -95,7 +67,7 @@ class SettingsDHCPResource(Resource):
if attribute:
if not attribute in self.config.get_all_childname(self.key_name):
return exception(
"Cannot found that attribute {} on {}!".format(key, self.key_name),
"Cannot found that attribute {} on {}!".format(attribute, self.key_name),
code=400,
)
return jsonify({attribute: self.config.get(self.key_name, attribute)})

View File

@ -1,4 +1,4 @@
from flask_restful import Resource
from flask_restx import Resource
from flask import request, jsonify, make_response
from werkzeug.security import generate_password_hash, check_password_hash
import jwt
@ -59,9 +59,10 @@ class LoginResource(Resource):
+ datetime.timedelta(minutes=3000),
},
admin_SECRET_KEY,
algorithm="HS256",
)
return jsonify({"token": token.decode("UTF-8")})
return jsonify({"token": token})
return make_response(
"Could not verify",

View File

@ -1,6 +1,6 @@
from flask import jsonify, request
from wifipumpkin3 import PumpkinShell
from flask_restful import Resource
from flask_restx import Resource
from io import StringIO
import sys
from wifipumpkin3.core.servers.rest.ext.auth import token_required
@ -37,12 +37,10 @@ class Capturing(list):
class CommandsResource(Resource):
def __init__(self):
self.root = PumpkinShell.getInstance()
super(CommandsResource, self).__init__()
@token_required
def get(self, command=None):
self.root = PumpkinShell.getInstance()
output = []
with Capturing(output) as output:
self.root.onecmd(command)
@ -50,15 +48,13 @@ class CommandsResource(Resource):
class CommandsPostResource(Resource):
def __init__(self):
self.root = PumpkinShell.getInstance()
super(CommandsPostResource, self).__init__()
@token_required
def post(self, command=None):
data = request.get_json(force=True)
if not "commands" in data:
return exception("Cannot found that key commands on data", code=400,)
self.root = PumpkinShell.getInstance()
output = []
with Capturing(output) as output:
self.root.onecmd(data.get("commands"))

View File

@ -1,6 +1,6 @@
from wifipumpkin3.core.utility.collection import SettingsINI
import wifipumpkin3.core.utility.constants as C
from flask_restful import Resource
from flask_restx import Resource
from flask import jsonify, request
import os, json
from itertools import islice

View File

@ -1,7 +1,7 @@
from wifipumpkin3.core.utility.collection import SettingsINI
import wifipumpkin3.core.utility.constants as C
from wifipumpkin3 import PumpkinShell
from flask_restful import Resource
from flask_restx import Resource
from flask import jsonify, request
from wifipumpkin3.core.servers.rest.ext.auth import token_required
from wifipumpkin3.core.servers.rest.ext.exceptions import exception
@ -28,12 +28,9 @@ class MitmPluginsResource(Resource):
config = SettingsINI.getInstance()
key_name = "mitm_modules"
def __init__(self):
self.root = PumpkinShell.getInstance()
super(MitmPluginsResource, self).__init__()
@token_required
def get(self):
self.root = PumpkinShell.getInstance()
mitm_plugins = self.root.mitm_controller.getInfo(excluded=("Config"))
for item in mitm_plugins:
mitm_plugins[item]["Activate"] = self.config.get(
@ -46,10 +43,6 @@ class PluginsInfoResource(Resource):
config = SettingsINI.getInstance()
key_name = "mitm_modules"
def __init__(self):
self.root = PumpkinShell.getInstance()
super(PluginsInfoResource, self).__init__()
@token_required
def get(self, plugin_name=None):
if plugin_name:
@ -60,6 +53,7 @@ class PluginsInfoResource(Resource):
),
code=400,
)
self.root = PumpkinShell.getInstance()
proxy_plugins = self.root.mitm_controller.getInfo(excluded=("Config"))
for item in proxy_plugins:
proxy_plugins[item]["Activate"] = self.config.get(
@ -77,7 +71,7 @@ class SettingsPluginResource(Resource):
if attribute:
if not attribute in self.config.get_all_childname(self.key_name):
return exception(
"Cannot found that attribute {} on {}!".format(key, self.key_name),
"Cannot found that attribute {} on {}!".format(attribute, self.key_name),
code=400,
)
return jsonify({attribute: self.config.get(self.key_name, attribute)})

View File

@ -1,7 +1,7 @@
from wifipumpkin3.core.utility.collection import SettingsINI
import wifipumpkin3.core.utility.constants as C
from wifipumpkin3 import PumpkinShell
from flask_restful import Resource
from flask_restx import Resource
from flask import jsonify, request
from wifipumpkin3.core.servers.rest.ext.auth import token_required
from wifipumpkin3.core.servers.rest.ext.exceptions import exception
@ -28,12 +28,9 @@ class ProxysPluginsResource(Resource):
config = SettingsINI.getInstance()
key_name = "proxy_plugins"
def __init__(self):
self.root = PumpkinShell.getInstance()
super(ProxysPluginsResource, self).__init__()
@token_required
def get(self):
self.root = PumpkinShell.getInstance()
proxy_plugins = self.root.proxy_controller.getInfo(excluded=("Config"))
list_plugins = []
for item in proxy_plugins:
@ -48,10 +45,6 @@ class ProxiesInfoResource(Resource):
config = SettingsINI.getInstance()
key_name = "proxy_plugins"
def __init__(self):
self.root = PumpkinShell.getInstance()
super(ProxiesInfoResource, self).__init__()
@token_required
def get(self, proxy_name=None):
if proxy_name:
@ -62,6 +55,7 @@ class ProxiesInfoResource(Resource):
),
code=400,
)
self.root = PumpkinShell.getInstance()
proxy_plugins = self.root.proxy_controller.getInfo(excluded=("Config"))
for item in proxy_plugins:
proxy_plugins[item]["Activate"] = self.config.get(
@ -74,12 +68,9 @@ class ProxiesAllInfoResource(Resource):
config = SettingsINI.getInstance()
key_name = "proxy_plugins"
def __init__(self):
self.root = PumpkinShell.getInstance()
super(ProxiesAllInfoResource, self).__init__()
@token_required
def get(self):
self.root = PumpkinShell.getInstance()
proxy_plugins = self.root.proxy_controller.getInfo(excluded=("Config"))
for item in proxy_plugins:
proxy_plugins[item]["Activate"] = self.config.get(

View File

@ -36,11 +36,12 @@ def token_required(f):
try:
app_secret_key = conf.get("rest_api_settings", "SECRET_KEY")
data = jwt.decode(token, app_secret_key)
data = jwt.decode(token, app_secret_key, algorithms=["HS256"])
app_public_id = conf.get("rest_api_settings", "public_id")
if app_public_id != data["public_id"]:
return make_response(jsonify({"message": "Token is invalid!"}), 401)
except:
except Exception as e:
print(e)
return make_response(jsonify({"message": "Token is invalid!"}), 401)
return f(*args, **kwargs)