Определяне на уязвимости при XSS атака

Изпитвам безмилостна XSS атака, която изглежда не мога да предотвратя. Имам общо три формуляра за въвеждане на моя сайт - един е за качване на изображения, един за добавяне на коментари към страница и трети, който изпраща имейл чрез php. Защитавам ги всички по един или друг начин, но по някакъв начин уязвимостта все още е там.

Кодът на моите коментари:

for($j = 0; $j < 3 ; $j++)
                    {
                            $s = $styles[array_rand($styles)];
                            if($song_arr[$k] != '' && $artist_arr[$k] != '' && $name_arr[$k] != '')
                            {
                            echo '<td>';    
                            echo '<div class="'.$s.'" style="clear:left" >';
                                echo '<p class="rendom">';
                                    echo 'Song:&nbsp;'.htmlspecialchars($song_arr[$k]).'<br>Artist:&nbsp;'.htmlspecialchars($artist_arr[$k]).'<br>Submitted By:&nbsp;'.htmlspecialchars($name_arr[$k]);
                                echo '</p>';
                            echo '</div>';
                            echo '</td>';
                            }
                        $k++;
                    }

Форма за качване:

    if ((($_FILES["userfile"]["type"] == "image/jpg")
|| ($_FILES["userfile"]["type"] == "image/jpeg")
|| ($_FILES["userfile"]["type"] == "image/pjpeg"))
&& ($_FILES["userfile"]["size"] < 20000)) {
    if (is_uploaded_file($_FILES['userfile']['tmp_name'])) {
        if (move_uploaded_file ($_FILES['userfile']['tmp_name'],'userfile.jpg')) {
            $image = new SimpleImage();
            $image->load('userfile.jpg');
            $image->resize(29,136);
            $image->save('userfile.jpg');
            ?>
            <img src="img/text/uploadSuccess.jpg" alt="Image uploaded successfully." /><br />
                    <br />
                    <img src="userfile.jpg?rand=<? echo rand(1,10000); ?>" />
            <?
        } else {
            echo 'Moving uploaded file failed';
        }
    } else {
        echo 'File upload failed';
    }
} else {
echo 'Invalid Filetype';
}

Имейл формуляр:

<?php
// Process input variables (trim, stripslash, reformat, generally prepare for email)
    $recipients = trim($_POST['recipients']);
    $sender_email = trim($_POST['sender_email']);
    $sender_name = stripslashes(trim($_POST['sender_name']));
    $subject = stripslashes(str_replace(array("\r\n", "\n", "\r"), " ", trim($_POST['subject'])));
    $message = stripslashes(str_replace(array("\r\n", "\n", "\r"), "<br />", trim($_POST['message'])));

// Check email addresses for validity
    // Explode the comma-separated list of recipients + the sender email address into an array. Even if there is only one recipient, this will check for validity.
    $addresses = explode("," , $recipients.",".$sender_email);
    // For each email address specified...
    foreach ($addresses as $address) {
        // If the email address doesn't match the RFC8622 spec regex, assume invalid 
        if (!(preg_match("~^[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+(?:[A-Z]{2}|com|org|net|uk|edu|jp|de|br|ca|gov|au|info|nl|fr|us|ru|it|cn|ch|tw|es|se|be|dk|pl|at|il|tv|nz|biz)$~i", trim($address)))) {
            // Output error message for invalid email address and end script.
            echo '"' . $address . '" is not a valid email address. Please try again.';
            return;
        }
    }

// Check other vars are not empty
    if ((empty($sender_name)) OR (empty($subject)) OR (empty($message))) {
        // Output error message and end script.
        echo 'Please complete all form fields and try again.';
        return;
    }

// Send HTML email
    $headers = "MIME-Version: 1.0\r\nContent-type:text/html;charset=iso-8859-1\r\nFrom: ". $sender_name ." <". $sender_email ."> \n\n";
    if (mail($recipients,$subject,$message,$headers)) {
        // Mail successfully sent, output success message and end script
        echo 'Message sent. We will be in touch with you shortly.';
        return;
    } else {
        // Something unknown went wrong. =(
        echo 'Something went wrong which the little worker monkeys could not fix. Please try again.';
        return;
    }
?>

XSS продължава да се показва в абсолютната долна част на моята индексна страница, в която включвам () всичките три файла по-горе, чието съдържание е в различни файлове.

Някакви идеи?


person Dave Kiss    schedule 23.02.2010    source източник


Отговори (3)


Във формуляра за електронна поща вие връщате невалидни имейл адреси, които са изпратени, без да ги избягвате. Променете този ред:

 echo '"' . $address . '" is not a valid email address. Please try again.';

to

 echo '"' . htmlspecialchars($address) . '" is not a valid email address. Please try again.';
