Skip to content

Commit

Permalink
* Fixed a huge bug- kerberos passwords are now url-encoded prior to b…
Browse files Browse the repository at this point in the history
…eing sent to the server.

* Added DEBUG explicitly to all compiled source
* Created a functional test harness, albeit not testing kerberos, it tests the curl.* libraries and some minor kerberos loading functionality
  • Loading branch information
CboeSecurity committed Oct 8, 2019
1 parent 53b5dc7 commit 4a41960
Show file tree
Hide file tree
Showing 5 changed files with 136 additions and 14 deletions.
44 changes: 41 additions & 3 deletions common/curl.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

char rfc3986[256] = {0};

static size_t
WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
{
Expand All @@ -38,7 +40,40 @@ WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp)
return realsize;
}

void init_urlencode(void)
{
int i;
for (i = 0; i < 256; i++)
{
rfc3986[i] = isalnum(i)||i == '~'||i == '-'||i == '.'||i == '_' ? i : 0;
}
}

void urlencode(const char* src, char* encoded)
{
//syslog(LOG_DEBUG,"Got url escape request: %s",src);
for (; *src; src++) {
if (rfc3986[*src])
{
sprintf(encoded, "%c", rfc3986[*src]);
//syslog(LOG_DEBUG,"std Here: %c: %s",*src,src);
}
else
{
sprintf(encoded, "%%%02X", *src);
//syslog(LOG_DEBUG,"esc Here: %c: %s",*src,src);
}
while (*++encoded);
}
}

////////////////////////////////////////////////////////////////////////////////////

#ifdef DEBUG
int __export queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL)
#else
int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL)
#endif
{
CURL *curl;
CURLcode res;
Expand All @@ -48,8 +83,11 @@ int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSS

curl = curl_easy_init();
if(curl) {
char* escaped_url = curl_easy_escape(curl, dest_url, 0);
curl_easy_setopt(curl, CURLOPT_URL, escaped_url);
//char* escaped_url = curl_easy_escape(curl, dest_url, 0);
#ifdef DEBUG
syslog(LOG_INFO, "pwncheck: queryUrl: DEBUG: destination url: %s",dest_url);
#endif
curl_easy_setopt(curl, CURLOPT_URL, dest_url);

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void*)chunk);
Expand All @@ -68,7 +106,7 @@ int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSS
syslog(LOG_ERR, "pwncheck: queryUrl: curl_easy_perform() failed: %s", curl_easy_strerror(res));

/* always cleanup */
curl_free(escaped_url);
//curl_free(escaped_url);
curl_easy_cleanup(curl);
}

Expand Down
14 changes: 13 additions & 1 deletion common/curl.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,23 @@

#include <curl/curl.h> // curl

#ifdef DEBUG
#ifndef __export
#define __export __attribute__((__visibility__("default")))
#endif
#endif

struct MemoryStruct {
char *memory;
size_t size;
};

void init_urlencode(void);
void urlencode(const char* src, char* encoded);

static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
#ifdef DEBUG
int __export queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL);
#else
int queryUrl(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL);

#endif
4 changes: 2 additions & 2 deletions kerberos/build-debug.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
#cp /lib/security/pwncheck.so /usr/lib/x86_64-linux-gnu/krb5/plugins/pwqual/

gcc -g -shared -fPIC -fno-stack-protector -DDEBUG -c src/krb_password_pwncheck.c -lcurl -lcrypto -o bin/krb_password_pwncheck.o && \
gcc -g -shared -fPIC -fno-stack-protector -c src/config.c -lcurl -lcrypto -o bin/config.o && \
gcc -g -shared -fPIC -fno-stack-protector -c ../common/curl.c -lcurl -lcrypto -o bin/curl.o && \
gcc -g -shared -fPIC -fno-stack-protector -DDEBUG -c src/config.c -lcurl -lcrypto -o bin/config.o && \
gcc -g -shared -fPIC -fno-stack-protector -DDEBUG -c ../common/curl.c -lcurl -lcrypto -o bin/curl.o && \
gcc -g -o bin/harness src/harness.c -ldl
ld -g -x --shared -o bin/pwncheck.so bin/krb_password_pwncheck.o bin/config.o bin/curl.o -lefence -lcurl -lcrypto -lyaml
cp bin/pwncheck.so /usr/lib/x86_64-linux-gnu/krb5/plugins/pwqual/
65 changes: 62 additions & 3 deletions kerberos/src/harness.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,21 @@
#include <krb5/pwqual_plugin.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <dlfcn.h>
#include "../../common/curl.h"
#include "../../common/constants.h"

#include <stddef.h>

/*
krb5_error_code __export
pwqual_pwncheck_initvt(krb5_context context, int maj_ver, int min_ver,
krb5_plugin_vtable vtable)
static krb5_error_code
pwqual_pwncheck_check(krb5_context context, krb5_pwqual_moddata data,
const char *passwd, const char *policy_name,
krb5_principal princ, const char **languages)
*/

