我试图将主机名/ipv4/ipv6 传递给 linux 中的 ping 实用程序(以避免使用原始套接字、root),但是,我想在运行命令之前确保它是有效的。例如,如果提供了恶意域名,比如
char host[] = "google.com;cat > pwned.txt";
消毒剂应该拒绝它,因为它会允许远程代码执行
ping -c 4 google.com;cat > pwned.txt
到目前为止,我已经在下面编写了代码来检测有效的 ipv4、ipv6 和主机名。
问题
代码有异味,所以我想知道是否有更好的 Boost C++ 方法来清理用户输入?
#include <iostream>
#include <string>
#include <algorithm>
#include <boost/asio.hpp>
int main(int argc, char* argv[])
{
//char host[] = "google.com";
char host[] = "google.com;cat > pwned.txt";
std::string allowed = "1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-.";
bool bValid = false;
boost::asio::ip::address ipv4Addr;
boost::asio::ip::address ipv6Addr;
try
{
ipv4Addr = boost::asio::ip::address::from_string(host);
bValid = ipv4Addr.is_v4();
}
catch (std::exception& e)
{
std::cerr << "NOT ipv4: " << e.what() << std::endl;
bValid = false;
}
if (!bValid)
{
// not ipv4, let's try ipv6
try
{
ipv6Addr = boost::asio::ip::address::from_string(host);
bValid = ipv6Addr.is_v6();
}
catch (std::exception& e)
{
std::cerr << "NOT ipv6: " << e.what() << std::endl;
bValid = false;
}
if (!bValid)
{
// ipv4 and ipv6 failed, try a string
std::string hostname = std::string(host);
if (hostname.find_first_not_of(allowed) != std::string::npos) {
std::cerr << "NOT valid host" << std::endl;
return 1;
}
}
}
std::string sCommand = "ping -c 4 ";
sCommand.append(host);
std::cout << "Running PING command: " << sCommand << std::endl;
int result = std::system(sCommand.c_str());
if (result != 0) {
std::cerr << "Command failed: " << result << std::endl;
}
return 0;
}
就像其他人说的那样,不要消毒,只是不要不安全地传递论点。您的 ping 工具已经清理完毕,并且您从未调用过 shell。
#include <boost/process.hpp>
#include <iostream>
namespace bp = boost::process;
int main(int argc, char** argv) {
if (argc > 1) {
std::error_code ec;
int code = bp::system(bp::search_path("ping"), "-c", "4", argv[1], ec);
std::cout << code << " (" << ec.message() << ")\n";
}
}