diff --git a/.github/workflows/update.yml b/.github/workflows/update.yml index e1ccb9d..6835516 100644 --- a/.github/workflows/update.yml +++ b/.github/workflows/update.yml @@ -35,7 +35,7 @@ jobs: - name: commit changes # need to override the default shell so we can check - # for error codes. Otherwise it will always fail if + # for error codes. Otherwise, it will always fail if # one command returns an error code other than 0 shell: bash --noprofile --norc -o pipefail {0} run: | diff --git a/Readme.md b/Readme.md index fd7b5d8..7aba641 100644 --- a/Readme.md +++ b/Readme.md @@ -162,7 +162,7 @@ return the defaults. This command tries all passwords from a given file for a username via the TURN protocol (UDP). This can be useful when analysing a pcap where you can see the username but not the password. -Please note that an offline bruteforce is much more faster in this case. +Please note that an offline bruteforce is much faster in this case. ### Options @@ -226,9 +226,9 @@ If it works you should see big loads of memory coming in, otherwise you will onl ## udp-scanner -If a TURN server allows UDP connections to targets this scanner can be used to scan all private ip ranges and send them +If a TURN server allows UDP connections to internal targets this scanner can be used to scan all private ip ranges and send them SNMP and DNS requests. As this checks a lot of IPs this can take multiple days to complete so use with caution or -specify smaller targets via the parameters. You need to supply a SNMP community string that will be tried and a domain +specify smaller targets via the parameters. You need to supply an SNMP community string that will be tried and a domain name that will be resolved on each IP. For the domain name you can for example use burp collaborator. ### Options @@ -286,9 +286,9 @@ First step is to get the required data. I suggest to launch Wireshark in the bac to collect all HTTP and Websocket traffic. Next search your burp history for some keywords related to TURN like `3478`, `password`, `credential` and `username` (be sure to also check the websocket tab for these keywords). This might reveal the turn server and the protocol (UDP and TCP endpoints might have different ports) and the credentials used to connect. -If you can't find the data in burp start looking at wireshark to identify the traffic. If it's on a non standard port ( +If you can't find the data in burp start looking at wireshark to identify the traffic. If it's on a nonstandard port ( anything else then 3478) decode the protocol in Wireshark via a right click as `STUN`. This should show you the username -used to connect and you can use this information to search burps history even further for the required data. Please note +used to connect, and you can use this information to search burps history even further for the required data. Please note that Wireshark can't show you the password as the password is used to hash some package contents so it can not be reversed. diff --git a/internal/helper/connection.go b/internal/helper/connection.go index 46aa7b3..b9bf3c7 100644 --- a/internal/helper/connection.go +++ b/internal/helper/connection.go @@ -48,7 +48,8 @@ func connectionRead(ctx context.Context, r *bufio.Reader, maxSizeToRead *int, ti if err != nil { if err != io.EOF { // also return read data on timeout so caller can use it - if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + var netErr net.Error + if errors.As(err, &netErr) && netErr.Timeout() { return ret, ErrTimeout } return nil, err @@ -86,10 +87,9 @@ func ConnectionWrite(ctx context.Context, conn net.Conn, data []byte, timeout ti default: written, err = conn.Write(data[written:toWriteLeft]) if err != nil { - if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + var netErr net.Error + if errors.As(err, &netErr) && netErr.Timeout() { return ErrTimeout - } else { - return err } } if written == toWriteLeft { diff --git a/internal/helper/helper.go b/internal/helper/helper.go index f17bb6f..a74ccab 100644 --- a/internal/helper/helper.go +++ b/internal/helper/helper.go @@ -48,8 +48,7 @@ func IsPrivateIP(ip netip.Addr) bool { // numbers (16,383 possible values). func RandomChannelNumber() ([]byte, error) { token := make([]byte, 2) - valid := false - for !valid { + for { if _, err := cryptorand.Read(token); err != nil { return nil, err } diff --git a/internal/socksimplementations/socksturntcphandler.go b/internal/socksimplementations/socksturntcphandler.go index 16f6c18..c8606c9 100644 --- a/internal/socksimplementations/socksturntcphandler.go +++ b/internal/socksimplementations/socksturntcphandler.go @@ -30,7 +30,7 @@ type SocksTurnTCPHandler struct { nonce string } -// PreHandler connects to the STUN server, sets the connection up and returns the data connections +// Init connects to the STUN server, sets the connection up and returns the data connections func (s *SocksTurnTCPHandler) Init(ctx context.Context, request socks.Request) (context.Context, io.ReadWriteCloser, *socks.Error) { var target netip.Addr var err error @@ -129,8 +129,8 @@ func (s *SocksTurnTCPHandler) ReadFromClient(ctx context.Context, client io.Read for { // anonymous func for defer // this might not be the fastest, but it does the trick - // in this case the timeout is per buffer read/write to support long - // running downloads. + // in this case the timeout is per buffer read/write to support + // long-running downloads. err := func() error { timeOut := time.Now().Add(s.Timeout) @@ -174,8 +174,8 @@ func (s *SocksTurnTCPHandler) ReadFromRemote(ctx context.Context, remote io.Read for { // anonymous func for defer // this might not be the fastest, but it does the trick - // in this case the timeout is per buffer read/write to support long - // running downloads. + // in this case the timeout is per buffer read/write to support + // long-running downloads. err := func() error { timeOut := time.Now().Add(s.Timeout) @@ -214,8 +214,8 @@ func (s *SocksTurnTCPHandler) ReadFromRemote(ctx context.Context, remote io.Read } } -// Cleanup closes the stored control connection -func (s *SocksTurnTCPHandler) Close(ctx context.Context) error { +// Close closes the stored control connection +func (s *SocksTurnTCPHandler) Close(_ context.Context) error { if s.ControlConnection != nil { return s.ControlConnection.Close() } diff --git a/internal/stun.go b/internal/stun.go index ad52556..4f3ef77 100644 --- a/internal/stun.go +++ b/internal/stun.go @@ -56,7 +56,7 @@ func (s *Stun) String() string { // Serialize converts the object into a byte stream func (s *Stun) Serialize() ([]byte, error) { - // first start with the attributes so we can calculate the message length afterwards + // first start with the attributes so we can calculate the message length afterward var attributes []byte authenticated := false for _, a := range s.Attributes { diff --git a/internal/types_turn.go b/internal/types_turn.go index 04a7288..25917ca 100644 --- a/internal/types_turn.go +++ b/internal/types_turn.go @@ -5,7 +5,7 @@ package internal 0x004 : Refresh (only request/response semantics defined) 0x006 : Send (only indication semantics defined) 0x007 : Data (only indication semantics defined) -0x008 : CreatePermission (only request/response semantics defined +0x008 : CreatePermission (only request/response semantics defined) 0x009 : ChannelBind (only request/response semantics defined) This STUN extension defines the following new attributes: