The antivirus said 'no malware detected'. It was sitting right there on the disk.
I was tidying up scheduled tasks on my Synology NAS and opened Task Scheduler. Two entries I didn…

The antivirus said "no malware detected". It was sitting right there on the disk.
A real incident, and a lesson about green lights. Every command output, version number and CVE ID below is from the actual investigation. Nothing was invented for the narrative.
It started with an unrelated question
I was tidying up scheduled tasks on my Synology NAS and opened Task Scheduler. Two entries I didn't remember creating:
PowerOff task 0 → 2026-07-26 09:00
PowerOn task 0 → 2026-07-26 20:00
So I asked: "Why is this here? I never set this up."
While digging through the system crontab, I found this:
*/20 * * * * /bin/sh /etc/.conf #Sn5Yj8A2l0T
A dot-prefixed (hidden) file in /etc, executed as root every 20 minutes, tagged with a random string.
The power schedule turned out to be unrelated. But if I hadn't asked that question, I would never have opened that file.
I didn't scan it. I just read it.
#!/bin/bash
MATCH_STRING="Sn5Yj8A2l0T"
DOWNLOAD_URL="http://zuoye.free.fr/files/synology-10441.png"
Reading further, it does four things:
- If it's been deleted →
wgetitself back - If
/etc/crontablacks the marker → overwrite the file (>, not>>) to reinstall the cron line - If
/etc/rc.subrlacks the marker → appendbash /etc/.conf &(boot persistence) - If the payload isn't running → download
000119.png, save it asnode, execute it
That .png is not an image. First 16 bytes:
0000000 177 E L F 002 001 001 \0
\177ELF. It's a Linux binary. The extension is camouflage.
It lived at /etc/node, 568 KB, dated 2026-01-14.
(The real Node.js is at /usr/local/bin/node. Something called node sitting in /etc/ is not a system component.)
The file was dated January. I found it in July. Six months.





Then I asked the vendor's own tool
Synology ships Security Advisor, which scans for malware. I ran a full scan.
Result:
✅ No malware detected on your system
✅ No malicious cryptocurrency mining software detected
✅ No malicious system configuration files detected
Three green checks.
And at that exact moment, /etc/.conf and /etc/node were on the disk. I could cat them again for anyone who asked.
What that green light actually proved
This is the part worth your time.
The tool didn't lie. It just didn't see. Three concrete reasons:
1. The payload was UPX-packed. The only readable string I could extract from the binary was http://upx.sf.net. UPX compresses executables; a side effect is that every string inside is compressed too. Signature-based scanners match fingerprints. Compress the fingerprint and there's nothing to match.
2. The dropper is an ordinary shell script. It isn't a "virus format". Every line, read alone, is legitimate bash: wget, chmod, echo. What's malicious is what they do together — and that requires comprehension, not comparison.
3. The cron entry is valid syntax. The "malicious configuration file" check looks for known-bad templates, not for "what is this line doing". */20 * * * * /bin/sh /etc/.conf is syntactically indistinguishable from any legitimate schedule.
So:
A green light proves "no bad news was seen". It does not prove "there is no bad news".
In daily life those two are nearly equivalent, so we treat them as one thing. They aren't. And the gap shows up exactly when it matters most.
The attacker left a business card
Before cleaning up, I recorded the SHA256 of both files and went back to that download URL:
http://zuoye.free.fr/files/synology-10441.png
^^^^^^^^^^^^^^^^
synology-10441.
CVE-2024-10441 — an unauthenticated remote code execution flaw in Synology DSM's system plugin daemon. CVSS 9.8. It came out of Pwn2Own 2024. No credentials, no user interaction: one crafted request, arbitrary code execution.
The attacker named the payload after the vulnerability they used to get in.
Then I checked versions:
| Fixed in | DSM 7.2.1-69057-6 |
| I was running | DSM 7.2.1-69057 Update 3 |
Below the fix. The advisory was published in late 2024. My NAS sat on an older build the whole time.




