Question

Nous sommes en train de construire une application qui exécute un certain nombre d'outils externes.Nous avons souvent de faire passer des informations dans notre système par les utilisateurs de ces outils.

Évidemment, c'est une grande sécurité cauchemar en attente de se produire.

Malheureusement, nous n'avons pas encore trouvé toutes les classes dans le .NET Framework qui exécutent des programmes en ligne de commande, tout en offrant le même genre de protections contre les attaques par injection de la IDbCommand objets de bases de données.

Droit maintenant, nous utilisons une très primitive chaîne de substitution, ce qui je pense est plutôt insuffisante:

protected virtual string Escape(string value)
{
      return value
        .Replace(@"\", @"\\")
        .Replace(@"$", @"\$")
        .Replace(@"""", @"\""")
        .Replace("`", "'")
      ;
}

Que faites-vous les gars faire pour l'empêcher de ligne de commande attaques par injection?Nous prévoyons de mettre en œuvre une regex qui est très stricte et ne permet qu'un très petit sous-ensemble de caractères, mais je me demandais si il y avait une meilleure façon.

Quelques précisions:

  • Certains de ces outils n'ont pas d'Api de programmation des contre.Si ils l'ont fait, nous ne serions pas à avoir ce problème.
  • Les utilisateurs ne prenez pas d'outils pour exécuter, ils entrent dans les méta-données que les outils que nous avons choisi d'usage (par exemple, l'injection de méta-données telles que les avis de droit d'auteur dans les dossiers de cible).
Était-ce utile?

La solution

Êtes-vous l'exécution des programmes directement ou en passant par le shell?Si vous avez toujours lancer un programme externe en donnant le nom de chemin complet de l'exécutable et en laissant la coquille de l'équation, alors vous ne sont pas vraiment sensibles à tout type de ligne de commande d'injection.

EDIT:DrFloyd, la coquille est responsable de l'évaluation des choses comme le backtick.Pas de shell, pas de coquille d'évaluation.Évidemment, vous avez toujours être au courant des éventuels problèmes de sécurité dans les programmes que vous appelez -- mais je ne pense pas que cette question est à propos de ça.

Autres conseils

Lorsque vous Processus.Démarrer un nouveau processus d'approvisionnement plus sur les paramètres son Paramètres argument au lieu de construire l'ensemble de la ligne de commande vous-même.

N'ai pas le temps pour un bon test, mais je pense que cela devrait aider à la garde à un certain niveau.

Vais tester cela demain.

EDIT: Ah, quelqu'un me battre à nouveau.Mais voici un autre point:Essayez d'utiliser la Console.InputStream (ne me souviens pas le nom exact) pour la fourniture de données au lieu de passer des paramètres, c'est qu'une solution possible?comme correctif de la commande de manière à ce qu'il lit à partir de la CON de l'appareil et de vous fournir les données via des flux d'entrée à la place.

En C++ sur Windows, vous venez d'échapper \ et " en cas de besoin, de citer l'argument et ShellExecute il.Puis, tout à l'intérieur des citations devraient être traités comme du texte.

Cela devrait illustrer:


#include <iostream>
#include <string>
#include <windows.h>
#include <cstdlib>
using namespace std;

// Escape and quote string for use as Windows command line argument
string qEscape(const string& s) {
    string result("\"");
    for (string::const_iterator i = s.begin(); i != s.end(); ++i) {
        const char c = *i;
        const string::const_iterator next = i + 1;
        if (c == '"' || (c == '\\' && (next == s.end() || *next == '"'))) {
            result += '\\';
        }
        result += c;
    }
    result += '"';
    return result;
}

int main() {
    // Argument value to pass: c:\program files\test\test.exe
    const string safe_program = qEscape("c:\\program files\\test\\test.exe");
    cout << safe_program << " ";

    // Argument value to pass: You're the "best" around.
    const string safe_arg0 = qEscape("You're the \"best\" around.");

    // Argument value to pass: "Nothing's" gonna ever keep you down.
    const string safe_arg1 = qEscape("\"Nothing's\" gonna ever keep you down.");

    const string safe_args = safe_arg0 + " " + safe_arg1;
    cout << safe_args << "\n\n";

    // c:\program files\test\  to pass.
    const string bs_at_end_example = qEscape("c:\\program files\\test\\");
    cout << bs_at_end_example << "\n\n";

    const int result = reinterpret_cast<int>(ShellExecute(NULL, "open", safe_program.c_str(), safe_args.c_str(), NULL, SW_SHOWNORMAL));
    if (result < 33) {
        cout << "ShellExecute failed with Error code " << result << "\n";
        return EXIT_FAILURE;
    }
}

Mais, avec n'importe quelle méthode que vous utilisez, vous devez tester l'enfer hors de lui pour voir que c'est vraiment éviter l'injection.

Ne pas utiliser une liste noire pour la prévention des injections.Si il y a n des moyens pour injecter du code, vous aurez l'impression de n - mm > 0.

L'utilisation d'une liste blanche de accepté de paramètres (ou des modèles).Il est beaucoup plus restrictif par rapport à la nature, mais c'est la nature de la sécurité.

Eh bien, si vous pouvez invoquer les outils par programmation sans la ligne de commande, ce serait probablement votre meilleure option.Sinon, vous pourriez potentiellement d'exécuter l'outil en ligne de commande par un utilisateur qui n'a absolument pas accès à tout faire (sauf peut-être un seul répertoire qu'ils ne peuvent pas faire de mal avec)...mais qui peut finir par casser l'outil, en fonction de ce que l'outil ne.

Il suffit de noter, je n'ai jamais eu à faire face à ce problème, parce que je n'ai jamais eu réellement d'invoquer un outil de ligne de commande à partir de l'extérieur face à l'application de l'outil nécessite une entrée de l'utilisateur.

Hmmm...

Il semble que vous avez une liste de commandes valides que les utilisateurs sont en mesure d'exécuter.Mais vous ne voulez pas à exécuter tous.

Vous pourriez essayer de prendre la ligne de commande et vérifiez que le fichier existe dans le "coffre-fort" emplacement au moins.

Vous pouvez également résoudre le problème avec plus d'interface, de fournir une liste déroulante de commandes et les paramètres qu'ils pourraient utiliser.C'est plus de travail sur votre fin, mais au final, il aide les utilisateurs.

Êtes-vous l'exécution des programmes directement ou en passant par le shell?Si vous avez toujours lancer un programme externe en donnant le nom de chemin complet de l'exécutable et en laissant la coquille de l'équation, alors vous ne sont pas vraiment sensibles à tout type de ligne de commande d'injection.

@Curt Hagenlocher Le backtick peut vous tuer.Si le Système Windows est le programme d'installation de "mauvais", ou le système unix, il permet, d'une dir &bt;del *&bt;va d'abord exécuter la del * commande alors l'utilisation de la sortie à la place de la del *, qui, dans ce cas, n'a pas d'importance car il n'y a rien à dir (ou ls)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top