summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2013-01-17 09:48:13 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2013-01-17 09:48:13 +0100
commita3686893c77a0ebe37043a6a52504e077e9abd6b (patch)
tree3ac2e5ea21dc81638f48c7f1b7c22dd560bf53f4
parentDon't allow more privs. (diff)
downloadtelnet-password-honeypot-a3686893c77a0ebe37043a6a52504e077e9abd6b.tar.xz
telnet-password-honeypot-a3686893c77a0ebe37043a6a52504e077e9abd6b.zip
Use seccomp bpf filter.
-rw-r--r--Makefile2
-rw-r--r--honeypot.c41
-rw-r--r--seccomp-bpf.h44
3 files changed, 82 insertions, 5 deletions
diff --git a/Makefile b/Makefile
index 0b87cac..16a3197 100644
--- a/Makefile
+++ b/Makefile
@@ -1 +1 @@
-honeypot: honeypot.c telnet.h
+honeypot: honeypot.c telnet.h seccomp-bpf.h
diff --git a/honeypot.c b/honeypot.c
index 02fc17a..7b5c768 100644
--- a/honeypot.c
+++ b/honeypot.c
@@ -64,6 +64,8 @@
* a protocol, and not just raw text transmission)
*/
#include "telnet.h"
+#include "seccomp-bpf.h"
+
FILE *input = 0;
FILE *output = 0;
@@ -435,7 +437,36 @@ void drop_privileges()
limit.rlim_cur = limit.rlim_max = 100;
setrlimit(RLIMIT_NPROC, &limit);
- prctl(PR_SET_NO_NEW_PRIVS, 1);
+ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+ perror("prctl(NO_NEW_PRIVS");
+ exit(EXIT_FAILURE);
+ }
+}
+
+void seccomp_enable_filter()
+{
+ struct sock_filter filter[] = {
+ VALIDATE_ARCHITECTURE,
+ EXAMINE_SYSCALL,
+ ALLOW_SYSCALL(rt_sigreturn),
+ ALLOW_SYSCALL(rt_sigprocmask),
+ ALLOW_SYSCALL(rt_sigaction),
+ ALLOW_SYSCALL(nanosleep),
+ ALLOW_SYSCALL(exit_group),
+ ALLOW_SYSCALL(exit),
+ ALLOW_SYSCALL(read),
+ ALLOW_SYSCALL(write),
+ ALLOW_SYSCALL(alarm),
+ KILL_PROCESS
+ };
+ struct sock_fprog prog = {
+ .len = (unsigned short)(sizeof(filter) / sizeof(filter[0])),
+ .filter = filter
+ };
+ if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &prog)) {
+ perror("prctl(SECCOMP)");
+ exit(EXIT_FAILURE);
+ }
}
void handle_connection(int fd, char *ipaddr)
@@ -443,12 +474,12 @@ void handle_connection(int fd, char *ipaddr)
char username[1024];
char password[1024];
struct rlimit limit;
-
+
limit.rlim_cur = limit.rlim_max = 90;
setrlimit(RLIMIT_CPU, &limit);
limit.rlim_cur = limit.rlim_max = 0;
setrlimit(RLIMIT_NPROC, &limit);
-
+
input = fdopen(fd, "r");
if (!input) {
perror("fdopen");
@@ -459,6 +490,8 @@ void handle_connection(int fd, char *ipaddr)
perror("fdopen");
_exit(EXIT_FAILURE);
}
+
+ seccomp_enable_filter();
/* Set the alarm handler to quit on bad telnet clients. */
if (signal(SIGALRM, SIGALRM_handler) == SIG_ERR) {
@@ -470,7 +503,7 @@ void handle_connection(int fd, char *ipaddr)
perror("signal");
_exit(EXIT_FAILURE);
}
-
+
negotiate_telnet();
/* Quit after a minute and a half. */
diff --git a/seccomp-bpf.h b/seccomp-bpf.h
new file mode 100644
index 0000000..f2a259c
--- /dev/null
+++ b/seccomp-bpf.h
@@ -0,0 +1,44 @@
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/prctl.h>
+
+#include <linux/unistd.h>
+#include <linux/audit.h>
+#include <linux/filter.h>
+#include <linux/seccomp.h>
+
+#define syscall_nr (offsetof(struct seccomp_data, nr))
+#define arch_nr (offsetof(struct seccomp_data, arch))
+
+#if defined(__i386__)
+# define REG_SYSCALL REG_EAX
+# define ARCH_NR AUDIT_ARCH_I386
+#elif defined(__x86_64__)
+# define REG_SYSCALL REG_RAX
+# define ARCH_NR AUDIT_ARCH_X86_64
+#else
+# warning "Platform does not support seccomp filter yet"
+# define REG_SYSCALL 0
+# define ARCH_NR 0
+#endif
+
+#define VALIDATE_ARCHITECTURE \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, arch_nr), \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, ARCH_NR, 1, 0), \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)
+
+#define EXAMINE_SYSCALL \
+ BPF_STMT(BPF_LD+BPF_W+BPF_ABS, syscall_nr)
+
+#define ALLOW_SYSCALL(name) \
+ BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, __NR_##name, 0, 1), \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ALLOW)
+
+#define KILL_PROCESS \
+ BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_KILL)