Show HN:Coldframe,一款伪装成超市冰箱控制器的蜜罐
Show HN: Coldframe, a honeypot that poses as a supermarket fridge controller

原始链接: https://github.com/hedgerow-dev/coldframe

coldframe 是一个单文件 Python 蜜罐,模拟面向互联网的超市制冷控制器(Danfoss AK-SM 800A 与 Copeland/Dixell XWEB EVO)。它记录攻击者的 IP、凭据、请求及公开漏洞利用,同时不暴露任何真实系统。它模拟真实设备指纹——包括请求头、页面标题、TLS 设置、证书、favicon,以及(可选)固件索引页——并支持通过环境变量选择两种角色。弱密码/默认登录及特定基于 CVE 的绕过可获得虚假会话与仪表盘,其中包含无害的除霜操作。它可选运行 Modbus TCP 服务,提供虚假的温度与设定值。事件以 JSON 行形式输出,并由 summary.py 进行分析。设计用于容器化、加固部署,绝不执行命令或转发流量;漏洞利用载荷仅被记录并丢弃。采用 MIT 许可证。

Coldframe 是一个单文件 Python 蜜罐,它伪装成超市制冷控制器——具体是 Danfoss AK-SM 800A 和 Dixell XWEB 接口——逼真到 Shodan 会将其索引为真实设备。作者使用 Shodan 记录匹配了真实设备的指纹,包括请求头顺序、页面标题、TLS 版本和精确的字节填充。它可检测针对多个 Danfoss 和 XWEB CVE 的利用尝试,包括“每日代码”登录绕过,并允许默认登录访问带有除霜按钮的伪造控制面板,以观察后续操作。上线一天后,它只看到了通用扫描器和 Shodan 爬虫。一位评论者质疑此前关于冰箱被黑的报道是真实的,还是只是巧合的批量软件更新。请求有现场经验的人提供反馈。
相关文章

原文

A honeypot for supermarket refrigeration controllers.

In 2026, attackers broke into internet-facing refrigeration supervisors across Europe using default passwords and old, unpatched firmware, then forced defrost cycles. coldframe pretends to be one of those controllers. It records who connects, what passwords they try and which public exploits they use, and it never gives them anything real.

It is one Python file with no dependencies outside the standard library.

Persona Pretends to be What it serves
danfoss Danfoss AK-SM 800A system manager StoreView login, a fake store dashboard, the XML API at /html/xml.cgi and /xml.cgi, HTTP and HTTPS
dixell Copeland/Dixell XWEB EVO supervisor Login page and the XWEB 500 CGI paths targeted by public exploits

The Danfoss persona copies what internet scanners record for real AK-SM 800A units: the nginx server header and header order, the Danfoss StoreView page title, TLS 1.2 only, and a 1-year certificate for CN=DanfossSM800A issued by a SelfSigned-DanfossSM800A authority. Each build generates its own keys.

Weak logins (for example Supervisor / 12345) and a correct CVE-2025-41450 "code of the day" succeed. The attacker gets a session token and a dashboard of fake refrigerated cases with defrost buttons. Every action they take is logged as a control event; nothing is real.

The Dixell persona follows real XWEB EVO units the same way: no Server header, their security-header set and order, the same asset paths and page size. Its login uses the real /cgi-bin/login.lua flow: the documented factory login Admin / Admin succeeds, five failures in five minutes lock the user, and attempts at the XWEB Pro auth_mode bypass (CVE-2026-25085) are tagged.

Real units of both vendors serve their own favicon, and scanners match devices by its hash. That icon is the vendor's artwork, so it is not in this repository. For a private deployment you can point FAVICON_FILE at a copy you have the right to use.

The same goes for the Danfoss start page. Real units serve a short Angular loader page from the firmware, and thousands share its exact hash. Point INDEX_FILE at that index.html (from the public firmware package) and the decoy serves it byte for byte, with its original date in Last-Modified and ETag. The loader's main.*.js then shows the decoy's own login page, laid out like the firmware's remote login. If the firmware's assets/images/Danfoss-logo.png sits beside that index.html, the page uses it.

Both personas can also run an optional Modbus TCP service with fake case temperatures, setpoints and a defrost register. Real AK-SM 800A units only use Modbus to talk to their own case controllers, so Modbus is off by default. Turn it on to catch generic industrial scanners.

Requests that match a public exploit get an exploit field in the log:

  • CVE-2023-25914: AK-SM 800A path traversal via get_file
  • CVE-2023-25915: AK-SM 800A command injection via load_cert
  • CVE-2025-41452: AK-SM 800A nginx header overwrite via load_nginx_headers
  • CVE-2025-41450: AK-SM 800A "code of the day" login bypass (getauth with eds_only or quantum_only), noting whether the attacker computed the correct code
  • SM800 code-of-the-day bypass: eds_only / quantum_only on other commands
  • CVE-2021-45420: XWEB 500 upload and command paths under /cgi-bin/
  • CVE-2026-25085: XWEB Pro login bypass via an unexpected auth_mode
