From 0f8d21aca777ed950f2209d71089d2d4561e6a9d Mon Sep 17 00:00:00 2001 From: mohamad khawam Date: Mon, 4 Mar 2024 14:13:37 -0500 Subject: [PATCH] continue --- src/db/db.ts | 1 - src/front/page/addComputer.ts | 6 +- .../password/change_password_windows.ts | 7 +- src/modules/util/commands.ts | 76 ++++++++------- src/modules/util/run_command.ts | 2 +- src/modules/util/ssh_utils.ts | 96 ++++++++++++++----- 6 files changed, 122 insertions(+), 66 deletions(-) diff --git a/src/db/db.ts b/src/db/db.ts index 3b119e9..bd312cd 100644 --- a/src/db/db.ts +++ b/src/db/db.ts @@ -131,7 +131,6 @@ class DataBase { if (!fs.existsSync(this.filePath)) { // If not, create the muffins folder fs.mkdirSync(this.filePath); - ``; } else { // If muffins path exists, check if it's a directory const stats = fs.statSync(this.filePath); diff --git a/src/front/page/addComputer.ts b/src/front/page/addComputer.ts index e9c5c75..a88b8a2 100644 --- a/src/front/page/addComputer.ts +++ b/src/front/page/addComputer.ts @@ -31,9 +31,9 @@ const addComputer = async function () { }, ]); await trySSH(); - async function trySSH() { + async function trySSH(): Promise { var computer_info = await scanSSH(ip, user, pass); - + // console.log(computer_info); let success = false; if (typeof computer_info == "object") { await runningDB.addTargetAndUser(computer_info.hostname, ip, user, pass, computer_info.operatingSystem, computer_info.domain); @@ -52,7 +52,7 @@ const addComputer = async function () { }, ]); if (confirm) { - await trySSH(); + return await trySSH(); } } diff --git a/src/modules/password/change_password_windows.ts b/src/modules/password/change_password_windows.ts index c9f86f8..b22a5f4 100644 --- a/src/modules/password/change_password_windows.ts +++ b/src/modules/password/change_password_windows.ts @@ -128,15 +128,10 @@ type check_report = { forceNetUser: boolean; }; async function check(conn: SSH2CONN): Promise { - var passed = 2; + var passed = 1; var forceNetUser = false; conn.log("Running Checks"); - let os_check = await conn.exec("echo %OS%"); - if (os_check.trim() != "Windows_NT") { - conn.error(`Windows check error GOT ${os_check} WANTED Windows_NT, Please check for environment vars`); - passed--; - } let get_local_check; try { diff --git a/src/modules/util/commands.ts b/src/modules/util/commands.ts index 68f8914..31718e5 100644 --- a/src/modules/util/commands.ts +++ b/src/modules/util/commands.ts @@ -14,40 +14,52 @@ const commands = { step_2: (ch_pass_string: string) => `echo '${ch_pass_string}' | chpasswd -e`, step_3: (sudo_pass: string, ch_pass_string: string) => `echo -e '${sudo_pass}\n${ch_pass_string}' | sudo -S chpasswd -e`, shadow: { - cat_shadow_file:"cat /etc/shadow", + cat_shadow_file: "cat /etc/shadow", copy_shadow_file: "cp /etc/shadow /etc/shadow.copy", revert_shadow_file: "cp /etc/shadow.copy /etc/shadow", del_shadow_copy_file: "rm /etc/shadow.copy", - } + }, + }, + sunos: { + step_1: (username: string, ch_pass_string: string) => `sudo sed -i 's/\\(${username}:\\)[^:]\+/\\1${ch_pass_string}/' /etc/shadow`, }, - sunos:{ - step_1: (username:string, ch_pass_string:string) => `sudo sed -i 's/\\(${username}:\\)[^:]\+/\\1${ch_pass_string}/' /etc/shadow` - } }, - // the first escape for for node the second is for the target. + // the first escape for for node the second is for the target. ssh: { eject: { - windows_cmd: (ssh_key:string)=> `echo ${ssh_key} >> %ALLUSERSPROFILE%\\ssh\\administrators_authorized_keys ; icacls.exe %ALLUSERSPROFILE%\\ssh\\administrators_authorized_keys /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"`, + windows_cmd: (ssh_key: string) => + `echo ${ssh_key} >> %ALLUSERSPROFILE%\\ssh\\administrators_authorized_keys ; icacls.exe %ALLUSERSPROFILE%\\ssh\\administrators_authorized_keys /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"`, windows: (ssh_key: string) => `powershell.exe "Add-Content -Force -Path $env:ALLUSERSPROFILE\\ssh\\administrators_authorized_keys -Value '${ssh_key}';icacls.exe \\"$env:ALLUSERSPROFILE\\ssh\\administrators_authorized_keys\\" /inheritance:r /grant \\"Administrators:F\\" /grant \\"SYSTEM:F\\""`, linux: (ssh_key: string) => `mkdir -p ~/.ssh && echo "${ssh_key}" | cat >> ~/.ssh/authorized_keys`, sunos: (ssh_key: string) => `mkdir -p $HOME/.ssh && echo "${ssh_key}" | cat >> $HOME/.ssh/authorized_keys`, - + home: { + windows_cmd: (ssh_key: string) => `(mkdir "%USERPROFILE%\\.ssh" 2> NUL) & echo ${ssh_key} >> %USERPROFILE%\\.ssh\\authorized_keys`, + windows: (ssh_key: string) => `powershell.exe "Add-Content -Force -Path $env:USERPROFILE\\.ssh\\authorized_keys -Value '${ssh_key}'`, + }, }, remove: { - windows_cmd: (ssh_key:string) =>`findstr /v "${ssh_key}" %ProgramData%\\ssh\\administrators_authorized_keys > %ProgramData%\\ssh\\administrators_authorized_keys.tmp && move /y %ProgramData%\\ssh\\administrators_authorized_keys.tmp %ProgramData%\\ssh\\administrators_authorized_keys`, + windows_cmd: (ssh_key: string) => + `findstr /v "${ssh_key}" %ProgramData%\\ssh\\administrators_authorized_keys > %ProgramData%\\ssh\\administrators_authorized_keys.tmp && move /y %ProgramData%\\ssh\\administrators_authorized_keys.tmp %ProgramData%\\ssh\\administrators_authorized_keys`, windows: (ssh_key: string) => `powershell.exe -command \"$keyToRemove = \\"${ssh_key}\\";$authorizedKeysPath = Join-Path $env:ProgramData \\"ssh\\administrators_authorized_keys\\"; $authorizedKeysContent = Get-Content -Path $authorizedKeysPath; $authorizedKeysContent = $authorizedKeysContent -notmatch [regex]::Escape($keyToRemove); $authorizedKeysContent | Set-Content -Path $authorizedKeysPath; icacls.exe $authorizedKeysPath /inheritance:r /grant \\"Administrators:F\\" /grantclear \\"SYSTEM:F\\"; Write-Host \\"SSH key removal complete.\\"\"`, linux: (ssh_key: string) => `ssh_key="${replaceAll(ssh_key, "/", "\\/")}" && sed -i "s/$ssh_key//g" ~/.ssh/authorized_keys`, sunos: (ssh_key: string) => `ssh_key="${replaceAll(ssh_key, "/", "\\/")}" && perl -ne '/$ssh_key/g' $HOME/.ssh/authorized_keys`, freebsd: (ssh_key: string) => `setenv ssh_key "${replaceAll(ssh_key, "/", "\\/")}" && sed -i "" "s/$ssh_key//g" ~/.ssh/authorized_keys`, }, + echo: { windows_cmd: "type %ProgramData%\\ssh\\administrators_authorized_keys", windows: `powershell.exe "cat \\"$env:ProgramData\\ssh\\administrators_authorized_keys\\""`, linux: "cat ~/.ssh/authorized_keys", sunos: "cat $HOME/.ssh/authorized_keys", - + }, + }, + windows_util: { + shell_type: "(dir 2>&1 *`|echo CMD);&<# rem #>echo PowerShell", + openSSH: { + cmd: "if exist %ProgramData%\\ssh (echo Exist)", + ps: `if (Test-Path -path "$env:ALLUSERSPROFILE\\ssh") { Write-Host "Exist"}`, }, }, detect: { @@ -59,7 +71,7 @@ const commands = { current: { windows: "query user", linux: "who -a --ips --lookup -H", - sunos:"who -a", + sunos: "who -a", freebsd: "who -HumT", }, windows: `wmic.exe useraccount get name,sid,disabled,domain,fullname,status,passwordexpires,passwordrequired,description`, @@ -67,14 +79,14 @@ const commands = { darwin: 'dscl . list /Users | grep -v "^_"', parsing: { linux: `cat /etc/passwd | awk -F: '{print $1 " " $3 " " $4 " " $6 " " $5}'`, - windows: `wmic useraccount get name,sid,domain,description,Caption /format:csv` - } + windows: `wmic useraccount get name,sid,domain,description,Caption /format:csv`, + }, }, network: { ports: { linux: { step_1: `netstat -tuan | grep "LISTEN"|awk '/^tcp/ {print "TCP", $4} /^udp/ {print "UDP", $4}'`, - step_2: `ss -tuan | grep "LISTEN" | awk '/^tcp/ {print "TCP", $5} /^udp/ {print "UDP", $5}'` + step_2: `ss -tuan | grep "LISTEN" | awk '/^tcp/ {print "TCP", $5} /^udp/ {print "UDP", $5}'`, }, freebsd: `netstat -an | grep "LISTEN"|awk '/^tcp/ {print "TCP", $4} /^udp/ {print "UDP", $4}'`, windows: `powershell.exe "Get-NetTCPConnection | Where-Object { $_.State -eq 'Listen' } | ForEach-Object {$($_.LocalPort)}"`, @@ -82,30 +94,29 @@ const commands = { windows: `powershell.exe "Get-NetTCPConnection | Where-Object { $_.State -eq 'Established' }"`, linux: { step_1: `netstat -an | grep "ESTABLISHED"`, - step_2: `ss -tan | grep ESTAB` + step_2: `ss -tan | grep ESTAB`, }, }, processes: { - installed:{ - windows:{ - step_1:`powershell.exe "Get-ItemProperty HKLM:/Software/Microsoft/Windows/CurrentVersion/Uninstall/*, HKLM:/Software/Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall/*, HKCU:/Software/Microsoft/Windows/CurrentVersion/Uninstall/* |Select-Object DisplayName, Publisher, InstallDate | Format-Table -AutoSize"`, - step_2: `powershell.exe "Get-ItemProperty HKLM:/Software/Microsoft/Windows/CurrentVersion/Uninstall/*, HKLM:/Software/Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall/* |Select-Object DisplayName, Publisher, InstallDate | Format-Table -AutoSize"` + installed: { + windows: { + step_1: `powershell.exe "Get-ItemProperty HKLM:/Software/Microsoft/Windows/CurrentVersion/Uninstall/*, HKLM:/Software/Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall/*, HKCU:/Software/Microsoft/Windows/CurrentVersion/Uninstall/* |Select-Object DisplayName, Publisher, InstallDate | Format-Table -AutoSize"`, + step_2: `powershell.exe "Get-ItemProperty HKLM:/Software/Microsoft/Windows/CurrentVersion/Uninstall/*, HKLM:/Software/Wow6432Node/Microsoft/Windows/CurrentVersion/Uninstall/* |Select-Object DisplayName, Publisher, InstallDate | Format-Table -AutoSize"`, }, linux: { - step_1:`for x in $(ls -1t /var/log/dpkg.log*); do zcat -f $x |tac |grep -e " install " -e " upgrade "; done |awk -F ":a" '{print $1}'`, - step_2:`rpm -qa --qf '%{INSTALLTIME} %{NAME}\n' | sort -n` + step_1: `for x in $(ls -1t /var/log/dpkg.log*); do zcat -f $x |tac |grep -e " install " -e " upgrade "; done |awk -F ":a" '{print $1}'`, + step_2: `rpm -qa --qf '%{INSTALLTIME} %{NAME}\n' | sort -n`, }, freebsd: { step_1: `pkg info`, - step_2: 'pkg_info' + step_2: "pkg_info", }, - sunos: "pkginfo" - + sunos: "pkginfo", }, windows: "powershell.exe Get-Process", linux: "ps -aux --forest", freebsd: "ps aux", - sunos: "ps -Ajd" + sunos: "ps -Ajd", }, failedLogins: { linux: `grep "Failed password" /var/log/auth.log`, @@ -113,22 +124,21 @@ const commands = { windows: `powershell.exe "Get-WinEvent -FilterHashTable @{LogName='Security'; ID=4625} | Format-Table TimeCreated, Message -AutoSize"`, darwin: `log show --predicate 'eventMessage contains "failed"'`, }, - variables:{ + variables: { linux: `printenv`, windows: "set", freebsd: "env", - sunos:"env" + sunos: "env", }, - AD:{ + AD: { check: `powershell.exe -Command "& {Get-ADDefaultDomainPasswordPolicy}"`, - domain: `systeminfo | findstr /B "Domain"` + domain: `systeminfo | findstr /B "Domain"`, }, os_info: { - windows:"systeminfo.exe /FO csv", + windows: "systeminfo.exe /FO csv", linux: "uname -osnpr | awk '{print $2, $1, $3, $4}'", - linux_name: "uname -v" - } - + linux_name: "uname -v", + }, }; export { commands }; diff --git a/src/modules/util/run_command.ts b/src/modules/util/run_command.ts index daaeb34..14ba175 100644 --- a/src/modules/util/run_command.ts +++ b/src/modules/util/run_command.ts @@ -34,7 +34,7 @@ async function runCommandNotExpect(conn: SSH2CONN, command: string, not_expected } return true; } catch (error: any) { - if (error.trim().toLowerCase().includes(not_expected)) { + if (error.toString().trim().toLowerCase().includes(not_expected)) { return typeof error === "string" ? replaceAll(error, "\n", " ") : replaceAll(error.message, "\n", " "); } return true; diff --git a/src/modules/util/ssh_utils.ts b/src/modules/util/ssh_utils.ts index f18c565..9f39235 100644 --- a/src/modules/util/ssh_utils.ts +++ b/src/modules/util/ssh_utils.ts @@ -99,6 +99,7 @@ async function makeConnection(user: User, timeout = 3000, retryCount = 5, retryD // Note remove permanent connection //NOTE : MAKE PUBLIC KEY OUTPUT +//NOTE: remove ssh check for windows bitvise due to bitvise having a different ways it handles ssh keys async function removeSSHkey(conn: SSH2CONN, os_type: options): Promise { const ssh_key = await runningDB.getPublicSSHKey(); @@ -157,14 +158,14 @@ async function removeSSHkey(conn: SSH2CONN, os_type: options): Promise break; } conn.log("Removed SSH Key"); - return !(await testSSH(conn)); + return !(await testSSHKey(conn)); } /** * * @param conn * @returns Should return true if it can connect using the public key */ -async function testSSH(conn: SSH2CONN) { +async function testSSHKey(conn: SSH2CONN) { try { conn.info("Testing SSH Private Key"); const sshConfig: SSHConfig = { @@ -226,15 +227,18 @@ async function testPassword(conn: SSH2CONN, password: string) { //should check for ssh key in the folder, if it doesn't exist inject it. //will try to ssh using the key, if it cant it will eject one more time //TO DO DARWIN +//TO DO Move Windows Functions to another another function async function injectSSHkey(conn: SSH2CONN, os_type: options, force?: undefined | boolean, trials: number = 0): Promise { - if (trials > 1) { - return false; - } + if (os_type === "windows") return await injectSSHKeyWindows(conn); + if (trials > 1) return false; + const ssh_key = await runningDB.getPublicSSHKey(); if (force) { await injectKey(); return await test(); } + + // Tests if ssh key is already on target computer switch (os_type) { case "linux": var ssh_keys = await getOutput(conn, commands.ssh.echo.linux); @@ -256,18 +260,18 @@ async function injectSSHkey(conn: SSH2CONN, os_type: options, force?: undefined break; case "darwin": break; - case "windows": - var ssh_keys = await getOutput(conn, commands.ssh.echo.windows); - if (ssh_keys.includes("Timed")) { - conn.warn( - "Using CMD to inject make sure %ProgramData%\\ssh\\administrators_authorized_keys Exists, We are unable to detect completion" - ); - return await injectSSHKeyWindowsCMD(conn, "windows"); - } - if (ssh_keys.includes(ssh_key)) { - return await test(); - } - break; + // case "windows": + // var ssh_keys = await getOutput(conn, commands.ssh.echo.windows); + // if (ssh_keys.includes("Timed")) { + // conn.warn( + // "Using CMD to inject make sure %ProgramData%\\ssh\\administrators_authorized_keys Exists, We are unable to detect completion" + // ); + // return await injectSSHKeyWindowsCMD(conn, "windows"); + // } + // if (ssh_keys.includes(ssh_key)) { + // return await test(); + // } + // break; } conn.log("Ejecting SSH Key"); await injectKey(); @@ -276,7 +280,7 @@ async function injectSSHkey(conn: SSH2CONN, os_type: options, force?: undefined // Tries to connect to the ssh with the private key async function test() { try { - let result = await testSSH(conn); + let result = await testSSHKey(conn); if (result) return true; else { trials = trials + 1; @@ -289,9 +293,9 @@ async function injectSSHkey(conn: SSH2CONN, os_type: options, force?: undefined } async function injectKey() { switch (os_type) { - case "windows": - await runCommandNoExpect(conn, commands.ssh.eject.windows(ssh_key)); - break; + // case "windows": + // await runCommandNoExpect(conn, commands.ssh.eject.windows(ssh_key)); + // break; case "sunos": await runCommandNoExpect(conn, commands.ssh.eject.sunos(ssh_key)); break; @@ -303,6 +307,54 @@ async function injectSSHkey(conn: SSH2CONN, os_type: options, force?: undefined } } } +async function injectSSHKeyWindows(conn: SSH2CONN): Promise { + const ssh_key = await runningDB.getPublicSSHKey(); + + let shell_type_output = await getOutput(conn, commands.windows_util.shell_type); + let shell_type = shell_type_output.includes("CMD") ? "CMD" : "Powershell"; + conn.log("SSH Key Inject with " + shell_type); + let openSshExistOutput = await getOutput(conn, shell_type == "CMD" ? commands.windows_util.openSSH.cmd : commands.windows_util.openSSH.ps); + let openSSHExist = openSshExistOutput.includes("Exist"); + + if (openSSHExist) { + var ssh_keys = await getOutput(conn, commands.ssh.echo.windows); + if (ssh_keys.includes(ssh_key)) { + return await test(); + } + } + + await inject(); + return await test(); + + async function test(trails = 0): Promise { + if (trails > 2) return false; + + try { + let result = await testSSHKey(conn); + if (result) return true; + else { + await inject(); + trails = trails + 1; + return await test(trails); + } + } catch (error) { + await inject(); + trails = trails + 1; + return await test(trails); + } + } + async function inject() { + if (openSSHExist) { + await runCommandNoExpect(conn, commands.ssh.eject.windows(ssh_key)); + } else { + //BitVise Requires use of authorized_keys + await runCommandNoExpect( + conn, + shell_type == "CMD" ? commands.ssh.eject.home.windows_cmd(ssh_key) : commands.ssh.eject.home.windows(ssh_key) + ); + } + } +} async function injectSSHKeyWindowsCMD(conn: SSH2CONN, os_type: options, force?: undefined | boolean, trials: number = 0): Promise { if (trials > 1) { @@ -326,7 +378,7 @@ async function injectSSHKeyWindowsCMD(conn: SSH2CONN, os_type: options, force?: async function test() { try { - let result = await testSSH(conn); + let result = await testSSHKey(conn); if (result) return true; else { trials = trials + 1;