sakko: Perl: Zahl Vergleichsoperator

Hi !

Ich will checken, ob eine Zahl größer ist als 20 und im Falle TRUE will ich diese dann speichern:

  
my $zahl = "20bla";  
if ($zahl > 20) {  
   $gespeicherte_zahl = $zahl;  
}  
  

Das scheint aber ein Sicherheitsrisiko zu sein wenn man nämlich nur reine Zahlen haben will, wie ich.
Obiges Beispiel ergibt nämlich TRUE, obwohl $zahl keine reine Zahl ist!

Komisch!

  1. my $zahl = "20bla";
    if ($zahl > 20) {
       $gespeicherte_zahl = $zahl;
    }

    
    > Das scheint aber ein Sicherheitsrisiko zu sein wenn man nämlich nur reine Zahlen haben will, wie ich.  
    > Obiges Beispiel ergibt nämlich TRUE, obwohl $zahl keine reine Zahl ist!  
      
    Ja und?  
    auch int() nimmt dir obige Prüfung nicht ab.  
      
    mfg Beat
    
    -- 
    
    ><o(((°>           ><o(((°>  
    
       <°)))o><                     ><o(((°>o  
    Der Valigator leibt diese Fische
    
    1. my $zahl = "20bla";
      if ($zahl > 20) {
         $gespeicherte_zahl = $zahl;
      }

      
      > > Das scheint aber ein Sicherheitsrisiko zu sein wenn man nämlich nur reine Zahlen haben will, wie ich.  
      > > Obiges Beispiel ergibt nämlich TRUE, obwohl $zahl keine reine Zahl ist!  
      >   
      > Ja und?  
      > auch int() nimmt dir obige Prüfung nicht ab.  
      >   
      > mfg Beat  
        
      und wie solls jetzt weitergehen? Ich kann $zahl auf keinen Fall so in die Datenbank eintragen, das gibt einen Error wenn ich versuche $zahl in eine INT-Spalte einzutragen.
      
      1. und wie solls jetzt weitergehen? Ich kann $zahl auf keinen Fall so in die Datenbank eintragen, das gibt einen Error wenn ich versuche $zahl in eine INT-Spalte einzutragen.

        Da du userinput entgegennimmst wirst du mit einem regulären Ausdruck zuerst ein gültiges Datum herausziehen müssen.

        $unclean{zahl} =~/(\d+)/ and $clean{zahl}=$1
           or $clean{zahl}=42;

        mfg Beat

        --
        ><o(((°>           ><o(((°>
           <°)))o><                     ><o(((°>o
        Der Valigator leibt diese Fische
        1. und wie solls jetzt weitergehen? Ich kann $zahl auf keinen Fall so in die Datenbank eintragen, das gibt einen Error wenn ich versuche $zahl in eine INT-Spalte einzutragen.

          Da du userinput entgegennimmst wirst du mit einem regulären Ausdruck zuerst ein gültiges Datum herausziehen müssen.

          $unclean{zahl} =~/(\d+)/ and $clean{zahl}=$1
             or $clean{zahl}=42;

          mfg Beat

          was soll ich denn bitte mit /(\d+)/ ??? Das heisst ja nur, dass im String min. 1 Zahl vorkommen muss.
          Du meintest wohl eher sowas wie /^\d$/
          Und die clean-Lösung durchblick ich auch nicht so richtig. Was soll das bezwecken?

          1. und wie solls jetzt weitergehen? Ich kann $zahl auf keinen Fall so in die Datenbank eintragen, das gibt einen Error wenn ich versuche $zahl in eine INT-Spalte einzutragen.

            Da du userinput entgegennimmst wirst du mit einem regulären Ausdruck zuerst ein gültiges Datum herausziehen müssen.

            $unclean{zahl} =~/(\d+)/ and $clean{zahl}=$1
               or $clean{zahl}=42;

            mfg Beat

            was soll ich denn bitte mit /(\d+)/ ??? Das heisst ja nur, dass im String min. 1 Zahl vorkommen muss.
            Du meintest wohl eher sowas wie /^\d$/
            Und die clean-Lösung durchblick ich auch nicht so richtig. Was soll das bezwecken?

            Wenn du dein script mit -T aufrufst, musst du allen Userinput waschen.
            Das kann nur geschehen durch eine RE, wobei du den gültigen Wert extrahierst.

            falsches Vorgehen
              $unclean{zahl} =~/^\d+$/ and $clean{zahl}=$unclean{zahl};

            jetzt ist $clean{zahl) immer noch tainted

            liest du selber nach zum Thema tainted und Sicherheit.

            Ich habe die hashes zu Verdeutlichung benannt.

            mfg Beat

            --
            ><o(((°>           ><o(((°>
               <°)))o><                     ><o(((°>o
            Der Valigator leibt diese Fische
            1. Dann mach ichs so:

                
              if ($zahl > 20) {  
                 if ($zahl =~ /^(\d+)$/) {  
                    $saubere_zahl = $1;  
                 }  
              
              

              komische Vergleichsoperatoren hat Perl..... ist ja echt beschissen

              1. Dann mach ichs so:

                if ($zahl > 20) {
                   if ($zahl =~ /^(\d+)$/) {
                      $saubere_zahl = $1;
                   }

                  
                Falsch  
                Du sollst zuerst einen sauberen brauchbareren Wert herausziehen, bevor du irgend eine Nutzauswertung am Wert vornimmst.  
                  
                mfg Beat
                
                -- 
                
                ><o(((°>           ><o(((°>  
                
                   <°)))o><                     ><o(((°>o  
                Der Valigator leibt diese Fische
                
                1. wieso soll ich überhaupt mit Taint arbeiten?
                  Ich lösche ja keine Dateien und will auch nichts evaluieren. Es kommt auch kein Userinput in Hashkeys, sondern allenfalls in Strings und die werden ja eh gequotet.

                  Zum regex: am besten fände ich ja einen regex, der gleich beides erledigt:
                  etwa so:

                    
                  if ($zahl =~ /^(\d+>20)$/) {  
                  ...  
                  
                  
  2. moin,

    Das scheint aber ein Sicherheitsrisiko zu sein wenn man nämlich nur reine Zahlen haben will, wie ich.
    Obiges Beispiel ergibt nämlich TRUE, obwohl $zahl keine reine Zahl ist!

    Mir ist nicht ganz klar, was Du machen willst. Vermutlich gehts Dir darum, eine Benutzereingabe zu prüfen und offensichtlich ist es das Erstemal, dass Du mit solch einer Aufgabe konfrontiert bist.

    Hierzu gibt es auch ein paar grundsätzliche Überlegungen, was im Fall einer fehlerhaften Benutzereingabe nämlich gemacht werden soll, Beispiele:

    • ignorieren
    • den Benutzer darauf hinweisen
    • reparieren
    • das Programm abbgechen
    • nicht abbrechen
      o.v.a.m.

    Und btw., benutzt Du warnings oder perl -w?

    Hotti

    1. Ich will folgendes machen:

      Ein User registriert sich. Ich will checken, ob er Vorname und Nachname angegeben hat. Dann prüfe ich noch die E-Mail Adresse und Geburtstag.

        
      my %sql_values = ();     # Werte für SQL-Insert-Statement  
      my %errors = ();         # Fehlermeldungen  
        
      if ($vorname >= 2 and $vorname <= 100) {  
         $sql_values{vorname} = $vorname;  
      } else {  
         $errors{vorname} = 'ungültiger Vorname';  
      }  
        
      if ($nachname >= 2 and $nachname <= 100) {  
         $sql_values{nachname} = $nachname;  
      } else {  
         $errors{nachname} = 'ungültiger Nachname';  
      }  
      
      

      %sql_values enthält dann alle diejenigen Werte, die in die Tabelle eingetragen werden.

      Ich nutze warnings.

  3. Ich will checken, ob eine Zahl größer ist als 20 und im Falle TRUE will ich diese dann speichern:

    my $zahl = "20bla";
    if ($zahl > 20) {
       $gespeicherte_zahl = $zahl;
    }

      
    Aber nicht so:  
    Argument "20bla" isn't numeric in numeric gt (>) at ...  
      
    Du solltest dir die Warnungen anzeigen lassen.  
      
    
    > Das scheint aber ein Sicherheitsrisiko zu sein wenn man nämlich nur reine Zahlen haben will, wie ich.  
    > Obiges Beispiel ergibt nämlich TRUE, obwohl $zahl keine reine Zahl ist!  
      
    Da du offensichtlich die Warnungen ausgeschaltet hast, wandelt Perl wie jede andere Skriptsprache auch, den Wert in eine Zahl um, aber das obige Beispiel ist nicht wahr, du musst etwas falsch interpretiert haben.  
      
    ~~~perl
    #!/usr/bin/perl  
      
    my $zahl = "20bla";  
    if ($zahl > 20) {  
       print "true";  
    } else {  
        print "false";  
    }  
    
    

    ergibt 'false'. Denn die Zeichenkette "20bla" wird bei einem Zahlenvergleich zu 20.

    #!/usr/bin/perl  
    my $zahl = "20bla";  
    if ($zahl == 20) {  
       print "true";  
    } else {  
        print "false";  
    }  
    
    

    Das sind Fallen, die dir bei jeder Skriptsprache über den Weg laufen, daher ist es empfehlenswert die Hilfen, die dir Perl anbietet zu nutzen, dazu gehrt auf jeden Fall use warnings (resp. -w)

    Struppi.

    1. Hi,

      erstmal danke für deine Teilnahme :)
      Ich nutze warnings, diese werden aber irgendwie von Fcgi unterdrückt. Ich habe deshalb jetzt ein CGI-Testscript erstellt.

      Mein Problem ist halt folgemdes:

        
      #!/usr/bin/perl  
      my $zahl = "20bla";  
      if ($zahl > 5) {  
         # INSERT INTO table (int_value) VALUES ($zahl)  
      } else {  
          print "false";  
      }  
      
      

      Wenn $zahl größer ist als 5, dann will ich $zahl in eine mySQL-Tabelle schreiben. Da $zahl aber kein gültiger INT-Wert ist, produziert das obige INSERT einen Fehler.

      Wie umgehst du denn sowas? Benutze keinen taint-modus da keine gefährlichen Aktionen (unlink usw.) stattfinden.
      In der Praxis geht es lediglich um eine User-Registrierung. Ich prüfe also Geburtsdatum, Vorname, Nachname und trage den Senf dann in eine Tabelle ein.
      In den ganzen Büchern und Tutorials wird aber niemals auf mein beschriebenes Problem eingegangen!

      1. Moin Moin!

        Ich nutze warnings, diese werden aber irgendwie von Fcgi unterdrückt.

        Mumpitz! FastCGI schreibt Warnungen raus, nur nicht dort hin, wo Du sie erwartest.

        Davon abgesehen hast Du zwei getrennte Probleme, die getrennt behandelt werden müssen.

        Erstens willst Du wissen, ob die Eingabe eine Zahl ist oder nicht.

        Zweitens willst Du wissen, ob die eingegebene Zahl größer als irgendein Minumum ist (kannst Du Dich bitte mal zwischen 5 und 20 entscheiden?).

        Schitt 1: Eingabevalidierung

        Ich gehe mal davon aus, dass Du nur nicht-negative Integer haben willst, falls nicht, brauchst Du eine andere RE:

          
        $input=~/^(\d+)$/ or die "Bad Input";  
        my $n=$1; # untaint  
        
        

        Sehr viel mehr zum Thema findest Du in perlsec.

        Schritt 2: Fallunterscheidung

          
        if ($n>$min) {  
            print "Mach was mit $n"  
        } else {  
            print "Ignoriere $n";  
        }  
        
        

        Sowas gibt es übrigens auch schon fertig verpackt: Data::FormValidator.

        Alexander

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