Skip to main content

Printer Shares 3 picoCTF 2026 Solution

Explore an exposed network file share and find a way to escalate access to retrieve a protected flag.

Published: March 20, 2026Updated: September 20, 2026

Description

I accidentally left the debug script in place... Well, I think that's fine - No one could possibly access my super secure directory.

Launch the challenge instance and note the host and port.
This is the third Printer Shares challenge (see also Printer Shares 2) - the twist here is that a script on the share executes automatically every minute via cron.
bash
sudo apt install smbclient

Solution

Want to try it yourself first?

The guided walkthrough reveals hints one step at a time.

Walk me through it
  1. Step 1Connect to the SMB share anonymously and list its contents
    Observation
    The 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.
    bash
    smbclient -L //<HOST> -p <PORT_FROM_INSTANCE> -N
    bash
    smbclient //<HOST>/shares -p <PORT_FROM_INSTANCE> -N
    bash
    smb: \> ls
    bash
    smb: \> get script.sh
    bash
    smb: \> get cron.log
    bash
    smb: \> exit
    bash
    cat script.sh
    bash
    cat cron.log
    What 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 anonymous is 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.sh you will see it is a health-check script that appends output to cron.log. Reading cron.log shows 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.

  2. Step 2Overwrite script.sh with a payload that copies the flag
    Observation
    script.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 locally
    bash
    cat > script.sh << 'EOF'
    bash
    #!/bin/bash
    bash
    echo "Health Check: $(date)"
    bash
    cat /challenge/secure-shares/flag.txt >> /challenge/shares/cron.log 2>&1
    bash
    EOF
    bash
    # Upload the modified script back to the share
    bash
    smbclient //<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. The 2>&1 redirect 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.

  3. Step 3Wait for cron to run, then retrieve the flag from cron.log
    Observation
    The 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 log
    bash
    smbclient //<HOST>/shares -p <PORT_FROM_INSTANCE> -N -c 'get cron.log'
    bash
    cat cron.log

    Expected 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; done

    This writable-script-plus-cron pattern appears frequently in CTF privilege escalation chains and in real penetration tests. Tools like pspy monitor 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.

Key takeaway

Cron hijacking happens when a scheduled task runs a file a lower-privileged user can overwrite, which lends the cron user's permissions to whoever controls that file. Put an anonymously writable network share next to a privileged cron job and you have privilege escalation with no credentials at all. Penetration testers rate this high severity, because exploiting it needs write access to one file, no code vulnerability, and patience equal to the interval.

Related reading

Useful tools for General Skills

Where to go next