TILLSHIELD · ENDPOINTS

Your hosts, on the same stream.

Beta

The TillTell agent reports what happens on your Linux, macOS and Windows hosts: processes started, sign-ins, privilege use, new accounts and admins, persistence, SSH keys, kernel modules, listening ports, cleared logs and defences turned off. Those events join the security stream every Till product writes, so TillTell rules, TillHunt, incidents and the coverage map read them like any other source. It runs in user mode on each OS’s own event sources, with no kernel driver. From TillShield you can end a process on a host or cut the host off the network. Manage hosts under Shield → Endpoints.

01Install

One command per host

Not yet downloadable
The first signed release of the agent is not published yet, so the commands below return an error until it is. Enrolment tokens you make now work once it is out.

Make an enrolment token under Shield → Endpoints, then on each host run, as root:

sh
curl -fsSL https://tilldev.dev/downloads/tell-agent/install.sh | sudo sh

On Windows, in PowerShell run as Administrator:

powershell
irm https://tilldev.dev/downloads/tell-agent/install.ps1 | iex

The installer:

  1. Picks this host’s build: Linux, macOS or Windows, on x86-64 or ARM64.
  2. Checks the release’s signed checksum list against the release key built into the installer, then the binary against that list. If either check fails it installs nothing.
  3. Installs the agent to /usr/local/bin or Program Files\TillTell, asks for the token without echoing it, enrols the host and starts the service.
  4. Prints the host key’s fingerprint, which you compare when you approve the host.

Running it again upgrades the agent and keeps the enrolment. Linux and macOS need curl and ssh-keygen. Windows needs ssh-keygen too, from the OpenSSH Client optional feature. TELL_AGENT_VERSION pins a version and, on Linux and macOS, TELL_AGENT_DIR installs somewhere else.

Without a prompt

For images and configuration management, give the token in a file instead:

sh
# Linux and macOS: the token in a file only root can read
curl -fsSL https://tilldev.dev/downloads/tell-agent/install.sh -o install.sh
sudo TELL_ENROLL_TOKEN_FILE=/root/tell-token sh install.sh

# Windows, elevated PowerShell
$env:TELL_ENROLL_TOKEN_FILE = 'C:\secure\tell-token'
irm https://tilldev.dev/downloads/tell-agent/install.ps1 | iex

TELL_ENROLL_TOKEN works too, but a variable can leak into process listings and logs where a file does not.

Checking a release by hand

The same checks the installer makes, for a host where you place the binary yourself. Each release lists its six builds in SHA256SUMS, signed with the release key:

