2009-11-23 4 views
21

Хорошо, так что я и друг делают мини-презентацию по безопасности PHP (я не совсем в PHP), и он попросил меня найти несколько примеров уязвимого кода PHP (тот, который подвержен SQL-инъекциям и всем другим типам от атак). Мне было интересно, есть ли какие-либо сайты с хорошими и плохими фрагментами кода, показывающими, как вы должны и не должны кодировать?Примеры уязвимого кода PHP?

В основном я помещу их на наш сайт, и он попытается взломать его, затем мы покажем «правильный» веб-сайт, и он попытается снова его взломать.

+0

+1 так как это звучит весело :) – Johan

ответ

18

SQL injection легко:

$var = $_POST['var']; 
mysql_query("SELECT * FROM sometable WHERE id = $var"); 

Это легко решается:

$var = mysql_real_escape_string($_POST['var']); 

Другой распространенной является XSS (cross site scripting):

$var = $_POST['var']; 
echo "<div>$var</div>\n"; 

позволяет вводить Javascript, выполняемую с вашего сайта. Есть несколько способов борьбы с этим, например:

$var = strip_tags($_POST['var']); 

и

$var = filter_var($_POST['var'], FILTER_SANITIZE_STRING); 
+1

Да, по сути, вы никогда не сможете доверять пользовательскому вводу, относитесь ко всему как к вредоносному вводу и избегайте его с помощью 'addslashes()', 'strip_tags()' или 'htmlspecialchars()'. – Rob

+16

'strip_tags' недостаточно, чтобы остановить инъекцию HTML (вставить значение значения атрибута). Массирование массива запросов с помощью FILTER_SANITIZE_STRING - ужасный хак, который никогда не должен использоваться. Вместо этого избегайте встраивания HTML, вызывая 'htmlspecialchars' на каждую строку, которую вы помещаете в содержимое HTML. – bobince

+4

вы можете разобрать его с помощью регулярного выражения ... – nickf

3

Другим примером SQL-инъекцией уязвимой сценария входа. Это, к сожалению, очень распространено среди новых программистов.

$username = $_POST["username"]; 
$password = $_POST["password"]; 
$query = "SELECT username, password 
      FROM users 
      WHERE (username = '{$username}') 
      AND (password = '{$password}')"; 
+7

Не говоря уже о хранении паролей в открытом тексте. –

+0

@ Vilx- если только $ _POST ["password"] hashed клиентская сторона;) Это ненадежно, так как созданный хэш-клиент не может быть солен, не раскрывая соль на стороне клиента. –

+0

@ dwarf015 - Хм, я думаю, что выявление соли не было бы большой проблемой, если бы сама хеширующая функция была достаточно медленной. Но я не эксперт, поэтому не забудь об этом. :) –

17

Ошибочная ошибка начинающего пользователя - это прекращение выполнения скрипта после перенаправления.

<?php 
if ($_SESSION['user_logged_in'] !== true) { 
    header('Location: /login.php'); 
} 

omg_important_private_functionality_here(); 

Решение:

if ($_SESSION['user_logged_in'] !== true) { 
    header('Location: /login.php'); 
    exit(); 
} 

Это может быть пропущено при тестировании в обычном браузере, так как браузеры обычно следуют заголовку Location без оказания какого-либо из выхода сценария.

+0

Может быть, это слишком рано утром для меня, но какая здесь уязвимость? – Jakub

+3

Заголовок может быть проигнорирован, а скрипт php все еще выполняется. Частная функция все еще выполняется, даже если пользователь не вошел в систему. – Ikke

+1

Переадресация header() может не вступить в силу или может быть намеренно проигнорирована, показывая частные данные ниже. –

4

Я видел код, как это написано в прошлом:

foreach ($_REQUEST as $var => $val) { 
    $$var = $val; 
} 

Это способ для имитации клеветы register_globals варианта. Это означает, что вы можете получить доступ к переменным, как это:

$myPostedVar 

, а не страшно сложнее:

$_POST['myPostedVar'] 

Риск безопасности всплывает в ситуациях, как это:

$hasAdminAccess = get_user_access(); 

foreach ($_REQUEST as $var => $val) { 
    $$var = $val; 
} 

if ($hasAdminAccess) { ... } 

Поскольку все вам нужно будет добавить ?hasAdminAccess=1 к URL-адресу, и вы входите.

+2

Функция, имитирующая 'register_globals' –

+0

ах спасибо! это одна из тех вещей, которые я заблокировал из своего разума. Ужас ... ужас ... – nickf

10

Bobby Tables

alt text

Bobby Tables является страница, посвященная детализация пути, что сценарий может быть уязвим через SQL injection. Это не уникально для PHP, однако SQL-инъекция является причиной многих уязвимостей веб-страниц.

Возможно, это будет предложение, которое вы хотите включить в свою презентацию.

0

НЕПРАВИЛЬНЫЙ способ делать шаблоны.

