Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] Add cross site scripting #1676

Merged
Merged
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Demo database resets every hour. A lot of features are disabled for obvious reas
- Teamviewer-like remote desktop control
- Real-time remote shell
- Remote file browser (download and upload files)
- Remote command and script execution (batch, powershell and python scripts)
- Remote command and script execution (batch, powershell, python, nushell and deno scripts)
- Event log viewer
- Services management
- Windows patch management
Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/agents/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,6 +570,8 @@ def run_script(
},
"run_as_user": run_as_user,
"env_vars": parsed_env_vars,
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

if history_pk != 0:
Expand Down
4 changes: 4 additions & 0 deletions api/tacticalrmm/alerts/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -1429,6 +1429,8 @@ def test_alert_actions(
"run_as_user": False,
"env_vars": ["hello=world", "foo=bar"],
"id": AgentHistory.objects.last().pk, # type: ignore
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

nats_cmd.assert_called_with(data, timeout=30, wait=True)
Expand Down Expand Up @@ -1460,6 +1462,8 @@ def test_alert_actions(
"run_as_user": False,
"env_vars": ["resolved=action", "env=vars"],
"id": AgentHistory.objects.last().pk, # type: ignore
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

nats_cmd.assert_called_with(data, timeout=35, wait=True)
Expand Down
8 changes: 8 additions & 0 deletions api/tacticalrmm/apiv3/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,12 @@ def get_agent_config() -> AgentCheckInConfig:
*getattr(settings, "CHECKIN_SYNCMESH", (800, 1200))
),
limit_data=getattr(settings, "LIMIT_DATA", False),
install_nushell=getattr(settings, "INSTALL_NUSHELL", False),
install_nushell_version=getattr(settings, "INSTALL_NUSHELL_VERSION", ""),
install_nushell_url=getattr(settings, "INSTALL_NUSHELL_URL", ""),
nushell_enable_config=getattr(settings, "NUSHELL_ENABLE_CONFIG", False),
install_deno=getattr(settings, "INSTALL_DENO", False),
install_deno_version=getattr(settings, "INSTALL_DENO_VERSION", ""),
install_deno_url=getattr(settings, "INSTALL_DENO_URL", ""),
deno_default_permissions=getattr(settings, "DENO_DEFAULT_PERMISSIONS", ""),
)
3 changes: 3 additions & 0 deletions api/tacticalrmm/autotasks/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from django.utils import timezone as djangotime
from rest_framework import serializers
from django.conf import settings

from scripts.models import Script
from tacticalrmm.constants import TaskType
Expand Down Expand Up @@ -257,6 +258,8 @@ def get_task_actions(self, obj):
shell=script.shell,
env_vars=env_vars,
),
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}
)
if actions_to_remove:
Expand Down
13 changes: 10 additions & 3 deletions api/tacticalrmm/core/agent_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ agentBin="${agentBinPath}/${binName}"
agentConf='/etc/tacticalagent'
agentSvcName='tacticalagent.service'
agentSysD="/etc/systemd/system/${agentSvcName}"
agentDir='/opt/tacticalagent'
meshDir='/opt/tacticalmesh'
meshSystemBin="${meshDir}/meshagent"
meshSvcName='meshagent.service'
Expand All @@ -65,16 +66,20 @@ RemoveOldAgent() {
if [ -f "${agentSysD}" ]; then
systemctl disable ${agentSvcName}
systemctl stop ${agentSvcName}
rm -f ${agentSysD}
rm -f "${agentSysD}"
systemctl daemon-reload
fi

if [ -f "${agentConf}" ]; then
rm -f ${agentConf}
rm -f "${agentConf}"
fi

if [ -f "${agentBin}" ]; then
rm -f ${agentBin}
rm -f "${agentBin}"
fi

if [ -d "${agentDir}" ]; then
rm -rf "${agentDir}"
fi
}

Expand Down Expand Up @@ -134,6 +139,8 @@ Uninstall() {

if [ $# -ne 0 ] && [ $1 == 'uninstall' ]; then
Uninstall
# Remove the current script
rm "$0"
exit 0
fi

Expand Down
4 changes: 4 additions & 0 deletions api/tacticalrmm/scripts/tasks.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import asyncio

from django.conf import settings

from agents.models import Agent, AgentHistory
from scripts.models import Script
from tacticalrmm.celery import app
Expand Down Expand Up @@ -78,6 +80,8 @@ def bulk_script_task(
},
"run_as_user": run_as_user,
"env_vars": script.parse_script_env_vars(agent, script.shell, env_vars),
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}
tup = (agent.agent_id, data)
items.append(tup)
Expand Down
7 changes: 7 additions & 0 deletions api/tacticalrmm/scripts/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.views import APIView
from django.conf import settings

from agents.permissions import RunScriptPerms
from tacticalrmm.constants import ScriptShell, ScriptType
Expand Down Expand Up @@ -162,6 +163,8 @@
},
"run_as_user": request.data["run_as_user"],
"env_vars": parsed_env_vars,
"nushell_enable_config": settings.NUSHELL_ENABLE_CONFIG,
"deno_default_permissions": settings.DENO_DEFAULT_PERMISSIONS,
}