sh
v=$(curl -fsSL https://tilldev.dev/downloads/tell-agent/LATEST)
f=tell-agent_${v}_linux_amd64
curl -fsSLO https://tilldev.dev/downloads/tell-agent/allowed_signers
curl -fsSLO https://tilldev.dev/downloads/tell-agent/$v/SHA256SUMS
curl -fsSLO https://tilldev.dev/downloads/tell-agent/$v/SHA256SUMS.sig
curl -fsSLO https://tilldev.dev/downloads/tell-agent/$v/$f
ssh-keygen -Y verify -f allowed_signers -I releases@tilldev.dev -n tell-agent-release -s SHA256SUMS.sig < SHA256SUMS
grep " $f\$" SHA256SUMS | sha256sum -c -

On macOS, use shasum -a 256 -c - for the last line.

02Enrol

Tokens and approval

A host enrols with a single-purpose enrolment token. On first enrolment it makes its own Ed25519 key, which never leaves the host, and every later request is signed with it. The server takes the workspace and host from that key, never from what an event claims.

Token settingMeans
Shown onceOnly a short hint of it is kept. Lose it and make another.
Expiry1 to 365 days; 30 by default.
Hosts it can enrolUnlimited, or 1 to 100,000.
ApprovalBy a person by default. A token made to approve on its own adds hosts that report straight away.
Live tokensUp to 50 per workspace.

A host enrolled with a token that needs approval waits under Shield → Endpoints. It keeps collecting into its local spool and sends nothing until an owner or admin types the fingerprint the host printed. A fingerprint that doesn’t match is refused, so get it from the host itself:

sh
sudo tell-agent enroll --token -      # paste the token; it is read from stdin
sudo tell-agent install                # register and start the service
sudo tell-agent fingerprint            # compare this before approving the host
sudo tell-agent check                  # permissions, enrolment, a signed session, clock, service, collectors
sudo tell-agent status                 # what the running agent last reported

Automatic approval suits machines you build yourself. Anyone holding such a token can add a host, so give it a host limit and a short expiry. Revoking a token stops it enrolling more hosts. Hosts it already enrolled keep reporting. The same steps run from the CLI: tilldev shield endpoints tokens create, tilldev shield endpoints approve.

03Collectors

What each OS reports

EventLinuxmacOSWindows
host.process_startedEvery process, from the kernel’s process connectorEndpoint Security when entitled; otherwise a 2-second poll, shown degradedSysmon event 1 when Sysmon is installed; otherwise Security 4688
host.login, host.login_failedSSH and console, from journald or the auth logSSH, console and Screen Sharing; failed local password checks with Endpoint SecuritySecurity 4624 and 4625, with logon type and source address
host.privilege_usedsudo and susudo and su—
host.user_created, host.user_deletedAccounts file pollDirectory Services poll, or Endpoint SecuritySecurity 4720 and 4726
host.group_member_addedGroup file poll; admin-equivalent groups flaggedDirectory Services; admin and wheel flaggedSecurity 4728, 4732 and 4756; administrator-equivalent groups flagged
host.group_member_removedGroup file pollDirectory Services poll—
host.persistence_added, host.persistence_changedsystemd units, cron and at, rc.local, init scripts, ld.so.preload, shell profiles, autostartLaunch daemons and agents, background items, startup items, cron, at and periodic jobs, shell profilesStartup folders, scheduled tasks, Run and RunOnce keys, services installed
host.ssh_key_addedEvery authorized_keys file sshd readsEvery authorized_keys file sshd readsEach user’s authorized_keys and administrators_authorized_keys
host.kernel_module_loadedLoaded modules, with taint flagsKernel extensions—
host.listener_openedTCP and UDP, with the owning processTCP and UDP, with the owning processTCP and UDP, with the owning process
host.log_clearedAuth, system, login-record and audit logs emptied, deleted or swapped—Security log cleared (1102), any log cleared (104)
host.defense_changedSELinux, AppArmor, the firewallFirewall, Gatekeeper, System Integrity Protection, FileVaultFirewall per profile, Defender real-time and tamper protection, audit policy
host.malware_detected—XProtect, with Endpoint SecurityDefender detections (1116, 1117)
host.credential_access——A process opening LSASS, with Sysmon

File, account, module and listener changes are found by comparing against a baseline every 30 seconds, so the first pass reports nothing and a restart doesn’t report again. A change the logs and a poller both see is reported once. Process starts are capped at 1,500 a minute per host; past that they are counted, not sent. Very short-lived processes can exit before a polling collector reads them, and those are counted too.

macOS and Endpoint Security

Apple’s Endpoint Security framework is the full-fidelity source on macOS. Using it needs Apple’s entitlement, root and Full Disk Access, and only a release signed with the entitlement includes it. Every other build polls the process table, reads the unified log for sign-ins, sudo and su, and shows the process collector as degraded with the reason.

Windows and Sysmon

The agent runs as a service under LocalSystem and reads the event logs, registry and socket tables through Windows’ own interfaces, so it works the same in any system language. Sysmon, if installed when the agent starts, adds binary hashes, LSASS reads and the process behind Run key writes.

04Health

Degraded collectors and how to fix them

Every collector is live, degraded or off on each host, with the reason. Open a host under Shield → Endpoints, or run tell-agent check on it. A degraded collector names the command that fixes it:

ReasonFix
Windows: an audit subcategory is off, such as Process Creation or LogonThe auditpol /set command the host shows, or the same setting in Group Policy under Advanced Audit Policy Configuration.
Windows: process command lines are offSet ProcessCreationIncludeCmdLine_Enabled to 1, or enable “Include command line in process creation events” in Group Policy.
Windows: a log is disabledThe wevtutil sl … /e:true command the host shows. Task Scheduler’s operational log is off by default.
Linux: process connector unavailableRun the agent as root outside a container. Without CAP_NET_ADMIN it polls and misses short-lived processes.
macOS: no Endpoint Security clientShown on every build without the entitlement; a Mac also refuses one without root or Full Disk Access.

Each host also shows its counters: events spooled, sent and rejected, and every drop by cause. A host that misses 30 minutes of check-ins shows as silent. The server records that as its own event, and again when the host comes back, so a rule can act on an agent going quiet.

05Respond

Ending a process and isolating a host

From a host under Shield → Endpoints, the CLI or a playbook, an owner or admin can end a process on the host or isolate it. Each is a command TillShield signs for that one host. The agent checks the signature, that the command names this host and that it hasn’t lapsed before it acts, runs each command once, and reports what happened. An online agent picks a command up within about a minute.

CommandWhat the agent doesLapses if not taken
End a processEnds the process only if the PID still runs the binary you name, so a PID the system has reused is left alone.15 minutes
IsolateBlocks all traffic, connections already open included, except loopback, DHCP, the agent’s link to TillShield and any networks you leave open.1 day
ReleaseRemoves the block.7 days
sh
tilldev shield endpoints isolate <endpoint-id> --reach 10.0.8.0/24 --for 4h
tilldev shield endpoints release <endpoint-id>
tilldev shield endpoints kill <endpoint-id> 4312 /tmp/.x/miner
tilldev shield endpoints commands <endpoint-id>
tilldev shield endpoints --status isolated
  • An isolated host keeps reporting, so you can watch it and release it from TillShield. Up to 16 more addresses or networks can stay open, none wider than a /8, or a /16 for IPv6.
  • An isolation can lift by itself after 5 minutes to 30 days. The agent lifts it on time even if the host can’t reach TillShield. Without a time, it holds until released.
  • The block is kept in place. The agent checks it every 30 seconds and puts back rules that were removed. It uses nftables, or iptables where nftables is missing, on Linux; a pf anchor on macOS; and Windows Filtering Platform filters on Windows. On Windows the block holds through a restart; on Linux and macOS the agent puts it back when it starts.
  • Lifted on the host, it is reported. Someone with administrator rights on the host can lift it with the command below. If the agent reports the host open again with no release sent, TillShield records it as a server-observed event, which the library rule “Host isolation lifted on the host” reads.
  • Revoking an isolated host lifts its isolation once the agent learns it is revoked, and commands the host hasn’t taken are called back. A command still waiting can be called back by hand.
sh
sudo tell-agent isolation                # whether this host is isolated, and until when
sudo tell-agent isolation release        # lift it on the host, without TillShield
If TillShield’s addresses change
The agent looks up TillShield’s addresses when it isolates the host and uses only those while isolated, since the host can’t reach DNS. If they change during an isolation, the host loses touch until the isolation lifts by its time or is released on the host.
06Revoke

Revoking and removing a host

Revoking a host refuses its events at once, or within 10 minutes at most, and refuses its next check-in. The agent then stops for good and doesn’t start again with the same key. To bring the host back, enrol it with a new key and a token:

sh
sudo tell-agent enroll --new-key --token -

Removing deletes a pending or revoked host’s record. Its events stay in the stream for the workspace’s retention. A pending host that is removed stops too. tell-agent uninstall removes the service and leaves the key, enrolment and spool in the data directory.

07Data

What leaves the host

  • Secrets are scrubbed on the host before anything is spooled: passwords and tokens after their flag or name, bearer and basic credentials, credentials in URLs, known token formats and private key blocks. Run tell-agent preview to see each event exactly as it would be sent, without enrolling or sending anything.
  • Everything the agent reports is client-reported. An agent on a host an attacker owns can be made to lie, so most rules that read host events suggest notifying people. The few that suggest ending a process or isolating the host wait for a person unless the rule has earned unattended runs. What the server sees for itself, such as enrolment, approval, revocation, silence and an isolation lifted on the host, is server-observed.
  • Values are clipped: command lines to 4,096 characters, at most 64 arguments of 1,024 characters each.
  • Events are kept for the workspace’s TillTell retention: 30, 90 or 400 days.
  • The data directory holds the key, enrolment, spool and baselines, and is closed to everyone but root, or SYSTEM and Administrators on Windows.
08Detect

Rules and hunts

The library ships 21 rules that read host events:

RuleFires onATT&CK
tell-host-account-createdLocal account created on a hostT1136.001
tell-host-admin-group-addAccount added to an admin group on a hostT1098
tell-host-agent-silentEndpoint agent went silentT1685
tell-host-autostart-addedNew autostart entry on a hostT1547.001, T1543.001, T1547.015, T1546.004, T1037.004
tell-host-defense-disabledHost protection turned offT1685, T1685.001, T1686
tell-host-download-and-runScript downloaded and run in one commandT1105, T1059.004, T1059.001
tell-host-encoded-powershellPowerShell given an encoded commandT1059.001, T1027.010
tell-host-isolation-liftedHost isolation lifted on the hostT1685
tell-host-kernel-moduleKernel module loaded after bootT1547.006
tell-host-log-clearedSecurity log cleared on a hostT1685.005, T1685.006
tell-host-lsass-readProcess read the memory of lsassT1003.001
tell-host-malware-detectedMalware detected on a hostT1204.002
tell-host-preload-hijackLibrary preloaded into every processT1574.006
tell-host-proxy-executionWindows system binary used to run remote codeT1218.005, T1218.010, T1218.011
tell-host-remote-admin-loginRemote login as root or AdministratorT1078.003
tell-host-reverse-shellReverse shell startedT1059.004
tell-host-scheduled-jobNew scheduled job on a hostT1053.003, T1053.005
tell-host-service-installedNew system service on a hostT1543.002, T1543.003, T1543.004
tell-host-ssh-brute-forcePassword guessing against a hostT1110.001
tell-host-ssh-key-addedSSH key added to an account on a hostT1098.004
tell-host-web-shellWeb server started a shellT1505.003

Every host event carries raw.host.id, raw.host.os and raw.collector, and process events carry raw.process.path, raw.process.sha256 and raw.process.user. “Hunt this host” on a host opens TillHunt on its events. Some searches:

text
raw.host.id:<endpoint-id> action:host.process_started
action:host.login_failed raw.host.os:linux actor.ip|cidr:203.0.113.0/24
raw.collector:run_keys
09Limits

Limits

WhatLimit
Events per host2,000 a minute; the agent spools the rest
A batch500 events and 512 KB
Spool on the host64 MB; the oldest events drop first, and every drop is counted
Check-insabout every 8 minutes; 20 per host per 10 minutes
Enrolments60 per address per 10 minutes
Clockwithin 5 minutes of server time; signed requests fail past that
Commands waiting per host20

Managing hosts and tokens and sending commands take an owner or admin, and every change and command is in the audit log. The API is under /api/v1/shield/endpoints in the API reference.