person ArIck    schedule 23.02.2010
comment
Добър улов, мислите ли, че XSS, вмъкнат тук, може по някакъв начин да се залепи в долната част на страницата, дори при последващо зареждане на страница на различни машини? - person Dave Kiss; 24.02.2010
comment
Не, не може. Този вид вмъкване е непостоянен XSS (en.wikipedia.org/wiki /Cross-site_scripting#Non-persistent) и засяга само потребителя, изпратил заявката. Твоята е по-гадна ;) ! - person Wookai; 24.02.2010
comment
Ще отида с Wookai и ще приема, че нападателят е получил един от неговите скриптове на вашия сървър. Освен това включването на файл, чийто път получавате чрез свързване на inc/, страницата с променливи GET и .inc.php изисква проблеми. Ако вашият PHP код е в /home/dave, а моят е в /home/eric, мога да отворя една от вашите страници със page=../../eric/evil_script в низа на заявката и да накарам вашата страница да включва моя evil_script .inc.php файл. - person ArIck; 24.02.2010
comment
Арик, въз основа на вашата препоръка проверих моя php error_log и открих някои странни грешки... [11 декември 2009 г. 00:38:56] PHP предупреждение: include(inc//../../../ ../../../var/log/apache2/access.log) : не успя да отвори поток: Няма такъв файл или директория в /home......../index2 copy.php на линия 137 Направете имате ли предложения как мога да потвърдя въвеждането или различен подход? - person Dave Kiss; 24.02.2010
comment
Като цяло искате просто да имате бял списък с одобрени файлове, които да включите и да се откажете от него. Променете URL адресите, така че „страница“ да е просто някакво число от 0 до (брой страници - 1). Променете начина, по който включвате страницата, като декларирате масив с имената на файловете (ще го наречем $MY_PAGES), след което включите ($MY_PAGES[$_GET[page]]). - person ArIck; 24.02.2010
comment
благодаря за вашето предложение... аз също обмислям ефективността на $page = preg_replace('/[^-a-zA-Z0-9_]/', '', $_GET['page']); имате ли някакви препоръки срещу използването на това освен потенциално нежелано включване на локален файл? - person Dave Kiss; 24.02.2010
comment
Това би трябвало да е добре. (Регулярният израз ще премахне знаците за паунд и тилдите, които са валидни в име на файл в повечето *nix... но предполагам, че никой не иска да види вашите архивни файлове на emacs.) - person ArIck; 24.02.2010

След бърз поглед изглежда, че единственото място, където показвате ненадеждни данни, са коментарите. И вие сте използвали htmlspecialchars, което би могло да предотврати интерпретирането на html код.

Казвате, че злонамереният код е в долната част на страницата ви. Може би нападателят е намерил начин да качи и включи скрипта си директно на вашия сървър? Как изглежда включеният код? JavaScript ли е, HTML?

person Wookai    schedule 23.02.2010
comment
XSS е вмъкване на JavaScript, което използва document.write за вмъкване на iframe, който произхожда от външен злонамерен сайт. Единствените включвания, които използвам, са чрез php: ‹?php if (!isset($_GET[page])) { include(inc/home.inc.php); } else { include(inc/.$_GET[page]..inc.php); } ?› - person Dave Kiss; 23.02.2010
comment
Добре. JS кодът в средата на вашия раздел за коментари ли е или е някъде другаде? В последния случай проблемът може да не идва от кода, който сте публикували. - person Wookai; 24.02.2010
comment
JS кодът се показва в най-долната част на страницата index.php, а не в средата на коментарите - person Dave Kiss; 24.02.2010
comment
В този случай бих казал, че вашите файлове са били компрометирани по някакъв начин. Ако погледнете вашия шаблон/PHP файл, който генерира страницата, има ли нещо? Може би нападателят използва .htacces, за да добави автоматично някакъв код към всички ваши php скриптове? Присъства ли на всички страници или само на страницата за похвала? - person Wookai; 24.02.2010
comment
Кодът присъства само на индексната страница, която е barebones файл, включващ елементи от различни файлове за изграждане на страницата.. Промених паролата на акаунта си в миналото на нещо много по-сигурно без резултат..не съм сигурен относно .htaccess, но бих предположил, че това е нещо, при което атакуващият ще се нуждае от достъп до акаунта? - person Dave Kiss; 24.02.2010
comment
Всичко се свежда до едно нещо: можете ли да намерите злонамерения код в някой от вашите PHP файлове? Ако да, тогава нападателят по някакъв начин е успял да получи достъп до тях. Ако не, значи е в базата данни (но изглежда, че сте почистили изхода, така че това не трябва да е така. Опитайте да го изпразните, за да сте сигурни). - person Wookai; 24.02.2010

Това не е отговор и не е добра новина, но видях нещо много подобно на това, което описахте в пример в доста смущаващата видео реклама от Symantec, „Zeus: King of the Crimeware Toolkits“ в Youtube: http://www.youtube.com/watch?v=hfjPO8_pGIk

Във всеки случай си струва да видите видеото.

Нямам връзка със Symantec.

person LarryW    schedule 02.03.2010