From 85740e6209d2573e5e170fcdf02da41ba3aaf77a Mon Sep 17 00:00:00 2001 From: Philipp Lehnet <80537345+truejp@users.noreply.github.com> Date: Fri, 13 Sep 2024 12:33:20 +0200 Subject: [PATCH] v0.1 upload of statping tool Added web ui with management functions + scripts for: - Linux x86_64 - Linux on ARM - MacOS x86_64 - MacOS on ARM - Windows x86_64 - Windows on ARM --- .gitignore | 1 + readme.md | 36 ++ statping-api-adapter/api/checker.php | 42 ++ statping-api-adapter/api/collector.php | 49 ++ statping-api-adapter/api/dl_proxy.php | 35 ++ .../api/generate-deployments.php | 540 ++++++++++++++++++ statping-api-adapter/api/status.php | 51 ++ statping-api-adapter/config.php | 33 ++ statping-api-adapter/index.php | 339 +++++++++++ 9 files changed, 1126 insertions(+) create mode 100644 .gitignore create mode 100644 readme.md create mode 100644 statping-api-adapter/api/checker.php create mode 100644 statping-api-adapter/api/collector.php create mode 100644 statping-api-adapter/api/dl_proxy.php create mode 100644 statping-api-adapter/api/generate-deployments.php create mode 100644 statping-api-adapter/api/status.php create mode 100644 statping-api-adapter/config.php create mode 100644 statping-api-adapter/index.php diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..496ee2c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.DS_Store \ No newline at end of file diff --git a/readme.md b/readme.md new file mode 100644 index 0000000..033aa5f --- /dev/null +++ b/readme.md @@ -0,0 +1,36 @@ +# Simple Statping NAT Gateway Adapter + +This repository contains a simple PHP Web Application that allows you to generate and deploy status scripts for the major OS plattforms. This will allow you to keep an eye on the basic online status of your hosts, even if they are located behind a private NAT gateway, don't have their own public IP address or if they are not running any web service. + +## Deployment +Just copy the contents of the folder "statping-api-adapter" to a directory on a webserver or shared webhosting of your choice. As long as PHP is enabled and the scripts are allowed to access your local files, you should be good to go. + +## How to use +1. Modify the tokens in the config.php file (VERY IMPORTANT) +2. Copy the contents to your webserver +3. Open the folder / the file index.php on your webserver. +4. Press the button to generate all deployment scripts +5. Copy the instructions for your OS and execut them in your shell + +## Live Demo + +You can see the tool in action over here: https://pixel-shift.de/statping-service/ +The status-export is used in this website: https://pixel-shift.de/status.html + +## Statping Setup + +Now that you have deployed your server to statping, you can add a new target in statping to make use of the newly created link. Copy the URL from the statping section of your index.php and add the device name to it, that you configured during deployment. You can also get the statping URL by opening accessing the manager script on your host. It will show you the correct URL on your shell output. + +## Security concerns + +The WebApp does not implement any sophisticated security mechanisms due to the (possibly) low severity of data leaks. This web app makes use of three different tokens: + +- api token (to authenticate deployments) +- download token (to download deployment scripts) +- statping token (optional) + +By default, the deployments folder and storage folders are autogenerated with permissions 0700, meaning that only the server itself has full privilges. Users requesting access to the files directly cannot get the deployment scripts or settings. This will not work on Windows Servers, in this case you would have to adjust the permissions manually after generation. + +To improve privacy, there are two settings. First of all, you can disable the debug mode. This will prevent the database export at the bottom of the index page. In addition to that, you can enable the privacy mode. While the privacy mode is active, you cannot change any of the settings until you enter the download token from the settings on the website. This also means that unauthenticated users cannot see any of the specifics. + +One final warning: this whole thing is based on security through obfuscation. If you are interested in establishing an actual production ready monitoring system for your private or public infrastructure, shoot us a message at info@pixel-shift.de or on www.pixel-shift.de. \ No newline at end of file diff --git a/statping-api-adapter/api/checker.php b/statping-api-adapter/api/checker.php new file mode 100644 index 0000000..d7afef4 --- /dev/null +++ b/statping-api-adapter/api/checker.php @@ -0,0 +1,42 @@ + $logData[$device], + 'device' => $device, + 'online' => true, + ]; + header('Content-Type: application/json'); + echo json_encode($response); +} else { + http_response_code(404); # Not Found - 404 will indicate inavailability of the device to statping + echo 'Device not found or offline.'; +} +?> diff --git a/statping-api-adapter/api/collector.php b/statping-api-adapter/api/collector.php new file mode 100644 index 0000000..0f532f6 --- /dev/null +++ b/statping-api-adapter/api/collector.php @@ -0,0 +1,49 @@ + $value) { + if ($value < $oneDayAgo) { + unset($logData[$key]); + } +} + +# Write the updated data back to the file +file_put_contents($file, json_encode($logData)); + +echo 'Device logged successfully.'; +?> \ No newline at end of file diff --git a/statping-api-adapter/api/dl_proxy.php b/statping-api-adapter/api/dl_proxy.php new file mode 100644 index 0000000..046b318 --- /dev/null +++ b/statping-api-adapter/api/dl_proxy.php @@ -0,0 +1,35 @@ + diff --git a/statping-api-adapter/api/generate-deployments.php b/statping-api-adapter/api/generate-deployments.php new file mode 100644 index 0000000..53693f8 --- /dev/null +++ b/statping-api-adapter/api/generate-deployments.php @@ -0,0 +1,540 @@ + "\$STATE_FILE" + echo "Device name set to: \$device_name" + register_cron_job + else + echo "Invalid device name. Please provide a valid device name." + fi +} + +# Function to check if a job is already registered in crontab +check_existing_cron_job() { + DEVICE_NAME=\$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + crontab -l | grep -q "\$DEVICE_NAME" + if [ \$? -eq 0 ]; then + echo -e "The device monitoring job for '\e[32m\$DEVICE_NAME\e[0m' is registered in crontab." + else + echo -e "The device monitoring job for '\e[91m\$DEVICE_NAME\e[0m' is not registered in crontab." + fi + fi +} + +# Function to remove the cron job associated with the device +remove_cron_job() { + DEVICE_NAME=\$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + crontab -l | grep -v "\$DEVICE_NAME" | crontab - + echo -e "Monitoring for '\e[91m\$DEVICE_NAME\e[0m' has been disabled." + else + echo "No device name found to disable monitoring." + fi +} + +# Function to re-enable monitoring +re_enable_monitoring() { + remove_cron_job + DEVICE_NAME=\$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + register_cron_job + echo -e "Monitoring for '\e[32m\$DEVICE_NAME\e[0m' has been re-enabled." + else + echo "No device name found to re-enable monitoring." + fi +} + +# Function to register a cron job for the device +register_cron_job() { + DEVICE_NAME=\$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + (crontab -l 2>/dev/null; echo "* * * * * /usr/bin/curl -I -s -o /dev/null \"\$BASE_URL\$DEVICE_NAME\"") | crontab - + echo -e "Monitoring for '\e[32m\$DEVICE_NAME\e[0m' has been registered." + else + echo "No device name found to register monitoring." + fi +} + +# Function to uninstall the tool +uninstall_tool() { + echo "Uninstalling the tool..." + remove_cron_job + rm -f "\$STATE_FILE" + echo "Tool uninstalled. All associated cron jobs and the config file have been removed." + exit 0 +} + +# Main script logic +check_existing_job + +if [ ! -f "\$STATE_FILE" ]; then + echo -e "\e[1mLifecycle Ping Script v0.1 - Philipp Lehnet, 2024\e[0m" + echo "---------------------" + read -p "Enter the device name to monitor: " device_name + set_device_name "\$device_name" +fi + +echo "All operations executed. Have a nice day!" +EOT; +# Write the script to the file +file_put_contents($ubuntu_script_path, $script_content); + +# Adjust r+w permissions +chmod($ubuntu_script_path, 0700); +echo "The script 'manager-ubuntu.sh' has been created in the 'deployment' directory.\n"; + + +#################### +# Manager Script MacOS +# MacOS +#################### + +$macos_script_path = $deployment_dir . '/' . $macos_manager_script; +# MacOS Manager Script Template +$script_content = << "\$STATE_FILE" + echo "Device name set to: \$device_name" + register_cron_job + else + echo "Invalid device name. Please provide a valid device name." + fi +} + +# Function to check if a job is already registered in crontab +check_existing_cron_job() { + DEVICE_NAME=$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + crontab -l | grep -q "\$DEVICE_NAME" + if [ $? -eq 0 ]; then + echo -e "The device monitoring job for '\033[32m\$DEVICE_NAME\033[0m' is registered in crontab." + else + echo -e "The device monitoring job for '\033[91m\$DEVICE_NAME\033[0m' is not registered in crontab." + fi + fi +} + +# Function to remove the cron job associated with the device +remove_cron_job() { + DEVICE_NAME=$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + (crontab -l | grep -v "\$DEVICE_NAME") | crontab - + echo -e "Monitoring for '\033[91m\$DEVICE_NAME\033[0m' has been disabled." + else + echo "No device name found to disable monitoring." + fi +} + +# Function to re-enable monitoring +re_enable_monitoring() { + remove_cron_job + DEVICE_NAME=$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + register_cron_job + echo -e "Monitoring for '\033[32m\$DEVICE_NAME\033[0m' has been re-enabled." + else + echo "No device name found to re-enable monitoring." + fi +} + +# Function to register a cron job for the device +register_cron_job() { + DEVICE_NAME=$(cat "\$STATE_FILE") + if [ -n "\$DEVICE_NAME" ]; then + (crontab -l 2>/dev/null; echo "* * * * * /usr/bin/curl -I -s -o /dev/null \"\$BASE_URL\$DEVICE_NAME\"") | crontab - + echo -e "Monitoring for '\033[32m\$DEVICE_NAME\033[0m' has been registered." + else + echo "No device name found to register monitoring." + fi +} + +# Function to uninstall the tool +uninstall_tool() { + echo "Uninstalling the tool..." + remove_cron_job + rm -f "\$STATE_FILE" + echo "Tool uninstalled. All associated cron jobs and the config file have been removed." + exit 0 +} + +# Main script logic +check_existing_job + +if [ ! -f "\$STATE_FILE" ]; then + echo -e "\033[1mLifecycle Ping Script v0.1 - Philipp Lehnet, 2024\033[0m" + echo "---------------------" + read -p "Enter the device name to monitor: " device_name + set_device_name "\$device_name" +fi + +echo "All operations executed. Have a nice day!" +EOT; +# Write the script to the file +file_put_contents($macos_script_path, $script_content); + +# Adjust r+w permissions +chmod($macos_script_path, 0700); +echo "The script 'manager-macos.sh' has been created in the 'deployment' directory.\n"; + + +#################### +# Windows Manager Script +# Windows (PowerShell) +#################### + +$windows_script_path = $deployment_dir . '/' . $windows_manager_script; +# Windows Manager Script Template - for now simple hello world +$script_content = <<\$null + Write-Host "Monitoring for '\$DEVICE_NAME' has been disabled." -ForegroundColor Red + } else { + Write-Host "No device name found to disable monitoring." -ForegroundColor Red + } +} + +# Function to re-enable monitoring +function Re-Enable-Monitoring { + Write-Host "Re-enabling monitoring..." -ForegroundColor Yellow + Remove-Cron-Job + \$DEVICE_NAME = Get-Content \$STATE_FILE + if (\$DEVICE_NAME) { + Register-Cron-Job + Write-Host "Monitoring for '\$DEVICE_NAME' has been re-enabled." -ForegroundColor Green + } else { + Write-Host "No device name found to re-enable monitoring." -ForegroundColor Red + } +} + +# Function to register a task for the device +function Register-Cron-Job { + Write-Host "Registering cron job..." -ForegroundColor Yellow + \$DEVICE_NAME = Get-Content \$STATE_FILE + if (\$DEVICE_NAME) { + \$action = New-ScheduledTaskAction -Execute "powershell.exe" -Argument "-Command `"Invoke-WebRequest -Uri '\$BASE_URL\$DEVICE_NAME'`"" + \$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date) -RepetitionInterval (New-TimeSpan -Minutes 1) + \$principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -LogonType ServiceAccount + \$settings = New-ScheduledTaskSettingsSet -AllowStartIfOnBatteries -DontStopIfGoingOnBatteries -StartWhenAvailable + Register-ScheduledTask -TaskName \$DEVICE_NAME -Action \$action -Trigger \$trigger -Principal \$principal -Settings \$settings + Write-Host "Monitoring for '\$DEVICE_NAME' has been registered." -ForegroundColor Green + } else { + Write-Host "No device name found to register monitoring." -ForegroundColor Red + } +} + +# Function to uninstall the tool +function Uninstall-Tool { + Write-Host "Uninstalling the tool..." -ForegroundColor Yellow + Remove-Cron-Job + Remove-Item -Path \$STATE_FILE -Force + Write-Host "Tool uninstalled. All associated tasks and the config file have been removed." + exit +} + +# Main script logic +if (-not (Test-Path \$STATE_FILE)) { + Write-Host "Lifecycle Ping Script v0.1 - Philipp Lehnet, 2024" -ForegroundColor Green + Write-Host "---------------------" + \$device_name = Read-Host "Enter the device name to monitor" + Set-Device-Name \$device_name +} else { + Check-Existing-Job +} + +Write-Host "All operations executed. Have a nice day!" +EOT; +# Write the script to the file +file_put_contents($windows_script_path, $script_content); + +# Adjust r+w permissions +chmod($windows_script_path, 0700); +echo "The script 'manager-windows.ps1' has been created in the 'deployment' directory.\n"; + +echo "Deployment scripts have been generated successfully.\n"; + +?> diff --git a/statping-api-adapter/api/status.php b/statping-api-adapter/api/status.php new file mode 100644 index 0000000..42b6878 --- /dev/null +++ b/statping-api-adapter/api/status.php @@ -0,0 +1,51 @@ +Invalid download token. Try again."; + } +} +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['lock_privacy'])) { + $_SESSION['privacy_unlocked'] = false; +} + +# Implement privacy mode + +$deployment_dir = __DIR__ . '/api/deployment'; +$storage_dir = __DIR__ . '/storage'; + + +$manager_script_ubuntu = $deployment_dir . '/manager-ubuntu.sh'; + +if ($privacy_mode && !$_SESSION['privacy_unlocked']) { + $dl_tk = 'YOUR_DOWNLOAD_TOKEN'; +} else { + $dl_tk = $downloadToken; +} + + + +$dl_proxy_url = 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['SCRIPT_NAME']) . '/api/dl_proxy.php?token=' . $dl_tk; +$statping_check_url = 'https://' . $_SERVER['HTTP_HOST'] . dirname($_SERVER['SCRIPT_NAME']) . '/api/checker.php?device='; + +# Deployment codes for different plattforms +# Currently supported: +# - Ubuntu Desktop +# - Ubuntu Server +# + + +# Define manager URLs +$ubuntu_url = $dl_proxy_url . '&fn=' . $ubuntu_manager_script; +$windows_url = $dl_proxy_url . '&fn=' . $windows_manager_script; +$macos_url = $dl_proxy_url . '&fn=' . $macos_manager_script; + +$deployment_commands_ubuntu_desktop = <<> ~/.bashrc +chmod +x ~/checkin-manager/checkin-manager.sh +checkin-manager +EOT; + +$deployment_commands_macos = << + + + + + + + Deployment Manager + + + + +'; + if (!$_SESSION['privacy_unlocked']) { ?> +
Privacy mode is enabled. Enter download token to unlock all features.
+
+ + + +
+ + +
Privacy mode is unlocked. You can now access all features.
+
+ +
+ '; +} + +if ($debug_mode): ?> +
+
Debug mode is enabled. You can view the device log below.
+
+ + +

