in reply to Re: Re: Re: Re: How Internet is a mess. (Playing with HTTPD)
in thread How Internet is a mess. (Playing with HTTPD)

Hack this.

sub normalize_path { my ( $path ) = @_ ; return '' unless $path; # ensure that multiple %HH encoded stuff is decoded completely (know +n hack) 1 while $path =~ s/%([0-9a-fA-F]{2})/chr hex $1/ge; # get rid of those damn back slashes $path =~ s!\\+!/!g; # I don't see the need for many more chars than these # as the stated purpose is docs, not cgi ?;&= are # pointless, espacially as I just destroyed the query # string (potentially) if these are encoded with %HH $path =~ s![^\w \Q-?&;:,=./#\E]!!g; # fix ../ we don't have any \ left to fool us $path =~ s!\.\.?/!!g; # trim leading whitespace $path =~ s/^\s+//g; # allow single spaces for say Documents and Settings $path =~ s/ +/ /g; return $path ; }

cheers

tachyon

s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

Replies are listed 'Best First'.
Re: Re: Re: Re: Re: Re: How Internet is a mess. (Playing with HTTPD)
by IlyaM (Parson) on Feb 28, 2003 at 09:42 UTC
    Hack this.

    Piece of cake:

    my $up_dir = '.../...//'; my $path = ($up_dir x 10) . 'etc/passwd'; print normalize_path($path), "\n";
    Prints:
    ../../../../../../../../../../etc/passwd

    --
    Ilya Martynov, ilya@iponweb.net
    CTO IPonWEB (UK) Ltd
    Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
    Personal website - http://martynov.org

      Cute! ++ of course. I find it fascinating how you can use ingenuity to spoof these types of filters. Here is one that provides more utility and of course patches your hack.

      sub ilya_proof_path { my ( $path ) = @_ ; return '' unless $path; my ($type, $domain, $q_string ); ( $path, $q_string ) = split '\?', $path; $q_string =~ tr/\0//d if $q_string; 1 while $path =~ s/%([0-9a-fA-F]{2})/chr hex $1/ge; $path =~ s!\\+!/!g; $path =~ s![^\w \Q-:./#\E]!!g; $path =~ s!\.\.*/!!g; $path =~ s/^\s+//g; $path =~ s/ +/ /g; $type = $1 if $path =~ s!^(\w+):/+!!; $domain = $1 if $type and $type =~ m/(?:https?|ftps?)/ and $path =~ +s!^([\w\.-]+)/!!; # tolerate win32 drive letters as a pseudo domain $domain = $1 if $type and $type =~ m/file/ and $path =~ s!^([A-Z]:)/ +!!; return $path, $type, $domain, $q_string ; }

      cheers

      tachyon

      s&&rsenoyhcatreve&&&s&n.+t&"$'$`$\"$\&"&ee&&y&srve&&d&&print

        This one is indead IlyaM proof :) I stared on it for 5 mins and I could not find how it can be abused ++. Anyway I'm not sure I like this approach because it is very easy to do mistakes. I would not use regexps on whole string but I'd split path on components first and then I'd use regexps on them. I.e. something like:
        use URI; my $uri = URI->new($path); die "bad schema" unless is_safe_schema($uri->schema); die "bad domain" unless is_safe_domain($uri->host); die "bad path" unless is_safe_path($uri->path); sub is_safe_schema { # left as excersize to reader } sub is_safe_domain { # left as excersize to reader } sub is_safe_path { my $path = shift; my @comps = split '/', $path; for my $comp (@comps) { return 0 unless is_safe_path_comp } return 1; } sub is_safe_path_comp { my $comp = shift; return 0 if $comp =~ /\0\\/; return 0 if $comp eq '..'; # other unsafe patterns .... return 1; }

        --
        Ilya Martynov, ilya@iponweb.net
        CTO IPonWEB (UK) Ltd
        Quality Perl Programming and Unix Support UK managed @ offshore prices - http://www.iponweb.net
        Personal website - http://martynov.org