🔨 using str_intrusion.h to write to private string data

This commit is contained in:
EntireTwix 2021-07-08 14:58:03 -07:00
parent 053c20130e
commit da89d390ea
6 changed files with 87 additions and 35 deletions

View file

@ -1,6 +1,7 @@
#pragma once
#include <drogon/HttpController.h>
#include "simdjson.h"
#include "str_intrusion.h"
#include "json_filter.h"
#include "user_filter.h"

5
include/str_intrusion.h Normal file
View file

@ -0,0 +1,5 @@
#pragma once
#include <string>
void string_view_to_string(std::string &str, std::string_view sv);
void destroy_string(std::string &str);

View file

@ -2,6 +2,7 @@
#include <drogon/HttpFilter.h>
#include <libbase64.h>
#include <array>
#include "str_intrusion.h"
#include "bank.h"
using namespace drogon;

View file

@ -65,9 +65,9 @@ void api::SendFunds(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only
res = bank.SendFunds(NAME_PARAM, name_val.data(), amount.value());
static thread_local std::string name_val;
string_view_to_string(name_val, name.value());
res = bank.SendFunds(NAME_PARAM, name_val, amount.value());
}
RESPONSE_PARSE(std::move(res));
}
@ -86,9 +86,9 @@ void api::ChangePassword(req_args) const
}
else
{
static thread_local auto &pass_val = pass.value();
*(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only
bank.ChangePassword(NAME_PARAM, std::move(pass_val.data()));
static thread_local std::string pass_val;
string_view_to_string(pass_val, pass.value());
bank.ChangePassword(NAME_PARAM, std::move(pass_val));
}
RESPOND_TRUE;
}
@ -104,10 +104,10 @@ void api::AdminChangePassword(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
static thread_local auto &pass_val = name.value();
*(char *)(name_val.data() + name_val.size()) = *(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only
bank.ChangePassword(name_val.data(), std::move(pass_val.data()));
static thread_local std::string name_val, pass_val;
string_view_to_string(name_val, name.value());
string_view_to_string(pass_val, pass.value());
bank.ChangePassword(name_val, std::move(pass_val));
}
RESPOND_TRUE;
}
@ -123,9 +123,9 @@ void api::SetBal(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only
res = bank.SetBal(name_val.data(), amount.value());
static thread_local std::string name_val;
string_view_to_string(name_val, name.value());
res = bank.SetBal(name_val, amount.value());
}
RESPONSE_PARSE(std::move(res));
}
@ -141,9 +141,9 @@ void api::ImpactBal(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only
res = bank.ImpactBal(name_val.data(), amount.value());
static thread_local std::string name_val;
string_view_to_string(name_val, name.value());
res = bank.ImpactBal(name_val, amount.value());
}
RESPONSE_PARSE(std::move(res));
}
@ -188,7 +188,6 @@ void api::ApiProperties(req_args) const
CACHE_FOREVER;
callback(resp);
}
void api::AddUser(req_args) const
{
SIMD_JSON_GEN;
@ -201,10 +200,10 @@ void api::AddUser(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
static thread_local auto &pass_val = pass.value();
*(char *)(name_val.data() + name_val.size()) = *(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only
res = bank.AddUser(name_val.data(), 0, pass_val.data());
static thread_local std::string name_val, pass_val;
string_view_to_string(name_val, name.value());
string_view_to_string(pass_val, pass.value());
res = bank.AddUser(std::move(name_val), 0, std::move(pass_val));
}
RESPONSE_PARSE(std::move(res));
}
@ -221,10 +220,10 @@ void api::AdminAddUser(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
static thread_local auto &pass_val = pass.value();
*(char *)(name_val.data() + name_val.size()) = *(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only
res = bank.AddUser(name_val.data(), amount.value(), pass_val.data());
static thread_local std::string name_val, pass_val;
string_view_to_string(name_val, name.value());
string_view_to_string(pass_val, pass.value());
res = bank.AddUser(std::move(name_val), amount.value(), std::move(pass_val));
}
RESPONSE_PARSE(std::move(res));
}
@ -243,9 +242,9 @@ void api::AdminDelUser(req_args) const
}
else
{
static thread_local auto &name_val = name.value();
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only
res = bank.DelUser(name_val.data());
static thread_local std::string name_val;
string_view_to_string(name_val, name.value());
res = bank.DelUser(name_val);
}
RESPONSE_PARSE(std::move(res));
}

44
src/str_intrusion.cpp Normal file
View file

@ -0,0 +1,44 @@
#include "str_intrusion.h"
//this function is horribly jank
template <typename Tag>
struct result
{
typedef typename Tag::type type;
static type ptr;
};
template <typename Tag>
typename result<Tag>::type result<Tag>::ptr;
template <typename Tag, typename Tag::type p>
struct rob : result<Tag>
{
struct filler
{
filler() { result<Tag>::ptr = p; }
};
static filler filler_obj;
};
template <typename Tag, typename Tag::type p>
typename rob<Tag, p>::filler rob<Tag, p>::filler_obj;
struct string_length
{
typedef void (std::string::*type)(size_t);
};
template class rob<string_length, &std::string::_M_length>;
struct string_data
{
typedef void (std::string::*type)(char *);
};
template class rob<string_data, &std::string::_M_data>;
void string_view_to_string(std::string &str, std::string_view sv)
{
(str.*result<string_data>::ptr)((char *)sv.data());
(str.*result<string_length>::ptr)(sv.size());
}
//may be used later
void destroy_string(std::string &str)
{
(str.*result<string_data>::ptr)(nullptr);
(str.*result<string_length>::ptr)(0);
}

View file

@ -9,12 +9,12 @@ void UserFilter<set_body_flag, require_admin>::doFilter(const HttpRequestPtr &re
FilterChainCallback &&fccb)
{
static thread_local std::string_view auth_header = req->getHeader("Authorization");
if (auth_header.size() > 6)
if (auth_header.size() > 6 && auth_header.size() <= 517) //"Basic " + username + ':' + password
{
if (auth_header.substr(0, 6) == "Basic ")
{
static thread_local std::string_view base64_input = auth_header.substr(6);
static thread_local std::array<char, 511> base64_result; //255 username + ':' + 255 password
static thread_local std::array<char, 384> base64_result; //(255 username + ':' + 255 password) * 3/4
static thread_local size_t new_sz;
base64_decode(base64_input.data(), base64_input.size(), base64_result.begin(), &new_sz, 0);
@ -22,14 +22,15 @@ void UserFilter<set_body_flag, require_admin>::doFilter(const HttpRequestPtr &re
static thread_local std::size_t middle = results_view.find(':');
if (middle != std::string::npos)
{
base64_result[middle] = '\0';
static thread_local const std::string &username(results_view.substr(0, middle).data());
static thread_local std::string username;
string_view_to_string(username, results_view.substr(0, middle));
if constexpr (require_admin)
{
if (bank.AdminVerifyAccount(username))
{
base64_result[new_sz] = '\0';
if (bank.VerifyPassword(username, results_view.substr(middle + 1)))
static thread_local std::string password;
string_view_to_string(password, results_view.substr(middle + 1));
if (bank.VerifyPassword(username, password))
{
fccb();
return;
@ -38,7 +39,8 @@ void UserFilter<set_body_flag, require_admin>::doFilter(const HttpRequestPtr &re
}
else
{
base64_result[new_sz] = '\0';
static thread_local std::string password;
string_view_to_string(password, results_view.substr(middle + 1));
if (bank.VerifyPassword(username, results_view.substr(middle + 1)))
{
if constexpr (set_body_flag)