🔨 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 #pragma once
#include <drogon/HttpController.h> #include <drogon/HttpController.h>
#include "simdjson.h" #include "simdjson.h"
#include "str_intrusion.h"
#include "json_filter.h" #include "json_filter.h"
#include "user_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 <drogon/HttpFilter.h>
#include <libbase64.h> #include <libbase64.h>
#include <array> #include <array>
#include "str_intrusion.h"
#include "bank.h" #include "bank.h"
using namespace drogon; using namespace drogon;

View file

@ -65,9 +65,9 @@ void api::SendFunds(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val;
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only string_view_to_string(name_val, name.value());
res = bank.SendFunds(NAME_PARAM, name_val.data(), amount.value()); res = bank.SendFunds(NAME_PARAM, name_val, amount.value());
} }
RESPONSE_PARSE(std::move(res)); RESPONSE_PARSE(std::move(res));
} }
@ -86,9 +86,9 @@ void api::ChangePassword(req_args) const
} }
else else
{ {
static thread_local auto &pass_val = pass.value(); static thread_local std::string pass_val;
*(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only string_view_to_string(pass_val, pass.value());
bank.ChangePassword(NAME_PARAM, std::move(pass_val.data())); bank.ChangePassword(NAME_PARAM, std::move(pass_val));
} }
RESPOND_TRUE; RESPOND_TRUE;
} }
@ -104,10 +104,10 @@ void api::AdminChangePassword(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val, pass_val;
static thread_local auto &pass_val = name.value(); string_view_to_string(name_val, name.value());
*(char *)(name_val.data() + name_val.size()) = *(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only string_view_to_string(pass_val, pass.value());
bank.ChangePassword(name_val.data(), std::move(pass_val.data())); bank.ChangePassword(name_val, std::move(pass_val));
} }
RESPOND_TRUE; RESPOND_TRUE;
} }
@ -123,9 +123,9 @@ void api::SetBal(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val;
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only string_view_to_string(name_val, name.value());
res = bank.SetBal(name_val.data(), amount.value()); res = bank.SetBal(name_val, amount.value());
} }
RESPONSE_PARSE(std::move(res)); RESPONSE_PARSE(std::move(res));
} }
@ -141,9 +141,9 @@ void api::ImpactBal(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val;
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only string_view_to_string(name_val, name.value());
res = bank.ImpactBal(name_val.data(), amount.value()); res = bank.ImpactBal(name_val, amount.value());
} }
RESPONSE_PARSE(std::move(res)); RESPONSE_PARSE(std::move(res));
} }
@ -188,7 +188,6 @@ void api::ApiProperties(req_args) const
CACHE_FOREVER; CACHE_FOREVER;
callback(resp); callback(resp);
} }
void api::AddUser(req_args) const void api::AddUser(req_args) const
{ {
SIMD_JSON_GEN; SIMD_JSON_GEN;
@ -201,10 +200,10 @@ void api::AddUser(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val, pass_val;
static thread_local auto &pass_val = pass.value(); string_view_to_string(name_val, name.value());
*(char *)(name_val.data() + name_val.size()) = *(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only string_view_to_string(pass_val, pass.value());
res = bank.AddUser(name_val.data(), 0, pass_val.data()); res = bank.AddUser(std::move(name_val), 0, std::move(pass_val));
} }
RESPONSE_PARSE(std::move(res)); RESPONSE_PARSE(std::move(res));
} }
@ -221,10 +220,10 @@ void api::AdminAddUser(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val, pass_val;
static thread_local auto &pass_val = pass.value(); string_view_to_string(name_val, name.value());
*(char *)(name_val.data() + name_val.size()) = *(char *)(pass_val.data() + pass_val.size()) = '\0'; //ignoring read-only string_view_to_string(pass_val, pass.value());
res = bank.AddUser(name_val.data(), amount.value(), pass_val.data()); res = bank.AddUser(std::move(name_val), amount.value(), std::move(pass_val));
} }
RESPONSE_PARSE(std::move(res)); RESPONSE_PARSE(std::move(res));
} }
@ -243,9 +242,9 @@ void api::AdminDelUser(req_args) const
} }
else else
{ {
static thread_local auto &name_val = name.value(); static thread_local std::string name_val;
*(char *)(name_val.data() + name_val.size()) = '\0'; //ignoring read-only string_view_to_string(name_val, name.value());
res = bank.DelUser(name_val.data()); res = bank.DelUser(name_val);
} }
RESPONSE_PARSE(std::move(res)); 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) FilterChainCallback &&fccb)
{ {
static thread_local std::string_view auth_header = req->getHeader("Authorization"); 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 ") if (auth_header.substr(0, 6) == "Basic ")
{ {
static thread_local std::string_view base64_input = auth_header.substr(6); 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; static thread_local size_t new_sz;
base64_decode(base64_input.data(), base64_input.size(), base64_result.begin(), &new_sz, 0); 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(':'); static thread_local std::size_t middle = results_view.find(':');
if (middle != std::string::npos) if (middle != std::string::npos)
{ {
base64_result[middle] = '\0'; static thread_local std::string username;
static thread_local const std::string &username(results_view.substr(0, middle).data()); string_view_to_string(username, results_view.substr(0, middle));
if constexpr (require_admin) if constexpr (require_admin)
{ {
if (bank.AdminVerifyAccount(username)) if (bank.AdminVerifyAccount(username))
{ {
base64_result[new_sz] = '\0'; static thread_local std::string password;
if (bank.VerifyPassword(username, results_view.substr(middle + 1))) string_view_to_string(password, results_view.substr(middle + 1));
if (bank.VerifyPassword(username, password))
{ {
fccb(); fccb();
return; return;
@ -38,7 +39,8 @@ void UserFilter<set_body_flag, require_admin>::doFilter(const HttpRequestPtr &re
} }
else 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 (bank.VerifyPassword(username, results_view.substr(middle + 1)))
{ {
if constexpr (set_body_flag) if constexpr (set_body_flag)