r = asyncio.run(
Expand Down Expand Up @@ -190,6 +193,10 @@
ext = ".py"
case ScriptShell.SHELL:
ext = ".sh"
case ScriptShell.NUSHELL:
ext = ".nu"
case ScriptShell.DENO:
ext = ".ts"

Check warning on line 199 in api/tacticalrmm/scripts/views.py

View check run for this annotation

Codecov / codecov/patch

api/tacticalrmm/scripts/views.py#L196-L199

Added lines #L196 - L199 were not covered by tests
case _:
ext = ""

Expand Down
2 changes: 2 additions & 0 deletions api/tacticalrmm/tacticalrmm/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ class ScriptShell(models.TextChoices):
CMD = "cmd", "Batch (CMD)"
PYTHON = "python", "Python"
SHELL = "shell", "Shell"
NUSHELL = "nushell", "Nushell"
DENO = "deno", "Deno"


class ScriptType(models.TextChoices):
Expand Down
43 changes: 43 additions & 0 deletions api/tacticalrmm/tacticalrmm/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,49 @@

NATS_SERVER_VER = "2.10.5"

# Install Nushell on the agent
# https://github.com/nushell/nushell
INSTALL_NUSHELL = False
# GitHub version to download. The file will be downloaded from GitHub, extracted and installed.
# Version to download. If INSTALL_NUSHELL_URL is not provided, the file will be downloaded from GitHub,
# extracted and installed.
INSTALL_NUSHELL_VERSION = ""
# URL to download directly. This is expected to be the direct URL, unauthenticated, uncompressed, ready to be installed.
# Use {OS}, {ARCH} and {VERSION} to specify the GOOS, GOARCH and INSTALL_NUSHELL_VERSION respectively.
# Windows: The ".exe" extension will be added automatically.
# Examples:
# https://examplle.com/download/nushell/{OS}/{ARCH}/{VERSION}/nu
# https://examplle.com/download/nushell/nu-{VERSION}-{OS}-{ARCH}
INSTALL_NUSHELL_URL = ""
# Enable Nushell config on the agent
# The default is to not enable the config because it could change how scripts run.
# However, disabling the config prevents plugins from being registered.
# https://github.com/nushell/nushell/issues/10754
# False: --no-config-file option is added to the command line.
# True: --config and --env-config options are added to the command line and point to the Agent's directory.
NUSHELL_ENABLE_CONFIG = False

# Install Deno on the agent
# https://github.com/denoland/deno
INSTALL_DENO = False
# Version to download. If INSTALL_DENO_URL is not provided, the file will be downloaded from GitHub,
# extracted and installed.
INSTALL_DENO_VERSION = ""
# URL to download directly. This is expected to be the direct URL, unauthenticated, uncompressed, ready to be installed.
# Use {OS}, {ARCH} and {VERSION} to specify the GOOS, GOARCH and INSTALL_DENO_VERSION respectively.
# Windows: The ".exe" extension will be added automatically.
# Examples:
# https://examplle.com/download/deno/{OS}/{ARCH}/{VERSION}/deno
# https://examplle.com/download/deno/deno-{VERSION}-{OS}-{ARCH}
INSTALL_DENO_URL = ""
# Default permissions for Deno
# Space separated list of permissions as listed in the documentation.
# https://docs.deno.com/runtime/manual/basics/permissions#permissions
# Examples:
# DENO_DEFAULT_PERMISSIONS = "--allow-sys --allow-net --allow-env"
# DENO_DEFAULT_PERMISSIONS = "--allow-all"
DENO_DEFAULT_PERMISSIONS = ""

# for the update script, bump when need to recreate venv
PIP_VER = "40"

Expand Down
8 changes: 8 additions & 0 deletions api/tacticalrmm/tacticalrmm/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,11 @@ class AgentCheckInConfig(TRMMStruct):
checkin_wmi: int
checkin_syncmesh: int
limit_data: bool
install_nushell: bool
install_nushell_version: str
install_nushell_url: str
nushell_enable_config: bool
install_deno: bool
install_deno_version: str
install_deno_url: str
deno_default_permissions: str