#ifndef NULL
Expand All @@ -29,9 +36,12 @@ int main(int argc, char **argv) {
void *handle;
krb5_error_code (*initvt)(krb5_context context, int maj_ver, int min_ver, krb5_plugin_vtable vtable);
krb5_error_code (*check)(krb5_context context, krb5_pwqual_moddata data, const char *passwd, const char *policy_name, krb5_principal princ, const char **languages);
int (*queryUrl)(const char* dest_url, struct MemoryStruct* chunk, int useInsecureSSL);
void (*init_urlencode)(void);
void (*urlencode)(const char* src, char* encoded);
char *error;

printf("Opening Dynamic Library...");
printf("Opening Dynamic Library...\n");
//handle = dlopen ("./pwncheck.so", RTLD_LAZY);
//handle = dlopen (argv[1], RTLD_LAZY);
handle = dlopen (argv[1], PLUGIN_DLOPEN_FLAGS);
Expand All @@ -50,8 +60,56 @@ int main(int argc, char **argv) {
exit(1);
}
printf("Done\n");
printf("Loading Dynamic Symbol (urlencode)...");
urlencode = dlsym(handle, "urlencode");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
printf("\n");
exit(1);
}
printf("Done\n");
printf("Loading Dynamic Symbol (init_urlencode)...");
init_urlencode = dlsym(handle, "init_urlencode");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
printf("\n");
exit(1);
}
printf("Done\n");
printf("Loading Dynamic Symbol (queryUrl)...");
queryUrl = dlsym(handle, "queryUrl");
if ((error = dlerror()) != NULL) {
fputs(error, stderr);
printf("\n");
exit(1);
}
printf("Done\n");

(*init_urlencode)();
struct MemoryStruct chunk;
chunk.memory = malloc(1);
chunk.size = 0;
memset(chunk.memory,'\0',1);
printf("Attempting to execute loaded symbol (function queryUrl)...\n");
printf("\n");
char filled_url[CURL_MAX_BUFLEN];
char* user = "user";
char* passwd = "this ia a sample . pass\' word ";
char* url = "http://localhost:8000/checkpwd?u=%s&p=%s";
char* escaped_user = (char*)malloc(strlen(user)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
char* escaped_passwd = (char*)malloc(strlen(passwd)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
(*urlencode)(user,escaped_user);
(*urlencode)(passwd,escaped_passwd);
int furllen = strlen(url)+strlen(escaped_user)+strlen(escaped_passwd);
if (furllen > CURL_MAX_BUFLEN) furllen = CURL_MAX_BUFLEN;
snprintf(filled_url, furllen, url, escaped_user, escaped_passwd);
free(escaped_user);
free(escaped_passwd);
(*queryUrl)(filled_url,&chunk,1);
printf("Function queryUrl execution done\n");



/*
krb5_context context;
//krb5_plugin_vtable vt;
struct krb5_pwqual_vtable_st harness_vt = {NULL,NULL,NULL,NULL};
Expand All @@ -60,6 +118,7 @@ int main(int argc, char **argv) {
const char* policy_name = "policy";
krb5_principal princ = NULL; // {0,{7,"norealm"},NULL,5,0};
char** langs = NULL;
printf("Attempting to execute loaded symbol (function initvt)...");
printf("\n");
(*initvt)(context, 2, 0, (struct krb5_plugin_vtable_st *)&harness_vt);
Expand All @@ -69,7 +128,7 @@ int main(int argc, char **argv) {
printf("\n");
(*check)(context, moddata, passwd, policy_name,princ, NULL);
printf("\n");

*/
printf("Closing the Dynamic Library handle...");
dlclose(handle);
printf("Done\n");
Expand Down
23 changes: 18 additions & 5 deletions kerberos/src/krb_password_pwncheck.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
#include "../../common/curl.h"
#include "../../common/constants.h"

// for encoding
#include <stdio.h>
#include <ctype.h>

// kerberos

Expand All @@ -50,10 +53,13 @@
////////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////////////////
// Perform the actual password quality check //
////////////////////////////////////////////////////////////////////////////////////
static krb5_error_code
#ifdef DEBUG
krb5_error_code extern __export
#else
static krb5_error_code
#endif
pwqual_pwncheck_check(krb5_context context, krb5_pwqual_moddata data,
const char *passwd, const char *policy_name,
krb5_principal princ, const char **languages)
Expand Down Expand Up @@ -97,13 +103,18 @@ pwqual_pwncheck_check(krb5_context context, krb5_pwqual_moddata data,
url = config.url;
}



char filled_url[CURL_MAX_BUFLEN];
//int furllen = CURL_MAX_BUFLEN > strlen(url)+strlen(user)+strlen(passwd) ? CURL_MAX_BUFLEN : strlen(url)+strlen(user)+strlen(passwd);
int furllen = strlen(url)+strlen(user)+strlen(passwd);
char* escaped_user = (char*)malloc(strlen(user)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
char* escaped_passwd = (char*)malloc(strlen(passwd)*3+1); // up to 3 chars, e.g. ' ' => '%20' per original char, and end null
urlencode(user,escaped_user);
urlencode(passwd,escaped_passwd);
int furllen = strlen(url)+strlen(escaped_user)+strlen(escaped_passwd);
if (furllen > CURL_MAX_BUFLEN) furllen = CURL_MAX_BUFLEN;
snprintf(filled_url, furllen, url, user, passwd);
snprintf(filled_url, furllen, url, escaped_user, escaped_passwd);
free(escaped_user);
free(escaped_passwd);
#ifdef DEBUG
syslog(LOG_DEBUG, "pwncheck: check: user:%s password:%s",user,passwd);
syslog(LOG_DEBUG, "pwncheck: check: Created Filling URL: %s", filled_url);
Expand Down Expand Up @@ -159,6 +170,8 @@ pwqual_pwncheck_initvt(krb5_context context, int maj_ver, int min_ver,
vt = (struct krb5_pwqual_vtable_st *)vtable;
memset(vt, 0, sizeof *vt);

init_urlencode();

vt->name = "pwncheck";
vt->check = pwqual_pwncheck_check;
syslog(LOG_DEBUG,"pwncheck: initvt: Initiated");
Expand Down

0 comments on commit 4a41960

Please sign in to comment.