1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
|
From: Aron Xu <aron@debian.org>
Date: Mon, 13 Feb 2012 19:06:52 +0800
Subject: Misc failures and features
---
nc.1 | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++
netcat.c | 37 +++++++++++++++++++++++++++++--------
2 files changed, 80 insertions(+), 8 deletions(-)
diff --git a/nc.1 b/nc.1
index 8285c10..a159c73 100644
--- a/nc.1
+++ b/nc.1
@@ -371,6 +371,54 @@ The connection may be terminated using an
as the
.Fl N
flag was given.
+.Pp
+There is no
+.Fl c
+or
+.Fl e
+option in this netcat, but you still can execute a command after connection
+being established by redirecting file descriptors. Be cautious here because
+opening a port and let anyone connected execute arbitrary command on your
+site is DANGEROUS. If you really need to do this, here is an example:
+.Pp
+On
+.Sq server
+side:
+.Pp
+.Dl $ rm -f /tmp/f; mkfifo /tmp/f
+.Dl $ cat /tmp/f | /bin/sh -i 2>&1 | nc -l 127.0.0.1 1234 > /tmp/f
+.Pp
+On
+.Sq client
+side:
+.Pp
+.Dl $ nc host.example.com 1234
+.Dl $ (shell prompt from host.example.com)
+.Pp
+By doing this, you create a fifo at /tmp/f and make nc listen at port 1234
+of address 127.0.0.1 on
+.Sq server
+side, when a
+.Sq client
+establishes a connection successfully to that port, /bin/sh gets executed
+on
+.Sq server
+side and the shell prompt is given to
+.Sq client
+side.
+.Pp
+When connection is terminated,
+.Nm
+quits as well. Use
+.Fl k
+if you want it keep listening, but if the command quits this option won't
+restart it or keep
+.Nm
+running. Also don't forget to remove the file descriptor once you don't need
+it anymore:
+.Pp
+.Dl $ rm -f /tmp/f
+.Pp
.Sh DATA TRANSFER
The example in the previous section can be expanded to build a
basic data transfer model.
@@ -523,6 +571,9 @@ Original implementation by
.br
Rewritten with IPv6 support by
.An Eric Jackson Aq Mt ericj@monkey.org .
+.br
+Modified for Debian port by Aron Xu
+.Aq aron@debian.org .
.Sh CAVEATS
UDP port scans using the
.Fl uz
diff --git a/netcat.c b/netcat.c
index 2f8890b..2a3714a 100644
--- a/netcat.c
+++ b/netcat.c
@@ -114,7 +114,7 @@
#include "atomicio.h"
#define PORT_MAX 65535
-#define UNIX_DG_TMP_SOCKET_SIZE 19
+#define UNIX_DG_TMP_SOCKET_SIZE 25
#define POLL_STDIN 0
#define POLL_NETOUT 1
@@ -618,10 +618,20 @@ main(int argc, char *argv[])
if (sflag) {
unix_dg_tmp_socket = sflag;
} else {
- strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
+ /* On Linux it's tempting to use abstract sockets here in
+ * order to limit bookkeeping and avoid cluttering /tmp.
+ * Unfortunately though this has security implications, as a
+ * second client could inject server responses if they
+ * manage to connect(2) to the temporary socket between the
+ * first client's bind(2) and connect(2) calls. OTOH for
+ * pathname sockets the injection is only possible on Linux
+ * when write access to the socket is granted. */
+ strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc-XXXXXX",
+ UNIX_DG_TMP_SOCKET_SIZE);
+ if (mkdtemp(unix_dg_tmp_socket_buf) == NULL)
+ err(1, "mkdtemp");
+ strlcat(unix_dg_tmp_socket_buf, "/recv.sock",
UNIX_DG_TMP_SOCKET_SIZE);
- if (mktemp(unix_dg_tmp_socket_buf) == NULL)
- err(1, "mktemp");
unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
}
}
@@ -851,8 +861,14 @@ main(int argc, char *argv[])
ret = 1;
}
- if (uflag)
+ if (uflag && !sflag) {
unlink(unix_dg_tmp_socket);
+ char *nam = strrchr(unix_dg_tmp_socket, '/');
+ if (nam != NULL) {
+ nam[0] = '\0';
+ rmdir(unix_dg_tmp_socket);
+ }
+ }
return ret;
} else {
int i = 0;
@@ -991,6 +1007,11 @@ unix_bind(char *path, int flags)
0)) == -1)
return -1;
+#ifdef __linux__
+ if (path[0] != '@')
+#endif
+ unlink(path);
+
if (bind(s, (struct sockaddr *)&s_un, addrlen) == -1) {
save_errno = errno;
close(s);
@@ -1108,7 +1129,7 @@ unix_connect(char *path)
if (uflag) {
if ((s = unix_bind(unix_dg_tmp_socket, SOCK_CLOEXEC)) == -1)
- return -1;
+ err(1, "%s", unix_dg_tmp_socket);
} else {
if ((s = socket(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0)) == -1)
return -1;
@@ -1381,12 +1402,12 @@ local_listen(const char *host, const char *port, struct addrinfo hints)
ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &x, sizeof(x));
if (ret == -1)
- err(1, NULL);
+ warn("Couldn't set SO_REUSEADDR");
#ifdef SO_REUSEPORT
ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
if (ret == -1)
- err(1, NULL);
+ warn("Couldn't set SO_REUSEPORT");
#endif
set_common_sockopts(s, res->ai_addr);
|