Created
April 12, 2017 09:55
-
-
Save bennydictor/0d827b922960306c90a7da7680a2ef25 to your computer and use it in GitHub Desktop.
Proxy for one website and it injects javascript (and probably doesn't work)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include <arpa/inet.h> | |
#include <sys/ioctl.h> | |
#include <errno.h> | |
#include <netdb.h> | |
#include <poll.h> | |
#include <stdint.h> | |
#include <stdio.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <sys/socket.h> | |
#include <unistd.h> | |
#define BACKLOG 64 | |
#define BUF_LEN (1024*1024) | |
#define CLIENTS_MAX 256 | |
#define NFDS (2 * CLIENTS_MAX + 1) | |
#define LOCAL_PORT 8081 | |
#define REMOTE "bash.im" | |
#define REMOTE_LEN (sizeof(REMOTE) - 1) | |
#define REMOTE_PORT 80 | |
#define PAYLOAD "<script>alert(\"hOI!\")</script>" | |
#define PAYLOAD_LEN (sizeof(PAYLOAD) - 1) | |
#define HEADER_HOST "Host: localhost" | |
#define HEADER_HOST_LEN (sizeof(HEADER_HOST) - 1) | |
#define HEADER_ENC "Accept-Encoding: " | |
#define HEADER_ENC_LEN (sizeof(HEADER_ENC) - 1) | |
#define END_BODY "</head>" | |
#define END_BODY_LEN (sizeof(END_BODY) - 1) | |
void shit_happened(const char *s) { | |
if (s) { | |
fprintf(stderr, "%s\n", s); | |
} else { | |
fprintf(stderr, "%s (%d)\n", strerror(errno), errno); | |
} | |
exit(1); | |
} | |
int make_tcp_socket(const char *host, uint16_t port) { | |
int ret = socket(AF_INET, SOCK_STREAM, 0); | |
if (ret == -1) shit_happened(NULL); | |
struct sockaddr_in addr; | |
memset(&addr, 0, sizeof(struct sockaddr_in)); | |
addr.sin_family = AF_INET; | |
addr.sin_port = htons(port); | |
in_addr_t host_ip; | |
if (host) { | |
struct hostent *hostent = gethostbyname(host); | |
if (!hostent) shit_happened(NULL); | |
host_ip = *(in_addr_t *) hostent->h_addr_list[0]; | |
} else { | |
host_ip = htonl(INADDR_ANY); | |
} | |
addr.sin_addr.s_addr = host_ip; | |
if (host) { | |
if (connect(ret, (struct sockaddr *) &addr, | |
sizeof(struct sockaddr_in)) == -1) shit_happened(NULL); | |
} else { | |
if (bind(ret, (struct sockaddr *) &addr, | |
sizeof(struct sockaddr_in)) == -1) shit_happened(NULL); | |
if (listen(ret, BACKLOG) != 0) shit_happened(NULL); | |
} | |
return ret; | |
} | |
void nonblock(int fd) { | |
int on = 1; | |
if (ioctl(fd, FIONBIO, (char *) &on) == -1) shit_happened(NULL); | |
} | |
struct pollfd fds[NFDS]; | |
void close_all(void) { | |
for (int i = 0; i < NFDS; ++i) { | |
if (fds[i].fd != 0) { | |
close(fds[i].fd); | |
} | |
} | |
} | |
int main() { | |
atexit(close_all); | |
int sock_listen = make_tcp_socket(NULL, LOCAL_PORT); | |
nonblock(sock_listen); | |
memset(&fds, 0, sizeof(fds)); | |
fds[0].fd = sock_listen; | |
fds[0].events = POLLIN; | |
char buf[BUF_LEN]; | |
for (;;) { | |
int evs = poll(fds, NFDS, 3 * 60 * 1000); | |
if (evs == -1) shit_happened(NULL); | |
if (evs == 0) continue; | |
if (fds[0].revents == POLLIN) { | |
int new_client = accept(fds[0].fd, NULL, NULL); | |
if (new_client == -1) shit_happened(NULL); | |
int new_client_pos = -1; | |
for (int i = 1; i < NFDS; i += 2) { | |
if (fds[i].fd == 0) { | |
new_client_pos = i; | |
break; | |
} | |
} | |
if (new_client_pos == -1) { | |
shit_happened("Too many clients"); | |
} | |
printf("client %d new\n", new_client_pos / 2 + 1); | |
fds[new_client_pos].fd = new_client; | |
fds[new_client_pos].events = POLLIN; | |
fds[new_client_pos + 1].fd = make_tcp_socket(REMOTE, REMOTE_PORT); | |
fds[new_client_pos + 1].events = POLLIN; | |
nonblock(fds[new_client_pos + 1].fd); | |
} | |
for (int i = 1; i < NFDS; i += 2) { | |
char closed = 0; | |
if (fds[i].revents & POLLIN) { | |
printf("client %d send\n", i / 2 + 1); | |
int len; | |
if ((len = read(fds[i].fd, buf, BUF_LEN)) == -1) | |
shit_happened(NULL); | |
if (len == 0) | |
goto close_conn; | |
buf[len] = 0; | |
char modbuf[BUF_LEN * 2]; | |
int modbuf_ptr = 0; | |
for (int p = 0; p < len;) { | |
if (strncmp(buf + p, HEADER_HOST, HEADER_HOST_LEN) == 0) { | |
printf("client %d fixing Host\n", i / 2 + 1); | |
strcpy(modbuf + modbuf_ptr, "Host: " REMOTE); | |
modbuf_ptr += strlen("Host: " REMOTE); | |
p += HEADER_HOST_LEN; | |
} else if (strncmp(buf + p, HEADER_ENC, | |
HEADER_ENC_LEN) == 0) { | |
printf("client %d fixing Accept-Encoding\n", i / 2 + 1); | |
strcpy(modbuf + modbuf_ptr, HEADER_ENC "identity"); | |
modbuf_ptr += strlen(HEADER_ENC "identity"); | |
modbuf[modbuf_ptr++] = '\r'; | |
for (; buf[p] != '\n'; ++p); | |
} else { | |
modbuf[modbuf_ptr++] = buf[p++]; | |
} | |
} | |
if (write(fds[i + 1].fd, modbuf, modbuf_ptr) == -1) | |
shit_happened(NULL); | |
} | |
if (fds[i + 1].revents & POLLIN) { | |
int len; | |
printf("client %d recv\n", i / 2 + 1); | |
if ((len = read(fds[i + 1].fd, buf, BUF_LEN)) == -1) | |
shit_happened(NULL); | |
buf[len] = 0; | |
if (len == 0) | |
goto close_conn; | |
char modbuf[BUF_LEN + PAYLOAD_LEN + 1]; | |
int modbuf_ptr = 0; | |
for (int p = 0; p < len;) { | |
if (strncmp(buf + p, END_BODY, END_BODY_LEN) == 0) { | |
printf("client %d injecting payload\n", i / 2 + 1); | |
strcpy(modbuf + modbuf_ptr, PAYLOAD); | |
modbuf_ptr += PAYLOAD_LEN; | |
} | |
modbuf[modbuf_ptr++] = buf[p++]; | |
} | |
if (write(fds[i].fd, modbuf, modbuf_ptr) == -1) | |
shit_happened(NULL); | |
} | |
if (closed) { | |
close_conn: | |
close(fds[i].fd); | |
close(fds[i + 1].fd); | |
memset(fds + i, 0, 2 * sizeof(struct pollfd)); | |
printf("client %d term\n", i / 2 + 1); | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment