· about 40 minutes · runs on ubuntu-26.04-devops · unrated
An unrated lab. It runs on your machine with no account and no network, and everything about it — the faults, the checks, the hints and the reference solution — is in the repository. An attempt on it is recorded on your profile and never moves a rating: only rated labs do. Rated and unrated labs.
partner-sync.service runs /opt/partner/sync.py every few minutes. It reads an API token from
/etc/partner/token, asks the partner API for the day's orders, and writes them to
/var/lib/partner/orders.json.
The security review found three things. The token is in the journal — the client logs the request it
is about to make, headers and all, and logs the URL again when a request fails. /etc/partner/token
is readable by every account on the machine. And the service runs as root although it needs nothing
that root can do.
The partner's API is simulated on this machine by partner-api.service on http://127.0.0.1:8977,
which accepts the token in /etc/partner/token.
What is expected, and graded:
/etc/partner/token can be read by its owner only, and that owner is not every user of the
machine.partner-sync.service runs as a system account of its own, not as root, and that account cannot
be logged in to.You have root through sudo. The token itself stays as it is.
The machine is checked, rebooted, and checked again. A check passes only if it passes both times.
| Check | Objective |
|---|---|
| 01_the_sync_still_works | Keep a credential out of the log, whatever is logged |
| 02_the_journal_holds_no_token | Keep a credential out of the log, whatever is logged |
| 03_the_token_file_is_private | Keep a credential out of reach of other accounts on the machine |
| 04_the_service_is_not_root | Give a service only the access it needs, and no interactive account |
Where the lab's hints send you, level by level, as you ask for them (h, then l opens a journal section in the TUI).
man 5 systemd.serviceman 1 chmodman 1 chownman 8 useraddman 5 systemd.exec4 questions on the same topic, in the lab's Theory tab. They never affect the lab's grade. Three of them, to answer here:
What does this print?
import urllib.error
e = urllib.error.HTTPError("https://api.example.com/orders?token=ptk_live_secret",
403, "Forbidden", {}, None)
print("secret" in str(e), "secret" in e.url)
False True
str(HTTPError) is "HTTP Error 403: Forbidden" — no URL — but the exception keeps the full URL in .url (and .filename), so any log line that prints the URL, or code that formats the request, publishes the token. Logging e.code rather than the exception or the URL keeps it out.
https://docs.python.org/3/library/urllib.error.html · executed in a sandbox
A client authenticates with a bearer token. Which of these put the token somewhere other people can read it? Select all that apply.
logging the request URL when the token is in the query string, log.debug("headers=%s", headers) with the Authorization header in them — more than one answer
A URL with the token is written to the client's log, to proxy logs and to the server's access log; a debug line with the headers publishes it to whoever reads the journal. An environment variable is visible to the same user's processes but not written anywhere by default, and a status code carries nothing secret. (LoadCredential= is better still than an environment variable.)
man 5 systemd.exec
`/etc/app/token` is `-rw------- 1 appsvc appsvc` and `/etc/app` is `drwx------ 2 root root`. The service runs as `appsvc`. What happens when it reads the token?
Permission denied: it cannot traverse the directory
Opening a file needs execute (search) permission on every directory in the path. /etc/app allows only root, so appsvc cannot reach the file whatever the file's own mode says. The directory wants 0755, or 0750 with a group the service is in.
man 7 path_resolution · man 1 chmod