Phân tích lỗ hổng trên giao thức SMB server

1040

SMB Server là gì

SMB server là giao thức chia sẻ file qua cổng 445. Giao thức này được xử lý chính ở driver file srv.sys, srvnet.sys.

Lỗ hổng nghiệm trọng tron thời gian vừa rồi bắt nguồn từ các hàm: SrvOs2FeaToNt,SrvOs2FeaListSizeToNt,SrvOs2FeaToNt. Trong các hàm chức năng liên quan Open, CreateDirectory tại srv.sys.

Vấn đề nằm ở hàm tính toán kích thước : SrvOs2FeaListSizeToNt  sẽ tính toán sai kích thước khi có 2 paged memory pool tiếp chung một vùng bị gộp lại.

unsigned  int  __fastcall  SrvOs2FeaListSizeToNt(int  pOs2Fea)

{

…..

{

if  (  pBody  +  4 >=  v4

||  (v5  =  *(_BYTE  *)(pBody  +  1)  +  *(_WORD  *)(pBody  +  2),

v8  =  *(_BYTE  *)(pBody  +  1)  +  *(_WORD  *)(pBody  +  2),

v5  +  pBody  +  5 >  v4)  )

{

*(_WORD  *)pOs2Fea  =  pBody  –  pOs2Fea;

return  v1;

}

if  (  RtlULongAdd(v1,  (v5  +  0xC) &  0xFFFFFFFC, &v9) <  0  )

return  0;

v1  =  v9;

pBody  +=  v8  +  5;

}

return  v1;

}

Dẫn đến tiếp theo càng hàm xử lý càng làm kích thước dữ liệu sai lệch lớn:

unsigned  int  __fastcall  SrvOs2FeaListToNt(int  pOs2Fea,  int  *pArgNtFea,  int  *a3,  _WORD  *a4)

{

…….

while  (  !(*(_BYTE  *)pOs2FeaBody &  0x7F)  )

{

v12  =  (int)pNtFea;

v5  =  pOs2FeaBody;

pNtFea  =  (NTFEA  *)SrvOs2FeaToNt(pNtFea,  pOs2FeaBody);

pOs2FeaBody  +=  *(_BYTE  *)(pOs2FeaBody  +  1)  +  *(_WORD  *)(pOs2FeaBody  +  2)  +  5;

//  bởi vì SrvOs2FeaListSizeToNt tính pOs2Fea sai, cho nên số lượng dữ liệu bị memove tại đây tràn ra.

if  (  pOs2FeaBody >  v14  )

{v10  =  v12;

goto  LABEL_13;

}

……..

}

Đầu tiên SrvOs2FeaListToNt sử dụng hàm SrvOs2FeaListSizeToNt để tính kích thước pNtFea, SrvOs2FeaListSizeToNt sẽ sửa đổi giá trị kích thước tại pOs2Fea  sau đó tính toán ra độ dài để alloc cho  pNtFea, cuối cùng dùng SrvOs2FeaToNt để convert dữ liệu. Quá trình này sẽ nảy sinh vấn đề logic ở việc kiểm tra pOs2FeaBody để kết thúc vòng lặp memove,convert dữ liệu. Và với việc SrvOs2FeaListSizeToNt thay đổi gía trị pOs2Fea, khi tính toán các số quá lớn, sẽ làm tràn.

Cách thức khai thác

Sau khi gây lỗi tràn bộ đẹm, điều khiển được EIP của chương trình về shellcode.

Vì đây là lỗ hổng ở kernelmode nên shellcode exploit chỉ có thể sử dụng một số native API của ntoskrnl.exe hoặc các driver khác. Cho nên trong quá trình này shellcode sẽ thực thi các công việc sau để tạo 1 backdoor với chức năng Inject dll vào userland process chứ không có hành động can thiệp trực tiếp vào dữ liệu người dùng trên máy.

Bước 0: shellcode xác định xem hệ điều hành hiện tại là x86 hay x64

Bước 1: Định vị IDT Entry từ KPCR và từ địa chỉ đó lần ngược trở lại địa chỉ base address của ntoskrnl.exe (có header DOS MZ).

Bước 2: Từ base adddress của ntoskrnl.exe tìm các hàm ExAllocPool / ExFreePool / ZwQuerySystemInformation. Từ export table bằng hash name, tương tự usermode

Bước 3: Gọi ZwQuerySystemInformation () tìm tất cả drivers, tìm Srv.sys driver của SMB.

Bước 4: Hook SrvTransactionNotImplemented () trong SrvTransaction2DispatchTable [14] để tạo chức năng backdoor trên giao thức smb .

Bước 5: Dựa vào việc hook hàm xử lý. Khi input đúng điều kiện sẽ thực hiện các chức năng backdoor như Injectdll, thực thi shellcode khác…

Quá trình khai thác

Sử dụng msfvenom (kalilinux) để generate một payload dll (shell.dll) có chức năng backconnect về máy ta.

Và thực hiện lệnh lắng nghe cổng 4444

Gửi file dll đã tạo qua exploit NSA:

Exploit thành công: