ทางเลือกในการตรวจสอบที่ได้ผลจริงๆ มีเพียงสองกรณี คือการตรวจสอบแพตช์ด้วยโซลูชันต่างๆ และการตรวจสอบโดยการทดสอบโจมตีจริง วิธีการการตรวจสอบโดยใช้สคริปต์ Scanner ไม่สามารถช่วยยืนยันได้ว่าระบบมีช่องโหว่จริงหรือไม่

หลังการหลุดออกมาของรายละเอียดของช่องโหว่ในฟังก์ชันซึ่งมีการใช้โปรโตคอล SMB รวมไปถึงคุณลักษณะที่ช่องโหว่นั้น Wormable ได้ เราเห็นความตื่นตัวที่เพิ่มขึ้นมาอย่างฉับพลันและสะท้อนให้เห็นถึงการเรียนรู้จากการแพร่กระจายของ WannaCry ซึ่งโจมตีช่องโหว่ CVE-2017-0143 และ CVE-2017-0144 ด้วย ETERNALBLUE หนึ่งในความตื่นตัวนั้นคือการปรากฎออกมาถึงวิธีการในใช้เพื่อยืนยันการมีอยู่ของช่องโหว่ในระบบต่างๆ ในรูปแบบของสคริปต์ที่สามารถทำงานได้จากการระบุเพียงแค่หมายเลขไอพีแอดเดรสที่ต้องการตรวจสอบไปอย่างเดียว

อย่างไรก็ตามเนื่องจากที่มีของช่องโหว่นี้นั้นมาจากการ “หลุด” และยังเห็นได้ถึงความพยายามในการปิดข่าวก่อนที่ทางไมโครซอฟต์จะพร้อมปล่อยแพตช์จริงๆ ในช่วงนั้นเราอาจพูดได้ว่าแทบไม่มีใครที่ทราบอย่างแท้จริงถึงรายละเอียดและที่มาของช่องโหว่นั้นนอกเสียจากเป็นบุคคลกลุ่มที่หนึ่งและที่สองซึ่งเกี่ยวข้องกับการป้องกันและลดผลกระทบจากการโจมตีช่องโหว่นี้เองที่ควรจะทราบข้อมูลดีที่สุด

ด้วยเหตุนี้เราอาจถือได้ว่าผลผลิตใดๆ ที่เกิดในช่วงเวลาที่ข้อมูลยังไม่ชัดเจนนั้นสามารถที่จะสร้างผลลัพธ์ที่ไม่ชัดเจนได้ตามข้อมูลที่มันนำมาประเมิน และนี่คือประเด็นหลักที่เราจะพูดถึงกันในบล็อกนี้ครับ

การเกิดขึ้นของสคริปต์ 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 ได้ตามขั้นตอนดังต่อไปนี้

  1. เชื่อมไปต่อไปยังพอร์ต 445 ของหมายเลขไอพีแอดเดรสที่ระบุ
  2. ทำการส่งข้อมูลที่ถูกเก็บในตัวแปร pkt ไป โดยข้อมูลที่ถูกเก็บอยู่ในตัวแปร pkt คือข้อมูลที่ SMB จะส่งเพื่อทำกระบวนการ Negotitate Protocol Request
  3. เมื่อปลายทางได้รับ Negotitate Protocol Request มันจะทำการส่ง Negotitate Protocol Response มา โดยค่านี้จะถูกเก็บไว้ที่ตัวแปร res
  4. สคริปต์ทำการตรวจสอบค่าในตัวแปร res ในสองตำแหน่ง ได้แก่
    1. ตำแหน่ง 0x7e - 0x7f ว่ามีค่าเป็น \x11\x03 หรือไม่
    2. ตำแหน่ง 0x80 - 0x81 ว่ามีค่าเป็น \x02\x00 หรือไม่
  5. ข้อความ 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 ก็ไม่สามาถระบุได้ว่าระบบดังกล่าวถูกแพตช์แล้วหรือยัง ดังนั้นวิธีการที่อาจยอมรับได้คือการระบุหาข้อมูลของระบบใดระบบหนึ่งที่เข้ายึดครองได้มาก่อนในเครือข่ายเป้าหมาาย และตรวจสอบความเป็นไปได้จากปัจจัยอื่นๆ ภายในองค์กร อาทิ ความกระตือรือล้นในการติดตั้งแพตช์และรับข้อมูลข่าวสารด้านภัยคุกคาม ปริมาณงานซึ่งอาจทำให้พนักงานภายในองค์กรไม่มีเวลามาทำการติดตั้งแพตช์ เป็นต้น ทั้งนี้การใช้ช่องโหว่ที่เป็นที่รู้จักอย่างช่องโหว่นี้ก็อาจสร้างความเสี่ยงที่จะส่งผลให้ปฏิบัติการถูกเปิดโปงได้เช่นเดียวกัน