Problems in CVE-2020-0796 Scanner Scripts
ทางเลือกในการตรวจสอบที่ได้ผลจริงๆ มีเพียงสองกรณี คือการตรวจสอบแพตช์ด้วยโซลูชันต่างๆ และการตรวจสอบโดยการทดสอบโจมตีจริง วิธีการการตรวจสอบโดยใช้สคริปต์ Scanner ไม่สามารถช่วยยืนยันได้ว่าระบบมีช่องโหว่จริงหรือไม่
หลังการหลุดออกมาของรายละเอียดของช่องโหว่ในฟังก์ชันซึ่งมีการใช้โปรโตคอล SMB รวมไปถึงคุณลักษณะที่ช่องโหว่นั้น Wormable ได้ เราเห็นความตื่นตัวที่เพิ่มขึ้นมาอย่างฉับพลันและสะท้อนให้เห็นถึงการเรียนรู้จากการแพร่กระจายของ WannaCry ซึ่งโจมตีช่องโหว่ CVE-2017-0143 และ CVE-2017-0144 ด้วย ETERNALBLUE หนึ่งในความตื่นตัวนั้นคือการปรากฎออกมาถึงวิธีการในใช้เพื่อยืนยันการมีอยู่ของช่องโหว่ในระบบต่างๆ ในรูปแบบของสคริปต์ที่สามารถทำงานได้จากการระบุเพียงแค่หมายเลขไอพีแอดเดรสที่ต้องการตรวจสอบไปอย่างเดียว
อย่างไรก็ตามเนื่องจากที่มีของช่องโหว่นี้นั้นมาจากการ “หลุด” และยังเห็นได้ถึงความพยายามในการปิดข่าวก่อนที่ทางไมโครซอฟต์จะพร้อมปล่อยแพตช์จริงๆ ในช่วงนั้นเราอาจพูดได้ว่าแทบไม่มีใครที่ทราบอย่างแท้จริงถึงรายละเอียดและที่มาของช่องโหว่นั้นนอกเสียจากเป็นบุคคลกลุ่มที่หนึ่งและที่สองซึ่งเกี่ยวข้องกับการป้องกันและลดผลกระทบจากการโจมตีช่องโหว่นี้เองที่ควรจะทราบข้อมูลดีที่สุด
ด้วยเหตุนี้เราอาจถือได้ว่าผลผลิตใดๆ ที่เกิดในช่วงเวลาที่ข้อมูลยังไม่ชัดเจนนั้นสามารถที่จะสร้างผลลัพธ์ที่ไม่ชัดเจนได้ตามข้อมูลที่มันนำมาประเมิน และนี่คือประเด็นหลักที่เราจะพูดถึงกันในบล็อกนี้ครับ
การเกิดขึ้นของสคริปต์ Scanner
ในช่วงก่อนมีการออกแพตช์และเปิดเผยรายละเอียดของช่องโหว่อย่างชัดเจน มีการปรากฎของสคริปต์ที่อ้างว่าสามารถยืนยันการมีอยู่ของช่องโหว่ได้เป็นจำนวนมาก บางส่วนที่เราพบมีตามรายการดังนี้
- สคริปต์จาก ollypwn/SMBGHost
- สคริปต์จาก xax007/CVE-2020-0796-Scanner
เมื่อเราใช้สคริปต์ในการตรวจหาการมีอยู่ของช่องโหว่ในมุมของผู้ใช้งาน เราคาดหวังว่าผลลัพธ์ของสคริปต์จะต้องสามารถบอกได้ว่าระบบที่เราตรวจสอบนั้นมีช่องโหว่ (Vulnerable) หรือไม่มีช่องโหว่ (Not Vulnerable) และที่สำคัญกว่านั้นความน่าเชื่อถือของผลลัพธ์ที่มาจากการใช้สคริปต์เหล่านี้ซึ่งจะส่งผลต้องกระบวนการ Vulnerability management อย่างชัดเจน ดังนั้นการจะยืนยันความน่าเชื่อถือของผลลัพธ์จากสคริปต์เหล่านี้ได้นั้นคือเข้าใจวิธีการในการตรวจหาและเงื่อนไขที่ทำให้สคริปต์ระบุว่าระบบนั้นๆ มีช่องโหว่
เงื่อนไขของ ollypwn/SMBGhost ในการระบุหาช่องโหว่
สำหรับสคริปต์ ollypwn/SMBGhost นั้น มันถูกพัฒนาขึ้นมาจากการทำงานของโปรโตคอลจริงๆ ตามที่ปรากฎไว้ในไฟล์ SmbGhost.pcap ตามรูปภาพด้านล่าง
pkt = b'\x00\x00\x00\xc0\xfeSMB@\x00\x00\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00$\x00\x08\x00\x01\x00\x00\x00\x7f\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00x\x00\x00\x00\x02\x00\x00\x00\x02\x02\x10\x02"\x02$\x02\x00\x03\x02\x03\x10\x03\x11\x03\x00\x00\x00\x00\x01\x00&\x00\x00\x00\x00\x00\x01\x00 \x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03\x00\n\x00\x00\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00'
subnet = sys.argv[1]
for ip in IPNetwork(subnet):
sock = socket.socket(socket.AF_INET)
sock.settimeout(3)
try:
sock.connect(( str(ip), 445 ))
except:
sock.close()
continue
sock.send(pkt)
nb, = struct.unpack(">I", sock.recv(4))
res = sock.recv(nb)
if res[68:70] != b"\x11\x03" or res[70:72] != b"\x02\x00":
print(f"{ip} Not vulnerable.")
else:
print(f"{ip} Vulnerable")
จากโค้ดด้านบน เราสามารถอธิบายขั้นตอนการตรวจสอบการมีอยู่ของช่องโหว่โดยสคริปต์จาก ollypwn/SMBGhost ได้ตามขั้นตอนดังต่อไปนี้
- เชื่อมไปต่อไปยังพอร์ต 445 ของหมายเลขไอพีแอดเดรสที่ระบุ
- ทำการส่งข้อมูลที่ถูกเก็บในตัวแปร
pkt
ไป โดยข้อมูลที่ถูกเก็บอยู่ในตัวแปรpkt
คือข้อมูลที่ SMB จะส่งเพื่อทำกระบวนการ Negotitate Protocol Request - เมื่อปลายทางได้รับ Negotitate Protocol Request มันจะทำการส่ง Negotitate Protocol Response มา โดยค่านี้จะถูกเก็บไว้ที่ตัวแปร
res
- สคริปต์ทำการตรวจสอบค่าในตัวแปร
res
ในสองตำแหน่ง ได้แก่- ตำแหน่ง
0x7e
-0x7f
ว่ามีค่าเป็น\x11\x03
หรือไม่ - ตำแหน่ง
0x80
-0x81
ว่ามีค่าเป็น\x02\x00
หรือไม่
- ตำแหน่ง
- ข้อความ Vulnerable จะปรากฎขึ้นมาเมื่อในตำแหน่งดังกล่าวมีค่าทั้งสองค่านี้เท่านั้น
เมื่อตรวจสอบเพิ่มเติมในมาตรฐานของโปรโตคอลที่ SMB2 NEGOTIATE Response อ้างอิง (ดูเพิ่มเติม 2.2.4 SMB2 NEGOTIATE Response) การตรวจสอบค่าทั้งสองค่ามีความหมายดังนี้
- ในตำแหน่งที่มีการปรากฎของค่า
\x11\x03
นั้น คือตำแหน่งDialectRevision
ขนาด 2 ไบต์ ซึ่งใช้ในการระบุหมายเลข Revision ของโปรโตคอล โดยค่า0x0311
นั้นเป็นค่า Dialect revision number ของ SMB 3.1.1 ดังนั้นการตรวจสอบค่านี้จะช่วยยืนยันถึงเลข Revision ที่โปรโตคอล SMB ใช้งานอยู่ได้ - ในตำแหน่งที่มีการปรากฎของค่า
\x02\x00
นั้น คือตำแหน่งNegotiateContextCount
ขนาด 2 ไบต์ซึ่งใช้ในการแสดงจำนวน Context ที่มีอยู่ในNegotitateContextList
ในกระบวนการ Negotitate ของโปรโตคอล SMB เราอาจมองได้ว่า Context คือ “ฟีเจอร์” ของโปรโตคอล อาทิ การบีบอีด, การเข้ารหัสและอื่นๆ โดย “ฟีเจอร์” เหล่านี้จะถูกเก็บไว้ในNegotitateContextList
และใช้NegotitateContextCount
ในการบอกจำนวน ดังนั้นการตรวจสอบค่านี้จะใช้ในการยืนยันจำนวน “ฟีเจอร์” ที่จะมีการใช้งานกับโปรโตคอล SMB
อ้างอิงจากข่าวหลุดซึ่งระบุไว้ว่าช่องโหว่นั้นเกี่ยวข้องกับกระบวนการ Compression ที่เกิดขึ้นในโปรโตคอล SMB ที่ถูกอิมพลีเมนต์โดยไมโครซอฟต์ เราจะสังเกตเห็นได้ว่าสคริปต์ ollypwn/SMBGhost ไม่ได้ทำการตรวจสอบฟีเจอร์ของโปรโตคอลใน NegotiateContextList เลย กระบวนการตรวจสอบฟีเจอร์ทำเพียงแค่นับจำนวนฟีเจอร์เท่านั้น ไม่ได้ระบุเข้าไปว่าฟีเจอร์ดังกล่าวคืออะไร
จุดสำคัญอีกจุดหนึ่งคือถึงแม้สคริปต์จะทำการตรวจสอบฟีเจอร์ใน NegotitateContextList
ว่ามีฟีเจอร์ชื่อ SMB2_COMPRESSION_CAPABILITIES
หรือไม่ สคริปต์จะต้องทำการตรวจสอบด้วยว่าค่าใน offset ของ CompressionAlgorithms
เป็นค่าใด เพราะหากค่าใน offset ดังกล่าวคือ 0x0000
แล้ว กระบวนการ Compression จะไม่มีทางเกิดขึ้นเลย
เงื่อนไขของ xax007/CVE-2020-0796-Scanner ในการระบุหาช่องโหว่
เมื่อเรามาดูสคริปต์จากโครงการ xax007/CVE-2020-0796-Scanner ซึ่งระบุว่าได้รับแรงบันดาลใจมาจากสคริปต์ ollypwn/SMBGhost เราจะพบข้อแตกต่างที่เห็นอย่างชัดเจนตามซอร์สโค้ดด้านล่าง
try:
sock = socket.socket(socket.AF_INET)
sock.settimeout(3)
sock.connect(( sys.argv[1], 445 ))
sock.send(payload)
response = sock.recv(2020)
sock.close()
# Detect support SMB version
# 1103 -> 3.1.1
if binascii.hexlify(response)[144:148].startswith('1103'):
print(sys.argv[1] + " support SMB protocol version 3.1.1")
# See above Value:Meaning comment
if binascii.hexlify(response)[-36:].startswith('03'):
if response[-2:] == b'\x01\x00':
exit(sys.argv[1] + "\tVulnerable!!!\tTarget support LZNT1 compression algorithm")
if response[-2:] == b'\x02\x00':
exit(sys.argv[1] + "\tVulnerable!!!\tTarget support LZ77 compression algorithm")
if response[-2:] == b'\x03\x00':
exit(sys.argv[1] + "\tVulnerable!!!\tTarget support LZ77+Huffman compression algorithm")
except Exception as identifier:
exit(sys.argv[1] + " " + str(identifier))
โค้ดสำหรับการตรวจสอบช่องโหว่ของ xax007/CVE-2020-0796-Scanner แยกเงื่อนไขออกเป็นสองส่วนเช่นเดียวกัน คือส่วนที่มีการตรวจสอบ DialectRevision
ว่าใช่ค่า 0x0311
หรือไม่ อย่างไรก็ตามในส่วนที่สองนั้น สคริปต์ไม่ได้ตรวจสอบ NegotiateContextCount
แต่ข้ามไปตรวจสอบค่าใน NegotiateContextList
ทันทีว่าสามารถระบุหาการใช้ CompressionAlgorithms
ได้หรือไม่
จากที่เราได้อธิบายไปแล้วในหัวข้อด้านบน สคริปต์นี้จะแสดงผล “Not vulnerable” ก็ต่อเมื่อค่าใน CompressionAlgorithms
เป็น 0x000
ซึ่งหมายถึงว่าไม่มีการ Compression
เกิดขึ้น และจะแสดงผลก็ต่อเมื่อค่าใน CompressionAlgorithms
เป็นค่าใดค่าหนึ่งที่เกี่ยวข้องกับอัลกอริธึมในการบีบอัดข้อมูล
แน่นนอนว่าสคริปต์จากโครงการ xax007/CVE-2020-0796-Scanner สามารถระบุได้ดีกว่า ollypwn/SMBGhost ถึงการมีอยู่ของฟีเจอร์ชื่อ SMB2_COMPRESSION_CAPABILITIES
และค่าในฟีเจอร์ดังกล่าว แต่ปัญหาอีกปัญหาหนึ่งที่ยังคงถูกซ่อนอยู่คือประเด็นสำคัญว่า หากการแก้ไขช่องโหว่นั้นไม่เกี่ยวข้องหรือทำให้เกิดการเปลี่ยนแปลงในกระบวนการ Negotitate ของโปรโตคอล SMB แล้ว สคริปต์จากโครง xax007/CVE-2020-0796 จะไม่สามารถแยกระบบที่ถูกแพตช์แล้วออกจากระบบที่ยังไม่ถูกแพตช์ได้ เพราะทุกระบบจะยังคงมีหน้าตาของการ Negotitate เหมือนเดิม
การที่จะยืนยันประเด็นนี้ได้สามารถทำได้เพียงวิธีการเดียวคือทำเข้าใจแพตช์และเงื่อนไขในการโจมตีช่องโหว่เท่านั้น
วิเคราะห์แพตช์ CVE-2020-0796
โดยปกติการอิมพลีเมนต์การใช้งานโปรโตคอล SMB ในระบบปฏิบัติการ Windows จะอยู่ในไฟล์ไดรเวอร์ื่อ srv2.sys
ที่ตำแหน่ง C:\Windows\System32\drivers\srv2.sys
ดังนั้นเราจะต้องหาไฟล์จากระบบที่สอดคล้องกับเงื่อนไขของช่องโหว่ทั้งที่ยังแพตช์และยังไม่ได้มีการแพตช์มาเปรียบเทียบหาข้อแตกต่างกัน ในเบื้องต้นเราสามารถยืนยันไฟล์ srv2.sys
ทั้งสองลักษณะตามค่าแฮชได้ดังนี้
- ค่า MD5 ของ srv2.sys ก่อนถูกแพตช์ f508ec2bfc244442d76091cb03bae110
- ค่า MD5 ของ srv2.sys หลังถูกแพตช์ f037de85645d30a21cd79cb1f8bb706a
หากจะทำการวิเคราะห์แพตช์ตาม ลองตรวจสอบค่าแฮชของไฟล์ srv2.sys
ทั้งสองไฟล์ว่าตรงกับที่ระบุไว้หรือไม่ดูครับ ส่วนเครื่องมือในการวิเคราะห์และเปรียบเทียบความแตกต่าง อ่านเพิ่มเติมได้ที่โพสต์ขั้นตอนการติดตั้ง BinExport กับ Ghidra เพื่อเปรียบเทียบความแตกต่างของไบนารีด้วย BinDiff 6
อ้างอิงจากบทความการวิเคราะห์ช่องโหว่โดย Synacktiv และผลจากการหาความแตกต่างของไฟล์ srv2.sys ทั้งสองเวอร์ชัน เราจะพบสิ่งที่ตรงกันคือฟังก์ชัน Srv2DecompressData
เป็นฟังก์ชันที่พบการเปลี่ยนแปลงมากที่สุดเมื่อเทียบกับฟังก์ชันอื่นๆ
ผลลัพธ์จากการดีคอมไพล์ฟังก์ชันดังกล่าวจากไฟล์ srv2.sys
ทั้งสองเวอร์ชันแสดงให้เห็นถึงโค้ดของแพตช์ที่ถูกเพิ่มเข้ามาก่อนจะถึงโค้ดที่มีช่องโหว่ รูปภาพด้านล่างแสดงให้เห็นถึงโค้ดของฟังก์ชันที่มีช่องโหว่ในจุดที่ SrvNetAllocateBuffer
สามารถถูกทำ integer overflow ด้วยการเปลี่ยนแปลงค่า OriginalCompressedSegmentSize
และ OffsetOrLength
โดยมี flow การทำงานคือมีการเปรียบเทียบ CompressAlgorithm
ก่อน จากนั้นจึงเรียกใช้ฟังก์ชัน SrvNetAllocateBuffer
และเริ่มการคลายการบีบอัดด้วย SmbCompressionDecompress
if (allocated_buffer == 0) {
return 0xc000009a;
}
iVar6 = SmbCompressionDecompress
((ulonglong)uVar2,
(ulonglong)PayloadSize + 0x10 +
*(longlong *)(*(longlong *)(smb_packet + 0xf0) + 0x18),
(ulonglong)
((*(int *)(*(longlong *)(smb_packet + 0xf0) + 0x24) - PayloadSize) - 0x10),
*(longlong *)(allocated_buffer + 0x18) + (ulonglong)PayloadSize,iVar9,Header,
uVar8,uVar10);
if ((-1 < iVar6) && (Header[0] == iVar9)) {
if (PayloadSize != 0) {
memcpy(*(void **)(allocated_buffer + 0x18),
(void *)(*(longlong *)(*(longlong *)(smb_packet + 0xf0) + 0x18) + 0x10),
(ulonglong)PayloadSize);
}
*(int *)(allocated_buffer + 0x24) = Header[0] + PayloadSize;
Srv2ReplaceReceiveBuffer(smb_packet,allocated_buffer);
return 0;
}
SrvNetFreeBuffer(allocated_buffer)
สำหรับโค้ดที่ถูกเพิ่มขึ้นมาใหม่ในไฟล์ไดรเวอร์ srv2.sys
นั้น เป็นการใช้ฟังก์ชัน RtlULongAdd เพื่อช่วยตรวจสอบหากเกิดกรณีของ Integer overflow โดยฟังก์ชัน RtlULongAdd
จะให้ผลลัพธ์ STATUS_INTEGER_OVERFLOW
ทันทีเมื่อตรวจพบ
if (0xf < *(uint *)(*(longlong *)(param_1 + 0xf0) + 0x24)) {
puVar3 = *(undefined **)(*(longlong *)(param_1 + 0xf0) + 0x18);
uVar2 = *(uint *)(lVar7 + 0x8c);
/* WARNING: Load size is inaccurate */
auVar4 = *(undefined *)puVar3;
uVar1 = *(uint *)(puVar3 + 0xc);
uVar13 = SUB124(auVar4,0);
uVar14 = SUB124(auVar4 >> 0x20,0);
uVar15 = SUB124(auVar4 >> 0x40,0);
if (uVar2 != (SUB164(*(undefined *)puVar3 >> 0x40,0) & 0xffff)) {
return 0xc00000bb;
}
uVar6 = RtlULongAdd(uVar14,SUB164(*(undefined *)puVar3 >> 0x60,0),local_res10);
uVar16 = (undefined)uVar1;
if ((int)uVar6 < 0) {
if ((undefined **)WPP_GLOBAL_Control == &WPP_GLOBAL_Control) {
return 0xc000090b;
}
if ((*(uint *)(WPP_GLOBAL_Control + 0x2c) & 1) == 0) {
return 0xc000090b;
}
if (WPP_GLOBAL_Control[0x29] == '\0') {
return 0xc000090b;
}
WPP_SF_LL((char)*(undefined8 *)(WPP_GLOBAL_Control + 0x18),10,0x98,(char)uVar14,uVar16);
return 0xc000090b;
}
if ((ulonglong)(*(int *)(lVar7 + 0x24) + 0x100) + 0x34 < (ulonglong)local_res10[0]) {
if ((undefined **)WPP_GLOBAL_Control == &WPP_GLOBAL_Control) {
return 0xc000090b;
}
if ((*(uint *)(WPP_GLOBAL_Control + 0x2c) & 1) == 0) {
return 0xc000090b;
}
if (WPP_GLOBAL_Control[0x29] == '\0') {
return 0xc000090b;
}
WPP_SF_L();
return 0xc000090b;
}
lVar7 = SrvNetAllocateBuffer();
if (lVar7 == 0) {
return 0xc000009a;
}
lVar12 = *(longlong *)(param_1 + 0xf0);
uVar10 = SUB81(local_res10,0);
uVar9 = (ulonglong)uVar1;
uVar11 = (undefined)*(int *)(lVar12 + 0x24);
local_res10[0] = *(int *)(lVar12 + 0x24) - 0x10;
uVar8 = uVar16;
uVar6 = RtlULongSub(local_res10[0],uVar1,(int *)local_res10);
if ((int)uVar6 < 0) {
if ((((undefined **)WPP_GLOBAL_Control != &WPP_GLOBAL_Control) &&
((*(uint *)(WPP_GLOBAL_Control + 0x2c) & 1) != 0)) && (WPP_GLOBAL_Control[0x29] != '\0'))
{
WPP_SF_LLL((char)*(undefined8 *)(WPP_GLOBAL_Control + 0x18),uVar8,uVar10,uVar11,
in_stack_ffffffffffffffb8,uVar16);
}
}
else {
iVar5 = SmbCompressionDecompress
((ulonglong)uVar2,uVar9 + 0x10 + *(longlong *)(lVar12 + 0x18),
(ulonglong)local_res10[0],*(longlong *)(lVar7 + 0x18) + uVar9,uVar14,
local_res8,uVar13,uVar15);
if ((-1 < iVar5) && (local_res8[0] == uVar14)) {
if (uVar1 != 0) {
memcpy(*(undefined8 **)(lVar7 + 0x18),
(undefined8 *)(*(longlong *)(*(longlong *)(param_1 + 0xf0) + 0x18) + 0x10),uVar9);
}
*(int *)(lVar7 + 0x24) = local_res8[0] + uVar1;
Srv2ReplaceReceiveBuffer(param_1,lVar7);
return 0;
}
}
SrvNetFreeBuffer(lVar7);
เราจะสามารถเห็นจากแพตช์ได้ว่า เนื่องจากปัญหาการ Overflow เกิดขึ้นที่ฟังก์ชัน SrvNetAllocateBuffer
และเกี่ยวข้องกับค่า OriginalCompressedSegmentSize
และ OffsetOrLength
และโค้ดของแพตช์ที่เพิ่มเข้ามานั้นไม่มีจุดที่แก้ในกระบวนการตรวจสอบ CompressionAlgorithms
เลย เงื่อนไขเดียวที่เกี่ยวข้องกับ CompressionAlgorithms
นั้นคือค่าของ CompressionAlgorithms
ใน SMB2_TRANSFORM_HEADER
จะต้องตรงกับค่าของ CompressmionAlgorithms
ใน Negotitate Protocol Response เท่านั้น
ดังนั้นช่องโหว่นี้จึงไม่มีส่วนเกี่ยวข้องกับอัลกอริธึมที่ใช้ในการบีบอัด และในขณะเดียวกันการตรวจสอบว่าระบบนั้นมีช่องโหว่หรือไม่มีช่องโหว่จึงไม่สามารถทำได้แม้จะทำการตรวจสอบไปถึงระบบอัลกอริมธึมการบีบอีดใน SMB2_COMPRESSION_CAPABILITIES
ทางเลือกในการตรวจสอบช่องโหว่
ในมุมของผู้ดูแลระบบนั้น ทางเลือกในการตรวจสอบช่องโหว่ที่มีประสิทธิภาพที่สุดคือการระบุหารุ่นของระบบปฏิบัติการที่ได้รับผลกระทบและตรวจสอบ KB ที่ระบบติดตั้งอยู่ว่ามี KB4551762 หรือไม่
สำหรับในมุมของผู้โจมตี อาจแทบเป็นไปได้ที่จะยืนยันได้ว่าระบบที่จะโจมตีนั้นมีช่องโหว่ CVE-2020-0796 อยู่จริงแน่นอนหากต้องเริ่มต้นจากการไม่มีข้อมูลใดๆ เลย เพราะการยืนยันด้วย Active information gathering ก็ไม่สามาถระบุได้ว่าระบบดังกล่าวถูกแพตช์แล้วหรือยัง ดังนั้นวิธีการที่อาจยอมรับได้คือการระบุหาข้อมูลของระบบใดระบบหนึ่งที่เข้ายึดครองได้มาก่อนในเครือข่ายเป้าหมาาย และตรวจสอบความเป็นไปได้จากปัจจัยอื่นๆ ภายในองค์กร อาทิ ความกระตือรือล้นในการติดตั้งแพตช์และรับข้อมูลข่าวสารด้านภัยคุกคาม ปริมาณงานซึ่งอาจทำให้พนักงานภายในองค์กรไม่มีเวลามาทำการติดตั้งแพตช์ เป็นต้น ทั้งนี้การใช้ช่องโหว่ที่เป็นที่รู้จักอย่างช่องโหว่นี้ก็อาจสร้างความเสี่ยงที่จะส่งผลให้ปฏิบัติการถูกเปิดโปงได้เช่นเดียวกัน