Outils pour utilisateurs

Outils du site


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