<?php 

    include("header.php"); 
    include($_GET["source"]); //http://www.mysite.com/page.php?source=index.php 
    include("footer.php"); 

?> 
+4

Вы также должны показать, каков жесткий способ делать шаблоны. – Ikke

+0

Вопрос был для уязвимых примеров, а не для правильных примеров. – Sampson

0

Уязвимости XSS легко показать. Просто создать страницу, которая помещает значение переменной ГЭТ «Q» где-то на странице, а затем нажмите на следующую ссылку:

http://mysite.com/vulnerable_page.php?q%3D%3Cscript%20type%3D%22javascript%22%3Ealert(document.cookie)%3B%3C%2Fscript%3E 

Это заставит печенье на пользователя, которое будет отображаться в окне предупреждения.

0

Разрешение на загрузку и не проверку расширения. Обратите внимание:

Сайт A позволяет загружать изображения и отображать их.

Cracker guy загружает файл и обманывает вас, чтобы поверить в его файл изображения (через HTTP mimetypes). Этот файл имеет расширение PHP и содержит вредоносный код. Затем он пытается увидеть свой файл изображения и потому, что каждый PHP-файл, исполняемый PHP, выполняется, код запускается. Он может делать все, что может сделать пользователь Apache.

12

О, мальчик, у вас не будет примеров. Просто Google PHP tutorial, и каждый из них имеет достаточно отверстий, чтобы заполнить Альберт-Холл.

Результаты 1, w3schools. Каков их первый пример для включения пользовательского ввода?

Welcome <?php echo $_POST["fname"]; ?>!<br /> 

Bzzt. HTML-инъекция, повторяющаяся во всех частях кода примера. Каков их первый запрос к базе данных?

$sql="INSERT INTO Persons (FirstName, LastName, Age) VALUES ('$_POST[firstname]','$_POST[lastname]','$_POST[age]')"; 

Bzzt. SQL-инъекция, вы теряете. Следующий.

Результат 2, официальный учебник по PHP. Каков первый пример вывода переменной?

echo $_SERVER['HTTP_USER_AGENT']; 

Bzzt. HTML-инъекция. Не является легкодоступной, но все же плохой практикой такого рода, которая повторяется в учебных материалах php.net.

Результаты 3, tizag.com. Каков первый пример эхо ввода пользователя?

echo "You ordered ". $quantity . " " . $item . ".<br />"; 

Bzzt.

Результаты 4, freewebmasterhelp.com. Слишком основное, чтобы включать много, но все еще управляет:

print "Hello $name"; // Welcome to the user 

Bzzt.

Результат 5, learnphp-tutorial.com.

<title><?= $greeting ?> World!</title> 

Bz ...

я мог идти дальше.

Неудивительно, что общее качество кода PHP в дикой природе так катастрофично, когда этот горестный мусор - это то, что изучают кодеры?

+0

«отверстия для заполнения Альберт-Холла»? Неплохо. +1 – Franz

+0

И ты прав. Весьма забавно видеть пример кода, показывающий вам, как тестировать свой код для этого и что вводить/пропускать/оставлять другие примеры уязвимостей ... – Franz

+2

Моя любимая книга Apress «Pro PHP Security». Автор делает краткий обзор общих уязвимостей и предлагает решение для каждого (часто довольно неуместное, например, сопоставление POST через SQL-выход). И затем в остальных примерах для решения других уязвимостей он снова ошибается, предоставляя код, который страдает от уязвимостей, которые он только что предупредил нас о последней главе. В главе XSS даже есть уязвимости XSS в примерах того, как избежать незначительных уязвимостей XSS. И довольно страшные разделы об использовании 'eval' и' system'. «Про» безопасность действительно. – bobince

2

CSRF для победы.

<?php 
$newEmail = filter_input(INPUT_POST, 'email', FILTER_SANITIZE_EMAIL); 
$pdoStatement = $pdoDb->prepare('UPDATE user SET email=:email WHERE ID=:id'); 
$pdoStatement->execute(array(':email'=>$newEmail, ':id'=>$_SESSION['userId'])); 

Вы чувствуете себя в безопасности с помощью такого кода. Все хорошо, что ваши пользователи могут изменять свои электронные письма, не вводя SQL из-за вашего кода. Но, представьте, у вас есть это на вашем сайте http://siteA/, подключен один из ваших пользователей. С того же браузера, он идет на http://siteB/, где некоторые AJAX делает эквивалент этого кода:

<form method="post" action="http://site/updateMyAccount.php"> 
    <p> 
    <input name="email" value="[email protected]"/> 
    <input type="submit"/> 
    </p> 
</form> 

Ваш пользователь только что получил его по электронной почте изменена без его ведома его. Если вы не думаете, что этот вид атаки опасно, ask google about it

