pl: Parametername gleich Name der Methode

s. Thema. Welche Frameworks machen das so, daß ein eingehender Aktionparameter eine gleichnamige Funktion/Methode aufruft?

Bitte mal um Hinweise, MfG

  1. Tach!

    Welche Frameworks machen das so, daß ein eingehender Aktionparameter eine gleichnamige Funktion/Methode aufruft?

    Bei diversen ist es der Fall, dass der Router zumindest eine Default-Regel hat, die aus Teilen der URL direkt den Namen des Controllers und der Action (bei MVC-Frameworks) ableitet. Üblicherweise ist der Router so aufgebaut, dass auch Regeln hinzugefügt werden können, die das Ziel auf anderen Wegen finden, beispielsweise eine explizite Zuordnung von URLs zu einer Controller-Action.

    Mit anderen Worten, ein guter Router hat das als eine der Möglichkeiten vorgesehen, aber nicht als alleinige.

    Such nach MVC-Frameworks, die meisten sind so aufgebaut. ASP.NET MVC, ASP.NET MVC Core, Zend Framework, um nur mal drei zu nennen, die mir ad-hoc einfallen.

    dedlfix.

  2. hallo

    s. Thema. Welche Frameworks machen das so, daß ein eingehender Aktionparameter eine gleichnamige Funktion/Methode aufruft?

    Bitte mal um Hinweise, MfG

    Es erscheint mir bei einer modularen Anwendung eigentlich natürlich, das zu tun.

    Man kann zwar in einem Dutzend verschiedenen Scripten die ewig gleichen Input/output Module einbinden, und hat dann für jedes Script eine eigene URL. Man kann aber auch den umgekehrten Weg gehen, gerade dann wenn Speicher/Account-Methoden über alles identisch sein sollen.

    Arbeitsmethodisch erscheint mir der letztere Weg der bessere.

    1. problematische Seite

      hallo

      s. Thema. Welche Frameworks machen das so, daß ein eingehender Aktionparameter eine gleichnamige Funktion/Methode aufruft?

      Bitte mal um Hinweise, MfG

      Es erscheint mir bei einer modularen Anwendung eigentlich natürlich, das zu tun.

      Man kann zwar in einem Dutzend verschiedenen Scripten die ewig gleichen Input/output Module einbinden, und hat dann für jedes Script eine eigene URL. Man kann aber auch den umgekehrten Weg gehen, gerade dann wenn Speicher/Account-Methoden über alles identisch sein sollen.

      Arbeitsmethodisch erscheint mir der letztere Weg der bessere.

      Ich sehe das genau umgekehrt. Wobei Dutzend verschiedenen Scripten sowieso schon ein falscher Ansatz ist. Deswegen binden moderne FW's ja den URL an eine Klasse. Damit bleibt die Anzahl der Aktionparameter (ich nenne die Schlüsselparameter) endlich und daraus ergibt sich auch eine übersichtliche, wartungsfreundliche und gut strukturierte Kontrollstruktur.

      Wenn jedoch der Aufruf einer Funktion/Methode mit einem gleichnamigen Parameter möglich ist, hat man da ein potentielles Sicherheitsleck. Grad' eben bei Opensource wo jeder weiß wie die Funktionen heißen 😉

      Ich wollt' eigentlich nur wissen ob es derart Opensource noch gibt. Meine Recherchen haben da gegenwärtig noch nichts dergleichen zutage befördert.

      Bedenklich finde ich jedoch, wie FW's wie Magento u.ä. den Namen der Klasse im URL verwenden, auch wenn es ein Pseudonym ist (Pseudoklasse).

      MfG

      1. problematische Seite

        hallo

        Ich sehe das genau umgekehrt. Wobei Dutzend verschiedenen Scripten sowieso schon ein falscher Ansatz ist. Deswegen binden moderne FW's ja den URL an eine Klasse. Damit bleibt die Anzahl der Aktionparameter (ich nenne die Schlüsselparameter) endlich und daraus ergibt sich auch eine übersichtliche, wartungsfreundliche und gut strukturierte Kontrollstruktur.

        Erstmal musst du mir bweisen, dass das im anderen Fall nicht möglich ist.

        Wenn jedoch der Aufruf einer Funktion/Methode mit einem gleichnamigen Parameter möglich ist, hat man da ein potentielles Sicherheitsleck. Grad' eben bei Opensource wo jeder weiß wie die Funktionen heißen 😉

        Inwiefern habe ich ein Sicherheitsleck, wenn im Formular als hidden feld

        module=login action=logout

        stehen und dann ein eine entsprechende login.pm eingebunden wird, die eben diese Methode enthält?

        1. problematische Seite

          hi,

          Inwiefern habe ich ein Sicherheitsleck, wenn im Formular als hidden feld

          module=login action=logout

          stehen und dann ein eine entsprechende login.pm eingebunden wird, die eben diese Methode enthält?

          Das hidden feld ist nicht das Problem. Das Problem ist, daß Parameter gleichnamige Funktionen aufrufen. D.h., man kann beliebige Funktionen per HTTP aufrufen 😉

          MfG

          1. problematische Seite

            hallo

            Inwiefern habe ich ein Sicherheitsleck, wenn im Formular als hidden feld

            module=login action=logout

            stehen und dann ein eine entsprechende login.pm eingebunden wird, die eben diese Methode enthält?

            Das hidden feld ist nicht das Problem. Das Problem ist, daß Parameter gleichnamige Funktionen aufrufen. D.h., man kann beliebige Funktionen per HTTP aufrufen 😉

            Wie soll das hier möglich sein?

            	elsif( exists $POST->{xhr} and $POST->{xhr} eq 'xhr'){
            		$postresponseformat="json";
            		if( exists $POST->{modul} and $POST->{modul} =~ /^[a-z]+$/ ){
            			warn "param modul [" . $POST->{modul} . "] \r\n";
            			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
            			if( -e $pm && -r _ && -f _ ){
            				my $modulrun = require $pm;
            				$actionresult = $modulrun->();
            			}
            			else{ warn("pm not found: $pm \r\n"); }
            		}
            		elsif( 
            			$POST->{action} =~ /^[A-Za-z]+$/
            			and 
            			exists( $actions->{ $POST->{action} } )
            		){	
            			$actionresult = $actions->{ $POST->{action} }();
            		}
            		else{ warn "param modul [" . $POST->{modul} . "] chars outside [a-z] \r\n"; }
            	}
            
            
            1. problematische Seite

              Hallo beatovich,

              du darfst nicht von einer konkreten Implementierung auf die Sicherheit des Prinzips schließen.

              Ein MVC-Framework muss sicherstellen, dass

              • nur Klassen als Controller verwendet werden, die als MVC-Controller vorgesehen sind
              • darin nur Methoden via MVC aufgerufen werden, die als MVC-Actions gedacht sind

              Wenn das Framework dieses Minimum nicht gewährleistet, taugt es nichts und gehört in die Tonne. Die Frage, WIE die Implementierung das konkret gewährleistet, ist erstmal egal.

              Ein zusätzlicher Bonus ist es, wenn das Framework ein Security-Modell mitbringt und es mir auf einfache Weise erlaubt, pro Action festzulegen, ob sie einen Login voraussetzt und ggf. sogar den Login eines bestimmten Users, bzw. den Login eines Users, der in einer bestimmten Security-Gruppe ist. Ohne diesen Bonus muss ich zu Beginn jeder zu sichernden Methode eine Verifikationsmethode aufrufen, die diesen Teil übernimmt.

              In ASP.NET MVC ist es zum Beispiel so, dass das Standard-Routing jede Klasse, deren Name auf "Controller" endet und die vom MVC Controller abgeleitet ist, als Controller nutzt. Ganz automatisch und ohne jede Konfiguration. Jede öffentliche Methode darin kann Action sein, sofern ihre Parameter auf die vom Routing vorgesehene Parametrierung passen.

              D.h. MVC schiebt den URL-Fabrikanten zwei Riegel vor: Es muss ein Controller sein, und die Methode muss public sein. Wenn ich als Programmierer Klassen und Methoden schreibe, die auf dieses Muster passen, die aber nicht per MVC erreichbar sein sollen, mache ich was falsch; aber das weiß ich als ASP.NET MVC Programmierer.

              Fragen wie "darf dieser Client diese Action verwenden" werden im ASP.NET MVC Routing ebenfalls adressiert. Hier muss ich dann doch konfigurieren, es gibt das [Authorize] Attribut für Action-Methoden, das einen eingeloggten User verlangt um eine Methode aufrufen zu können, und über das ASP.NET Rollenmodell kann ich mit [Authorize(RolleXY)] auch verlangen, dass der User eine bestimmte Rolle hat, um diese Action verwenden zu dürfen. Für den Login und die Ermittlung der Rollen, die dieser User hat, kann ich konfigurativ im ASP.NET MVC Framework Module hinterlegen, die sich darum kümmern. Das ist eine komplette eigene Abteilung des ASP.NET Frameworks, die ASP.NET MVC ganz einfach mit nutzt.

              Rolf

              --
              sumpsi - posui - clusi
              1. problematische Seite

                hallo

                du darfst nicht von einer konkreten Implementierung auf die Sicherheit des Prinzips schließen.

                Einverstanden.

                Ich habe nun aber weniger Sicherheitsbedenken. Sondern ich möchte diese Praxis in einen Kontext beschränken, wo keine Parameter in URIs gespeichert werden. Das aber eher aus dem Grund, Interna nicht an eine API zu binden.

                1. problematische Seite

                  Tach!

                  Das aber eher aus dem Grund, Interna nicht an eine API zu binden.

                  Interna des Controllers sind private und der Router kann den Request nicht dorthin durchreichen. Andere public Klassen sind keine Controller und der Router routet auch keine Requests dorthin. Das Problem ist also nicht vorhanden bei den großen Frameworks.

                  dedlfix.

                2. problematische Seite

                  hallo

                  Das aber eher aus dem Grund, Interna nicht an eine API zu binden.

                  Namen einer Klasse, eines Moduls oder eines Symbols (Funktionsname, Variablenname) sind Interna die auf dem HTTP Layer absolut nichts zu suchen haben.

                  MfG

              2. problematische Seite

                Hi Rolf

                du darfst nicht von einer konkreten Implementierung auf die Sicherheit des Prinzips schließen.

                Aber sicher doch!

                Ein MVC-Framework muss sicherstellen, dass

                Ein MVC an sich löst erstens das Problem nicht und hat auch gar nichts damit zu tun.

                MfG

            2. problematische Seite

              hallo

              Inwiefern habe ich ein Sicherheitsleck, wenn im Formular als hidden feld

              module=login action=logout

              stehen und dann ein eine entsprechende login.pm eingebunden wird, die eben diese Methode enthält?

              Das hidden feld ist nicht das Problem. Das Problem ist, daß Parameter gleichnamige Funktionen aufrufen. D.h., man kann beliebige Funktionen per HTTP aufrufen 😉

              Wie soll das hier möglich sein?

              	elsif( exists $POST->{xhr} and $POST->{xhr} eq 'xhr'){
              		$postresponseformat="json";
              		if( exists $POST->{modul} and $POST->{modul} =~ /^[a-z]+$/ ){
              			warn "param modul [" . $POST->{modul} . "] \r\n";
              			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
              			if( -e $pm && -r _ && -f _ ){
              				my $modulrun = require $pm;
              				$actionresult = $modulrun->();
              

              Ab require passiert es: require compiliert ein Modul, was per HTTP namentlich genannt wird.

              Und wenn das da oben Perl sein soll, ist das ein ganz schlechtes Beispiel für lesbaren Code. Das ist Spaghetti Carbonara 😉

              MfG

              1. problematische Seite

                hallo

                hallo

                Inwiefern habe ich ein Sicherheitsleck, wenn im Formular als hidden feld

                module=login action=logout

                stehen und dann ein eine entsprechende login.pm eingebunden wird, die eben diese Methode enthält?

                Das hidden feld ist nicht das Problem. Das Problem ist, daß Parameter gleichnamige Funktionen aufrufen. D.h., man kann beliebige Funktionen per HTTP aufrufen 😉

                Wie soll das hier möglich sein?

                	elsif( exists $POST->{xhr} and $POST->{xhr} eq 'xhr'){
                		$postresponseformat="json";
                		if( exists $POST->{modul} and $POST->{modul} =~ /^[a-z]+$/ ){
                			warn "param modul [" . $POST->{modul} . "] \r\n";
                			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
                			if( -e $pm && -r _ && -f _ ){
                				my $modulrun = require $pm;
                				$actionresult = $modulrun->();
                

                Ab require passiert es: require compiliert ein Modul, was per HTTP namentlich genannt wird.

                Ja erzähle mir genau, was da passieren kann, statt Spaghetti mit Käse zu würzen. Versuche mindestens mal hilfreich zu sein.

                1. problematische Seite

                  Ab require passiert es: require compiliert ein Modul, was per HTTP namentlich genannt wird.

                  Ja erzähle mir genau, was da passieren kann, statt Spaghetti mit Käse zu würzen. Versuche mindestens mal hilfreich zu sein.

                  War das nicht hilfreich genug? Ein Benutzer gibt den Namen eines Moduls ein was kompiliert werden soll!? Sowas möchten wir doch nicht wirklich oder?

                  Zumal es tausend andere Möglichkeiten gibt, Interna interna sein zu lassen. Du hast eine Klassenbindung aber warum diese über HTTP abwickeln? Der Benutzer gibt eine andere Klasse vor und schon macht Deine Anwendung was ganz anderes, auf jeden Fall nicht mehr das was sie soll!

                  Besser ist es, die Klasse per Konfiguration an den URL zu binden das kann ein Benutzer nicht ändern, weil die Konfiguration serverseitig vorliegt.

                  Mit freundlichen Grüßen und dem Wunsch verbunden daß Du Dir das Obenstehende mal zu Herzen nimmst, anstatt hier rumzupoltern.

                  1. problematische Seite

                    Tach!

                    Ein Benutzer gibt den Namen eines Moduls ein was kompiliert werden soll!? Sowas möchten wir doch nicht wirklich oder?

                    Man kann die erlaubten Kandidaten mittels Whitelist oder anhand ihrer Merkmale (Namensbestandteil, Abstammung von einer Basisklasse, Implementation eines bestimmten Interfaces) einschränken.

                    Zumal es tausend andere Möglichkeiten gibt, Interna interna sein zu lassen. Du hast eine Klassenbindung aber warum diese über HTTP abwickeln? Der Benutzer gibt eine andere Klasse vor und schon macht Deine Anwendung was ganz anderes, auf jeden Fall nicht mehr das was sie soll!

                    Macht sie nicht, siehe oben.

                    Besser ist es, die Klasse per Konfiguration an den URL zu binden das kann ein Benutzer nicht ändern, weil die Konfiguration serverseitig vorliegt.

                    Das ist nicht besser oder schlechter. Routing per Konfiguration statt per Konvention ist lediglich eine andere Vorgehensweise. Der Nutzer kann bei beiden Varianten nichts anderes als erlaubt ist.

                    dedlfix.

                    1. problematische Seite

                  2. problematische Seite

                    hallo

                    Ab require passiert es: require compiliert ein Modul, was per HTTP namentlich genannt wird.

                    Ja erzähle mir genau, was da passieren kann, statt Spaghetti mit Käse zu würzen. Versuche mindestens mal hilfreich zu sein.

                    War das nicht hilfreich genug? Ein Benutzer gibt den Namen eines Moduls ein was kompiliert werden soll!? Sowas möchten wir doch nicht wirklich oder?

                    Und selbst wenn du ein Config-File verwendest, ich aber den Schlüssel deines Config-File Parameters via Formular manipuliere, da hast du exakt das gleiche Problem.

                    1. problematische Seite

                      hallo

                      Ab require passiert es: require compiliert ein Modul, was per HTTP namentlich genannt wird.

                      Ja erzähle mir genau, was da passieren kann, statt Spaghetti mit Käse zu würzen. Versuche mindestens mal hilfreich zu sein.

                      War das nicht hilfreich genug? Ein Benutzer gibt den Namen eines Moduls ein was kompiliert werden soll!? Sowas möchten wir doch nicht wirklich oder?

                      Und selbst wenn du ein Config-File verwendest, ich aber den Schlüssel deines Config-File Parameters via Formular manipuliere, da hast du exakt das gleiche Problem.

                      Nein. Wenn es konfiguriert ist, nämlich, kann ein Benutzer den Namen des Moduls nicht mehr ändern. Dein Modul jedoch kann per HTTP Parameter namentlich bestimmt werden, es liefert eine Referenz auf Code der unmittelbar ausgeführt wird. Was praktisch auf dasselbe hinausläuft als würde man eine Funktion namentlich direkt aufrufen.

                      Ein Benutzer kann praktisch über diesen URL auch einen anderen Code ausführen, indem er den Parameter entsprechend setzt.

                      MfG

                      1. problematische Seite

                        hallo

                        Und selbst wenn du ein Config-File verwendest, ich aber den Schlüssel deines Config-File Parameters via Formular manipuliere, da hast du exakt das gleiche Problem.

                        Nein. Wenn es konfiguriert ist, nämlich, kann ein Benutzer den Namen des Moduls nicht mehr ändern.

                        Brauch ich doch gar nicht. Hauptsache ich kann deine ach so kluge Konfig austricksen!

                      2. problematische Seite

                        hallo

                        Ein Benutzer kann praktisch über diesen URL auch einen anderen Code ausführen, indem er den Parameter entsprechend setzt.

                        Ergänzung: Die Art und Weise

                        my $coderef = require "Modulname lt. Parameter";
                        $coderef->();
                        

                        schätze ich als besonders kritisch ein, weil es den Namespace erweitert bzw. das Ausführen von Code eines anderen Namespaces ermöglicht.

                        MfG

                        1. problematische Seite

                          hallo

                          my $coderef = require "Modulname lt. Parameter";
                          $coderef->();
                          

                          Da gebe ich dir recht, aber das hat wenig mit meinem Code zu tun.

                          1. problematische Seite

                            hallo

                            my $coderef = require "Modulname lt. Parameter";
                            $coderef->();
                            

                            Da gebe ich dir recht, aber das hat wenig mit meinem Code zu tun.

                            Der Code den Du hier gezeigt hat, macht genau dasselbe. MfG

                            1. problematische Seite

                              my $coderef = require "Modulname lt. Parameter";
                              $coderef->();
                              

                              Da gebe ich dir recht, aber das hat wenig mit meinem Code zu tun.

                              Der Code den Du hier gezeigt hat, macht genau dasselbe. MfG

                              Nein, und das weisst du auch.

                2. problematische Seite

                  Hi,

                  1.			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
                  			if( -e $pm && -r _ && -f _ ){
                  2.				my $modulrun = require $pm;
                  3.				$actionresult = $modulrun->();
                  
                  1. Der Name des Moduls wird durch einen Parameter bestimmt
                  2. Code wird kompiliert und liefert eine Codereferenz
                  3. der referenzierte Code wird ausgeführt.
                  

                  Zu 1. wäre also noch zu sagen daß das jeder Benutzer der Anwendung tun kann. Er könnte z.B. auch eine Modul laden was dem Administrator vorbehalten ist. Bei 3. wird der Code unmittelbar ausgeführt.

                  Es ist Deine Entscheidung, diese Hinweise zu ignorieren: Die Anwendung hat eine erhebliche Sicherheitslücke!

                  MfG

                  1. problematische Seite

                    1.			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
                    			if( -e $pm && -r _ && -f _ ){
                    2.				my $modulrun = require $pm;
                    3.				$actionresult = $modulrun->();
                    
                    1. Der Name des Moduls wird durch einen Parameter bestimmt
                    2. Code wird kompiliert und liefert eine Codereferenz
                    3. der referenzierte Code wird ausgeführt.
                    

                    Es ist Deine Entscheidung, diese Hinweise zu ignorieren: Die Anwendung hat eine erhebliche Sicherheitslücke!

                    Für mich sieht das danach aus, als ob nur Module aus dem Unterverzeichnis "apps" geladen werden können. Wenn da per Konvention nur Module abgelegt werden, die auch öffentlich erreichbar sein sollen, gibt es keine Sicherheitslücke. Ansonsten natürlich schon.

                    1. problematische Seite

                      Für mich sieht das danach aus, als ob nur Module aus dem Unterverzeichnis "apps" geladen werden können. Wenn da per Konvention nur Module abgelegt werden, die auch öffentlich erreichbar sein sollen, gibt es keine Sicherheitslücke.

                      Das kannst Du gerne für Dich selbst entscheiden. Fakt ist, daß ein Benutzer die Klassenbindung aufheben kann und die dem URL zugedachte Anwendung mit einer anderen Klasse nicht das macht was sie soll.

                      Empfehlenswert ist sowas auf gar keinen Fall. Das Sicherheitsloch ist systematisch vorprogrammiert!

                      MfG

                      1. problematische Seite

                        Das kannst Du gerne für Dich selbst entscheiden. Fakt ist, daß ein Benutzer die Klassenbindung aufheben kann und die dem URL zugedachte Anwendung mit einer anderen Klasse nicht das macht was sie soll.

                        Dann erkläre mal, wie so ein Angriffsvektor aussehen könnte.

                    2. problematische Seite

                      hallo

                      1.			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
                      			if( -e $pm && -r _ && -f _ ){
                      2.				my $modulrun = require $pm;
                      3.				$actionresult = $modulrun->();
                      
                      1. Der Name des Moduls wird durch einen Parameter bestimmt
                      2. Code wird kompiliert und liefert eine Codereferenz
                      3. der referenzierte Code wird ausgeführt.
                      

                      Es ist Deine Entscheidung, diese Hinweise zu ignorieren: Die Anwendung hat eine erhebliche Sicherheitslücke!

                      Für mich sieht das danach aus, als ob nur Module aus dem Unterverzeichnis "apps" geladen werden können. Wenn da per Konvention nur Module abgelegt werden, die auch öffentlich erreichbar sein sollen, gibt es keine Sicherheitslücke. Ansonsten natürlich schon.

                      So ist es.

                  2. problematische Seite

                    hallo

                    Hi,

                    1.			my $pm = 'apps/'.$POST->{modul}.'/'.$POST->{modul}.'.pm';
                    			if( -e $pm && -r _ && -f _ ){
                    2.				my $modulrun = require $pm;
                    3.				$actionresult = $modulrun->();
                    
                    1. Der Name des Moduls wird durch einen Parameter bestimmt
                    2. Code wird kompiliert und liefert eine Codereferenz
                    3. der referenzierte Code wird ausgeführt.
                    

                    Zu 1. wäre also noch zu sagen daß das jeder Benutzer der Anwendung tun kann. Er könnte z.B. auch eine Modul laden was dem Administrator vorbehalten ist. Bei 3. wird der Code unmittelbar ausgeführt.

                    Ah und du würdest also in einer Config festlegen, welche Funktionen wann verfügbar sind? Warum diese Aufgabe nicht dem Modul selbst anvertrauen?

                    Es ist Deine Entscheidung, diese Hinweise zu ignorieren: Die Anwendung hat eine erhebliche Sicherheitslücke!

                    Sie hat keine Lücke die nicht auch durch eine Config bestünde. Im Gegenteil ist es in einer Config sehr viel einfacher eine Lücke aufzureissen, als dies geschieht, wenn man einem Modul die ihm eigene Rechteprüfung anvertraut.