The best way has got to be parameterised queries. Then it doesn't matter what the user types in the data goes to the database as a value.
A quick search online shows some possibilities in PHP which is great! Even on this site - http://php.net/manual/en/pdo.prepared-statements.php
which also gives the reasons this is good both for security and performance.SQL инјекција
Почист и полокален преглед на PHP референцата, со задржана структура од PHP.net и подобра читливост за примери, секции и белешки.
SQL инјекција
Референца за `security.database.sql-injection.php` со подобрена типографија и навигација.
SQL инјекција
SQL инјекција е техника каде напаѓач експлоатира недостатоци во код на апликација одговорен за градење динамички SQL прашања. Напаѓачот може да добие пристап до привилегирани делови од апликацијата, да ги извлече сите информации од базата на податоци, да ги промени постоечките податоци, или дури и да изврши опасни команди на системско ниво на домаќинот на базата на податоци. Уulnerabilност се јавува кога програмерите ги спојуваат или интерполираат произволни влезови во нивните SQL изјави.
Пример #1 Поделување на множеството резултати на страници ... и правење суперкорисници (PostgreSQL)
Во следниот пример, корисничкиот влез е директно интерполиран во SQL прашањето, дозволувајќи му на напаѓачот да добие суперкорисничка сметка во базата на податоци.
<?php
$offset = $_GET['offset']; // beware, no input validation!
$query = "SELECT id, name FROM products ORDER BY name LIMIT 20 OFFSET $offset;";
$result = pg_query($conn, $query);
?>0;
insert into pg_shadow(usename,usesysid,usesuper,usecatupd,passwd)
select 'crack', usesysid, 't','t','crack'
from pg_shadow where usename='postgres';
--
0; е да се обезбеди валиден офсет на оригиналното прашање и да се заврши.
Забелешка:
Тоа е вообичаена техника да се присили SQL парсерот да го игнорира остатокот од прашањето напишано од програмерот со
--што е знакот за коментар во SQL.
Изводлив начин за добивање лозинки е да ги заобиколите страниците со резултати од пребарувањето. Единственото нешто што напаѓачот треба да го направи е да види дали има некои поднесени променливи што се користат во SQL изјави кои не се правилно обработени. Овие филтри можат да се постават вообичаено во претходна форма за да се прилагодат WHERE, ORDER BY,
LIMIT and OFFSET клаузули во SELECT
изјави. Ако вашата база на податоци го поддржува UNION конструкција, напаѓачот може да се обиде да додаде цело прашање на оригиналното за да ги наведе лозинките од произволна табела. Силно се препорачува да се чуваат само безбедни хешови на лозинките наместо самите лозинки.
Пример #2 Наведување написи ... и некои лозинки (кој било сервер за бази на податоци)
<?php
$query = "SELECT id, name, inserted, size FROM products
WHERE size = '$size'";
$result = odbc_exec($conn, $query);
?>SELECT изјава што ги открива сите лозинки:
' union select '1', concat(uname||'-'||passwd) as name, '1971-01-01', '0' from usertable; --
UPDATE and INSERT изјавите се исто така подложни на такви напади.
Пример #3 Од ресетирање лозинка ... до добивање повеќе привилегии (кој било сервер за бази на податоци)
<?php
$query = "UPDATE usertable SET pwd='$pwd' WHERE uid='$uid';";
?>' or uid like'%admin% to $uid Ако злонамерен корисник ја поднесе вредноста $pwd to
hehehe', trusted=100, admin='yes за промена на лозинката на администраторот, или едноставно поставува
<?php
// $uid: ' or uid like '%admin%
$query = "UPDATE usertable SET pwd='...' WHERE uid='' or uid like '%admin%';";
// $pwd: hehehe', trusted=100, admin='yes
$query = "UPDATE usertable SET pwd='hehehe', trusted=100, admin='yes' WHERE
...;";
?>за добивање повеќе привилегии, тогаш прашањето ќе биде извртено:
Иако останува очигледно дека напаѓачот мора да поседува барем некое знаење за архитектурата на базата на податоци за да изврши успешен напад, добивањето на оваа информација често е многу едноставно. На пример, кодот може да биде дел од софтвер со отворен код и да биде јавно достапен. Оваа информација може да се открие и преку затворен код - дури и ако е кодиран, обфусциран или компајлиран - па дури и преку вашиот сопствен код преку прикажување на пораки за грешки. Други методи вклучуваат употреба на типични имиња на табели и колони. На пример, форма за најавување што користи табела 'users' со имиња на колони 'id', 'username' и 'password'.
Пример #4 Напад на оперативниот систем на домаќинот на базата на податоци (MSSQL Server)
<?php
$query = "SELECT * FROM products WHERE id LIKE '%$prod%'";
$result = mssql_query($query);
?>a%' exec master..xp_cmdshell 'net user test testpass /ADD' --
to $prodАко напаѓачот ја поднесе вредноста $query , тогаш
<?php
$query = "SELECT * FROM products
WHERE id LIKE '%a%'
exec master..xp_cmdshell 'net user test testpass /ADD' --%'";
$result = mssql_query($query);
?>sa MSSQL Server ги извршува SQL изразите во серијата, вклучувајќи команда за додавање нов корисник во базата на податоци за локални сметки. Ако оваа апликација работеше како
Забелешка:
и услугата MSSQLSERVER работеше со доволно привилегии, напаѓачот сега би имал сметка со која би можел да пристапи до оваа машина.
Некои од горенаведените примери се поврзани со специфичен сервер за бази на податоци, но тоа не значи дека сличен напад е невозможен против други производи. Вашиот сервер за бази на податоци може да биде слично ранлив на друг начин. Сликата е со дозвола од
» xkcd
Техники за избегнување WHERE,
SETПрепорачаниот начин за избегнување на SQL инјекција е со врзување на сите податоци преку подготвени изрази. Користењето на параметризирани прашања не е доволно за целосно избегнување на SQL инјекција, но тоа е најлесниот и најбезбедниот начин за обезбедување влез во SQL изразите. Сите динамични литерали на податоци во VALUES и
клаузите мора да се заменат со места за задржување. Реалните податоци ќе бидат врзани за време на извршувањето и испратени одделно од SQL командата.
Врзувањето на параметри може да се користи само за податоци. Другите динамични делови од SQL прашањето мора да се филтрираат според познат список на дозволени вредности.
<?php
// The dynamic SQL part is validated against expected values
$sortingOrder = $_GET['sortingOrder'] === 'DESC' ? 'DESC' : 'ASC';
$productId = $_GET['productId'];
// The SQL is prepared with a placeholder
$stmt = $pdo->prepare("SELECT * FROM products WHERE id LIKE ? ORDER BY price {$sortingOrder}");
// The value is provided with LIKE wildcards
$stmt->execute(["%{$productId}%"]);
?>Подготвените изјави се обезбедени од PDO, од MySQLi, и од други библиотеки за бази на податоци.
SQL инјекциските напади главно се засноваат на експлоатирање на кодот што не е напишан со оглед на безбедноста. Никогаш не верувајте на никаков влез, особено од клиентската страна, дури и ако доаѓа од селективно поле, скриено поле за внесување или колаче. Првиот пример покажува дека таков едноставен упит може да предизвика катастрофи.
Стратегијата за одбрана во длабочина вклучува неколку добри практики за кодирање:
- Никогаш не се поврзувајте на базата на податоци како суперкорисник или како сопственик на базата на податоци. Секогаш користете прилагодени корисници со минимални привилегии.
- Проверете дали дадениот влез има очекуван тип на податок. PHP има широк спектар на функции за валидација на влез, од наједноставните што се наоѓаат во Функции на променливи и во Функции на типот на карактер (на пр. is_numeric(), ctype_digit() , односно) и понатаму до Регуларни изрази компатибилни со Perl support.
- Ако апликацијата очекува нумерички влез, разгледајте верификација на податоци со ctype_digit(), тивко променете го неговиот тип користејќи settype(), или користете ја неговата нумеричка репрезентација со sprintf().
- Ако слојот на базата на податоци не поддржува врзување на променливи, тогаш цитирајте секоја не-нумеричка вредност што ја внесува корисникот што се пренесува до базата на податоци со функцијата за бегство од низа специфична за базата на податоци (на пр. mysql_real_escape_string(), sqlite_escape_string(), итн.). Општи функции како addslashes() се корисни само во многу специфична средина (на пр. MySQL во еднобајтен сет на знаци со оневозможено), така што е подобро да се избегнуваат. NO_BACKSLASH_ESCAPESНе печатете никакви специфични информации за базата на податоци, особено за шемата, со сите средства или со нечесни средства. Видете исто така
- Функции за ракување со грешки и евидентирање Известување за грешки and Покрај овие, имате корист од евидентирање на прашањата или во вашиот скрипт или од самата база на податоци, ако поддржува евидентирање. Очигледно, евидентирањето не може да спречи никаков штетен обид, но може да биде корисно за да се проследи кој дел од апликацијата бил заобиколен. Дневникот сам по себе не е корисен, туку преку информациите што ги содржи. Повеќе детали генерално се подобри од помалку..
Richard dot Corfield at gmail dot com