PERSONA=danfoss HTTP_PORT=8080 python3 -I honeypot.py

Open http://localhost:8080 and every request shows up as a JSON line on stdout and in events.jsonl.

Run the tests (they start the honeypot on loopback and attack it):

python3 -I test_honeypot.py

Quickest: paste into "User data"

Create an Ubuntu 24.04 server (a $4 DigitalOcean droplet is plenty) and paste cloud-init.yaml into the User data box. Change PERSONA=danfoss to dixell if you want the XWEB persona. About two minutes after boot the decoy is listening on port 80 (and 443 for Danfoss), hardened as below.

Then, in your provider's firewall, allow only the decoy's ports from anywhere and SSH from your own address. Read the log with:

ssh root@<server> 'podman logs coldframe'

Build the container. Each build makes a fresh self-signed certificate, so two deployments never share one.

podman build -t coldframe .

Run it with rootful podman or Docker. Rootless port forwarding rewrites the source address, which makes every attacker look like the same internal IP.

--userns=auto maps the container to an unused host UID range, so even the container user is nobody on the host. Podman needs a range to hand out, once per host:

echo "containers:2147483647:2147483648" | sudo tee -a /etc/subuid /etc/subgid
sudo podman run -d --name coldframe --restart=always \
  --read-only --cap-drop=ALL --security-opt no-new-privileges --userns=auto \
  --memory 128m --pids-limit 512 --log-opt max-size=10m \
  -p 80:8080 -p 443:8443 \
  -v coldframe-logs:/logs:U \
  -e PERSONA=danfoss \
  coldframe

For Modbus, add -e MODBUS_PORT=5020 -p 502:5020.

On the host, only expose the ports the persona would really have, and block outbound traffic except DNS and package updates: the decoy never needs to connect out. Keep SSH reachable only from your own address: a fridge controller with SSH open to the world looks wrong.

Variable Default Meaning
PERSONA danfoss danfoss or dixell
HTTP_PORT 8080 HTTP listener
HTTPS_PORT 0 (off) HTTPS listener, needs CERT_FILE and KEY_FILE
MODBUS_PORT 0 (off) Modbus TCP listener
LOG_PATH events.jsonl Where events are appended
FAVICON_FILE none Optional favicon to serve (private deployments only)
INDEX_FILE none Optional Danfoss firmware index.html to serve as the start page (private deployments only)

Each line is one event:

{"ts": "2026-11-05T10:57:21.158+00:00", "persona": "danfoss", "proto": "http",
 "src_ip": "203.0.113.7", "src_port": 6782, "event": "login_attempt",
 "username": "admin", "password": "admin"}
event When
request Any HTTP(S) request, with method, path, Host, User-Agent, Authorization and body
login_attempt Credentials submitted through the login page or the XML API, with granted
control An action from a logged-in session, such as starting a defrost
xml_cmd A Danfoss XML API command, with its attributes and any exploit match
tls_error A failed TLS handshake (often a scanner speaking plain HTTP to 443)
connect, read, write, device_id, unsupported, malformed Modbus activity; writes to the defrost registers carry "defrost": true

summary.py turns a log into a short report:

python3 -I summary.py --hours 24 --ignore <your-own-ip> < events.jsonl
  • It never runs commands, reads files, or forwards traffic. Exploit payloads are logged and dropped.
  • Request bodies, logged fields and connections are capped, including a per-source limit so one attacker cannot crowd out others. Idle sockets time out, and the event log rotates once it gets large.
  • Connections that trickle data to stay open are cut after 30 seconds, and refused connections are logged.
  • Over-long log lines are truncated, and summary.py neutralises terminal escape codes from attacker input.
  • The container runs as a non-root user in its own user namespace, on a read-only filesystem with no capabilities.
  • Log fields are attacker-controlled. Treat them as untrusted when you view or process them.
  • Shallow interaction. Logged-in attackers see a small dashboard and a handful of XML commands, not the full StoreView app.
  • Public code can be fingerprinted. Anyone can read this repository and spot its exact responses. Change the persona strings, page layout and certificate subject for your deployment.
  • Unconfirmed details. Static paths, the full web app and some XML response shapes of real units are not public. Where they were missing, coldframe uses plausible values.
  • Cloud IPs look suspicious. Some scanners flag industrial devices on cloud hosting as likely honeypots.

eppser/danfoss-ak-sm-decoy is another AK-SM decoy, with SNMP and Service Tool listeners and a richer simulated store. coldframe focuses on matching real units' web fingerprints, detecting specific exploits, and Dixell XWEB support.

MIT. See LICENSE.

联系我们 contact @ memedata.com