Statping Reverse Shell Tool

+

This tool helps you to monitor your hosts in private networks and behind NAT Gateways with Statping.
+It generates the deployment scripts and instructions for you to deploy the monitoring script on your devices.
+The underlying principle is based on reverse SSH tunneling, where the devices will check in with the server to update their status.

+ + + +
Starting deployments manager...
+

Generating deployment scripts...

"; + include 'api/generate-deployments.php'; + echo "

Deployment scripts generated successfully.
"; +} + +# Handle the storage file generation +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['create_storage'])) { + + if ($privacy_mode && !$_SESSION['privacy_unlocked']) { + echo "
Error: Privacy mode is enabled. Unlock privacy mode to generate the storage file.
"; + echo "

Please reload this page.

"; + exit; + } + echo "
+    
Starting storage manager...
+

Wiping local storage...

"; + # Check if the storage directory exists + if (is_dir($storage_dir)) { + $files = glob($storage_dir . '/*'); + foreach ($files as $file) { + if (is_file($file)) { + unlink($file); + } + } + } + echo "

Generating local storage folder...

"; + # Check if the storage directory exists + if (!is_dir($storage_dir)) { + mkdir($storage_dir, 0700, true); + } + else { + echo "

The storage directory already exists.

"; + } + + echo "

Generating local storage file...