My first hypothesis was wrong
Before I found that filename, my working theory was: "Probably a brute-forced password — auto-block was disabled, after all."
That was wrong.
CVE-2024-10441 requires no authentication at all. The attacker never attempted a login, so auto-block was irrelevant — it would have made no difference either way.
The actual root cause needed exactly two conditions:
Unpatched DSM (below the fixed build)
×
Management interface reachable from the internet
↓
one request → root
I tested four ports from my phone on mobile data (WiFi off). All refused — so there were no port-forwarding rules on the router. Where did the exposure come from?
QuickConnect. The vendor's convenience feature that lets you reach your NAS from outside without touching your router. It works by relaying through the vendor's servers — no port forwarding required.
Convenience and exposure are the same thing viewed from two sides.
Removal: the order matters more than the commands
The commands are short, but the wrong order wastes the effort:
# 1. Break both persistence paths FIRST
sed -i '/Sn5Yj8A2l0T/d' /etc/crontab
sed -i '/Sn5Yj8A2l0T/d' /etc/rc.subr
# 2. THEN delete the files
rm -f /etc/.conf /etc/node
Reverse it — delete first, edit cron second — and within 20 minutes the schedule fires, wget pulls it back, and you conclude "I can't remove it."
One more trap worth recording: I first tried pasting the whole block with sudo prefixes. sudo printed Password: and consumed the remaining pasted lines as password attempts. Three failures, no commands run.
The fix is to run sudo -i alone, wait for the prompt to change from $ to #, then paste the commands without sudo.
How do you prove it's actually gone?
Files deleted, no errors — that is not proof.
This thing is designed to come back when deleted. The real verification is surviving a full trigger cycle.
It runs every 20 minutes, so I scheduled an automatic re-check 25 minutes out:
Cleanup ~16:40
Re-check 17:13:46
Result no indicators found
A complete cycle passed and it did not return. That's what counts.
(I also confirmed the outbound connection to an external IP was gone, no surviving processes, and the system crontab contained only legitimate entries. "It worked" declared immediately after deletion and "it worked" declared after one full cycle are claims of very different strength.)




The watcher I wrote doesn't check signatures
Since the vendor's scanner is green on this thing, I can't use it as detection. So I wrote a daily check that does no signature matching. It asks three questions:
- Does
/etc/.confexist? - Does
/etc/nodeexist? - Does that marker string appear in the crontab or boot script?
Packing defeats a scanner. It doesn't defeat ls.
I made a mistake writing it that's worth its own paragraph. In the first version, "clean" and "couldn't reach the host" both returned the same exit code and logged the same line.
Which means: the day SSH breaks, or the NAS is powered off, or the key expires — that watcher goes permanently silent, and I assume I'm being watched.
When a monitor is silent, "everything is fine" and "I am blind" look identical.
The fix: distinct exit codes, plus after three consecutive unreachable runs it alerts that it has gone blind. A watcher has to speak up about its own blindness, or its silence gets read as safety.
What I took away
1. "Not detected" and "not there" are different sentences. A tool's output is what that tool saw, not the state of the world. To know whether something exists, go look at the thing itself.
2. Convenience features are exposure. QuickConnect saved me from configuring a router. The price was putting a management interface on the public internet. That trade was fine before the vulnerability was published, and not fine after — and I didn't re-evaluate.
3. Updates are not a "when I get around to it" task. Over a year passed between the advisory and my compromise. Every time I saw the update prompt, I thought "later — what if it breaks something."
4. "Assuming it's fine" is more dangerous than "knowing it's broken". Six months, zero symptoms. No slowdown, nothing anomalous, and the official tool reporting all clear. The only reason I found it was that I asked a question about something else entirely.
If you also run a NAS
Three things, ten minutes:
- Patch to the latest build of your current version. Not the newest major release — the newest patch of what you're on. Lowest risk, most holes closed.
- Check whether your admin interface is reachable from the internet — both router port-forwarding and the vendor's remote-access service. Testing from a phone with WiFi off is the honest test.
- Enable auto-block. It wouldn't have stopped this particular attack, but it stops most credential attempts.
And if you want to check whether you're clean:
grep -rn "/etc/\.conf" /etc/crontab /etc/rc.subr 2>/dev/null
ls -la /etc/.conf /etc/node 2>/dev/null
No output is good. If you get output — you now know what it is.
I'm not a security researcher. I roast coffee and write software on the side. This is an incident log: an unpatched NAS, a vulnerability public for over a year, a program that sat there for six months, and a green light that said everything was fine.