Чтобы помочь против такого рода атак, вы можете:

  • Проверь пользователь Referer (далеко от совершенства)
  • Реализации некоторыхов вы получили ваши формы и проверяли их присутствие, когда возвращаете данные.

Еще один сеанс - захват. Один из способов сделать это - это комбинирование. Если ваш сервер принимает не cookie-сессии, у вас могут быть URL-адреса, такие как http://siteA/?PHPSESSID=blabla, что означает, что ваш идентификатор сеанса является blabla.

Злоумышленник может начать сеанс и отметить его идентификатор сеанса, а затем дать ссылку http://siteA/?PHPSESSID=attackerSessionId другим пользователям вашего сайта. Когда эти пользователи следуют этой ссылке, они используют тот же сеанс, что и ваш злоумышленник: сеанс без регистрации. Поэтому они заходят в систему. Если веб-сайт ничего не делает, ваш злоумышленник и ваш пользователь по-прежнему используют один и тот же сеанс с одинаковыми правами. Плохо, если пользователь является администратором.

Чтобы смягчить это, вы должны использовать session_regenerate_id при изменении учетных данных пользователей (вход в систему и выход, переход в раздел администрирования и т. Д.).

3

Today's DailyWTF:

if(strstr($username, '**')) { 

    $admin = 1; 
    $username = str_replace('**', '', $username); 
    $_SESSION['admin'] = 1; 

} else { 

    $admin = 0; 

} 
+0

просто прочитал его на thedailywtf. этот код болит ... – knittl

+0

... а тот, кто разгневался называть себя программистом ?! – Strae

3

HTTP Расщепление отклика атаки

Если веб-приложение хранит входные данные от запроса HTTP в куки скажем

<?php setcookie("author",$_GET["authorName"]); ?> 

очень склонны к Атака ответа HTTP-ответа, если вход не проверен правильно для символов «\ r \ n».

Если злоумышленник отправляет вредоносную строку, например "AuthorName \ r \ nHTTP/1.1 200 OK \ r \ n ..», То ответ HTTP будет разделен на два ответов следующего вида:

HTTP/1.1 200 OK
...
Set-Cookie: автор = AUTHORNAME

HTTP/1.1 200 OK ...

Очевидно, что второй ответ полностью контролируется злоумышленником и может быть построен с любым содержимым заголовка и тела вместо

+0

Хм, я думаю, что это версия PHP. PHP 5, кажется, кодирует все специальные символы в процентное кодирование. – Tower

+2

Разделение ответа HTTP было рассмотрено в течение довольно долгого времени. http://php.net/releases/5_1_2.php –

2

Email headerinjection attacks являются гораздо больше боли в шею, то вы можете подозревать (если только вам не приходилось иметь дело с ними).

Это очень плохо:

$to = '[email protected]'; 
$subject = $_POST["subject"]; 
$message = $_POST["message"]; 
$headers = "From: ".$_POST["from"]; 
mail($to,$subject,$message,$headers); 

(. Код копируется из второй ссылки выше)

0

Основные операции (часто чувствительной безопасности) не работает, как ожидалось, а не требуя от программиста использовать второй «реальная» версия, чтобы получить неисполненные функциональные возможности.

Самый серьезный из них - это то, на что влияет фактический оператор: Оператор «==» не работает, как и следовало ожидать, вместо этого необходим оператор «===», чтобы получить истинное сравнение равенства.

Уязвимость в одном из больших пакетов из 3 PHP-форумов была подвержена уязвимости в коде «оставаться в системе». Файл cookie будет содержать идентификатор пользователя и хэш-код пароля. PHP-скрипт будет считывать и очищать идентификатор, использовать его для запроса правильного хэша пользователя в базе данных и затем сравнивать его с файлом в файле cookie, чтобы узнать, должны ли они автоматически регистрироваться.

Однако сравнение было с ==, поэтому, изменяя cookie, злоумышленник использует хеш-значение «значение» логического значения: true, что делает утверждение сравнения хеш бесполезным. Таким образом, злоумышленник может заменить любой идентификатор пользователя для входа без пароля.

0

Позволяет людям загружать файлы, независимо от того, предполагается ли использование этого API пользователями или нет. Например, если программа загружает некоторые файлы на сервер, и эта программа никогда не загрузит плохой файл, это нормально.

Но хакер мог проследить, что отправляется, и где. Он мог узнать, что он позволяет загружать файлы.

Оттуда он может легко загрузить файл php. Как только это будет сделано, игра закончится. Теперь у него есть доступ ко всем вашим данным и может уничтожить или изменить все, что он хочет.

Другая распространенная ошибка - это наводнение. Вы должны ввести некоторые нормальные ограничения на свои данные. Не разрешайте пользователям вводить бессмысленные данные. Почему имя пользователя имеет длину 2 МБ? Такие вещи делают так просто, чтобы кто-то наполнил вашу базу данных или файловую систему и разбил систему из-за ошибок в пространстве.

Смежные вопросы