Safe, safe, SAFE!

Początkujący programiści często chcą zabłysnąć w internecie umieszczając swoje wypociny. Zresztą nie tylko oni. Bardzo często spotykamy nic nie warte kody, którymi możemy się tylko podetrzeć, bo użycie ich na własnej stronie jest szkodliwe. Owe dzieci (najczęściej gimnazjaliści, chociaż sam w sumie mam 15 lat) po zapoznaniu się z składnią języka zaczynają produkować – bo inaczej nie można tego nazwać – setki linijek ciągów znaków – bo nie można tego nazwać kodem. Chodzi o najczęstszy problem w załączaniu podstron w serwisach wykorzystując słynną funkcję include(). W sieci co drugi przykład jest w ogóle niezabezpieczony lub niedostatecznie bezpieczny.

Ostatnio mój kolega złapał się na ten chytry plan i wykorzystał pierwszy lepszy kod z googli. Na szczęście przed wystartowaniem serwisu poprawiłem bezpieczeństwo strony. Pomyślałem, że mogę to udostępnić, więc trochę odpicowałem i w ogóle… Kod jest wg. mnie elegancki, ale niektórzy mogą uznać to jako przesyt, bo jak wiadomo – co za dużo, to nie zdrowo. Ale niestety taki już jestem : ). Zapraszam do przeanalizowania kodu i zgłoszenia usterek, o ile takie zauważycie.

<?php

/**
 * Załączanie plików
 * ======================================================
 * Bezpieczny system załączania podstron serwisu.
 * Akceptuje podstrony w formatach zawartych w $priority.
 * Plików szuka w katalogach zdefiniowanych w $dir.
 * Domyślną podstroną jest plik o nazwie zawartym w MAIN.
 *
 * Copyrights by Piotr `Pax` Skowronek
 */

// Config
define( "MAIN", "glowna" );
$priority = array( "php", "html", "htm", "txt" );
$dir = array( "subpages/" );
$lang = array(
    "invalid.chars" => "Nazwa podstrony nie może zawierać innych znaków,
niż a-z, A-Z, 0-9 oraz podkreślnika (_)",
    "no.page" => "Podstrona nie istnieje"
);

function validURL( $segment )
{
    global $lang;

    if ( !preg_match( "#^\w+$#", $segment ) )
    {
        throw new Exception( $lang[ "invalid.chars" ] );
    }
}

function multiInclude( $URL )
{
    global $lang, $dir, $priority;

    foreach ( $dir as $tmp_dir )
    {
        foreach ( $priority as $tmp_priority )
        {
            $tmp_url = "./$tmp_dir" . "$URL.$tmp_priority";
            if ( file_exists( $tmp_url ) )
            {
                include $tmp_url;
                return;
            }
        }
    }
    throw new Exception( $lang[ "no.page" ] );
}

$content = isset( $_GET['id'] ) ? $_GET['id'] : MAIN;
try
{
    validURL( $content );
    multiInclude( $content );
}
catch( Exception $e )
{
    echo "Error 404

";
    echo $e->getMessage();
}

?>


About this entry