"; + $logData = []; + file_put_contents($storage_dir . '/' . $storage_file, json_encode($logData)); + + echo "
Local storage file generated successfully.
"; +} + +# Check if scripts were indeed generated +$all_scripts_exist = (file_exists('api/deployment/' . $ubuntu_manager_script) && file_exists('api/deployment/' . $windows_manager_script) && file_exists('api/deployment/' . $macos_manager_script)); +$storage_exists = file_exists($storage_dir) && file_exists($storage_dir . '/' . $storage_file); +?> + +
+ +
All required deployment scripts are available.
+ +
Error: One or more required deployment scripts are missing.
+ +
+ +
+ Storage folder and file exist.
'; + } else { + echo '
Error: Storage folder or file is missing.
'; + } + ?> + +
+ +
+ +
+ +
+ + +
+

Deployment Instructions

+

Use the following instructions to execute the local manager script on the host. With these scripts, you will be able to use the command line interface (CLI) to control if your clients are updating your proxy server.

+ +

Ubuntu 2x.xx (regular)

+
+ + +

Ubuntu (Single User alternative)

+
+ + +

macOS (Apple Silicon / x86_64)

+

If brew is not installed, you can install it by running the following commands:

+
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
+brew --version
+ +

This might take a while. Afterwards you might need to run some post-install steps, to add brew to your environment. The installer will tell you.
+ Then you can run the following commands to install the manager script:

+ +
+ + +

Windows

+
+ +

This script is using the MS Task Scheduler. It will ask you to become an administrator. Once it has been set up, there is no additional need for administrative privileges unless you want to update the settings.

+ +
+

Device Status

+ + + + + + + + + $timestamp) { + echo ""; + } + if (empty($logData)) { + echo ''; + } + ?> +
DeviceLast Check-inStatusStatping URL
$device" . date('Y-m-d H:i:s', $timestamp) . "" . ($currentTime - $timestamp <= 180 ? 'Online' : 'Offline') . "" . $statping_check_url . $device . "
No devices found.
+

Note: The device status is based on the last check-in time. Devices that have not checked in within the last 3 minutes are considered offline.

+ +
Debug mode is disabled. Enable it in the config file to view the device log.
+ + +
+ +

Written by: Pixel Shift / Philipp Lehnet

+ + + + + \ No newline at end of file