diff options
author | Anton Luka Šijanec <anton@sijanec.eu> | 2024-09-01 00:15:18 +0200 |
---|---|---|
committer | Anton Luka Šijanec <anton@sijanec.eu> | 2024-09-01 00:15:18 +0200 |
commit | b94bef6e820fec0ffde7971d3134d5738c1521d1 (patch) | |
tree | 2ae275e51629ae9979a7303f5605bb4988b30234 /iv | |
parent | hacker gets hacked, double fdput vuln (diff) | |
download | r-b94bef6e820fec0ffde7971d3134d5738c1521d1.tar r-b94bef6e820fec0ffde7971d3134d5738c1521d1.tar.gz r-b94bef6e820fec0ffde7971d3134d5738c1521d1.tar.bz2 r-b94bef6e820fec0ffde7971d3134d5738c1521d1.tar.lz r-b94bef6e820fec0ffde7971d3134d5738c1521d1.tar.xz r-b94bef6e820fec0ffde7971d3134d5738c1521d1.tar.zst r-b94bef6e820fec0ffde7971d3134d5738c1521d1.zip |
Diffstat (limited to 'iv')
-rw-r--r-- | iv/orodja/ldmitm/Makefile | 5 | ||||
-rw-r--r-- | iv/orodja/ldmitm/ldmitm.c | 153 | ||||
-rw-r--r-- | iv/orodja/ldmitm/tcp_times.c | 1 | ||||
-rw-r--r-- | iv/orodja/ldmitm/tcp_times_example.c | 32 | ||||
-rw-r--r-- | iv/orodja/napad/.gitignore | 1 | ||||
-rw-r--r-- | iv/orodja/napad/config | 44 | ||||
-rwxr-xr-x | iv/orodja/napad/exploit.sh | 23 | ||||
-rwxr-xr-x | iv/orodja/napad/submission.py | 64 | ||||
-rw-r--r-- | iv/orodja/waf/Dockerfile | 6 | ||||
-rw-r--r-- | iv/orodja/waf/regexes.txt | 2 | ||||
-rw-r--r-- | iv/orodja/waf/waf.py | 85 |
11 files changed, 363 insertions, 53 deletions
diff --git a/iv/orodja/ldmitm/Makefile b/iv/orodja/ldmitm/Makefile index 4010899..1ef8a92 100644 --- a/iv/orodja/ldmitm/Makefile +++ b/iv/orodja/ldmitm/Makefile @@ -14,4 +14,7 @@ clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean rm ldmitm.so tcp_times_example -.PHONY: allmods clean +prepare: + apt install libsqlite3-dev linux-headers-generic + +.PHONY: allmods clean prepare diff --git a/iv/orodja/ldmitm/ldmitm.c b/iv/orodja/ldmitm/ldmitm.c index 66cba41..2b8b815 100644 --- a/iv/orodja/ldmitm/ldmitm.c +++ b/iv/orodja/ldmitm/ldmitm.c @@ -5,7 +5,7 @@ Kako deluje: https://tbrindus.ca/correct-ld-preload-hooking-libc/ Prevedi z: gcc -shared -fPIC -ldl ldmitm.c -o ldmitm.so Poženi z: LD_PRELOAD=$PWD/ldmitm.so php -S 0:1234 A je treba beležit execve in fopen? Po mojem ne. Odtekanje flagov itak vidimo v TCP sessionu. -TODO: add mutex locks!!! +TODO: add mutex locks, openssl bio mitm, read, write, rtt, timestamps (if possible), namesto trenutnega mtu rajši dobi advertised mss iz tcp_info, dobi last ack timestamp option value: https://elixir.bootlin.com/linux/v6.11-rc3/source/include/linux/tcp.h#L302 <= tu notri je mogoče z BPF??? */ #include <stdio.h> #include <dlfcn.h> @@ -18,20 +18,25 @@ TODO: add mutex locks!!! #include <netinet/in.h> #include <arpa/inet.h> #include <string.h> +#include <sys/param.h> +#include <netinet/ip.h> #if SQLITE_VERSION_NUMBER < 3037000 #error "we require sqlite newer than 3037000, yours is " #SQLITE_VERSION_NUMBER " --- because of STRICT!" #endif #define LOG(x, ...) if (getenv("LDMITM_LOG")) printf("[ldmitm %s] " x "\n", __func__ __VA_OPT__(,) __VA_ARGS__) struct stream { - bool active; - bool silenced; - int id; // id in sqlite3 database + bool active; // only stream connections are true, listening sockets and inactive fds are false + bool silenced; // only makes sense for stream connections, true to silence traffic + int id; // id in sqlite3 database -- only makes sense for stream connections + int bound; // for listening sockets: port, for stream sockets: fd of listening socket }; typedef int (*accept_t)(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len); typedef int (*close_t)(int fd); -static accept_t real_accept; -static close_t real_close; -static __thread sqlite3 * db = NULL; +typedef int (*bind_t)(int sockfd, const struct sockaddr *addr, socklen_t addrlen); +static accept_t real_accept = NULL; +static close_t real_close = NULL; +static bind_t real_bind = NULL; +static sqlite3 * db = NULL; struct stream * streams = NULL; int streams_sizeof = 0; static void setup_db () { // should be able to ignore being called in case db is already set up on this thread @@ -74,8 +79,8 @@ static void setup_db () { // should be able to ignore being called in case db is LOG("failed to step create " name ": %s", sqlite3_errstr(ret)); \ goto fail; \ } - CREATE_TABLE("connections", "id INTEGER PRIMARY KEY, peer TEXT NOT NULL, accepted TEXT DEFAULT (strftime('%FT%R:%f', 'now')) NOT NULL, closed TEXT, silenced TEXT"); // accepted, closed and silenced are iso datestrings - CREATE_TABLE("messages", "connection INTEGER NOT NULL, direction INTEGER NOT NULL CHECK (direction IN (0, 1)), time TEXT DEFAULT (strftime('%FT%R:%f', 'now')) NOT NULL, FOREIGN KEY(connection) REFERENCES connections(id)"); + CREATE_TABLE("connections", "id INTEGER PRIMARY KEY, bound INTEGER NOT NULL, peer TEXT NOT NULL, accepted TEXT DEFAULT (strftime('%FT%R:%f', 'now')) NOT NULL, closed TEXT, silenced TEXT, mtu INTEGER NOT NULL"); // accepted, closed and silenced are iso datestrings, bound is listening port + CREATE_TABLE("messages", "connection INTEGER NOT NULL, direction INTEGER NOT NULL CHECK (direction IN (0, 1)), time TEXT DEFAULT (strftime('%FT%R:%f', 'now')) NOT NULL, rtt INTEGER NOT NULL, FOREIGN KEY(connection) REFERENCES connections(id)"); return; fail: if (db) @@ -114,6 +119,74 @@ static void end_stream (int fd) { // cleanup function, should be able to handle fail: memset(&(streams[fd]), 0, sizeof streams[fd]); } +static bool more_fds (int largest_fd) { + if (largest_fd >= streams_sizeof) { + int streams_sizeof_new; + if (streams_sizeof == 0) + streams_sizeof_new = 128; + else + streams_sizeof_new = streams_sizeof * 2; + struct stream * streams_new = realloc(streams, streams_sizeof_new*sizeof *streams); + if (!streams_new) { + LOG("ENOMEM realloc streams!"); + return false; + } + memset(streams_new+streams_sizeof, 0, (streams_sizeof_new-streams_sizeof)*sizeof *streams); + streams = streams_new; + streams_sizeof = streams_sizeof_new; + } + if (largest_fd < streams_sizeof) + return true; + return more_fds(largest_fd); +} +static int port_from_sa (const struct sockaddr * sa) { // gets port from sockaddr + switch (sa->sa_family) { + case AF_INET: + return ntohs(((struct sockaddr_in *) sa)->sin_port); + case AF_INET6: + return ntohs(((struct sockaddr_in6 *) sa)->sin6_port); + default: + return -1; + } +} +static void str_from_sa (char * peeraddress, const struct sockaddr * address) { + switch (address->sa_family) { + case AF_INET: + if (!inet_ntop(AF_INET, &(((struct sockaddr_in *) address)->sin_addr), peeraddress, *address_len)) { + int myerrno = errno; + strcpy(peeraddress, "!"); + strcat(peeraddress, strerror(myerrno)); + } + sprintf(peeraddress+strlen(peeraddress), "/%d", ntohs(((struct sockaddr_in *) address)->sin_port)); + break; + case AF_INET6: + if (!inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) address)->sin6_addr), peeraddress, *address_len)) { + int myerrno = errno; + strcpy(peeraddress, "!"); + strcat(peeraddress, strerror(myerrno)); + } + sprintf(peeraddress+strlen(peeraddress), "/%d", ntohs(((struct sockaddr_in6 *) address)->sin6_port)); + break; + default: + strcpy(peeraddress, "unknown family"); + break; + } +} +int bind (int sockfd, const struct sockaddr * addr, socklen_t addrlen) { + if (!real_bind) + real_bind = dlsym(RTLD_NEXT, "bind"); + LOG("called bind()"); + int ret = real_bind(sockfd, addr, addrlen); + int old_errno = errno; + if (ret == -1) + goto fail; + if (!more_fds(sockfd)) + goto fail; // enomem + streams[sockfd].bound = port_from_sa(addr); +fail: + errno = old_errno; + return ret; +} int close (int fd) { if (!real_close) real_close = dlsym(RTLD_NEXT, "close"); @@ -130,56 +203,42 @@ int accept (int socket, struct sockaddr *restrict address, socklen_t *restrict a LOG("called accept()"); int ret = real_accept(socket, address, address_len); int saved_errno = errno; - if (ret >= streams_sizeof) { - int streams_sizeof_new; - if (streams_sizeof == 0) - streams_sizeof_new = 128; - else - streams_sizeof_new = streams_sizeof * 2; - struct stream * streams_new = realloc(streams, streams_sizeof_new*sizeof *streams); - if (!streams_new) { - LOG("ENOMEM realloc streams!"); - goto fail; - } - memset(streams_new+streams_sizeof, 0, (streams_sizeof_new-streams_sizeof)*sizeof *streams); - streams = streams_new; - streams_sizeof = streams_sizeof_new; - } + if (ret == -1) + goto fail; + if (!more_fds(MAX(ret, socket)) + goto fail; // enomem end_stream(ret); streams[ret].active = true; + streams[ret].bound = socket; setup_db(); if (db) { sqlite3_stmt * stmt = NULL; - int sqlret = sqlite3_prepare_v3(db, "insert into connections (peer) values (:p);", -1, 0, &stmt, NULL); + int sqlret = sqlite3_prepare_v3(db, "insert into connections (peer, bound, mtu) values (:p, :b, :m);", -1, 0, &stmt, NULL); if (sqlret != SQLITE_OK) { LOG("failed to prepare insert connections: %s", sqlite3_errstr(sqlret)); goto sqlfail; } char peeraddress[INET_ADDRSTRLEN+128]; - switch (address->sa_family) { - case AF_INET: - if (!inet_ntop(AF_INET, &(((struct sockaddr_in *) address)->sin_addr), peeraddress, *address_len)) { - int myerrno = errno; - strcpy(peeraddress, "!"); - strcat(peeraddress, strerror(myerrno)); - } - sprintf(peeraddress+strlen(peeraddress), "/%d", ntohs(((struct sockaddr_in *) address)->sin_port)); - break; - case AF_INET6: - if (!inet_ntop(AF_INET6, &(((struct sockaddr_in6 *) address)->sin6_addr), peeraddress, *address_len)) { - int myerrno = errno; - strcpy(peeraddress, "!"); - strcat(peeraddress, strerror(myerrno)); - } - sprintf(peeraddress+strlen(peeraddress), "/%d", ntohs(((struct sockaddr_in6 *) address)->sin6_port)); - break; - default: - strcpy(peeraddress, "unknown family"); - break; - } + str_from_sa(peeraddress, address); sqlret = sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":p"), peeraddress, -1, SQLITE_STATIC); if (sqlret != SQLITE_OK) { - LOG("failed to bind insert connection: %s", sqlite3_errstr(sqlret)); + LOG("failed to bind insert connection text: %s", sqlite3_errstr(sqlret)); + goto sqlfail; + } + sqlret = sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, ":b"), streams[streams[ret].bound].bound); + if (sqlret != SQLITE_OK) { + LOG("failed to bind insert connection bound: %s", sqlite3_errstr(sqlret)); + goto sqlfail; + } + int mtu; + int mtusize = sizeof mtu; + if (getsockopt(socket, IPPROTO_IP, IP_MTU, &mtu, &mtusize) == -1) { + mtu = -errno; + LOG("failed to get MTU: %s", -mtu); + } + sqlret = sqlite3_bind_int64(stmt, sqlite3_bind_parameter_index(stmt, ":m"), mtu); + if (sqlret != SQLITE_OK) { + LOG("failed to bind insert connection mtu: %s", sqlite3_errstr(sqlret)); goto sqlfail; } sqlret = sqlite3_step(stmt); diff --git a/iv/orodja/ldmitm/tcp_times.c b/iv/orodja/ldmitm/tcp_times.c index 082d2d8..02a067a 100644 --- a/iv/orodja/ldmitm/tcp_times.c +++ b/iv/orodja/ldmitm/tcp_times.c @@ -28,7 +28,6 @@ if (ioctl(tcp_times, 0, &tt) == -1) { #include <linux/tcp.h> #include <linux/version.h> #include "tcp_times.h" -#define MIN(a,b) (((a)<(b))?(a):(b)) MODULE_AUTHOR("Anton Luka Šijanec <anton@sijanec.eu>"); MODULE_DESCRIPTION("tcp last received tsval, rtt procfs ioctl driver"); MODULE_LICENSE(""); diff --git a/iv/orodja/ldmitm/tcp_times_example.c b/iv/orodja/ldmitm/tcp_times_example.c index c98b29a..707bfce 100644 --- a/iv/orodja/ldmitm/tcp_times_example.c +++ b/iv/orodja/ldmitm/tcp_times_example.c @@ -12,7 +12,24 @@ Posluša na TCP vratih 6969, prejme eno povezavo, vsako sekundo nanjo izpiše LF #include <stdbool.h> #include <sys/ioctl.h> #include <fcntl.h> +#include <signal.h> +int samomor = 0; +void handler (int sig __attribute__((unused))) { + samomor = 1; +} int main (void) { + if (signal(SIGINT, handler) == SIG_ERR) { + perror("signal"); + return 1; + } + if (signal(SIGHUP, handler) == SIG_ERR) { + perror("signal"); + return 1; + } + if (signal(SIGTERM, handler) == SIG_ERR) { + perror("signal"); + return 1; + } int tcp_socket = socket(AF_INET6, SOCK_STREAM, 0); if (tcp_socket == -1) { perror("socket"); @@ -29,12 +46,12 @@ int main (void) { } if (listen(tcp_socket, 1 /* only one client is handled*/) == -1) { perror("listen"); - return 1; + goto die; } int flow = accept(tcp_socket, NULL, NULL); if (flow == -1) { perror("accept"); - return 1; + goto die; } int tcp_times = open("/proc/tcp_times", O_RDWR); struct tcp_times tt = { @@ -44,13 +61,20 @@ int main (void) { while (true) { if (ioctl(tcp_times, 0, &tt) == -1) { perror("ioctl"); - return 1; + break; } printf(TCP_TIMES_PRINTF_FORMAT "\n", TCP_TIMES_PRINTF_VARIABLES(tt.)); if (send(flow, &buf, 1, MSG_NOSIGNAL) == -1) { perror("write"); - return 1; + break; } + if (samomor) + break; sleep(1); } +die: + close(tcp_times); + close(flow); + close(tcp_socket); + return 1; } diff --git a/iv/orodja/napad/.gitignore b/iv/orodja/napad/.gitignore new file mode 100644 index 0000000..e417f8f --- /dev/null +++ b/iv/orodja/napad/.gitignore @@ -0,0 +1 @@ +flags.db diff --git a/iv/orodja/napad/config b/iv/orodja/napad/config new file mode 100644 index 0000000..371faed --- /dev/null +++ b/iv/orodja/napad/config @@ -0,0 +1,44 @@ +# Common config for exploit.sh and submission.py. +# It is to be sourced. It only sets environment variables. + +# ========================== +# ========= COMMON ========= + +export FLAG_REGEX="^[A-Z0-9]{31}=$" +export SUBMISSION_PORT=21502 + +# ========================== +# ======= EXPLOIT.SH ======= + +# Where can exploit.sh find submission.py. Port is a common setting. +export SUBMISSION_HOST=k.4a.si + +# Must be precise, not less than round duration. Used to calculate round id. +export ROUND_DURATION=120 + +# When does the game start (in UTC). Used to calculate current round id. +export GAME_START=2024-09-01T07:00:00 + +# ========================== +# ====== SUBMISSION.PY ===== + +export SUBMISSION_DB=flags.db + +# How much flags to send in one request. +# With 2560, if it takes 37 bytes per flag, 2560*37=94720 +# Ostane nam torej še dobrih 5280 za headerje, +# če je request limited na 100 kB +export SUBMISSION_MAX_FLAGS=2560 + +# PUT request, ECSC 2024 AD style +export SUBMISSION_URL=http://10.10.0.1:8080/flags + +# How many seconds to delay after a successful submission. +# With 15, we send at most 4 requests per minute out of 15 allowed. +export SUBMISSION_DELAY=15 + +# This is sent in X-Team-Token in requests to SUBMISSION_URL +export SUBMISSION_TEAM_TOKEN=e5152d70a4d18093cae8844f4e959cf1 + +# Where to bind to. Use SUBMISSION_PORT in common settings for port. +export SUBMISSION_BIND=:: diff --git a/iv/orodja/napad/exploit.sh b/iv/orodja/napad/exploit.sh new file mode 100755 index 0000000..1111b00 --- /dev/null +++ b/iv/orodja/napad/exploit.sh @@ -0,0 +1,23 @@ +#!/bin/sh +if [ x$1 = x ] +then +echo >&2 <<EOF +No command. Subcommands: + $0 once <exploit> # runs an exploit once, print captured flags + $1 loop <exploit> # runs an exploit in a loop once per round +<exploit> is an executable file. Flags, grepped from stdout, are submitted. +It is called for every target. Args are target IP and flag IDs JSON object. + Example: <exploit> 10.1.2.3 '{"user": "root", "pass": "hunter2"}' +Flag IDs are also available in the environment as variables FLAG_ID_<key>: + {"user": "root", "pass": "hunter2"} will be in environment as vars + FLAG_ID_user=root and FLAG_ID_pass=hunter2 +In loop mode, exploit is first exec'd rapidly for still valid old rounds. +Max execution time is $EXPLOIT_TIMEOUT seconds (EXPLOIT_TIMEOUT in config) +Exploits are NOT executed in parallel. +Make sure that your system time is set CORRECTLY TO THE SECOND, it's used + to get the current round id. Current time: `date`. +Configuration values are also available in environment of exploits. +EOF + exit 1 +fi +set -xeuo pipefail diff --git a/iv/orodja/napad/submission.py b/iv/orodja/napad/submission.py new file mode 100755 index 0000000..dcf75ca --- /dev/null +++ b/iv/orodja/napad/submission.py @@ -0,0 +1,64 @@ +#!/usr/bin/python3 +import os +import asyncio +import re +import sqlite3 +import aiohttp +db = sqlite3.connect(os.getenv("SUBMISSION_DB", "flags.db")) +db.execute("CREATE TABLE IF NOT EXISTS flags (id INTEGER PRIMARY KEY, flag TEXT NOT NULL UNIQUE, sent INTEGER NOT NULL DEFAULT 0, date TEXT DEFAULT (strftime('%FT%R:%f', 'now')) NOT NULL, status TEXT, msg TEXT) STRICT") +flag_regex = re.compile(os.getenv("FLAG_REGEX", "^[A-Z0-9]{31}=$").encode(), re.ASCII | re.DOTALL | re.VERBOSE) +async def submitter (): + while True: + print("submitter loop") + flags = [] + for row in db.execute("SELECT flag FROM flags WHERE sent == 0 ORDER BY date DESC"): + if len(flags) < int(os.getenv("SUBMISSION_MAX_FLAGS", "2560")): + flags.append(row[0]) + if len(flags) == 0: + await asyncio.sleep(1) + for i in [1]: + async with aiohttp.ClientSession(headers={"X-Team-Token": os.getenv("SUBMISSION_TEAM_TOKEN")}) as session: + async with session.put(os.getenv("SUBMISSION_URL", 'http://10.10.0.1:8080/flags'), json=flags) as response: + if response.status // 100 != 2: + print("submitter error: " + await response.text()) + break + cursor = db.cursor() + for obj in await response.json(): + cursor.execute("UPDATE flags SET sent=?, status=?, msg=? WHERE flag=?", [int(obj.get("status") != "RESUBMIT"), obj.get("status"), obj.get("msg"), obj.get("flag")]) + db.commit() + await asyncio.sleep(int(os.getenv("SUBMISSION_DELAY", "15"))) +async def handle_client (reader, writer): + while True: + incoming = await reader.readuntil(b'\n') + if len(incoming) == 0: + break + buffer = incoming.replace(b'\r', b'').replace(b'\n', b'') + if buffer.startswith(b' '): + for row in db.execute(buffer[1:].decode()): + writer.write(str(row).encode() + b'\n') + continue + if buffer.startswith(b'@'): + writer.write(str(db.execute(buffer[1:].decode()).fetchall()).encode() + b'\n') + continue + if buffer.startswith(b'#'): + writer.write(str(len(db.execute(buffer[1:].decode()).fetchall())).encode() + b'\n') + continue + if re.match(flag_regex, buffer) == None: + writer.write(b'BAD_FLAG\n') + continue + flag = buffer.decode() + try: + db.execute("INSERT INTO flags (flag) VALUES (?)", [flag]) + except sqlite3.IntegrityError: + status, msg, date = [x for x in db.execute("SELECT status, msg, date FROM flags WHERE flag=?", [flag])][0] + writer.write(b"OLD_FLAG " + date.encode() + b" " + str(status).encode() + b" " + str(msg).encode() + b"\n") + else: + writer.write(b'NEW_FLAG\n') + writer.close() +async def run_server (): + server = await asyncio.start_server(handle_client, os.getenv("SUBMISSION_BIND", "::"), os.getenv("SUBMISSION_PORT", "21502")) + event_loop = asyncio.get_event_loop() + event_loop.create_task(submitter()) + async with server: + await server.serve_forever() +asyncio.run(run_server()) diff --git a/iv/orodja/waf/Dockerfile b/iv/orodja/waf/Dockerfile new file mode 100644 index 0000000..bc87aaf --- /dev/null +++ b/iv/orodja/waf/Dockerfile @@ -0,0 +1,6 @@ +FROM alpine:latest +RUN apk add python3 +WORKDIR /waf +COPY ./waf.py . +RUN chmod +x ./waf.py +CMD ["./waf.py"] diff --git a/iv/orodja/waf/regexes.txt b/iv/orodja/waf/regexes.txt new file mode 100644 index 0000000..301a41c --- /dev/null +++ b/iv/orodja/waf/regexes.txt @@ -0,0 +1,2 @@ +HACKERS +HACKERS diff --git a/iv/orodja/waf/waf.py b/iv/orodja/waf/waf.py new file mode 100644 index 0000000..701b4dd --- /dev/null +++ b/iv/orodja/waf/waf.py @@ -0,0 +1,85 @@ +#!/usr/bin/python3 +import asyncio +import os +import ssl +import re + +def manyregex (string, patterns): + for pattern in patterns: + if re.search(pattern, string) != None: + return True + return False + +async def cevovod (reader, writer, writer2, compiled): + buffer = b'' + while True: + prebral = await reader.read(65536) + buffer += prebral + if manyregex(buffer, compiled): + break ## hacker detected + if len(buffer) > 65536: + buffer = buffer[-32768:] + if len(prebral) == 0: + break + writer.write(prebral) + writer.close() + writer2.close() + +async def handle_client (reader, writer): + try: + compiled = [] + reflags = re.ASCII | re.MULTILINE | re.DOTALL | re.VERBOSE + with open(os.getenv("WAF_REGEXES"), "rb") as rulesfile: + regexes = rulesfile.read().split(b"\n") + for regex in regexes: + if len(regex) == 0: + continue + compiled.append(re.compile(regex, reflags)) + write_to_backend = b'' + if os.getenv("WAF_HTTP"): + headers = [] + while True: + line = (await reader.readuntil(b'\n')).replace(b'\r', b'').replace(b'\n', b'') + if not line.lower().startswith(b"accept-encoding:"): + write_to_backend += line + b"\r\n" + if len(line) == 0: + break + headers.append(line) + if headers[0].startswith(b"GET /waf HTTP/"): + writer.write(b"HTTP/1.0 200 OK\r\nContent-Type: text/plain\r\n\r\nwaf works (: PID " + str(os.getpid()).encode() + b"\r\n") + writer.close() + return + context = None + if os.getenv("WAF_TLS"): + context = ssl.create_default_context() + context.check_hostname = False + context.verify_mode = ssl.CERT_NONE + backendr, backendw = await asyncio.open_connection(os.getenv("WAF_BACKEND_HOST"), os.getenv("WAF_BACKEND_PORT"), ssl=context) + if manyregex(write_to_backend, compiled): + writer.write(b'HTTP/1.0 469 Hacking\r\nContent-Type: text/plain\r\n\r\nHacking is illegal according to ZEKom-2.\r\n') + backendw.close() ## hacker + writer.close() + return + backendw.write(write_to_backend) + except Exception as e: + writer.write(b"HTTP/1.0 569 Exception\r\nContent-Type: text/plain\r\n\r\n") + writer.write(str(e).encode()) + writer.write(b"\r\n") + backendw.close() + writer.close() + raise e + else: + event_loop = asyncio.get_event_loop() + event_loop.create_task(cevovod(reader, backendw, writer, compiled)) + event_loop.create_task(cevovod(backendr, writer, backendw, compiled)) + +async def run_server (): + context = None + if os.getenv("WAF_TLS"): + context = ssl.SSLContext(ssl.PROTOCOL_TLS_SERVER) + context.load_cert_chain(certfile=os.getenv("WAF_TLS"), keyfile=os.getenv("WAF_TLS_KEY")) + server = await asyncio.start_server(handle_client, os.getenv("WAF_LISTEN_ADDR"), os.getenv("WAF_LISTEN_PORT"), ssl=context) + async with server: + await server.serve_forever() + +asyncio.run(run_server()) |