v2.0.0: Rename bruteforce to dictionary attack to avoid confusion (#71)
This commit is contained in:
committed by
GitHub
parent
b61fe52161
commit
0e7577ed7c
@@ -26,8 +26,8 @@
|
||||
// All the tasks managed by the dispatcher
|
||||
#include <tasks/mapping.h>
|
||||
#include <tasks/parsing.h>
|
||||
#include <tasks/brutelogs.h>
|
||||
#include <tasks/brutepath.h>
|
||||
#include <tasks/creds_attack.h>
|
||||
#include <tasks/path_attack.h>
|
||||
#include <tasks/thumbnail.h>
|
||||
#include <tasks/stream_check.h>
|
||||
#include <tasks/print.h>
|
||||
@@ -40,8 +40,8 @@ enum class task {
|
||||
preparation,
|
||||
mapping,
|
||||
parsing,
|
||||
brutepath,
|
||||
bruteforce,
|
||||
path_attack,
|
||||
creds_attack,
|
||||
thumb_generation,
|
||||
print,
|
||||
finished
|
||||
|
||||
+5
-5
@@ -24,25 +24,25 @@
|
||||
namespace etix {
|
||||
namespace cameradar {
|
||||
|
||||
class brutelogs : public etix::cameradar::cameradar_task {
|
||||
class creds_attack : public etix::cameradar::cameradar_task {
|
||||
const configuration& conf;
|
||||
std::shared_ptr<cache_manager> cache;
|
||||
std::string nmap_output;
|
||||
|
||||
public:
|
||||
brutelogs() = delete;
|
||||
brutelogs(std::shared_ptr<cache_manager> cache,
|
||||
creds_attack() = delete;
|
||||
creds_attack(std::shared_ptr<cache_manager> cache,
|
||||
const configuration& conf,
|
||||
std::string nmap_output)
|
||||
: conf(conf), cache(cache), nmap_output(nmap_output) {}
|
||||
brutelogs(const brutelogs& ref) = delete;
|
||||
creds_attack(const creds_attack& ref) = delete;
|
||||
|
||||
virtual bool run() const;
|
||||
|
||||
bool test_ids(const etix::cameradar::stream_model& cit,
|
||||
const std::string& pit,
|
||||
const std::string& uit) const;
|
||||
bool bruteforce_camera(const stream_model& stream) const;
|
||||
bool attack_camera_creds(const stream_model& stream) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
+5
-5
@@ -27,23 +27,23 @@
|
||||
namespace etix {
|
||||
namespace cameradar {
|
||||
|
||||
class brutepath : public etix::cameradar::cameradar_task {
|
||||
class path_attack : public etix::cameradar::cameradar_task {
|
||||
const configuration& conf;
|
||||
std::shared_ptr<cache_manager> cache;
|
||||
std::string nmap_output;
|
||||
|
||||
public:
|
||||
brutepath() = delete;
|
||||
brutepath(std::shared_ptr<cache_manager> cache,
|
||||
path_attack() = delete;
|
||||
path_attack(std::shared_ptr<cache_manager> cache,
|
||||
const configuration& conf,
|
||||
std::string nmap_output)
|
||||
: conf(conf), cache(cache), nmap_output(nmap_output) {}
|
||||
brutepath(const brutepath& ref) = delete;
|
||||
path_attack(const path_attack& ref) = delete;
|
||||
|
||||
virtual bool run() const;
|
||||
|
||||
bool test_path(const etix::cameradar::stream_model& cit, const std::string& it) const;
|
||||
bool bruteforce_camera(const stream_model& stream) const;
|
||||
bool attack_camera_path(const stream_model& stream) const;
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -95,7 +95,7 @@ curl_describe(const std::string& path, bool logs) {
|
||||
// Some cameras timeout and then curl considers the status as 0
|
||||
// GST-RTSP-SERVER returns 404 instead of 401, then 401 instead of 404.
|
||||
if (rc != 401 && rc != 400 && rc && pos == std::string::npos)
|
||||
LOG_INFO_("Unprotected camera discovered.", "brutelogs");
|
||||
LOG_INFO_("Unprotected camera discovered.", "creds_attack");
|
||||
return ((res == CURLE_OK) && rc != 401 && rc != 400 && rc);
|
||||
}
|
||||
return ((res == CURLE_OK) && rc != 404 && rc != 400 && rc);
|
||||
|
||||
@@ -64,11 +64,11 @@ dispatcher::do_stuff() {
|
||||
}
|
||||
if (opts.second.exist("-b")) {
|
||||
if (opts.second.exist("--gst-rtsp-server")) {
|
||||
queue.push_back(new etix::cameradar::brutepath(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::brutelogs(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::path_attack(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::creds_attack(cache, conf, nmap_output));
|
||||
} else {
|
||||
queue.push_back(new etix::cameradar::brutelogs(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::brutepath(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::creds_attack(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::path_attack(cache, conf, nmap_output));
|
||||
}
|
||||
}
|
||||
if (opts.second.exist("-t")) {
|
||||
@@ -82,11 +82,11 @@ dispatcher::do_stuff() {
|
||||
queue.push_back(new etix::cameradar::mapping(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::parsing(cache, conf, nmap_output));
|
||||
if (opts.second.exist("--gst-rtsp-server")) {
|
||||
queue.push_back(new etix::cameradar::brutepath(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::brutelogs(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::path_attack(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::creds_attack(cache, conf, nmap_output));
|
||||
} else {
|
||||
queue.push_back(new etix::cameradar::brutelogs(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::brutepath(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::creds_attack(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::path_attack(cache, conf, nmap_output));
|
||||
}
|
||||
queue.push_back(new etix::cameradar::thumbnail(cache, conf, nmap_output));
|
||||
queue.push_back(new etix::cameradar::stream_check(cache, conf, nmap_output));
|
||||
|
||||
@@ -33,14 +33,14 @@ parse_cmdline(int argc, char* argv[]) {
|
||||
opt_parse.optional("-c", "Path to the configuration file (-c /path/to/conf)", true);
|
||||
opt_parse.optional("-l", "Set log level (-l 4 will only show warnings and errors)", true);
|
||||
opt_parse.optional("-d", "Launch the discovery tool on the given target", false);
|
||||
opt_parse.optional("-b", "Launch the bruteforce tool on all discovered devices", false);
|
||||
opt_parse.optional("-b", "Launch the dictionary attack tool on all discovered devices", false);
|
||||
opt_parse.optional("-t", "Generate thumbnails from detected cameras", false);
|
||||
opt_parse.optional("-g", "Check if the stream can be opened with GStreamer", false);
|
||||
opt_parse.optional("-v", "Display Cameradar's version", false);
|
||||
opt_parse.optional("-h", "Display this help", false);
|
||||
opt_parse.optional(
|
||||
"--gst-rtsp-server",
|
||||
"Change the order of the bruteforce to match GST RTSP Server's implementation of "
|
||||
"Change the order of the attack to match GST RTSP Server's implementation of "
|
||||
"RTSP. Some cameras and RTSP servers will use this standard instead of the more "
|
||||
"standard one. For more information, see the README.md file.",
|
||||
false);
|
||||
|
||||
+15
-15
@@ -13,7 +13,7 @@
|
||||
// limitations under the License.
|
||||
|
||||
#include <cachemanager.h>
|
||||
#include <tasks/brutelogs.h>
|
||||
#include <tasks/creds_attack.h>
|
||||
|
||||
namespace etix {
|
||||
namespace cameradar {
|
||||
@@ -23,23 +23,23 @@ static const std::string no_ids_warning_ =
|
||||
"cameras. Either "
|
||||
"they have custom ids, or your ids.json file does not contain enough "
|
||||
"default routes. "
|
||||
"Path bruteforce is impossible without the IDs.";
|
||||
"Path dictionary attack is impossible without the credentials.";
|
||||
|
||||
// Tries to match the detected combination of Username / Password
|
||||
// with the camera stream. Creates a resource in the DB upon
|
||||
// valid discovery
|
||||
bool
|
||||
brutelogs::test_ids(const etix::cameradar::stream_model& stream,
|
||||
creds_attack::test_ids(const etix::cameradar::stream_model& stream,
|
||||
const std::string& password,
|
||||
const std::string& username) const {
|
||||
bool found = false;
|
||||
std::string path = stream.service_name + "://";
|
||||
if (username != "" || password != "") { path += username + ":" + password + "@"; }
|
||||
path += stream.address + ":" + std::to_string(stream.port) + stream.route;
|
||||
LOG_INFO_("Testing ids : " + path, "brutelogs");
|
||||
LOG_INFO_("Testing ids : " + path, "creds_attack");
|
||||
try {
|
||||
if (curl_describe(path, true)) {
|
||||
LOG_INFO_("[FOUND IDS] : " + path, "brutelogs");
|
||||
LOG_INFO_("[FOUND IDS] : " + path, "creds_attack");
|
||||
found = true;
|
||||
stream_model newstream{
|
||||
stream.address, stream.port, username, password,
|
||||
@@ -57,7 +57,7 @@ brutelogs::test_ids(const etix::cameradar::stream_model& stream,
|
||||
(*cache)->update_stream(newstream);
|
||||
}
|
||||
} catch (const std::runtime_error& e) {
|
||||
LOG_DEBUG_("Ids already tested : " + std::string(e.what()), "brutelogs");
|
||||
LOG_DEBUG_("Ids already tested : " + std::string(e.what()), "creds_attack");
|
||||
}
|
||||
return found;
|
||||
}
|
||||
@@ -71,7 +71,7 @@ ids_already_found(std::vector<stream_model> streams, stream_model stream) {
|
||||
}
|
||||
|
||||
bool
|
||||
brutelogs::bruteforce_camera(const stream_model& stream) const {
|
||||
creds_attack::attack_camera_creds(const stream_model& stream) const {
|
||||
for (const auto& username : conf.usernames) {
|
||||
if (signal_handler::instance().should_stop() != etix::cameradar::stop_priority::running)
|
||||
break;
|
||||
@@ -88,15 +88,15 @@ brutelogs::bruteforce_camera(const stream_model& stream) const {
|
||||
// Tries to discover the right IDs on all RTSP streams in DB
|
||||
// Uses the ids.json file to try different combinations
|
||||
bool
|
||||
brutelogs::run() const {
|
||||
creds_attack::run() const {
|
||||
std::vector<std::future<bool>> futures;
|
||||
|
||||
LOG_INFO_(
|
||||
"Beginning bruteforce of the usernames and passwords task, it may "
|
||||
"Beginning attack of the credentials , it may "
|
||||
"take a while.",
|
||||
"brutelogs");
|
||||
"creds_attack");
|
||||
std::vector<etix::cameradar::stream_model> streams = (*cache)->get_streams();
|
||||
LOG_DEBUG_("Found " + std::to_string(streams.size()) + " streams in the cache", "brutelogs");
|
||||
LOG_DEBUG_("Found " + std::to_string(streams.size()) + " streams in the cache", "creds_attack");
|
||||
size_t found = 0;
|
||||
for (const auto& stream : streams) {
|
||||
if (signal_handler::instance().should_stop() != etix::cameradar::stop_priority::running)
|
||||
@@ -106,23 +106,23 @@ brutelogs::run() const {
|
||||
" : This camera's ids were already discovered in "
|
||||
"the database. Skipping to "
|
||||
"the next camera.",
|
||||
"brutelogs");
|
||||
"creds_attack");
|
||||
++found;
|
||||
} else {
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, &brutelogs::bruteforce_camera, this, stream));
|
||||
std::async(std::launch::async, &creds_attack::attack_camera_creds, this, stream));
|
||||
}
|
||||
}
|
||||
for (auto& fit : futures) {
|
||||
if (fit.get()) { ++found; }
|
||||
}
|
||||
if (!found) {
|
||||
LOG_WARN_(no_ids_warning_, "brutelogs");
|
||||
LOG_WARN_(no_ids_warning_, "creds_attack");
|
||||
return false;
|
||||
} else
|
||||
LOG_INFO_("Found " + std::to_string(found) + " ids for " + std::to_string(streams.size()) +
|
||||
" cameras",
|
||||
"brutelogs");
|
||||
"creds_attack");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -114,7 +114,7 @@ parsing::run() const {
|
||||
if (data.size() == 0) { LOG_WARN_("No cameras were discovered", "parsing"); }
|
||||
return print_detected_cameras(data);
|
||||
} catch (const std::exception& e) {
|
||||
LOG_ERR_("Error during parsing. brutepath aborted : " + std::string(e.what()), "parsing");
|
||||
LOG_ERR_("Error during parsing. path_attack aborted : " + std::string(e.what()), "parsing");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
+12
-12
@@ -7,7 +7,7 @@
|
||||
// strictly forbidden unless
|
||||
// prior written permission is obtained from Etix Labs.
|
||||
|
||||
#include <tasks/brutepath.h>
|
||||
#include <tasks/path_attack.h>
|
||||
|
||||
namespace etix {
|
||||
namespace cameradar {
|
||||
@@ -23,18 +23,18 @@ static const std::string no_route_found_ =
|
||||
// with a route for the camera stream. Creates a resource in the DB upon
|
||||
// valid discovery
|
||||
bool
|
||||
brutepath::test_path(const stream_model& stream, const std::string& route) const {
|
||||
path_attack::test_path(const stream_model& stream, const std::string& route) const {
|
||||
bool found = false;
|
||||
std::string path = stream.service_name + "://" + stream.username + ":" + stream.password + "@" +
|
||||
stream.address + ":" + std::to_string(stream.port);
|
||||
if (route.front() != '/') { path += "/"; }
|
||||
path += route;
|
||||
LOG_INFO_("Testing path : " + path, "brutepath");
|
||||
LOG_INFO_("Testing path : " + path, "path_attack");
|
||||
try {
|
||||
if (curl_describe(path, false)) {
|
||||
// insert in DB and go to the next port, print a cool message
|
||||
found = true;
|
||||
LOG_INFO_("Discovered a valid path : [" + path + "]", "brutepath");
|
||||
LOG_INFO_("Discovered a valid path : [" + path + "]", "path_attack");
|
||||
stream_model newstream{
|
||||
stream.address, stream.port, stream.username, stream.password, route,
|
||||
stream.service_name, stream.product, stream.protocol, stream.state, true,
|
||||
@@ -51,7 +51,7 @@ brutepath::test_path(const stream_model& stream, const std::string& route) const
|
||||
if ((*cache)->has_changed(stream)) return true;
|
||||
(*cache)->update_stream(newstream);
|
||||
}
|
||||
} catch (const std::runtime_error& e) { LOG_INFO_(e.what(), "brutepath"); }
|
||||
} catch (const std::runtime_error& e) { LOG_INFO_(e.what(), "path_attack"); }
|
||||
return found;
|
||||
}
|
||||
|
||||
@@ -65,7 +65,7 @@ path_already_found(std::vector<stream_model> streams, stream_model model) {
|
||||
}
|
||||
|
||||
bool
|
||||
brutepath::bruteforce_camera(const stream_model& stream) const {
|
||||
path_attack::attack_camera_path(const stream_model& stream) const {
|
||||
for (const auto& route : conf.paths) {
|
||||
if (signal_handler::instance().should_stop() != etix::cameradar::stop_priority::running)
|
||||
break;
|
||||
@@ -78,10 +78,10 @@ brutepath::bruteforce_camera(const stream_model& stream) const {
|
||||
// Tries to discover a route on all RTSP streams in DB
|
||||
// Uses the url.json file to try different routes
|
||||
bool
|
||||
brutepath::run() const {
|
||||
path_attack::run() const {
|
||||
std::vector<std::future<bool>> futures;
|
||||
|
||||
LOG_INFO_("Beginning bruteforce of the camera paths task, it may take a while.", "bruteforce");
|
||||
LOG_INFO_("Beginning attack of the camera paths, it may take a while.", "path_attack");
|
||||
std::vector<stream_model> streams = (*cache)->get_streams();
|
||||
int found = 0;
|
||||
for (const auto& stream : streams) {
|
||||
@@ -91,23 +91,23 @@ brutepath::run() const {
|
||||
LOG_INFO_(stream.address +
|
||||
" : This camera's path was already discovered in the database. Skipping "
|
||||
"to the next camera.",
|
||||
"brutepath");
|
||||
"path_attack");
|
||||
++found;
|
||||
} else {
|
||||
futures.push_back(
|
||||
std::async(std::launch::async, &brutepath::bruteforce_camera, this, stream));
|
||||
std::async(std::launch::async, &path_attack::attack_camera_path, this, stream));
|
||||
}
|
||||
}
|
||||
for (auto& fit : futures) {
|
||||
if (fit.get()) { ++found; }
|
||||
}
|
||||
if (!found) {
|
||||
LOG_WARN_(no_route_found_, "brutepath");
|
||||
LOG_WARN_(no_route_found_, "path_attack");
|
||||
|
||||
} else
|
||||
LOG_INFO_("Found " + std::to_string(found) + " routes for " +
|
||||
std::to_string(streams.size()) + " cameras",
|
||||
"brutepath");
|
||||
"path_attack");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user