Veuillez rendre votre langue analysable / auditable pour les responsables de la sécurité informatique.
Les personnes chargées de la sécurité doivent être en mesure de détecter les vulnérabilités d'un programme avant son expédition. Idéalement, nous sommes appelés tôt et pouvons commenter la base de code au fur et à mesure de son développement, mais souvent pas.
Quand une nouvelle version du langage ou des librairies de base sortent, les choses qui étaient auparavant sûres ne sont peut-être plus:
- les bibliothèques peuvent devenir plus puissantes: par exemple, la bibliothèque d'URL prend désormais en charge
javascript:
- il peut y avoir de nouvelles façons de convertir des chaînes ou des octets en code: par exemple,
eval
ou des bibliothèques de désérialisation
- les techniques de réflexion linguistique peuvent devenir plus puissantes: par exemple, exposer des variables locales
N'importe lequel de ces changements peut augmenter la quantité d'autorité abusable d'un programme, mais comme l'autorité utilisée par le programme (lorsqu'il traite avec des clients non malveillants) n'a pas changé, les responsables de la sécurité ont du mal à comprendre cela sans une utilisation intensive. ré-audit.
Alors, pensez à nous lors de la conception et de la gestion de la langue. Voici quelques conseils:
Définissez quelques primitives dans lesquelles un programme peut être décomposé.
HTML5 est particulièrement mauvais de cette façon. Ils ont évidemment beaucoup réfléchi à la sécurité et ont des personnes très intelligentes, mais au lieu de spécifier de nouveaux éléments de programme, tels que les <video>
anciens, ou de créer une abstraction commune que les nouveaux <video>
et les anciens <img>
puissent être spécifiés, <video>
c'est encore un autre élément ponctuel du programme avec ses propres conséquences pour la sécurité.
Assurez-vous que votre langage est sujet à l'analyse statique (même s'il n'est pas typé de manière statique).
Les spécialistes de la sécurité ont souvent recours à l'analyse statique pour rechercher des modèles et pour tenter d'éliminer certaines parties d'un programme afin qu'ils puissent se concentrer sur les éléments les plus difficiles.
Il devrait être évident que les identificateurs sont des variables locales et ceux qui ne le sont pas.
Par exemple, ne commettez pas la même erreur que les anciennes versions de JavaScript, il était donc impossible de savoir s'il x
s'agit d'une référence de variable locale dans la liste ci-dessous (d'après une lecture littérale d'une ancienne version de la spécification):
if (Math.random() > 0.5) {
Object.prototype.x = 0;
}
function f() {
var x = 1;
(function () {
alert(x); // Might alert 0, might alert 1.
})();
}
Autoriser la sécurité décomposable
Un grand nombre de systèmes sécurisés sont conçus autour d'un noyau sécurisé qui préserve les propriétés de sécurité, afin que les spécialistes de la sécurité puissent concentrer leurs efforts sur l'analyse d'une petite quantité de code et évitant ainsi à la plupart des programmeurs d'avoir à traiter avec des spécialistes de la sécurité {agaçants, pédants, paranoïa} .
Il devrait être possible d'écrire un tel noyau dans votre langue. Si l'une des propriétés de sécurité de votre langue est que seul un certain sous-ensemble d'URL sera récupéré, les auteurs du noyau peuvent-ils faire quelque chose pour canaliser toutes les URL extraites à travers leur code? Ou bien les vérifications de construction statiques (telles que l’analyse des importations) remplissent la même fonction.
Certaines langues telles que Newspeak utilisent un modèle de fonctionnalités d'objet. C'est génial et un excellent moyen d'obtenir une sécurité décomposable.
Mais si vous ne pouvez pas faire cela, transformer le graphique en module en un artefact analysable statiquement peut vous procurer un avantage certain. Si je peux prouver qu'un module ne peut pas atteindre le module d'E / S de fichier (sauf en appelant du code dans un module du TCB), je peux alors exclure des classes entières de problèmes de ce module.
Limiter l'autorité des langages de script intégrés
Un grand nombre de systèmes utiles sont organisés comme un noyau statique qui lance beaucoup de code écrit dans des langages dynamiques (même fonctionnels).
Et l'intégration de langages de script peut rendre un système beaucoup plus extensible.
Mais un langage de script ne devrait pas avoir toute l'autorité de la machine virtuelle.
Si vous choisissez d'autoriser les langages de script intégrés, aidez-le à limiter ce qu'il peut faire. Un modèle de capacités d'objet (voir le commentaire sur Newspeak ci-dessus) est très approprié ici; Ainsi, lors de l'évaluation du code dans un langage de script, l'appelant doit transmettre le code à exécuter et toutes les variables globales pour ce code.
Traiter eval
comme un langage s’intégrant comme un langage de script
Si votre langage peut appeler son propre compilateur pour transformer une chaîne en code, autorisez-le à être mis en bac à sable de la même façon que vous le feriez avec un langage de script intégré.
Utilisez un modèle de concurrence simple
Nous, les responsables de la sécurité, n’aimons pas avoir à nous inquiéter des conditions de concurrence lorsque nous essayons de déterminer si une propriété de sécurité est conservée.
Veuillez envisager des alternatives au threading avant de choisir des threads comme une option par défaut presque impossible à sécuriser.
Un exemple simple est la concurrence d'accès aux boucles d'événement, similaire à celle trouvée dans E, Verilog et JavaScript.
N'encourage pas la confusion
Certaines langues sont des langues collées, et elles finissent par traiter des chaînes dans beaucoup de langues différentes.
Par exemple, JavaScript compose souvent des chaînes HTML, CSS, XML, JSON et même JavaScript. Il est très difficile pour les programmeurs de se rappeler d’encoder correctement les chaînes de texte brut lorsqu’ils les combinent pour créer des chaînes dans d’autres langues. Les programmes JS ont donc, sans surprise, toutes sortes de problèmes de confusion entre guillemets: XSS étant le pire.
Si vous souhaitez inclure des fonctionnalités de composition de chaîne, essayez de réduire la charge de sécurité du programmeur. Les DSL, les macros hygiéniques et les langages de gabarit intégrés peuvent être un excellent moyen de le faire en allégeant la tâche qui consiste à échapper correctement aux développeurs de bibliothèques ou de langages et à les éloigner du développeur final.