jfjallid / go-smb

A client library to interact with Windows RPC services such as MS-SRVS and MS-RRP.
MIT License
42 stars 9 forks source link

[Bug] hanging with server 2003 #8

Closed XiaoliChan closed 8 months ago

XiaoliChan commented 9 months ago

As the title said, when the target OS is Server 2003, it will be hanging, even set the DialTimeout

image

jfjallid commented 9 months ago

Thanks for the bug report. I don't currently have access to a Windows 2003 server to debug the problem so might take a while to figure out what is wrong.

Could you provide a PCAP with the network traffic when this occurs with encryption disabled?

XiaoliChan commented 9 months ago

@jfjallid Sure, here are two pcap file

the go-smb.pcap (DisableEncryption: true) is using this repository, and impacket.pcap is using impacket

smb-pcap.zip

Example

options := smb.Options{                                                                                                                                                                            
                Host: hostname,                                                                                                                                                                            
                Port: 445,                                                                                                                                                                                 
                Initiator: &smb.NTLMInitiator{                                                                                                                                                             
                        User:               "Administrator",                                                                                                                                               
                        Password:           "111qqq...",                                                                                                                                                   
                        Domain:             "",                                                                                                                                                            
                        EncryptionDisabled: true,                                                                                                                                                          
                },                                                                                                                                                                                         
        }
XiaoliChan commented 9 months ago

I probably know why it will hang because it negotiates 2003 with SMB2, but server 2003 does not support SMB2

It will be hanging for about 4-5 minutes even I set DialTimeout and it return EOF

XiaoliChan commented 9 months ago

I probably know how to play with it, just send data to target SMB service 00000045ff534d4272000000001801c8000000000000000000000000ffff000000000000002200024e54204c4d20302e31320002534d4220322e3030320002534d4220322e3f3f3f00

If the response data start with \xfe, that means the SMB version is higher than SMBv1

Reference:

jfjallid commented 9 months ago

Yes, you're correct. I have not implemented support for SMB 1, but I'll fix the problem with the connection hanging.

XiaoliChan commented 9 months ago

I think you can add an if condition to fix it temporary, like

if !strings.HasPrefix("SMB_Response", "\xfe") {
    resp := fmt.Sprintf("[-] Target %s is only accept SMBv1, but SMBv1 isn't implement yet.")
    return resp
}
XiaoliChan commented 9 months ago

I make a demo to test it

package main

import (
    "bytes"
    "fmt"
    "net"
)

func main() {
    // Hex-encoded packet string (from impacket & get it from wireshark)
    packetBytes := []byte{0x00, 0x00, 0x00, 0x45, 0xff, 0x53, 0x4d, 0x42, 0x72, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01, 0xc8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x4e, 0x54, 0x20, 0x4c, 0x4d, 0x20, 0x30, 0x2e, 0x31, 0x32, 0x00, 0x02, 0x53, 0x4d, 0x42, 0x20, 0x32, 0x2e, 0x30, 0x30, 0x32, 0x00, 0x02, 0x53, 0x4d, 0x42, 0x20, 0x32, 0x2e, 0x3f, 0x3f, 0x3f, 0x00}

    // Target host and port
    targetHost := "192.168.1.175"
    targetPort := "445"

    // Send the packet to the target host on port 445
    conn, err := net.Dial("tcp", fmt.Sprintf("%v:%v", targetHost, targetPort))
    if err != nil {
        fmt.Println("Error connecting to the target:", err)
        return
    }
    defer conn.Close()

    _, err = conn.Write(packetBytes)
    if err != nil {
        fmt.Println("Error sending packet:", err)
        return
    }

    fmt.Println("Packet sent successfully!")

    // Read the response from the target
    response := make([]byte, 5)
    n, err := conn.Read(response)
    if err != nil {
        fmt.Println("Error reading response:", err)
        return
    }

    if bytes.Contains(response[:n], []byte{0xfe}) {
        fmt.Println("[+] Target SMB version higher than v1")
    }
}
XiaoliChan commented 9 months ago

@jfjallid Another bug: Status 0xC0000234 is missing, it should be user is currently locked out

jfjallid commented 8 months ago

Turns out that the reason for the connection hanging is that this lib only attempts to send SMB2 packets and because Windows Server 2003 does not support SMB2 it will not respond to the requests. DialTimeout only affects the connection establishment e.g., the first TCP packet. The server opens the connection and waits for an SMB packet but only receives the SMB2 packet which it appears to discard while it waits for another one that never arrives.

I've released a new update with tag v0.3.3 that will attempt to perform SMB Multi-Protocol negotiate and close the connection if the server only responds with SMB1 packets to the Negotiate Protocol request.

Can you test against the Windows Server 2003 to see if it correctly identifies that only SMB1 is supported and close the connection? I've also added the missing "user is currently locked out" status message to the same release.

XiaoliChan commented 8 months ago

It works when detects the target protocol is not SMBv2, but the program seems like will not exit

I must use Ctrl + C to break it image

Demo code https://github.com/jfjallid/go-smb#list-smb-shares

XiaoliChan commented 8 months ago

BTW, how to disable the internal log to avoid raising error messages like this

2024/02/05 00:54:09 smb [Error] Received unknown SMB Header status for Create/open file response when opening with special options: 0xc00000ac
jfjallid commented 8 months ago

BTW, how to disable the internal log to avoid raising error messages like this

2024/02/05 00:54:09 smb [Error] Received unknown SMB Header status for Create/open file response when opening with special options: 0xc00000ac

The logging is handled by the lib github.com/jfjallid/golog Each module has its own logging settings that can be controlled to increase/decrease verbosity and to some extent modify the content of the outprint.

This specific message is handled by the smb module which can be seen as it is prefixed by the shortname "smb". So to disable the logging for this module you can import golog to your project and then call the following function in your code before you create the smb connection:

golog.Set("github.com/jfjallid/go-smb/smb", "smb", golog.LevelNone, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
XiaoliChan commented 8 months ago

Awesome, will test it tomorrow

The logging is handled by the lib github.com/jfjallid/golog Each module has its own logging settings that can be controlled to increase/decrease verbosity and to some extent modify the content of the outprint.

This specific message is handled by the smb module which can be seen as it is prefixed by the shortname "smb". So to disable the logging for this module you can import golog to your project and then call the following function in your code before you create the smb connection:

golog.Set("github.com/jfjallid/go-smb/smb", "smb", golog.LevelNone, golog.LstdFlags|golog.Lshortfile, golog.DefaultOutput, golog.DefaultErrOutput)
jfjallid commented 8 months ago

Sorry for the slow response. Forgot to handle the case where the server only responds with an SMBv1 message (which is expected when that is the only supported protocol.) I've released a new update with tag v0.3.4 that should correctly handle the issue and log an error message that SMBv1 is not supported before terminating the connection.

XiaoliChan commented 8 months ago

Sweet, I will test it later, thanks for your work!

XiaoliChan commented 8 months ago

Awesome, can confirm it works now :) image