lib:rlbox
Librairie SandBox développé par Firefox.
Théorie
Doc Archive du 31/03/202 le 08/08/2020
Code source Archive du 17/07/2020 le 08/08/2020
Théorie Archive du 10/03/2020 le 08/08/2020
Diaporama Archive du 22/07/2020 le 13/07/2021
De ce que j'ai compris, cela force la réalisation d'une copie dans le tas de la donnée à transmettre à la librairie.
Cela est sécuritaire car :
- même si la donnée est déclarée en
const
dans la librairie, elle vient peut-être d'une donnée où la mémoire est accessible en écriture. - Le fait de passer la donnée directement peut permettre de déterminer l'aléa de l'
ASLR
(Address space layout randomization) ou de déduire le pointeur vers la table virtuelle. - en cas de buffer overflow, on ne risque pas d'écrire sur la pile.
- Lorsque la fonction renvoie sa valeur, il y a :
- une vérification automatique de type UBSan pour vérifier que la variable qui va héberger la valeur est assez grande pour la valeur renvoyée.
- Une vérification manuelle peut être ajoutée. La fonction doit alors être écrite par le développeur.
Exemples
Fonction renvoyant un char* alloué
La libération de la mémoire du texte renvoyé est à notre charge.
#define RLBOX_SINGLE_THREADED_INVOCATIONS #define RLBOX_USE_STATIC_CALLS() rlbox_noop_sandbox_lookup_symbol #include <iostream> #include <memory> #include <mutex> #include <optional> #include <rlbox.hpp> #include <rlbox_noop_sandbox.hpp> #include <string_view> #include <simdjson.h> // Classe libérant la mémoire quand la donnée n'est plus utilisée. template <typename T> class AutoFree { public: AutoFree(rlbox::tainted<T, rlbox::rlbox_noop_sandbox> taint) : _taint(taint) { } ~AutoFree() { free(_taint.UNSAFE_unverified()); } rlbox::tainted<T, rlbox::rlbox_noop_sandbox>& get() { return _taint; } private: rlbox::tainted<T, rlbox::rlbox_noop_sandbox> _taint; }; // Fonction risquée char* unsecure_function(char* data, int nb) { char* retval = static_cast<char*>(malloc(sizeof(char) * (strlen(data) + 1))); strcpy(retval, data); return retval; } // Fonction sécurisée std::string secure_function(rlbox::rlbox_sandbox<rlbox::rlbox_noop_sandbox>& sandbox, const std::string& unsafe_data) { size_t helloSize = unsafe_data.length() + 1; auto taintedStr = sandbox.malloc_in_sandbox<char>(helloSize); // La librairie n'ayant pas la possibilité d'écrire, on le fait à sa place. std::strncpy( taintedStr.unverified_safe_pointer_because(helloSize, "writing only"), unsafe_data.c_str(), helloSize); // On récupère la valeur de retour de façon sécurisée. AutoFree<char*> retvalTainted( sandbox.invoke_sandbox_function(unsecure_function, taintedStr, 3)); // On récupère la valeur de retour après vérification. auto retval = retvalTainted.get().copy_and_verify_string( [](std::unique_ptr<char[]> ret) -> std::optional<std::string> { size_t len = strlen(ret.get()); if (simdjson::validate_utf8(ret.get(), len)) return std::optional<std::string>(std::string{ret.get(), len}); else return std::nullopt; }); sandbox.free_in_sandbox(taintedStr); return retval.value_or("nullptr"); } int main() { rlbox::rlbox_sandbox<rlbox::rlbox_noop_sandbox> sandbox; sandbox.create_sandbox(); std::cout << secure_function(sandbox, std::string{"\xc3\xb1"}) << std::endl; std::cout << secure_function(sandbox, std::string{"\xc3\x28"}) << std::endl; sandbox.destroy_sandbox(); }
lib/rlbox.txt · Dernière modification : 2021/07/14 17:05 de root