Comment puis-je programme sur la défensive en Ruby?
-
09-06-2019 - |
Question
Voici un parfait exemple du problème: Classificateur gem pauses Rails.
** Question d'origine:**
Une chose qui me préoccupe en tant que professionnel de la sécurité, c'est que Ruby n'ont pas de parallèle de Java package de-vie privée.C'est, ce n'est pas Ruby:
public module Foo
public module Bar
# factory method for new Bar implementations
def self.new(...)
SimpleBarImplementation.new(...)
end
def baz
raise NotImplementedError.new('Implementing Classes MUST redefine #baz')
end
end
private class SimpleBarImplementation
include Bar
def baz
...
end
end
end
Il serait vraiment agréable d'être en mesure d'empêcher le singe de correction de Foo::BarImpl.De cette façon, les gens qui se fient à la bibliothèque sais que personne n'a foiré avec elle.Imaginez si quelqu'un a changé la mise en œuvre de MD5 ou SHA1 sur vous!Je peux appeler freeze
sur ces classes, mais je dois le faire sur une classe par classe de base, et d'autres scripts peuvent les modifier avant de finir la sécurisation ma demande si je ne suis pas très prudent sur l'ordre de chargement.
Java fournit beaucoup d'autres outils de programmation défensives, dont beaucoup ne sont pas possible en Ruby.(Voir Josh Bloch du livre pour une bonne liste.) Est-ce vraiment un sujet de préoccupation?Devrais-je arrêter de se plaindre et d'utiliser Ruby léger choses et pas d'espoir pour les "enterprise ready" solutions?
(Et non, des classes de base ne sont pas figés par défaut en Ruby.Voir ci-dessous:)
require 'md5'
# => true
MD5.frozen?
# => false
La solution
Découvrez Immuable par Garry Dolley.
Vous pouvez empêcher la redéfinition de méthodes individuelles.
Autres conseils
Je ne pense pas que c'est un sujet de préoccupation.
Oui, le mythique "quelqu'un" peut remplacer la mise en œuvre de MD5 avec quelque chose d'insécurité.Mais pour ce faire, le mythique quelqu'un doit effectivement être en mesure d'obtenir son code dans le process Ruby.Et si il peut le faire, alors il pourrait vraisemblablement aussi injecter son code dans un processus Java par exempleréécrire le bytecode pour le MD5 de l'opération.Ou tout simplement intercepter les touches et pas vraiment la peine à se tripoter la cryptographie code.
L'une des préoccupations typiques est:Je suis en train d'écrire cette impressionnante bibliothèque, qui est censé être utilisé comme suit:
require 'awesome'
# Do something awesome.
Mais que faire si quelqu'un l'utilise comme ceci:
require 'evil_cracker_lib_from_russian_pr0n_site'
# Overrides crypto functions and sends all data to mafia
require 'awesome'
# Now everything is insecure because awesome lib uses
# cracker lib instead of builtin
La solution la plus simple est:ne le faites pas!Former vos utilisateurs qu'ils ne doivent pas exécuter de code non sécurisé ils téléchargés à partir de sources obscures de sécurité pour les applications critiques.Et s'ils le font, ils ont probablement le méritent.
Pour en revenir à votre exemple Java:c'est vrai qu'en Java, vous pouvez faire votre crypto code private
et final
et ce n'est pas.Cependant, quelqu'un peut encore remplacer votre crypto mise en œuvre!En fait, quelqu'un a fait:de nombreux open-source implémentations Java d'utiliser OpenSSL pour mettre en œuvre leurs routines de chiffrement.Et, comme vous le savez probablement, Debian livré avec un cassé, l'insécurité, la version de OpenSSL depuis des années.Ainsi, tous les programmes Java en cours d'exécution sur Debian depuis quelques années déjà n' exécuter avec l'insécurité crypto!
Java fournit beaucoup d'autres outils pour la programmation défensive
Au départ, je pensais que tu parlais normal une programmation défensive,
dans lequel l'idée est de défendre le programme (ou votre sous-ensemble, ou votre fonction unique) à partir de données non valides d'entrée.
C'est une excellente chose, et j'encourage tout le monde à aller lire cet article.
Cependant, il semble que vous êtes en train de parler de la "défense de votre code d'autres programmeurs."
À mon avis, c'est complètement inutile objectif, peu importe ce que vous faites, un malveillant programmeur peut toujours exécuter votre programme sous un débogueur, ou de l'utilisation injection de dll ou n'importe quel nombre d'autres techniques.
Si vous êtes simplement à la recherche pour protéger votre code d'incompétents co-travailleurs, c'est ridicule. Informez vos collègues, ou obtenir une meilleure co-travailleurs.
En tout cas, si de telles choses sont de grande préoccupation pour vous, ruby n'est pas le langage de programmation pour vous.Monkeypatching est là, de par leur conception, et d'interdire, il va à l'encontre de l'ensemble du point de la fonction.
Je suppose que Ruby a qu'une fonction à valeur de plus de plus de il être un problème de sécurité.Ducktyping trop.
E. g.Je peux ajouter mes propres méthodes pour le Ruby classe String plutôt que de l'étendre ou en l'enveloppant.
"Sensibiliser vos collègues, ou obtenir une meilleure co-travailleurs" fonctionne très bien pour un petit logiciel de démarrage, et il fonctionne très bien pour les gros canons comme Google et Amazon.Il est ridicule de penser que tous les humbles développeur contracté pour certains petits aux dossiers médicaux de l'application dans le bureau d'un médecin à un mineur de la ville.
Je ne dis pas que nous devons construire pour le plus petit dénominateur commun, mais nous devons être réalistes qu'il y a beaucoup de médiocre programmeurs qui va tirer dans toute bibliothèque qui fait le travail, ne prêtant aucune attention à la sécurité.Comment pourrait ils sont attentifs à la sécurité?Peut-être l'a pris un algorithmes et structures de données de la classe.Peut-être qu'ils ont pris une compilateurs de classe.Ils ont presque certainement ne pas prendre un des protocoles de cryptage de classe.Certainement qu'ils n'ont pas tous lu Schneier ou l'un des autres personnes qui ont à peu près à mendier et à plaider même avec de très bons programmeurs de considérer la sécurité lors de la construction de logiciels.
Je ne suis pas inquiet à ce sujet:
require 'evil_cracker_lib_from_russian_pr0n_site'
require 'awesome'
Je suis inquiet au sujet de awesome
exigeant foobar
et fazbot
, et foobar
exigeant has_gumption
, et ...par la suite, deux de ces conflits dans certaines manière obscure qui annule un important aspect de la sécurité.
Un important principe de sécurité est de "défense en profondeur" -- l'ajout de ces couches supplémentaires de sécurité vous aider accidentellement tirer une balle dans le pied.Ils ne peuvent pas empêcher complètement le il;rien ne peut.Mais ils peuvent aider.
Si monkey patching est votre concentration, vous pouvez utiliser l'Immuable module (ou l'une des fonctions similaires).
Vous pouvez prendre un coup d'oeil à Pourquoi la Lucky Stiff du "bac à sable"du projet, que vous pouvez utiliser si vous vous inquiétez au sujet potentiellement l'exécution de code non sécurisé.http://code.whytheluckystiff.net/sandbox/
Un exemple (en ligne TicTacToe):http://www.elctech.com/blog/safely-exposing-your-app-to-a-ruby-sandbox
Raganwald a un post récent à propos de cette.En fin de compte, il construit le suivant:
class Module
def anonymous_module(&block)
self.send :include, Module.new(&block)
end
end
class Acronym
anonymous_module do
fu = lambda { 'fu' }
bar = lambda { 'bar' }
define_method :fubar do
fu.call + bar.call
end
end
end
Qui expose fubar
comme une méthode publique Acronym
s, mais maintient l'intérieur des tripes (fu
et bar
privé et cache de module d'aide de la vue extérieure.
Si quelqu'un monkeypatched un objet ou d'un module, alors vous avez besoin de regarder les 2 cas:Il a ajouté une nouvelle méthode.Si il est le seul à l'ajout de cette meyhod (ce qui est très probable), il n'y a aucun problème.Si il n'est pas le seul, vous avez besoin de voir si les deux méthodes de faire de même et de dire le développeur de la bibliothèque sur ce grave problème.
Si ils changent de méthode, vous devriez commencer à la recherche pourquoi la méthode a été modifiée.Ont-ils le changer en raison de certains cas limites de comportement ou ont-ils réellement correction d'un bug?surtout dans le dernier cas, la monkeypatch est un dieu, parce qu'il corrige un bogue dans de nombreux endroits.
En outre, vous êtes en utilisant un langage dynamique avec l'hypothèse que les programmeurs utilisent cette liberté, dans un façon saine.La seule façon de supprimer cette hypothèse n'est pas à utiliser un langage dynamique.