Dr. No: XSS Problem! Wie vermeiden?

Hallo zusammen,
ich muss gestehen dass ich mich in Perl nicht so auskenne, nun darf ich eine Sicherheitslücke in unserem Shopsystem beseitigen.

Mit folgender Anweisung lässt sich Code bei uns einschleusen:
https://www.example.de/cgi-bin/login.pl?step1=1&step=1&LoginType=%22%3E%
3CSCRIPT%3Ealert%28%22XSS%22%29%3B%3C%2FSCRIPT%3E

Nun muss ich irgendwie die GET/POST Parameter "bereinigen".
Ich hole mir die Parameter mit folgender Anweisung:

$cgi = new CGI();  
@usrData = $cgi->param();

Wie nun soll ich weiter vorgehen um ein Sinnvolles Ergebnis zu erhalten?
RegExp?

Leider bin ich mit der Thematik nicht sehr vertraut, und der Code ist auch nicht von mir, daher fällt es mir relativ schwer das Richtige raus zusuchen.

Ich hoffe um ein paar nützliche Tipps, danke.

  1. Mit folgender Anweisung lässt sich Code bei uns einschleusen:
    https://www.example.de/cgi-bin/login.pl?step1=1&step=1&LoginType=%22%3E%
    3CSCRIPT%3Ealert%28%22XSS%22%29%3B%3C%2FSCRIPT%3E

    Nun muss ich irgendwie die GET/POST Parameter "bereinigen".

    Naja, du musst dort Bereinigen wo das Problem auftritt. Was darf der Wert LoginType enthalten? Alles andere fliegt raus.

    Ich hole mir die Parameter mit folgender Anweisung:

    $cgi = new CGI();

    @usrData = $cgi->param();

      
    Das ist eigentlich Unsinn, da du bereits vorhandene Daten kopierst, also der komplette Input ist jetzt doppelt vorhanden.  
      
    
    > Wie nun soll ich weiter vorgehen um ein Sinnvolles Ergebnis zu erhalten?  
    > RegExp?  
      
    Jede Eingabe, die von aussen kommt, prüfen. Und ungültige Zeichen ersetzen.  
      
    Struppi.
    
    1. Naja, du musst dort Bereinigen wo das Problem auftritt. Was darf der Wert LoginType enthalten? Alles andere fliegt raus.

      Es gibt eine Sub die die Eingabe entgegennimmt, also wäre es doch Klug dort das ganze Input durch eine RegExp. durch zujagen oder?

      Ich hole mir die Parameter mit folgender Anweisung:

      $cgi = new CGI();

      @usrData = $cgi->param();

      
      >   
      > Das ist eigentlich Unsinn, da du bereits vorhandene Daten kopierst, also der komplette Input ist jetzt doppelt vorhanden.  
      
      Kann sein, ist nicht meine Programmierung, daher werde ich keine großen Umbauten vornehmen da das Projekt bald online geht.  
        
      
      > Jede Eingabe, die von aussen kommt, prüfen. Und ungültige Zeichen ersetzen.  
      
      Und genau das ist das Problem, der Syntax von Perl ist etwas "eigen", daher wäre vielleicht ein Bespiel ganz hilfreich...
      
      1. Naja, du musst dort Bereinigen wo das Problem auftritt. Was darf der Wert LoginType enthalten? Alles andere fliegt raus.
        Es gibt eine Sub die die Eingabe entgegennimmt, also wäre es doch Klug dort das ganze Input durch eine RegExp. durch zujagen oder?

        Das Wissen wir nicht, die Frage ist was darf der Wert enthalten, vorher kann man schlecht sagen was du filtern willst.

        Ich hole mir die Parameter mit folgender Anweisung:

        $cgi = new CGI();

        @usrData = $cgi->param();

        
        > >   
        > > Das ist eigentlich Unsinn, da du bereits vorhandene Daten kopierst, also der komplette Input ist jetzt doppelt vorhanden.  
        > Kann sein, ist nicht meine Programmierung, daher werde ich keine großen Umbauten vornehmen da das Projekt bald online geht.  
          
        Hmmm? Du hast ein unsicheres Skript, das offensichtlich auch nicht sonderlich effizient programmiert ist, du hast kaum Kenntnisse der Programmsprache und willst damit online gehen? das ist gewagt.  
          
        
        > > Jede Eingabe, die von aussen kommt, prüfen. Und ungültige Zeichen ersetzen.  
        > Und genau das ist das Problem, der Syntax von Perl ist etwas "eigen", daher wäre vielleicht ein Bespiel ganz hilfreich...  
          
        `tr/x/u/;`{:.language-perl}  
        tauscht alle x gegen ein u  
          
        Struppi.
        
        1. Moin Moin!

          Kann sein, ist nicht meine Programmierung, daher werde ich keine großen Umbauten vornehmen da das Projekt bald online geht.

          Hmmm? Du hast ein unsicheres Skript, das offensichtlich auch nicht sonderlich effizient programmiert ist, du hast kaum Kenntnisse der Programmsprache und willst damit online gehen? das ist gewagt.

          Das sollte der Punkt sein, an dem man sich externes Know-How einkauft oder das Projekt verschiebt. Wer schon die Syntax von Perl nicht versteht, hat nahezu keine Chance, Fehler in fremdem Perl-Code zu finden und zu beseitigen.

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
          1. Das sollte der Punkt sein, an dem man sich externes Know-How einkauft oder das Projekt verschiebt. Wer schon die Syntax von Perl nicht versteht, hat nahezu keine Chance, Fehler in fremdem Perl-Code zu finden und zu beseitigen.

            Ja, sich da einen Durchblick zu verschaffen ist nicht leicht, aber ich habe es denoch geschafft :)

        2. Es gibt eine Sub die die Eingabe entgegennimmt, also wäre es doch Klug dort das ganze Input durch eine RegExp. durch zujagen oder?
          Das Wissen wir nicht, die Frage ist was darf der Wert enthalten, vorher kann man schlecht sagen was du filtern willst.

          So, es scheint nun zu klappen:

          $myResult =~ s/[a-zA-ZŒŽšœžŸÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖØÙÚÛÜÝßàáâãäåæçèéêëìíîïðñòóôõöøùúûüýþÿ0-9\-\,\.\+\s\|\=\~\#\^\/]//gi;  
          if(length($myResult) > 0)  
          {  
           # verlassen & meldung zeigen  
          }  
          # weiter machen
          

          Hmmm? Du hast ein unsicheres Skript, das offensichtlich auch nicht sonderlich effizient programmiert ist, du hast kaum Kenntnisse der Programmsprache und willst damit online gehen? das ist gewagt.

          Ähm, jein!
          Das Script bei dem Sicherheitstest (wegen XSS) durchgefallen.
          Jetzt muss diese Lücke geschlossen werden, dann läuft alles super.

          Ich bin ehr der PHP Programmierer, der auch viel mit CSS, HTML, JS arbeitet, aber ehr wenig mit Perl. Auf Perlbasis laufen die alten Shops, die nun nach und nach durch die neuen PHP Shop abgelöst werden.

          Das Thema ist durch, die RegExp greift, und leitet den Kunden um sobald nicht erlaubte Zeichen übergeben werden.

          Danke!

    2. Moin Moin!

      Jede Eingabe, die von aussen kommt, prüfen.

      Bis hierher einverstanden.

      Und ungültige Zeichen ersetzen.

      Hier nicht mehr. Wenn Schrott kommt, Annahme verweigern (die(), Status 404, Status 500, whatever). Reparaturversuche machen das Problem oft nur schlimmer und öffnen gelegentlich noch weitere Lücken.

      Alexander

      --
      Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
      1. Und ungültige Zeichen ersetzen.

        Hier nicht mehr. Wenn Schrott kommt, Annahme verweigern (die(), Status 404, Status 500, whatever). Reparaturversuche machen das Problem oft nur schlimmer und öffnen gelegentlich noch weitere Lücken.

        Naja, es muss sich ja nicht immer bösartige Absicht dahinterstecken.

        Struppi.

        1. Moin Moin!

          Und ungültige Zeichen ersetzen.

          Hier nicht mehr. Wenn Schrott kommt, Annahme verweigern (die(), Status 404, Status 500, whatever). Reparaturversuche machen das Problem oft nur schlimmer und öffnen gelegentlich noch weitere Lücken.

          Naja, es muss sich ja nicht immer bösartige Absicht dahinterstecken.

          Nein, deswegen muß man ja den Falscheingeber-Angreifer ja auch nicht gleich für Tage per Firewall-Regeln von jedem weiteren Zugriff abschneiden. Eine einfache Fehlerseite (sinngemäß sowas wie >>Ihre Eingabe "80925 Mün" ist keine gültige Postleitzahl.<< bzw. >>Ihre Eingabe "' or '1'='1" ist keine gültige Postleitzahl.<<) reicht ja aus.

          Aber eine automatische Reparatur ist bei den Fehlern, die ein User so verbocken kann, ohnehin nicht möglich. Und selbst wenn Du nur ein paar Fehler kompensieren willst, riskierst Du, stattdessen Schrott zu verarbeiten. Und wie schon gesagt, kann dein Reparaturversuch die Sache gelegentlich noch verschlimmern, indem erst ein (weiterer) Fehler in der Reparatur-Routine einen Angriff ermöglicht.

          Wenn Du dem Benutzer etwas helfen willst, könntest Du ja einen VORSCHLAG machen, was Du für richtig hältst: >>Meinten Sie vielleicht "80925"?<<

          Alexander

          --
          Today I will gladly share my knowledge and experience, for there are no sweeter words than "I told you so".
    3. hi,

      Ich hole mir die Parameter mit folgender Anweisung:

      $cgi = new CGI();

      @usrData = $cgi->param();

      
      >   
      > Das ist eigentlich Unsinn, da du bereits vorhandene Daten kopierst, also der komplette Input ist jetzt doppelt vorhanden.  
        
      Was ist denn daran unsinnig, wenn zum Parsen der Parameter das CGI.pm verwendet wird? Gerade in Hinsicht eines sicheren CGIs macht es duchaus Sinn eine Liste aller Parameter zu haben in @usrData.  
        
      Nurmalso nebenbei.  
        
      Hotti
      
      1. Das ist eigentlich Unsinn, da du bereits vorhandene Daten kopierst, also der komplette Input ist jetzt doppelt vorhanden.

        Was ist denn daran unsinnig, wenn zum Parsen der Parameter das CGI.pm verwendet wird?

        gar nichts, das habe ich auch nicht gesagt. Nur das alle Parameter nochmal in eine Variabel kopiert werden ist unsinnig.

        Struppi.

        1. hi,

          .. Nur das alle Parameter nochmal in eine Variabel kopiert werden ist unsinnig.

          Du kennst das Script und den (Un)Sinn dahinter? Btw. param() liefert nicht alle Parameter, sondern nur die Namen aller Parameter.

          Hotti

          1. Btw. param() liefert nicht alle Parameter, sondern nur die Namen aller Parameter.

            Stimmt, du hast Recht.

            Struppi.