PHP හි SQL එන්නත් කිරීම වළක්වා ගන්නේ කෙසේද?


2773

SQL විමසුමකට වෙනස් කිරීමකින් තොරව පරිශීලක ආදානය ඇතුළත් කර ඇත්නම් , පහත දැක්වෙන උදාහරණයේ දී මෙන්, SQL එන්නත් කිරීම සඳහා යෙදුම අවදානමට ලක් වේ :

$unsafe_variable = $_POST['user_input']; 

mysql_query("INSERT INTO `table` (`column`) VALUES ('$unsafe_variable')");

එයට හේතුව පරිශීලකයාට එවැනි දෙයක් ඇතුළත් කළ හැකි value'); DROP TABLE table;--අතර විමසුම මෙසේ වේ:

INSERT INTO `table` (`column`) VALUES('value'); DROP TABLE table;--')

මෙය සිදුවීම වැළැක්වීමට කුමක් කළ හැකිද?

Answers:


8969

සකස් කළ ප්‍රකාශ සහ පරාමිතිගත විමසුම් භාවිතා කරන්න. මේවා ඕනෑම පරාමිතීන්ගෙන් වෙන්ව දත්ත සමුදා සේවාදායකයා වෙත යවන හා විග්‍රහ කරන SQL ප්‍රකාශයන් ය. මේ ආකාරයෙන් ප්‍රහාරකයාට අනිෂ්ට SQL එන්නත් කළ නොහැක.

මෙය සාක්ෂාත් කර ගැනීම සඳහා ඔබට මූලික වශයෙන් විකල්ප දෙකක් තිබේ:

  1. PDO භාවිතා කිරීම (ඕනෑම සහය දක්වන දත්ත සමුදා ධාවකයක් සඳහා):

    $stmt = $pdo->prepare('SELECT * FROM employees WHERE name = :name');
    
    $stmt->execute([ 'name' => $name ]);
    
    foreach ($stmt as $row) {
        // Do something with $row
    }
  2. MySQLi භාවිතා කිරීම (MySQL සඳහා):

    $stmt = $dbConnection->prepare('SELECT * FROM employees WHERE name = ?');
    $stmt->bind_param('s', $name); // 's' specifies the variable type => 'string'
    
    $stmt->execute();
    
    $result = $stmt->get_result();
    while ($row = $result->fetch_assoc()) {
        // Do something with $row
    }

ඔබ MySQL හැර වෙනත් දත්ත සමුදායකට සම්බන්ධ වන්නේ නම්, ඔබට යොමු කළ හැකි ධාවක-විශේෂිත දෙවන විකල්පයක් ඇත (නිදසුනක් ලෙස, pg_prepare()සහ pg_execute()PostgreSQL සඳහා). PDO යනු විශ්වීය විකල්පයයි.


සම්බන්ධතාවය නිවැරදිව සැකසීම

PDOMySQL දත්ත ගබඩාවට ප්‍රවේශ වීමට භාවිතා කරන විට සත්‍ය ලෙස සකස් කළ ප්‍රකාශ පෙරනිමියෙන් භාවිතා නොකරන බව සලකන්න . මෙය නිවැරදි කිරීම සඳහා ඔබ විසින් සකස් කරන ලද ප්‍රකාශ අනුකරණය කිරීම අක්‍රීය කළ යුතුය. PDO භාවිතා කරමින් සම්බන්ධතාවයක් නිර්මාණය කිරීමේ උදාහරණයක්:

$dbConnection = new PDO('mysql:dbname=dbtest;host=127.0.0.1;charset=utf8', 'user', 'password');

$dbConnection->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$dbConnection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

ඉහත උදාහරණයේ දී දෝෂ ප්‍රකාරය තදින්ම අවශ්‍ය නොවේ, නමුත් එය එක් කිරීමට උපදෙස් දෙනු ලැබේ . මේ ආකාරයෙන් Fatal Errorයමක් වැරදී ගිය විට තිර රචනය නතර නොවේ . තවද එය සංවර්ධකයාට catchඕනෑම දෝෂයකට ( අවස්ථාවකට) අවස්ථාව ලබා දෙයිthrowPDOException s ලෙස n වන .

දේ අනිවාර්ය , කෙසේ වෙතත්, පළමු setAttribute()ආබාධිත emulated සූදානම් ප්රකාශ සහ භාවිතා කිරීම PDO කියයි අතර මාර්ගය සැබෑ සූදානම් ප්රකාශ. මෙය MySQL සේවාදායකයට යැවීමට පෙර ප්‍රකාශය සහ අගයන් PHP විසින් විග්‍රහ නොකිරීමට වග බලා ගනී (අනිෂ්ට SQL එන්නත් කිරීමට ප්‍රහාරකයෙකුට අවස්ථාවක් ලබා නොදේ).

ඔබට charsetඉදිකිරීම්කරුගේ විකල්පයන් සැකසිය හැකි වුවද , PHP හි 'පැරණි' අනුවාදයන් (5.3.6 ට පෙර) DSN හි අක්ෂර පරාමිතිය නිහ ly ව නොසලකා හැර ඇති බව සැලකිල්ලට ගැනීම වැදගත්ය .


පැහැදිලි කිරීම

ඔබ වෙත යවන SQL ප්‍රකාශය prepareදත්ත සමුදා සේවාදායකය විසින් විග්‍රහ කොට සම්පාදනය කරනු ලැබේ. පරාමිතීන් නියම කිරීමෙන් ( ඉහත උදාහරණයේ දී ?මෙන් හෝ නම් කරන ලද පරාමිතියක් :name) ඔබ පෙරීමට අවශ්‍ය තැන දත්ත සමුදා එන්ජිමට කියයි. එවිට ඔබ ඇමතූ විටexecute , සූදානම් කළ ප්‍රකාශය ඔබ සඳහන් කරන පරාමිති අගයන් සමඟ සංයුක්ත වේ.

මෙහි ඇති වැදගත් දෙය නම් පරාමිති අගයන් සංයුක්ත ප්‍රකාශය සමඟ සංයුක්ත කිරීම මිස SQL නූලක් නොවේ. SQL එන්නත් කිරීම ක්‍රියාත්මක වන්නේ දත්ත සමුදායට යැවීමට SQL නිර්මාණය කරන විට ස්ක්‍රිප්ට් අනිෂ්ට නූල් ඇතුළත් කිරීමෙනි. එබැවින් සත්‍ය SQL පරාමිතීන්ගෙන් වෙන වෙනම යැවීමෙන්, ඔබ අදහස් නොකළ දෙයක් සමඟ අවසන් වීමේ අවදානම ඔබ සීමා කරයි.

සූදානම් කළ ප්‍රකාශයක් භාවිතා කරන විට ඔබ යවන ඕනෑම පරාමිතියක් නූල් ලෙස සලකනු ලැබේ (දත්ත සමුදා එන්ජිම යම් ප්‍රශස්තිකරණයක් කළත් පරාමිතීන් සංඛ්‍යා ලෙස අවසන් විය හැක). ඉහත උදාහරණයේ දී, $nameවිචල්‍යයේ ප්‍රති'Sarah'; DELETE FROM employees result ලය අඩංගු වන්නේ නම් එය හුදෙක් නූලක් සෙවීමක් "'Sarah'; DELETE FROM employees"වන අතර ඔබ හිස් වගුවකින් අවසන් නොවනු ඇත .

සූදානම් කළ ප්‍රකාශ භාවිතා කිරීමේ තවත් වාසියක් නම්, ඔබ එකම ප්‍රකාශය එකම සැසියකදී බොහෝ වාරයක් ක්‍රියාත්මක කළහොත් එය විග්‍රහ කොට සම්පාදනය කරනු ලබන්නේ එක් වරක් පමණි.

ඔහ්, සහ ඇතුළත් කිරීමක් සඳහා එය කරන්නේ කෙසේදැයි ඔබ විමසූ බැවින්, මෙන්න උදාහරණයක් (PDO භාවිතා කරමින්):

$preparedStatement = $db->prepare('INSERT INTO table (column) VALUES (:column)');

$preparedStatement->execute([ 'column' => $unsafeValue ]);

ගතික විමසුම් සඳහා සූදානම් කළ ප්‍රකාශ භාවිතා කළ හැකිද?

විමසුම් පරාමිතීන් සඳහා ඔබට තවමත් සූදානම් කළ ප්‍රකාශ භාවිතා කළ හැකි වුවද, ගතික විමසුමේ ව්‍යුහය පරාමිතිකරණය කළ නොහැකි අතර ඇතැම් විමසුම් අංග පරාමිතිකරණය කළ නොහැක.

මෙම විශේෂිත අවස්ථා සඳහා, කළ හැකි හොඳම දේ විය හැකි අගයන් සීමා කරන සුදු ලැයිස්තු පෙරණයක් භාවිතා කිරීමයි.

// Value whitelist
// $dir can only be 'DESC', otherwise it will be 'ASC'
if (empty($dir) || $dir !== 'DESC') {
   $dir = 'ASC';
}

86
මෙහි වෙනත් තැනක මා දැක නැති නිසා එකතු කිරීම සඳහා, තවත් ආරක්ෂණ ක්‍රමයක් වන්නේ
වර්ග අඩි

37
එසේම, mysql_query හි නිල ලියකියවිලි මඟින් එක් විමසුමක් පමණක් ක්‍රියාත්මක කිරීමට ඉඩ ලබා දේ, එබැවින් හැර වෙනත් ඕනෑම විමසුමක්; නොසලකා හරිනු ලැබේ. මෙය දැනටමත් අතහැර දමා ඇතත් PHP 5.5.0 යටතේ පද්ධති විශාල ප්‍රමාණයක් ඇති අතර එමඟින් මෙම ශ්‍රිතය භාවිතා කළ හැකිය. php.net/manual/en/function.mysql-query.php
රැන්ඩල් වැලෙන්සියානෝ

12
මෙය නරක පුරුද්දක් වන නමුත් පශ්චාත්-ගැටලු විසඳුමකි: SQL එන්නත් කිරීම සඳහා පමණක් නොව ඕනෑම වර්ගයක එන්නත් සඳහා (නිදසුනක් ලෙස F3 රාමුව v2 හි දර්ශන ආකෘති එන්නත් සිදුරක් තිබුණි) ඔබ සූදානම් පැරණි වෙබ් අඩවියක් හෝ යෙදුමක් තිබේ නම් ඉන්ජෙක්ෂන් දෝෂ වලින්, එක් විසඳුමක් නම්, ඔබේ සුපිරි ග්ලෝබල් පූර්ව නිශ්චිත වර්ස් වල අගයන් $ _POST වැනි බූට්ස්ට්‍රැප් හි ගැලවී ගිය අගයන් සමඟ නැවත පැවරීමයි. PDO විසින්, තවමත් පැන යා හැකිය (අද රාමු සඳහාද): substr ($ pdo-> quote ($ str, \ PDO :: PARAM_STR), 1, -1)
Alix

15
මෙම පිළිතුරට සූදානම් කළ ප්‍රකාශයක් යනු කුමක්ද යන්න පිළිබඳ පැහැදිලි කිරීමක් නොමැත - එක් දෙයක් - ඔබගේ ඉල්ලීම අතරතුර ඔබ සූදානම් කළ ප්‍රකාශ රාශියක් භාවිතා කරන්නේ නම් එය කාර්ය සාධනයකි. සමහර විට එය 10x කාර්ය සාධනයට හේතු වේ. වඩා හොඳ අවස්ථාව වනුයේ PDO පරාමිති බන්ධනය සමඟ භාවිතා කිරීමයි, නමුත් ප්‍රකාශය සකස් කිරීම අක්‍රීයයි.
donis

6
භාවිතා PDO වඩා හොඳ වන අතර, නඩුව ඔබ ඍජු විමසුමක් කරන භාවිතා කරන බවට වග බලා ඔබ mysqli භාවිතා :: escape_string
Kassem Itani

1653

අවලංගු කරන ලද අවවාදයයි: මෙම පිළිතුරේ නියැදි කේතය (ප්‍රශ්නයේ නියැදි කේතය වැනි) PHP හි MySQLදිගුව භාවිතා කරයි , එය PHP 5.5.0 හි ඉවත් කර සම්පූර්ණයෙන්ම PHP 7.0.0 වලින් ඉවත් කරන ලදි.

ආරක්ෂක අවවාදයයි : මෙම පිළිතුර ආරක්ෂිත හොඳම භාවිතයන්ට අනුකූල නොවේ. SQL එන්නත් කිරීම වැළැක්වීම සඳහා පැන යාම ප්‍රමාණවත් නොවේ , ඒ වෙනුවට සූදානම් කළ ප්‍රකාශ භාවිතා කරන්න. ඔබේම අවදානමකින් පහත දක්වා ඇති උපාය මාර්ගය භාවිතා කරන්න. (එසේම, mysql_real_escape_string()PHP 7 හි ඉවත් කරන ලදි.)

ඔබ PHP හි මෑත සංස්කරණයක් භාවිතා කරන්නේ නම්, mysql_real_escape_stringපහත දක්වා ඇති විකල්පය තවදුරටත් ලබා ගත නොහැක ( mysqli::escape_stringනවීන සමාන වුවත්). මේ දිනවල mysql_real_escape_stringවිකල්පය අර්ථවත් වන්නේ PHP හි පැරණි අනුවාදයක පැරණි කේත සඳහා පමණි.


ඔබට විකල්ප දෙකක් තිබේ - ඔබගේ විශේෂ අක්ෂර වලින් ගැලවීම unsafe_variableහෝ පරාමිතිගත විමසුමක් භාවිතා කිරීම. දෙකම SQL එන්නත් වලින් ඔබව ආරක්ෂා කරයි. පරාමිතිගත විමසුම වඩා හොඳ භාවිතයක් ලෙස සලකනු ලබන නමුත් ඔබට එය භාවිතා කිරීමට පෙර PHP හි නවතම MySQL දිගුවකට වෙනස් කිරීම අවශ්‍ය වේ.

අපි පළමුවෙන් පලා යන පහළ බලපෑම් නූල ආවරණය කරන්නෙමු.

//Connect

$unsafe_variable = $_POST["user-input"];
$safe_variable = mysql_real_escape_string($unsafe_variable);

mysql_query("INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

//Disconnect

mysql_real_escape_stringශ්‍රිතයේ විස්තර ද බලන්න .

පරාමිතිගත විමසුම භාවිතා කිරීම සඳහා, ඔබ MySQL ශ්‍රිතවලට වඩා MySQLi භාවිතා කළ යුතුය . ඔබේ උදාහරණය නැවත ලිවීමට අපට පහත සඳහන් දෑ වැනි යමක් අවශ්‍ය වේ.

<?php
    $mysqli = new mysqli("server", "username", "password", "database_name");

    // TODO - Check that connection was successful.

    $unsafe_variable = $_POST["user-input"];

    $stmt = $mysqli->prepare("INSERT INTO table (column) VALUES (?)");

    // TODO check that $stmt creation succeeded

    // "s" means the database expects a string
    $stmt->bind_param("s", $unsafe_variable);

    $stmt->execute();

    $stmt->close();

    $mysqli->close();
?>

ඔබට එහි කියවීමට අවශ්‍ය ප්‍රධාන කාර්යය වනු ඇත mysqli::prepare.

එසේම, අනෙක් අය යෝජනා කර ඇති පරිදි, PDO වැනි දෙයක් සමඟ වියුක්ත තට්ටුවක් ඉහළට ඔසවා තැබීම ඔබට ප්‍රයෝජනවත් / පහසු විය හැකිය .

ඔබ විමසූ නඩුව තරමක් සරල එකක් බවත් වඩාත් සංකීර්ණ අවස්ථාවන්ට වඩාත් සංකීර්ණ ප්‍රවේශයන් අවශ්‍ය විය හැකි බවත් කරුණාවෙන් සලකන්න. විශේෂයෙන්:

  • පරිශීලක ආදානය මත පදනම්ව SQL හි ව්‍යුහය වෙනස් කිරීමට ඔබට අවශ්‍ය නම්, පරාමිතිගත විමසුම් උදව් නොකෙරෙන අතර අවශ්‍ය ගැලවීම ආවරණය නොවේ mysql_real_escape_string. මේ ආකාරයේ අවස්ථාවක, 'ආරක්ෂිත' අගයන් පමණක් අවසර දී ඇති බව සහතික කිරීම සඳහා පරිශීලකගේ ආදානය සුදු ලැයිස්තුවක් හරහා යැවීමට වඩා හොඳය.
  • ඔබ තත්වයක් තුළ පරිශීලක ආදානයෙන් පූර්ණ සංඛ්‍යා භාවිතා කර mysql_real_escape_stringප්‍රවේශය ලබා ගන්නේ නම්, පහත දැක්වෙන අදහස් දැක්වීමේදී බහුපද විස්තර කර ඇති ගැටලුවෙන් ඔබ පීඩා විඳිති . පූර්ණ සංඛ්‍යා උපුටා දැක්වීම් වලින් වට නොවන බැවින් මෙම නඩුව උපක්‍රමශීලී ය, එබැවින් පරිශීලක ආදානයේ ඇත්තේ ඉලක්කම් පමණක් බව තහවුරු කිරීමෙන් ඔබට ගනුදෙනු කළ හැකිය.
  • මා නොදන්නා වෙනත් අවස්ථා තිබේ. ඔබට වැටහෙනු මෙම ඔබ මුහුණ හැකි වඩා සියුම්, සමහර ප්රශ්න මත ප්රයෝජනවත් වේ.

1
භාවිතා mysql_real_escape_stringකිරීම ප්‍රමාණවත්ද නැතහොත් මම පරාමිතිකරණයද භාවිතා කළ යුතුද?
peiman F.

5
impeimanF. දේශීය ව්‍යාපෘතියක පවා පරාමිතිගත විමසුම් භාවිතා කිරීමට හොඳ පුරුද්දක් තබා ගන්න. පරාමිතිගත විමසුම් සමඟ SQL එන්නත් නොකරන බවට ඔබට සහතික වේ. ව්‍යාජ නැවත ලබා ගැනීම වළක්වා ගැනීම සඳහා ඔබ දත්ත සනීපාරක්ෂාව කළ යුතු බව මතක තබා ගන්න (එනම්, HTML කේතයක් පෙළකට දැමීම වැනි XSS එන්නත් කිරීම) htmlentitiesඋදාහරණයක් ලෙස
Goufalite

2
impeimanF. පරාමිතිගත විමසුම් හා වටිනාකම් බැඳීමට හොඳ පුරුදු, නමුත් සැබෑ ගැලවීමේ
රිචඩ්

mysql_real_escape_string()සම්පූර්ණත්වය සඳහා ඇතුළත් කිරීම මට වැටහී ඇත , නමුත් පළමුව වඩාත්ම දෝෂ සහිත ප්‍රවේශය ලැයිස්තුගත කිරීමේ රසිකයෙක් නොවෙමි. පා example කයාට පළමු උදාහරණය ඉක්මනින් ලබා ගත හැකිය. හොඳ දෙයක් එය දැන් අතහැර දමා ඇත :)
ස්ටීන් ෂොට්

1
@ ස්ටීන්ෂොට් - සියලුම mysql_*කාර්යයන් අතහැර දමා ඇත. වැනි සමාන mysqli_* කාර්යයන් මගින් ඒවා ප්‍රතිස්ථාපනය විය mysqli_real_escape_string.
රික් ජේම්ස්

1074

මෙහි ඇති සෑම පිළිතුරකින්ම ආවරණය වන්නේ ගැටලුවේ කොටසක් පමණි. ඇත්ත වශයෙන්ම, අපට SQL වෙත ගතිකව එකතු කළ හැකි විවිධ විමසුම් කොටස් හතරක් ඇත : -

  • නූලක්
  • ඉලක්කමක්
  • හඳුනාගැනීමක්
  • සින්ටැක්ස් යතුරු පදයකි

සකස් කළ ප්‍රකාශවලින් ආවරණය වන්නේ ඒවායින් දෙකක් පමණි.

නමුත් සමහර විට අපගේ විමසුම වඩාත් ගතික කර, ක්‍රියාකරුවන් හෝ හඳුනාගැනීම් එකතු කළ යුතුය. එබැවින් අපට විවිධ ආරක්ෂණ ක්‍රම අවශ්‍ය වේ.

පොදුවේ ගත් කල, එවැනි ආරක්ෂණ ප්රවේශයක් සුදු ලැයිස්තුගත කිරීම මත පදනම් වේ .

මෙම අවස්ථාවේදී, සෑම ගතික පරාමිතියක්ම ඔබේ ස්ක්‍රිප්ටයේ දෘඩ කේත කර එම කට්ටලයෙන් තෝරා ගත යුතුය. උදාහරණයක් ලෙස, ගතික අනුපිළිවෙලක් කිරීමට:

$orders  = array("name", "price", "qty"); // Field names
$key = array_search($_GET['sort'], $orders)); // if we have such a name
$orderby = $orders[$key]; // If not, first one will be set automatically. 
$query = "SELECT * FROM `table` ORDER BY $orderby"; // Value is safe

ක්‍රියාවලිය ලිහිල් කිරීම සඳහා මම සුදු ලැයිස්තු ලැයිස්තු සහායක ශ්‍රිතයක් ලිවූ අතර එය සියලු කාර්යයන් එක පේළියකින් කරයි:

$orderby = white_list($_GET['orderby'], "name", ["name","price","qty"], "Invalid field name");
$query  = "SELECT * FROM `table` ORDER BY `$orderby`"; // sound and safe

හඳුනාගැනීම් සුරක්ෂිත කිරීම සඳහා තවත් ක්‍රමයක් තිබේ - පැන යාම, නමුත් මම වඩාත් ශක්තිමත් හා පැහැදිලි ප්‍රවේශයක් ලෙස සුදු ලැයිස්තු ගත කිරීමට ඇලී සිටිමි. ඔබ සතුව හැඳුනුම්පතක් උපුටා දක්වා ඇති තාක් කල්, ඔබට එය සුරක්ෂිත කිරීම සඳහා උපුටා දැක්වීමේ චරිතයෙන් ගැලවිය හැකිය. උදාහරණයක් ලෙස, mysql සඳහා පෙරනිමියෙන් ඔබට එයින් ගැලවීමට උපුටා දැක්වීමේ අක්‍ෂරය දෙගුණ කළ යුතුය . වෙනත් ඩීබීඑම්එස් ගැලවීමේ නීති වෙනස් වේ.

තවමත්, SQL සින්ටැක්ස් මූල පද සමඟ ගැටළුවක් ඇත (වැනි AND, DESCසහ එවැනි), නමුත් සුදු ලැයිස්තුගත කිරීම මෙම නඩුවේ එකම ප්‍රවේශය ලෙස පෙනේ.

එබැවින්, සාමාන්‍ය නිර්දේශයක් ලෙස අර්ථ දැක්විය හැකිය

  • SQL දත්ත වචනාර්ථයෙන් නිරූපණය කරන ඕනෑම විචල්‍යයක් (හෝ, සරලව කිවහොත් - SQL නූලක් හෝ අංකයක්) සූදානම් කළ ප්‍රකාශයක් හරහා එකතු කළ යුතුය. ව්යතිරේක නොමැත.
  • SQL යතුරු පදයක්, වගුවක් හෝ ක්ෂේත්‍ර නාමයක් හෝ ක්‍රියාකරුවෙකු වැනි වෙනත් විමසුම් කොටසක් සුදු ලැයිස්තුවක් හරහා පෙරීම කළ යුතුය.

යාවත්කාලීන කරන්න

SQL එන්නත් කිරීමේ ආරක්ෂාව පිළිබඳ හොඳම භාවිතයන් පිළිබඳ පොදු එකඟතාවයක් ඇතත්, තවමත් නරක ක්‍රියා රාශියක් ඇත. ඔවුන්ගෙන් සමහරක් PHP භාවිතා කරන්නන්ගේ මනසෙහි ගැඹුරින් මුල් බැස ඇත. නිදසුනක් ලෙස, මෙම පිටුවේම (බොහෝ අමුත්තන්ට නොපෙනෙන) මකාදැමූ පිළිතුරු 80 කට වඩා තිබේ - සියල්ල නරක ගුණාත්මකභාවය නිසා හෝ නරක හා යල් පැන ගිය භාවිතයන් ප්‍රවර්ධනය කිරීම නිසා ප්‍රජාව විසින් ඉවත් කරනු ලැබේ. ඊටත් වඩා භයානක දෙය නම් සමහර නරක පිළිතුරු මකා නොදමා සමෘද්ධිමත් වීමයි.

නිදසුනක් ලෙස, (1) (2) තවමත් (3) බොහෝ (4) පිළිතුරු (5) , ඔබට අතින් නූල් ගැලවී යාම යෝජනා කරන දෙවන ඉහළම පිළිතුර ද ඇතුළුව - යල් පැන ගිය ප්‍රවේශයක් අනාරක්ෂිත බව ඔප්පු වී ඇත.

නැතහොත් තරමක් හොඳ පිළිතුරක් ඇති අතර එය තවත් හැඩතල ගැන්වීමේ ක්‍රමයක් යෝජනා කරන අතර එය අවසාන කෝකටත් තෛලය ලෙස පුරසාරම් දොඩයි. ඇත්ත වශයෙන්ම, එය එසේ නොවේ. මෙම ක්‍රමය සාමාන්‍ය නූල් හැඩතල ගැන්වීමට වඩා හොඳ නැත, නමුත් එය එහි ඇති සියලුම අඩුපාඩුකම් තබා ගනී: එය නූල් වලට පමණක් අදාළ වන අතර, වෙනත් ඕනෑම අත්පොත හැඩතල ගැන්වීමක් මෙන්, එය අත්‍යවශ්‍යයෙන්ම විකල්ප, අනිවාර්ය නොවන පියවරකි, ඕනෑම ආකාරයක මානව දෝෂයකට ගොදුරු වේ.

මේ සියල්ල OWASP හෝ PHP අත්පොත වැනි බලධාරීන්ගේ සහාය ඇතිව ඉතා පැරණි මිථ්‍යා විශ්වාසයක් නිසා යැයි මම සිතමි. එය පැන යාම සහ SQL එන්නත් වලින් ආරක්ෂා වීම අතර සමානාත්මතාවය ප්‍රකාශ කරයි.

PHP අත්පොත අවුරුදු ගණනාවක් තිස්සේ පැවසුවද, *_escape_stringකිසිසේත් දත්ත සුරක්‍ෂිත නොවන අතර කිසි විටෙකත් අදහස් කර නොමැත. නූල් හැර වෙනත් ඕනෑම SQL කොටසකට නිෂ් less ල වීමට අමතරව, අතින් පැන යාම වැරදිය, මන්ද එය ස්වයංක්‍රීයව ප්‍රතිවිරුද්ධ ලෙස අත්පොත වේ.

OWASP එය වඩාත් නරක අතට හරවන අතර, පරිශීලක ආදානයෙන් ගැලවීම අතිශයින්ම විකාරයකි: එන්නත් ආරක්ෂණ සන්දර්භය තුළ එවැනි වචන නොතිබිය යුතුය. සෑම විචල්‍යයක්ම භයානක විය හැකිය - ප්‍රභවය කුමක් වුවත්! නැතහොත්, වෙනත් වචන වලින් කිවහොත් - විමසුමකට ඇතුළත් කිරීම සඳහා සෑම විචල්‍යයක්ම නිසි ලෙස සංයුති කළ යුතුය - නැවත ප්‍රභවය කුමක් වුවත්. එය වැදගත් ගමනාන්තයයි. සංවර්ධකයෙකු එළුවන්ගෙන් බැටළුවන් වෙන් කිරීමට පටන් ගත් මොහොතේ (යම් නිශ්චිත විචල්‍යයක් “ආරක්ෂිතද” කියා සිතමින්) ඔහු / ඇය ඔහුගේ / ඇයගේ පළමු පියවර ව්‍යසනය කරා ගෙන යයි. මැජික් උපුටා දැක්වීමේ ලක්ෂණයට සමාන වන පරිදි, ඇතුල් වීමේ ස්ථානයෙන් තොග වශයෙන් පැන යාම වචන වලින් පවා යෝජනා කරන බව සඳහන් නොකල යුතුය - දැනටමත් හෙළා දැක ඇති, අතහැර දමා ඉවත් කර ඇත.

එබැවින්, "පැන යාම" මෙන් නොව, සූදානම් කළ ප්‍රකාශයන් යනු SQL එන්නත් කිරීමෙන් සැබවින්ම ආරක්ෂා වන මිනුමකි (අදාළ වන විට).


848

පරාමිතිගත SQL විමසුම් ක්‍රියාත්මක කිරීම සඳහා PDO (PHP Data Objects) භාවිතා කිරීම මම නිර්දේශ කරමි .

මෙය SQL එන්නත් වලින් ආරක්ෂා වනවා පමණක් නොව, විමසුම් වේගවත් කරයි.

හා PDO වඩා භාවිතා mysql_, mysqli_සහ pgsql_කාර්යයන්, ඔබ ඔබේ අයදුම් දත්ත සමුදායෙන් තව ටිකක් උපුටාගනු, දුර්ලභ සිදුවීමක් ඔබ දත්ත සපයන්නන් මාරු කිරීමට ඇති බවට.


මෙම පිළිතුර නොමඟ යවන සුළුය. PDO යනු ඔබේ විමසීම් හුදෙක් පැමිණ සිටීමෙන් ආරක්ෂා කරන මැජික් දණ්ඩක් නොවේ. PDO වෙතින් ආරක්ෂාවක් ලබා ගැනීම සඳහා ඔබේ විමසුමේ සෑම විචල්‍යයක්ම ස්ථානගත කරන්නෙකු සමඟ ආදේශ කළ යුතුය .
ඔබේ පොදු හැඟීම

620

භාවිතා PDOකර සකස් කළ විමසුම්.

( $connයනු PDOවස්තුව)

$stmt = $conn->prepare("INSERT INTO tbl VALUES(:id, :name)");
$stmt->bindValue(':id', $id);
$stmt->bindValue(':name', $name);
$stmt->execute();

548

ඔබට පෙනෙන පරිදි, සූදානම් කළ ප්‍රකාශ භාවිතා කිරීමට මිනිසුන් යෝජනා කරයි. එය වැරදියි, නමුත් ඔබේ විමසුම ක්‍රියාවලියකට එක් වරක් පමණක් ක්‍රියාත්මක කළ විට , සුළු කාර්ය සාධන ද .ුවමක් ලැබෙනු ඇත.

මම මෙම ගැටලුවට මුහුණ දී සිටියෙමි, නමුත් මම හිතන්නේ මම එය ඉතා නවීන ආකාරයකින් විසඳුවා - උපුටා දැක්වීම් භාවිතා කිරීමෙන් වැළකී සිටීමට හැකර්වරුන් භාවිතා කරන ආකාරය. මම මෙය භාවිතා කළේ සකස් කළ ප්‍රකාශ සමඟ ඒකාබද්ධව ය. හැකි සෑම වර්ගයකම SQL එන්නත් කිරීමේ ප්‍රහාර වැළැක්වීමට මම එය භාවිතා කරමි .

මගේ ප්‍රවේශය:

  • ආදානය පූර්ණ සංඛ්‍යාවක් වනු ඇතැයි ඔබ අපේක්ෂා කරන්නේ නම් එය සැබවින්ම පූර්ණ සංඛ්‍යාවක් බවට වග බලා ගන්න . PHP වැනි විචල්‍ය ආකාරයේ භාෂාවක මෙය ඉතා වැදගත් වේ. ඔබට ඉතා සරල නමුත් බලවත් විසඳුමක් භාවිතා කළ හැකිය:sprintf("SELECT 1,2,3 FROM table WHERE 4 = %u", $input);

  • ඔබ පූර්ණ සංඛ්‍යා හෙක්ස් වෙතින් වෙනත් දෙයක් බලාපොරොත්තු වන්නේ නම් එය හෙක්ස් කරන්න . ඔබ එය හෙක්ස් කළහොත්, ඔබ සියලු ආදාන වලින් පරිපූර්ණව ගැලවෙනු ඇත. C / C ++ mysql_hex_string()හි PHP හි ඔබට භාවිතා කළ හැකි ශ්‍රිතයක් bin2hex()ඇත.

    පැන ගිය නූලට එහි මුල් දිගට 2x ප්‍රමාණයක් තිබීම ගැන කරදර නොවන්න, මන්ද ඔබ භාවිතා කළත් mysql_real_escape_stringPHP හට එකම ධාරිතාවයක් වෙන් කළ යුතු ((2*input_length)+1)අතර එය සමාන වේ.

  • ඔබ ද්විමය දත්ත මාරු කිරීමේදී මෙම හෙක්ස් ක්‍රමය බොහෝ විට භාවිතා වේ, නමුත් SQL එන්නත් කිරීමේ ප්‍රහාර වැළැක්වීම සඳහා සියලු දත්තවල එය භාවිතා නොකිරීමට කිසිදු හේතුවක් මා දකින්නේ නැත. ඒ වෙනුවට ඔබට 0xMySQL ශ්‍රිතය සමඟ දත්ත සකස් කිරීමට හෝ භාවිතා කිරීමට සිදුවන බව සලකන්න UNHEX.

උදාහරණයක් ලෙස, විමසුම:

SELECT password FROM users WHERE name = 'root';

බවට පත්වේ:

SELECT password FROM users WHERE name = 0x726f6f74;

හෝ

SELECT password FROM users WHERE name = UNHEX('726f6f74');

හෙක්ස් යනු පරිපූර්ණ ගැලවීමයි. එන්නත් කිරීමට ක්‍රමයක් නැත.

UNHEX ශ්‍රිතය සහ 0x උපසර්ගය අතර වෙනස

අදහස් දැක්වීමේදී යම් සාකච්ඡාවක් පැවතුනි, එබැවින් අවසානයේ එය පැහැදිලි කිරීමට මට අවශ්‍යය. මෙම ප්‍රවේශයන් දෙක බෙහෙවින් සමාන ය, නමුත් ඒවා යම් ආකාරයකින් ටිකක් වෙනස් ය:

මෙම 0xඋපසර්ගය වැනි දත්ත තීරු සඳහා පමණක් භාවිතා කළ හැකි char, varchar, text, block, binary, ආදිය
ද, එහි භාවිතය ඔබ හිස් අගයක් ඇතුල් කිරීමට ගැන නම් සංකීර්ණ ටිකක් වේ. ඔබට එය සම්පූර්ණයෙන්ම ප්‍රතිස්ථාපනය කිරීමට සිදුවේ '', නැතහොත් ඔබට දෝෂයක් ලැබෙනු ඇත.

UNHEX()ඕනෑම තීරුවක වැඩ කරයි ; හිස් නූල ගැන ඔබට කරදර විය යුතු නැත.


හෙක්ස් ක්‍රම බොහෝ විට ප්‍රහාර ලෙස භාවිතා කරයි

මෙම හෙක්ස් ක්‍රමය බොහෝ විට භාවිතා කරනුයේ SQL එන්නත් කිරීමේ ප්‍රහාරයක් ලෙස වන අතර එහිදී පූර්ණ සංඛ්‍යා නූල් මෙන් වන අතර එයින් ගැලවී යයි mysql_real_escape_string. එවිට ඔබට උපුටා දැක්වීම් වළක්වා ගත හැකිය.

උදාහරණයක් ලෙස, ඔබ මේ වගේ දෙයක් කරන්නේ නම්:

"SELECT title FROM article WHERE id = " . mysql_real_escape_string($_GET["id"])

ප්‍රහාරයකින් ඔබට ඉතා පහසුවෙන් එන්නත් කළ හැකිය . ඔබගේ ස්ක්‍රිප්ට් එකෙන් ආපසු ලබා දුන් පහත සඳහන් එන්නත් කේතය සලකා බලන්න:

SELECT ... WHERE id = -1 UNION ALL SELECT table_name FROM information_schema.tables;

දැන් වගු ව්‍යුහය උපුටා ගන්න:

SELECT ... WHERE id = -1 UNION ALL SELECT column_name FROM information_schema.column WHERE table_name = __0x61727469636c65__;

ඉන්පසු ඔවුන්ට අවශ්‍ය ඕනෑම දත්ත තෝරන්න. එය සිසිල් නොවේ ද?

නමුත් එන්නත් කළ හැකි වෙබ් අඩවියක කෝඩරය එය හෙක්ස් කරයි නම්, කිසිදු එන්නතක් කළ නොහැකි වන්නේ විමසුම මේ ආකාරයට පෙනෙන බැවිනි:

SELECT ... WHERE id = UNHEX('2d312075...3635');

6
Um සුමිට් ගුප්තා ඔව්, ඔබ කළා. MySQL සමග සමපාත +නොවේ CONCAT. සහ කාර්ය සාධනය සඳහා: MySQL දත්ත විග්රහ කළ යුතු සහ මූලාරම්භය string හෝ hex නම්, ඒ ගැන doesnt නිසා මම එය කාර්ය සාධන බලපාන මනිරත්නම්
Zaffy

11
OurYourCommonSense ඔබට සංකල්පය තේරෙන්නේ නැත ... ඔබට mysql හි නූල් තිබිය යුතු නම් ඔබට එය මේ ආකාරයෙන් උපුටා දක්වන්න, 'root'නැතහොත් ඔබට එය හෙක්ස් කළ හැකිය, 0x726f6f74නමුත් ඔබට අංකයක් අවශ්‍ය නම් සහ එය නූල් ලෙස එවන්නේ නම් ඔබ බොහෝ විට '42' නොව CHAR (42) ලියනු ඇත. ) ... hex මගින් '42' වනු ඇත 0x3432නොවන0x42
Zaffy

7
OurYourCommonSense මට කියන්නට දෙයක් නැත ... නිකම්ම නිකම් ... ඔබට තවමත් සංඛ්‍යා ක්ෂේත්‍රයන්හි හෙක්ස් උත්සාහ කිරීමට අවශ්‍ය නම්, දෙවන අදහස බලන්න. එය සාර්ථක වනු ඇතැයි මම ඔබ සමඟ ඔට්ටු අල්ලමි.
සැෆි

2
පිළිතුර පැහැදිලිවම සඳහන් කරන්නේ එය පූර්ණ සංඛ්‍යා අගයන් සමඟ ක්‍රියා නොකරනු ඇති බවයි, එයට හේතුව bin2hex සම්මත අගය නූල් බවට පරිවර්තනය කිරීමයි (මේ අනුව bin2hex (0) 0x30 මිස 0x03 නොවේ) - එය ඔබව ව්‍යාකූල කරන කොටස විය හැකිය . ඔබ එය අනුගමනය කරන්නේ නම්, එය පරිපූර්ණව ක්‍රියා කරයි (අවම වශයෙන් මගේ වෙබ් අඩවියේ, ඩෙබියන් යන්ත්‍රවල විවිධ mysql අනුවාද 4 ක් සමඟ පරීක්ෂා කර ඇත, 5.1.x සිට 5.6.x දක්වා). සියල්ලට පසු, ෂඩාස්රාකාර යනු නිරූපණය කිරීමේ මාර්ගය මිස වටිනාකම නොවේ;)
ග්‍රිෆින්

5
YouYourCommonSense ඔබට තවමත් තේරෙන්නේ නැද්ද? ඔබට 0x සහ concat භාවිතා කළ නොහැක, මන්ද නූල් හිස් නම් ඔබ දෝෂයකින් අවසන් වනු ඇත. ඔබේ විමසුමට සරල විකල්පයක් අවශ්‍ය නම් මෙය උත්සාහ කරන්නSELECT title FROM article WHERE id = UNHEX(' . bin2hex($_GET["id"]) . ')
Zaffy

498

අවලංගු කරන ලද අවවාදයයි: මෙම පිළිතුරේ නියැදි කේතය (ප්‍රශ්නයේ නියැදි කේතය වැනි) PHP හි MySQLදිගුව භාවිතා කරයි , එය PHP 5.5.0 හි ඉවත් කර සම්පූර්ණයෙන්ම PHP 7.0.0 වලින් ඉවත් කරන ලදි.

ආරක්ෂක අවවාදයයි : මෙම පිළිතුර ආරක්ෂිත හොඳම භාවිතයන්ට අනුකූල නොවේ. SQL එන්නත් කිරීම වැළැක්වීම සඳහා පැන යාම ප්‍රමාණවත් නොවේ , ඒ වෙනුවට සූදානම් කළ ප්‍රකාශ භාවිතා කරන්න. ඔබේම අවදානමකින් පහත දක්වා ඇති උපාය මාර්ගය භාවිතා කරන්න. (එසේම, mysql_real_escape_string()PHP 7 හි ඉවත් කරන ලදි.)

වැදගත්

SQL එන්නත් කිරීම වළක්වා ගත හැකි හොඳම ක්‍රමය නම් පිළිගත් පිළිතුර පෙන්නුම් කරන පරිදි පැන යාම වෙනුවට සූදානම් කළ ප්‍රකාශ භාවිතා කිරීමයි .

Aura.Sql සහ EasyDB වැනි පුස්තකාල ඇත, එමඟින් සංවර්ධකයින්ට සූදානම් කළ ප්‍රකාශ පහසුවෙන් භාවිතා කළ හැකිය. SQL එන්නත් කිරීම නැවැත්වීමට සූදානම් කළ ප්‍රකාශ වඩා හොඳ වන්නේ මන්ද යන්න පිළිබඳ වැඩිදුර දැන ගැනීම සඳහා, මෙම mysql_real_escape_string()බයිපාස් සහ වර්ඩ්ප්‍රෙස් හි මෑතකදී ස්ථාවර යුනිකෝඩ් SQL එන්නත් කිරීමේ දුර්වලතා වෙත යොමු වන්න .

එන්නත් වැළැක්වීම - mysql_real_escape_string ()

මෙම ප්‍රහාර වැළැක්වීම සඳහා විශේෂයෙන් සාදන ලද කාර්යයක් PHP සතුව ඇත. ඔබ කළ යුත්තේ ශ්‍රිතයක මුඛය භාවිතා කිරීම පමණි mysql_real_escape_string.

mysql_real_escape_stringMySQL විමසුමක භාවිතා කිරීමට යන නූලක් ගෙන සියලු SQL එන්නත් කිරීමේ උත්සාහයන් ආරක්ෂිතව ගැලවී යාමත් සමඟම එකම නූලක් ආපසු එවන්න. මූලික වශයෙන්, එමඟින් එම කරදරකාරී උපුටා දැක්වීම් (') භාවිතා කරන්නෙකුට MySQL- ආරක්ෂිත ආදේශකයක් වන ගැලවී ගිය උපුටා දැක්වීමක් ආදේශ කරනු ඇත \'.

සටහන: මෙම ශ්‍රිතය භාවිතා කිරීම සඳහා ඔබ දත්ත සමුදායට සම්බන්ධ විය යුතුය!

// MySQL වෙත සම්බන්ධ වන්න

$name_bad = "' OR 1'"; 

$name_bad = mysql_real_escape_string($name_bad);

$query_bad = "SELECT * FROM customers WHERE username = '$name_bad'";
echo "Escaped Bad Injection: <br />" . $query_bad . "<br />";


$name_evil = "'; DELETE FROM customers WHERE 1 or username = '"; 

$name_evil = mysql_real_escape_string($name_evil);

$query_evil = "SELECT * FROM customers WHERE username = '$name_evil'";
echo "Escaped Evil Injection: <br />" . $query_evil;

ඔබට MySQL - SQL එන්නත් වැළැක්වීමේ වැඩි විස්තර සොයාගත හැකිය .


30
පැරණි mysql දිගුව සමඟ ඔබට කළ හැකි හොඳම දේ මෙයයි. නව කේතයක් සඳහා, ඔබට mysqli හෝ PDO වෙත මාරු වීමට උපදෙස් දෙනු ලැබේ.
ඇල්වාරෝ ගොන්සාලෙස්

7
'මෙම ප්‍රහාර වැළැක්වීම සඳහා වි‍ශේෂයෙන් සාදන ලද කාර්යයක්' සමඟ මම එකඟ නොවෙමි. mysql_real_escape_stringසෑම ආදාන දත්ත පෙළක් සඳහාම නිවැරදි SQL විමසුමක් තැනීමට එම අරමුණ ඉඩ දී ඇතැයි මම සිතමි . වැළැක්වීමේ sql- එන්නත් කිරීම මෙම ශ්‍රිතයේ අතුරු ආබාධයකි.
නිකාය

4
නිවැරදි ආදාන දත්ත නූල් ලිවීමට ඔබ කාර්යයන් භාවිතා නොකරයි. ඔබ පැන යාමට අවශ්‍ය නැති හෝ දැනටමත් ගැලවී ගොස් ඇති නිවැරදි ඒවා ලියන්න. mysql_real_escape_string () නිර්මාණය කර ඇත්තේ ඔබ සිතේ සඳහන් කර ඇති අරමුණින් විය හැකි නමුත් එහි එකම වටිනාකම එන්නත් කිරීම වැළැක්වීමයි.
නාස්කා

17
අවවාදයයි! mysql_real_escape_string() වැරදිසහගත නොවේ .
එගියාල්

9
mysql_real_escape_stringදැන් අතහැර දමා ඇත, එබැවින් එය තවදුරටත් ශක්‍ය විකල්පයක් නොවේ. එය අනාගතයේදී PHP වෙතින් ඉවත් කරනු ලැබේ. PHP හෝ MySQL පිරිස නිර්දේශ කරන දේ වෙත ගමන් කිරීම වඩාත් සුදුසුය.
jww

462

ඔබට මේ වගේ මූලික දෙයක් කළ හැකිය:

$safe_variable = mysqli_real_escape_string($_POST["user-input"], $dbConnection);
mysqli_query($dbConnection, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

මෙය සෑම ගැටලුවක්ම විසඳන්නේ නැත, නමුත් එය ඉතා හොඳ පියවරකි. විචල්‍යයේ පැවැත්ම, ආකෘතිය (අංක, අකුරු ආදිය) පරීක්ෂා කිරීම වැනි පැහැදිලි අයිතම මම අතහැර දැමුවෙමි.


28
මම ඔබේ ආදර්ශය අත්හදා බැලුවෙමි. එය මට හොඳය. "මෙය සෑම ගැටලුවක්ම විසඳන්නේ නැත" යනුවෙන් ඔබට පැහැදිලි කළ හැකිද
චිනූක්

14
ඔබ නූල උපුටා දක්වන්නේ නැත්නම්, එය තවමත් එන්නත් කළ හැකිය. ගත $q = "SELECT col FROM tbl WHERE x = $safe_var";උදාහරණයක්. උපුටා දැක්වීම් නොමැතිකම නිසා මෙම නඩුවේ වැඩ $safe_varකිරීමට සැකසීම 1 UNION SELECT password FROM users. CONCATසහ භාවිතා කරමින් විමසුමට නූල් එන්නත් කළ හැකිය CHR.
බහුපද

4
Ol බහුපද සම්පූර්ණයෙන්ම හරි, නමුත් මම මෙය හුදෙක් වැරදි භාවිතයක් ලෙස දකිමි. ඔබ එය නිවැරදිව භාවිතා කරන තාක් කල් එය අනිවාර්යයෙන්ම ක්‍රියාත්මක වේ.
glglgl

22
අවවාදයයි! mysql_real_escape_string() වැරදිසහගත නොවේ .
ఎగ్යාල්

8
mysql_real_escape_stringදැන් අතහැර දමා ඇත, එබැවින් එය තවදුරටත් ශක්‍ය විකල්පයක් නොවේ. එය අනාගතයේදී PHP වෙතින් ඉවත් කරනු ලැබේ. PHP හෝ MySQL පිරිස නිර්දේශ කරන දේ වෙත ගමන් කිරීම වඩාත් සුදුසුය.
jww

379

ඔබ කුමක් කළත් අවසන් වන්නේ නම්, ඔබේ ආදානය දැනටමත් magic_quotesහෝ වෙනත් හොඳ කුණු කසළ වලින් හසු වී නොමැති බවට වග බලා ගන්න , අවශ්‍ය නම්, එය හරහා stripslashesහෝ සනීපාරක්ෂාව සඳහා ඕනෑම දෙයක් ක්‍රියාත්මක කරන්න.


11
ඇත්ත වශයෙන්ම; මැජික්_කෝට්ස් සමඟ ධාවනය කිරීම දුර්වල පුහුණුවීම් දිරිගන්වයි. කෙසේ වෙතත්, සමහර විට ඔබට සෑම විටම එම මට්ටමට පරිසරය පාලනය කළ නොහැක - එක්කෝ ඔබට සේවාදායකය කළමනාකරණය කිරීමට ප්‍රවේශය නැත, නැතහොත් ඔබේ යෙදුමට එවැනි වින්‍යාසයන් මත රඳා පවතින (වෙව්ලීම) යෙදුම් සමඟ සහජීවනය කළ යුතුය. මෙම හේතූන් නිසා, අතේ ගෙන යා හැකි යෙදුම් ලිවීම හොඳය - පැහැදිලිවම ඔබ යෙදවීමේ පරිසරය පාලනය කරන්නේ නම් උත්සාහය අපතේ යනු ඇත, උදා: එය ගෘහස්ථ යෙදුමක් නිසා හෝ ඔබේ විශේෂිත පරිසරය තුළ පමණක් භාවිතා කිරීමට යන්නේ.
රොබ්

24
පීඑච්පී 5.4 වන විට, 'මැජික් කෝට්ස්' ලෙස හැඳින්වෙන පිළිකුල මිය ගොස් ඇත. නරක කුණු වලට හොඳ ප්‍රහේලිකාවක්.
බ්‍රයන් එච්

362

අවලංගු කරන ලද අවවාදයයි: මෙම පිළිතුරේ නියැදි කේතය (ප්‍රශ්නයේ නියැදි කේතය වැනි) PHP හි MySQLදිගුව භාවිතා කරයි , එය PHP 5.5.0 හි ඉවත් කර සම්පූර්ණයෙන්ම PHP 7.0.0 වලින් ඉවත් කරන ලදි.

ආරක්ෂක අවවාදයයි : මෙම පිළිතුර ආරක්ෂිත හොඳම භාවිතයන්ට අනුකූල නොවේ. SQL එන්නත් කිරීම වැළැක්වීම සඳහා පැන යාම ප්‍රමාණවත් නොවේ , ඒ වෙනුවට සූදානම් කළ ප්‍රකාශ භාවිතා කරන්න. ඔබේම අවදානමකින් පහත දක්වා ඇති උපාය මාර්ගය භාවිතා කරන්න. (එසේම, mysql_real_escape_string()PHP 7 හි ඉවත් කරන ලදි.)

පරාමිතිගත විමසුම සහ ආදාන වලංගු කිරීම යනු යා යුතු මාර්ගයයි. SQL එන්නත් කිරීම භාවිතා කළ හැකි අවස්ථා බොහොමයක් mysql_real_escape_string()තිබේ.

එම උදාහරණ SQL එන්නත් කිරීමට ගොදුරු වේ:

$offset = isset($_GET['o']) ? $_GET['o'] : 0;
$offset = mysql_real_escape_string($offset);
RunQuery("SELECT userid, username FROM sql_injection_test LIMIT $offset, 10");

හෝ

$order = isset($_GET['o']) ? $_GET['o'] : 'userid';
$order = mysql_real_escape_string($order);
RunQuery("SELECT userid, username FROM sql_injection_test ORDER BY `$order`");

අවස්ථා දෙකේදීම, 'සංසරණය ආරක්ෂා කිරීමට ඔබට භාවිතා කළ නොහැක .

මූලාශ්‍රය : අනපේක්ෂිත SQL එන්නත් කිරීම (පැන යාම ප්‍රමාණවත් නොවන විට)


2
දිග, වර්ගය සහ වාක්‍ය ඛණ්ඩය සහ ව්‍යාපාර නීති වලට එරෙහිව අර්ථ දක්වා ඇති නීති මාලාවකට එරෙහිව පරිශීලක ආදානය සත්‍යාපනය කරන ආදාන වලංගු කිරීමේ ක්‍රමවේදයක් ඔබ අනුගමනය කරන්නේ නම් ඔබට SQL එන්නත් කිරීම වළක්වා ගත හැකිය.
ජොසිප් අයිවික්

311

මගේ මතය අනුව, සාමාන්‍යයෙන් ඔබේ PHP යෙදුමේ SQL එන්නත් කිරීම වළක්වා ගත හැකි හොඳම ක්‍රමය (හෝ ඒ සඳහා ඕනෑම වෙබ් යෙදුමක්) ඔබේ යෙදුමේ ගෘහ නිර්මාණ ශිල්පය ගැන සිතීමයි. SQL එන්නත් වලින් ආරක්ෂා වීමට ඇති එකම ක්‍රමය නම්, ඔබ දත්ත සමුදාය සමඟ කතා කරන සෑම අවස්ථාවකම නිවැරදි දේ කරන විශේෂ ක්‍රමයක් හෝ ශ්‍රිතයක් භාවිතා කිරීම මතක තබා ගැනීම නම්, ඔබ එය වැරදිය. ඒ ආකාරයෙන්, ඔබේ කේතයේ යම් අවස්ථාවක දී ඔබේ විමසුම නිවැරදිව සංයුති කිරීමට ඔබට අමතක වන තෙක් එය කාලය පිළිබඳ ප්‍රශ්නයක් පමණි.

එම්වීසී රටාව හා කේක් පීඑච්පී හෝ කෝඩ්ඉග්නිටර් වැනි රාමුවක් අනුගමනය කිරීම බොහෝ විට නිවැරදි මාර්ගය විය හැකිය: ආරක්ෂිත දත්ත සමුදා විමසුම් නිර්මාණය කිරීම වැනි පොදු කාර්යයන් විසඳා ඇති අතර එවැනි රාමු තුළ කේන්ද්‍රීයව ක්‍රියාත්මක කර ඇත. ඔබේ වෙබ් යෙදුම සංවේදී ආකාරයකින් සංවිධානය කිරීමට සහ තනි SQL විමසුම් ආරක්ෂිතව තැනීමට වඩා වස්තු පැටවීම සහ සුරැකීම ගැන සිතීමට ඒවා ඔබට උදව් කරයි.


5
මම හිතන්නේ ඔබේ පළමු ඡේදය වැදගත්. අවබෝධය ප්‍රධාන ය. එසේම, සෑම කෙනෙකුම සමාගමක් සඳහා වැඩ කරන්නේ නැත. විශාල ජනකායක් සඳහා, රාමු ඇත්ත වශයෙන්ම අවබෝධය පිළිබඳ අදහසට පටහැනිය . නියමිත දින නියමයක් යටතේ වැඩ කරන අතරතුර මූලධර්ම සමඟ සමීපව කටයුතු කිරීම වටින්නේ නැත, නමුත් එහි සිටින අය තමන්ගේ දෑත් අපිරිසිදු කර ගැනීමට ප්‍රිය කරති. රාමු සංවර්ධකයින් එතරම් වරප්‍රසාද නොලබන අතර අනෙක් සියල්ලන්ම හිස නැමිය යුතු අතර ඔවුන් කිසි විටෙකත් වැරදි කරන්නේ නැතැයි උපකල්පනය කළ යුතුය. තීරණ ගැනීමේ බලය තවමත් වැදගත් ය. අනාගතයේදී මගේ රාමුව වෙනත් යෝජනා ක්‍රමයක් විස්ථාපනය නොකරනු ඇතැයි කීමට කවුද?
ඇන්තනි රට්ලෙජ්

Nt ඇන්තනි රට්ලෙජ් ඔබ නියත වශයෙන්ම නිවැරදි ය. සිදුවන්නේ කුමක්ද සහ ඇයි යන්න තේරුම් ගැනීම ඉතා වැදගත් වේ . කෙසේ වෙතත්, සත්‍ය හා උත්සාහ කළ හා ක්‍රියාශීලීව භාවිතා කරන ලද සහ දියුණු කරන ලද රාමුවක් තුළ ගැටලු රාශියක් විසඳා ඇති අතර දැනටමත් ආරක්ෂක වළවල් රාශියක් ඇලවී තිබේ. කේතයේ ගුණාත්මකභාවය පිළිබඳ හැඟීමක් ලබා ගැනීම සඳහා මූලාශ්‍රය දෙස බැලීම හොඳ අදහසකි. එය පරීක්ෂා නොකළ අවුලක් නම් එය බොහෝ විට ආරක්ෂිත නොවේ.
ජොහැන්නස් ෆැරන්ක්රුග්

3
මෙහි. මෙහි. හොඳ ලකුණු. කෙසේ වෙතත්, බොහෝ දෙනෙකුට MVC පද්ධතියක් හැදෑරීමට ඉගෙන ගත හැකි බව ඔබ එකඟ වන නමුත් සෑම කෙනෙකුටම එය අතින් ප්‍රතිනිෂ්පාදනය කළ නොහැක (පාලකයන් සහ සේවාදායකයා). යමෙකුට මෙම කරුණ සමඟ බොහෝ දුර යා හැකිය. මගේ පෙම්වතිය විසින් මා විසින් සාදන ලද රටකජු බටර් පීකන් කුකීස් උණුසුම් කිරීමට පෙර මගේ මයික්‍රෝවේව් උදුන තේරුම් ගත යුතුද? ;-)
ඇන්තනි රට්ලෙජ්

3
Nt ඇන්තනි රට්ලෙජ් මම එකඟයි! භාවිතා කිරීමේ අවස්ථාවද වෙනසක් ඇති කරයි යැයි මම සිතමි: මම මගේ පුද්ගලික මුල් පිටුව සඳහා ඡායාරූප ගැලරිය ගොඩනඟන්නේද නැතහොත් මම මාර්ගගත බැංකු වෙබ් යෙදුමක් ගොඩනඟනවාද? අවසාන අවස්ථාවේ දී ආරක්ෂාව පිළිබඳ විස්තර සහ මා භාවිතා කරන රාමුවක් ඒවාට ආමන්ත්‍රණය කරන්නේ කෙසේද යන්න තේරුම් ගැනීම ඉතා වැදගත් වේ.
ජොහැන්නස් ෆැරන්ක්රුග්

3
අහ්, ආරක්ෂක ව්‍යතිරේකය එයම සහසම්බන්ධය කරන්න. බලන්න, මම ඒ සියල්ල අවදානමට ලක් කිරීමට කැමැත්තෙන් සිටිමි. :-) විහිළු. ප්‍රමාණවත් කාලයක් තිබියදී, ලස්සන ආරක්‍ෂිත යෙදුමක් සෑදීමට මිනිසුන්ට ඉගෙන ගත හැකිය. ඕනෑවට වඩා මිනිස්සු කඩිමුඩියේ සිටිති. ඔවුන් තම දෑත් ඉහළට ඔසවා රාමු ආරක්ෂිත යැයි උපකල්පනය කරති . සියල්ලට පසු, දේවල් පරීක්ෂා කිරීමට සහ සොයා ගැනීමට ඔවුන්ට ප්‍රමාණවත් කාලයක් නොමැත. එපමණක් නොව, ආරක්ෂාව යනු කැපවූ අධ්‍යයනයක් අවශ්‍ය ක්ෂේත්‍රයකි. එය ඇල්ගොරිතම සහ සැලසුම් රටා අවබෝධ කර ගැනීමෙන් හුදෙක් ක්‍රමලේඛකයින් ගැඹුරින් දන්නා දෙයක් නොවේ.
ඇන්තනි රට්ලෙජ්

297

මම කරුණාව ගබඩා පටිපාටි ( MySQL 5.0 සිට ගබඩා පටිපාටි සහාය වී ඇත වාසි -) මතය ආරක්ෂක ස්ථානයේ සිට -

  1. බොහෝ දත්ත සමුදායන් ( MySQL ද ඇතුළුව ) පරිශීලක ප්‍රවේශය ගබඩා කළ ක්‍රියා පටිපාටි ක්‍රියාත්මක කිරීමට පමණක් සීමා කරයි. වරප්‍රසාද ප්‍රහාර උත්සන්න වීම වැළැක්වීම සඳහා සියුම් ආරක්ෂක ප්‍රවේශ ප්‍රවේශයන් ප්‍රයෝජනවත් වේ. සම්මුති විරහිත යෙදුම් දත්ත සමුදායට එරෙහිව SQL කෙලින්ම ධාවනය කිරීමට මෙය වළක්වයි.
  2. ඔවුන් යෙදුමෙන් අමු SQL විමසුම සාරාංශ කරන බැවින් දත්ත සමුදා ව්‍යුහය පිළිබඳ අඩු තොරතුරු යෙදුමට ලබා ගත හැකිය. මෙමඟින් දත්ත සමුදායේ යටින් පවතින ව්‍යුහය තේරුම් ගැනීමට සහ සුදුසු ප්‍රහාර සැලසුම් කිරීමට මිනිසුන්ට අපහසු වේ.
  3. ඔවුන් පිළිගන්නේ පරාමිතීන් පමණි, එබැවින් පරාමිතිගත විමසුම් වල වාසි ඇත. ඇත්ත වශයෙන්ම - IMO ඔබට තවමත් ඔබේ ආදානය සනීපාරක්ෂාව කළ යුතුය - විශේෂයෙන් ඔබ ගබඩා කළ ක්‍රියා පටිපාටිය තුළ ගතික SQL භාවිතා කරන්නේ නම්.

අවාසි නම් -

  1. ඒවා (ගබඩා කළ ක්‍රියා පටිපාටි) නඩත්තු කිරීමට අසීරු වන අතර ඉතා ඉක්මණින් ගුණ කිරීමට නැඹුරු වේ. මෙය ඔවුන් කළමනාකරණය කිරීම ගැටලුවක් බවට පත් කරයි.
  2. ගතික විමසුම් සඳහා ඒවා එතරම් සුදුසු නොවේ - ඒවා ගතික කේතය පරාමිතීන් ලෙස පිළිගැනීම සඳහා ගොඩනගා ඇත්නම් බොහෝ වාසි ප්‍රතික්ෂේප කරනු ලැබේ.

296

SQL එන්නත් සහ වෙනත් SQL හක්ක වලක්වා ගැනීමට බොහෝ ක්‍රම තිබේ. ඔබට එය පහසුවෙන් අන්තර්ජාලයෙන් සොයාගත හැකිය (ගූගල් සෙවුම). ඇත්ත වශයෙන්ම PDO හොඳ විසඳුමකි. නමුත් SQL එන්නත් කිරීම වැළැක්වීම සඳහා හොඳ සබැඳි කිහිපයක් යෝජනා කිරීමට මම කැමතියි.

SQL එන්නත් කිරීම යනු කුමක්ද සහ එය වළක්වා ගන්නේ කෙසේද

SQL එන්නත් කිරීම සඳහා PHP අත්පොත

PHP හි SQL එන්නත් කිරීම සහ වැළැක්වීම පිළිබඳ මයික්‍රොසොෆ්ට් පැහැදිලි කිරීම

MySQL සහ PHP සමඟ SQL එන්නත් කිරීම වැළැක්වීම වැනි තවත් සමහරක් .

දැන්, ඔබේ විමසුම SQL එන්නත් කිරීමෙන් වළක්වා ගැනීමට ඔබට අවශ්‍ය ඇයි?

මම ඔබට දන්වන්න කැමතියි: පහත දැක්වෙන කෙටි උදාහරණයකින් SQL එන්නත් කිරීම වැළැක්වීමට අප උත්සාහ කරන්නේ ඇයි:

පුරනය වීමේ සත්‍යාපන ගැලපීම සඳහා විමසුම:

$query="select * from users where email='".$_POST['email']."' and password='".$_POST['password']."' ";

දැන්, යමෙකු (හැකර්) දැමුවහොත්

$_POST['email']= admin@emali.com' OR '1=1

මුරපදය ඕනෑම දෙයක් ....

විමසුම පද්ධතියට විග්‍රහ කරනු ලබන්නේ පහත දක්වා පමණි:

$query="select * from users where email='admin@emali.com' OR '1=1';

අනෙක් කොටස ඉවතලනු ඇත. ඉතින්, කුමක් සිදුවේද? බලයලත් නොවන පරිශීලකයෙකුට (හැකර්) ඔහුගේ / ඇයගේ මුරපදය නොමැතිව පරිපාලක ලෙස ලොග් වීමට හැකි වේ. දැන්, ඔහුට / ඇයට පරිපාලක / විද්‍යුත් තැපැල් පුද්ගලයාට කළ හැකි ඕනෑම දෙයක් කළ හැකිය. බලන්න, SQL එන්නත් කිරීම වළක්වා නොගන්නේ නම් එය ඉතා භයානක ය.


266

මම හිතන්නේ යමෙකුට PHP සහ MySQL හෝ වෙනත් දත්ත පදනම් සේවාදායකයක් භාවිතා කිරීමට අවශ්‍ය නම්:

  1. PDO (PHP Data Objects) ඉගෙනීම ගැන සිතන්න - එය දත්ත සමුදා ප්‍රවේශ ස්ථරයක් වන අතර එය බහු දත්ත සමුදායන් වෙත ඒකාකාරී ප්‍රවේශයක් සපයයි.
  2. MySQLi ඉගෙනීම ගැන සිතන්න
  3. : වගේ ස්වදේශික PHP කටයුතු යොදා strip_tags , mysql_real_escape_string පමණක්, විචල්ය සංඛ්යාත්මක හෝ නම් (int)$foo. PHP හි විචල්‍ය වර්ග ගැන වැඩි විස්තර මෙතැනින් කියවන්න . ඔබ PDO හෝ MySQLi වැනි පුස්තකාල භාවිතා කරන්නේ නම්, සෑම විටම PDO :: quote () සහ mysqli_real_escape_string () භාවිතා කරන්න .

පුස්තකාල උදාහරණ:

---- පීඩීඕ

----- ස්ථාන දරන්නන් නැත - SQL එන්නත් කිරීම සඳහා ඉදුණු! ඒක නරකයි

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values ($name, $addr, $city)");

----- නම් නොකළ ස්ථාන දරන්නන්

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) values (?, ?, ?);

----- නම් කරන ලද ස්ථාන දරන්නන්

$request = $pdoConnection->("INSERT INTO parents (name, addr, city) value (:name, :addr, :city)");

--- MySQLi

$request = $mysqliConnection->prepare('
       SELECT * FROM trainers
       WHERE name = ?
       AND email = ?
       AND last_login > ?');

    $query->bind_param('first_param', 'second_param', $mail, time() - 3600);
    $query->execute();

PS :

PDO මෙම සටන පහසුවෙන් ජය ගනී. විවිධ දත්ත සමුදා ධාවක සහ නම් කරන ලද පරාමිතීන් දොළහක සහාය ඇතිව, අපට කුඩා කාර්ය සාධන අලාභය නොසලකා හැර එහි API වෙත පුරුදු විය හැකිය. ආරක්ෂක දෘෂ්ටි කෝණයකින්, සංවර්ධකයා ඒවා භාවිතා කළ යුතු ආකාරයට භාවිතා කරන තාක් කල් ඔවුන් දෙදෙනාම ආරක්ෂිත වේ

PDO සහ MySQLi යන දෙකම තරමක් වේගවත් වන අතර, MySQLi මිණුම් සලකුණු වල සැලකිය යුතු වේගයකින් ක්‍රියා කරයි - සූදානම් නොකළ ප්‍රකාශ සඳහා ~ 2.5% සහ සූදානම් කළ ඒවා සඳහා ~ 6.5%.

කරුණාකර ඔබේ දත්ත ගබඩාවට සෑම විමසුමක්ම පරීක්ෂා කරන්න - එය එන්නත් කිරීම වැළැක්වීමට වඩා හොඳ ක්‍රමයකි.


mysqli වැරදියි කියලා. පළමු පරාමිතිය දත්ත වර්ග ප්‍රකාශ කරයි.
mickmackusa

256

හැකි නම්, ඔබේ පරාමිති වර්ග දමන්න. නමුත් එය ක්‍රියාත්මක වන්නේ int, bool සහ float වැනි සරල වර්ගවල පමණි.

$unsafe_variable = $_POST['user_id'];

$safe_variable = (int)$unsafe_variable ;

mysqli_query($conn, "INSERT INTO table (column) VALUES ('" . $safe_variable . "')");

3
සූදානම් කළ ප්‍රකාශයක් වෙනුවට “ගැලවී ගිය අගයක්” මම භාවිතා කරන අවස්ථා කිහිපයෙන් එකකි මෙය. පූර්ණ සංඛ්‍යා වර්ග පරිවර්තනය අතිශයින්ම කාර්යක්ෂම වේ.
HoldOffHunger

232

ඔබ වැනි, හැඹිලි එන්ජින් ප්රයෝජනයක් ලබා ගැනීමට ඔබට අවශ්ය නම් Redis හෝ memcached , සමහරවිට DALMP තේරීමක් විය හැක. එය පිරිසිදු MySQLi භාවිතා කරයි . මෙය පරීක්ෂා කරන්න: PHP භාවිතා කරමින් MySQL සඳහා DALMP දත්ත සමුදා සාරාංශය.

එසේම, ඔබේ විමසුම සකස් කිරීමට පෙර ඔබේ තර්ක 'සූදානම්' කළ හැකි අතර එවිට ඔබට ගතික විමසුම් ගොඩනගා ගත හැකි අතර අවසානයේ සම්පුර්ණයෙන්ම සූදානම් කළ ප්‍රකාශ විමසුමක් ඇත. PHP භාවිතා කරමින් MySQL සඳහා DALMP දත්ත සමුදා සාරාංශ ස්ථරය.


224

PDO භාවිතා කරන්නේ කෙසේදැයි නොදන්නා අය සඳහා ( mysql_ශ්‍රිත වලින් එන ), මම තනි ගොනුවක් වන ඉතා සරල PDO එතුම සෑදුවෙමි . යෙදුම් කළ යුතු සියලුම පොදු දේවල් කිරීම කොතරම් පහසුදැයි පෙන්වීමට එය පවතී. PostgreSQL, MySQL, සහ SQLite සමඟ ක්‍රියා කරයි.

මූලික වශයෙන්, ඔබට අවශ්‍ය ආකෘතියේ අගයන් ගබඩා කිරීම සහ ලබා ගැනීම සරල කිරීම සඳහා සැබෑ ජීවිතයේ භාවිතා කිරීමට PDO කාර්යයන් දැමිය යුතු ආකාරය බැලීමට අත්පොත කියවන අතරතුර එය කියවන්න .

මට තනි තීරුවක් අවශ්‍යයි

$count = DB::column('SELECT COUNT(*) FROM `user`);

මට අරාව (යතුර => අගය) ප්‍රති results ල අවශ්‍යයි (එනම් තේරීම් කොටුවක් සෑදීම සඳහා)

$pairs = DB::pairs('SELECT `id`, `username` FROM `user`);

මට තනි පේළි ප්‍රති .ලයක් අවශ්‍යයි

$user = DB::row('SELECT * FROM `user` WHERE `id` = ?', array($user_id));

මට ප්‍රති .ල රාශියක් අවශ්‍යයි

$banned_users = DB::fetch('SELECT * FROM `user` WHERE `banned` = ?', array(TRUE));

222

මෙම PHP ශ්‍රිතය භාවිතා කිරීමෙන් mysql_escape_string()ඔබට වේගයෙන් හොඳ වැළැක්වීමක් ලබා ගත හැකිය.

උදාහරණයක් වශයෙන්:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."'

mysql_escape_string - mysql_query හි භාවිතා කිරීම සඳහා නූලක් මග හැරේ

වැඩි වැළැක්වීම සඳහා, ඔබට අවසානයේ එකතු කළ හැකිය ...

wHERE 1=1   or  LIMIT 1

අවසාන වශයෙන් ඔබට ලැබෙන්නේ:

SELECT * FROM users WHERE name = '".mysql_escape_string($name_from_html_form)."' LIMIT 1

220

SQL ප්‍රකාශ වල විශේෂ අක්ෂර වලින් ගැලවීම සඳහා මාර්ගෝපදේශ කිහිපයක්.

MySQL භාවිතා නොකරන්න . මෙම දිගුව ඉවත් කර ඇත. භාවිතය mysqli හෝ PDO වෙනුවට.

MySQLi

නූලක ඇති විශේෂ අක්ෂර අතින් ගැලවීම සඳහා ඔබට mysqli_real_escape_string ශ්‍රිතය භාවිතා කළ හැකිය . MySqli_set_charset සමඟ නිවැරදි අක්ෂර කට්ටලය සකසා ඇත්නම් මිස ශ්‍රිතය නිසි ලෙස ක්‍රියා නොකරනු ඇත .

උදාහරණයක්:

$mysqli = new mysqli('host', 'user', 'password', 'database');
$mysqli->set_charset('charset');

$string = $mysqli->real_escape_string($string);
$mysqli->query("INSERT INTO table (column) VALUES ('$string')");

සකස් කළ ප්‍රකාශ සමඟ අගයන් ස්වයංක්‍රීයව ගැලවීම සඳහා, සුදුසු පරිවර්තනයක් සඳහා අනුරූප බන්ධන විචල්‍යයන් සඳහා වර්ග ලබා දිය යුතු mysqli_prepare සහ mysqli_stmt_bind_param භාවිතා කරන්න :

උදාහරණයක්:

$stmt = $mysqli->prepare("INSERT INTO table (column1, column2) VALUES (?,?)");

$stmt->bind_param("is", $integer, $string);

$stmt->execute();

ඔබ සූදානම් ප්‍රකාශ භාවිතා කරන්නේ නම් හෝ mysqli_real_escape_stringඔබ වැඩ කරන ආදාන දත්ත වර්ගය දැන සිටිය යුතුය.

එබැවින් ඔබ සූදානම් ප්‍රකාශයක් භාවිතා කරන්නේ නම්, ඔබ mysqli_stmt_bind_paramශ්‍රිතය සඳහා විචල්‍ය වර්ග නියම කළ යුතුය .

හා භාවිතය mysqli_real_escape_stringයන නම පවසනවා වැලක් විශේෂ චරිත පලා එන, එම නිසා එය පූර්ණ සංඛ්යා ආරක්ෂිත කිරීමට නොහැකි වනු ඇත ලෙස, සඳහා වේ. මෙම ශ්‍රිතයේ පරමාර්ථය වන්නේ SQL ප්‍රකාශ වල ඇති නූල් කැඩීම වැළැක්වීම සහ එය සිදුවිය හැකි දත්ත සමුදායට වන හානියයි. mysqli_real_escape_stringනිසියාකාරව භාවිතා කරන විට, විශේෂයෙන් සංයුක්ත වන විට ප්‍රයෝජනවත් කාර්යයකි sprintf.

උදාහරණයක්:

$string = "x' OR name LIKE '%John%";
$integer = '5 OR id != 0';

$query = sprintf( "SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string($string), $integer);

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 5

$integer = '99999999999999999999';
$query = sprintf("SELECT id, email, pass, name FROM members WHERE email ='%s' AND id = %d", $mysqli->real_escape_string($string), $integer);

echo $query;
// SELECT id, email, pass, name FROM members WHERE email ='x\' OR name LIKE \'%John%' AND id = 2147483647

3
ප්රශ්නය ඉතා සාමාන්ය ය. ඉහත විශිෂ්ට පිළිතුරු කිහිපයක්, නමුත් බොහෝමයක් යෝජනා කරන්නේ සූදානම් කළ ප්‍රකාශයන් ය. MySQLi async සූදානම් කළ ප්‍රකාශයන්ට සහය නොදක්වයි, එබැවින් මෙම තත්වය සඳහා ස්ප්රින්ට්ෆ් හොඳ විකල්පයක් ලෙස පෙනේ.
ඩස්ටින් ග්‍රැහැම්

183

මෙම ගැටළුවට ඇති සරල විකල්පය දත්ත සමුදාය තුළම සුදුසු අවසර ලබා දීමෙන් විසඳා ගත හැකිය. උදාහරණයක් ලෙස: ඔබ MySQL දත්ත සමුදායක් භාවිතා කරන්නේ නම් ටර්මිනලය හෝ ලබා දී ඇති UI හරහා දත්ත සමුදායට ඇතුළු වී මෙම විධානය අනුගමනය කරන්න:

 GRANT SELECT, INSERT, DELETE ON database TO username@'localhost' IDENTIFIED BY 'password';

මෙය පරිශීලකයාට නිශ්චිත විමසුමට පමණක් සීමා වීමට සීමා කරයි. මකාදැමීමේ අවසරය ඉවත් කරන්න, එවිට PHP පිටුවෙන් ඉවත් කළ විමසුමෙන් දත්ත කිසි විටෙකත් මකා නොදමනු ඇත. කළ යුතු දෙවන දෙය නම් වරප්‍රසාද ලබා ගැනීමයි, එවිට MySQL විසින් අවසර සහ යාවත්කාලීන කිරීම් නැවුම් කරයි.

FLUSH PRIVILEGES; 

ෆ්ලෂ් ගැන වැඩි විස්තර .

පරිශීලකයාට දැනට පවතින වරප්‍රසාද බැලීමට පහත විමසුම ක්‍රියාත්මක කරන්න.

select * from mysql.user where User='username';

GRANT ගැන තව දැනගන්න .


25
මෙම පිළිතුර අත්‍යවශ්‍යයෙන්ම වැරදියි , මන්ද එය එන්නත් වැළැක්වීම වැළැක්වීමට උපකාරී නොවන නමුත් ප්‍රතිවිපාක මෘදු කිරීමට උත්සාහ කරයි. නිෂ් .ලයි.
ඔබේ පොදු හැඟීම

1
හරි, එය විසඳුමක් සපයන්නේ නැත, නමුත් දේවල් වළක්වා ගැනීමට ඔබට පෙර කළ හැකි දේ එයයි.
අපූර්ව් නර්ලෙකර්

1
P අපර්ව් මගේ ඉලක්කය ඔබේ දත්ත ගබඩාවෙන් පුද්ගලික තොරතුරු කියවීම නම්, මකාදැමීමේ අවසරය නොමැති වීමෙන් කිසිවක් නැත.
ඇලෙක්ස් හොල්ස්ග්‍රෝව්

1
Lex ඇලෙක්ස්හෝල්ස්ග්‍රෝව්: එය පහසු කර ගන්න, මම යෝජනා කළේ ප්‍රතිවිපාක මෘදු කිරීම සඳහා හොඳ පුරුදු.
අපූර්ව් නර්ලෙකර්

2
P අපූර්ව් ඔබට “ප්‍රතිවිපාක මෘදු කිරීමට” අවශ්‍ය නැත, එයින් ආරක්ෂා වීමට හැකි සෑම දෙයක්ම කිරීමට ඔබට අවශ්‍යය. සාධාරණ වීමට නම්, නිවැරදි පරිශීලක ප්‍රවේශය සැකසීම වැදගත් ය, නමුත් ඇත්ත වශයෙන්ම OP ඉල්ලා සිටින්නේ එය නොවේ.
ඇලෙක්ස් හොල්ස්ග්‍රෝව්

176

බොහෝ ප්‍රයෝජනවත් පිළිතුරු සම්බන්ධයෙන්, මෙම ත්‍රෙඩ් එකට යම් වටිනාකමක් එක් කිරීමට මම බලාපොරොත්තු වෙමි.

SQL එන්නත් කිරීම යනු පරිශීලක යෙදවුම් හරහා කළ හැකි ප්‍රහාරයකි (පරිශීලකයෙකු විසින් පුරවා පසුව විමසුම් තුළ භාවිතා කරන යෙදවුම්). SQL එන්නත් කිරීමේ රටා නිවැරදි විමසුම් වාක්‍ය ඛණ්ඩයක් ලෙස අපට හැඳින්විය හැකිය: නරක හේතු සඳහා නරක විමසීම්, සහ ආරක්‍ෂිත මූලධර්ම තුනට (රහස්‍යභාවයට) බලපාන රහස් තොරතුරු (ප්‍රවේශ පාලනය මඟ හැරීම) ලබා ගැනීමට උත්සාහ කරන නරක පුද්ගලයෙක් සිටිය හැකි යැයි අපි උපකල්පනය කරමු. , අඛණ්ඩතාව සහ උපයෝජ්‍යතාව).

දැන්, අපගේ අදහස වන්නේ SQL එන්නත් කිරීමේ ප්‍රහාර වැනි ආරක්ෂක තර්ජන වැළැක්වීම, ප්‍රශ්නය ඇසීම (PHP භාවිතා කරමින් SQL එන්නත් කිරීමේ ප්‍රහාරයක් වළක්වා ගන්නේ කෙසේද), වඩාත් යථාර්ථවාදී වීම, දත්ත පෙරීම හෝ ආදාන දත්ත ඉවත් කිරීම යනු පරිශීලක ආදාන දත්ත ඇතුළත භාවිතා කරන විට ය. එවැනි විමසුමක්, PHP හෝ වෙනත් ක්‍රමලේඛන භාෂාවක් භාවිතා කිරීම එසේ නොවේ, නැතහොත් සූදානම් කළ ප්‍රකාශය හෝ දැනට SQL එන්නත් කිරීම වැළැක්වීමට සහාය වන වෙනත් මෙවලම් වැනි නවීන තාක්‍ෂණය භාවිතා කිරීමට වැඩි පිරිසක් නිර්දේශ කර ඇති පරිදි, මෙම මෙවලම් තවදුරටත් ලබා ගත නොහැකි යැයි සලකනවාද? ඔබගේ අයදුම්පත සුරක්ෂිත කරන්නේ කෙසේද?

SQL එන්නත් කිරීමට එරෙහි මගේ ප්‍රවේශය නම්: දත්ත සමුදායට යැවීමට පෙර පරිශීලක ආදාන දත්ත ඉවත් කිරීම (ඕනෑම විමසුමක් තුළ එය භාවිතා කිරීමට පෙර).

සඳහා දත්ත පෙරීම (අනාරක්ෂිත දත්ත ආරක්ෂිත දත්ත බවට පරිවර්තනය කිරීම)

PDO සහ MySQLi සලකා බලන්න ලබා ගත නොහැකි . ඔබගේ යෙදුම සුරක්ෂිත කරන්නේ කෙසේද? ඒවා භාවිතා කිරීමට ඔබ මට බල කරනවාද? PHP හැර වෙනත් භාෂා ගැන කුමක් කිව හැකිද? විශේෂිත භාෂාවක් සඳහා පමණක් නොව පුළුල් මායිම සඳහා භාවිතා කළ හැකි බැවින් සාමාන්‍ය අදහස් සැපයීමට මම කැමැත්තෙමි.

  1. SQL පරිශීලකයා (පරිශීලක වරප්‍රසාදය සීමා කිරීම): වඩාත් සුලභ SQL මෙහෙයුම් (SELECT, UPDATE, INSERT), එසේ නම්, UPDATE වරප්‍රසාදය අවශ්‍ය නොවන පරිශීලකයෙකුට ලබා දෙන්නේ ඇයි? උදාහරණයක් ලෙස, පිවිසුම් සහ සෙවුම් පිටු භාවිතා කරන්නේ SELECT පමණි, එසේ නම්, ඉහළ වරප්‍රසාද සහිත මෙම පිටුවල DB භාවිතා කරන්නන් භාවිතා කරන්නේ ඇයි?

රීතිය: සියලු වරප්‍රසාද සඳහා එක් දත්ත සමුදා පරිශීලකයෙකු නිර්මාණය නොකරන්න. සියලුම SQL මෙහෙයුම් සඳහා, ඔබට පහසුවෙන් භාවිතා කිරීම සඳහා පරිශීලක නාමයන් ලෙස (deluser, selectuser, updateuser) වැනි යෝජනා ක්‍රමයක් නිර්මාණය කළ හැකිය.

අවම වරප්‍රසාදයේ මූලධර්මය බලන්න .

  1. දත්ත පෙරීම: ඕනෑම විමසුම් පරිශීලක ආදානයක් තැනීමට පෙර, එය වලංගු කර පෙරහන් කළ යුතුය. ක්‍රමලේඛකයින් සඳහා, එක් එක් පරිශීලක ආදාන විචල්‍යයන් සඳහා සමහර ගුණාංග නිර්වචනය කිරීම වැදගත් ය: දත්ත වර්ගය, දත්ත රටාව සහ දත්ත දිග . (X සහ y) අතර සංඛ්‍යාවක් ඇති ක්ෂේත්‍රයක් නිශ්චිත රීතිය භාවිතයෙන් නිවැරදිව වලංගු කළ යුතු අතර, නූලක් (පෙළ) ඇති ක්ෂේත්‍රයක් සඳහා: රටාව එයයි, උදාහරණයක් ලෙස, පරිශීලක නාමයක අඩංගු විය යුත්තේ අක්ෂර කිහිපයක් පමණි, අපි [a-zA-Z0-9_-.] කියන්න. X සහ n (නිඛිල, x <= n) අතර දිග (x සහ n) අතර වෙනස් වේ. රීතිය: නිශ්චිත පෙරහන් නිර්මාණය කිරීම සහ වලංගු කිරීමේ නීති මට හොඳම භාවිතයන් වේ.

  2. වෙනත් මෙවලම් භාවිතා කරන්න: මෙන්න, සූදානම් කළ ප්‍රකාශයක් (පරාමිතිගත විමසුම) සහ ගබඩා කළ ක්‍රියා පටිපාටි පිළිබඳව මම ඔබ සමඟ එකඟ වෙමි. මෙහි ඇති අවාසි නම් මෙම ක්‍රම බොහෝ පරිශීලකයින් සඳහා නොපවතින උසස් කුසලතා අවශ්‍ය වේ. මෙහි මූලික අදහස වන්නේ SQL විමසුම සහ ඇතුළත භාවිතා වන දත්ත අතර වෙනස හඳුනා ගැනීමයි. මෙම ප්‍රවේශයන් දෙකම අනාරක්ෂිත දත්ත සමඟ පවා භාවිතා කළ හැකිය, මන්ද මෙහි පරිශීලක ආදාන දත්ත (ඕනෑම හෝ x = x) වැනි මුල් විමසුමට කිසිවක් එකතු නොකරයි.

වැඩි විස්තර සඳහා කරුණාකර කියවන්න OWASP SQL එන්නත් වැළැක්වීමේ වංචා පත්‍රය කියවන්න .

දැන්, ඔබ දියුණු පරිශීලකයෙක් නම්, ඔබ කැමති පරිදි මෙම ආරක්‍ෂාව භාවිතා කිරීම අරඹන්න, නමුත් ආරම්භකයින් සඳහා, ගබඩා කළ ක්‍රියා පටිපාටියක් ඉක්මණින් ක්‍රියාත්මක කර ප්‍රකාශය සකස් කිරීමට ඔවුන්ට නොහැකි නම්, ආදාන දත්ත ඔවුන්ට හැකි තරම් පෙරීම වඩා හොඳය.

අවසාන වශයෙන්, පරිශීලකයෙකු ඔහුගේ / ඇයගේ පරිශීලක නාමය ඇතුළත් කිරීම වෙනුවට මෙම පා text ය පහළින් යවන බව සලකා බලමු:

[1] UNION SELECT IF(SUBSTRING(Password,1,1)='2',BENCHMARK(100000,SHA1(1)),0) User,Password FROM mysql.user WHERE User = 'root'

මෙම ආදානය කිසිදු සූදානම් කළ ප්‍රකාශයක් සහ ගබඩා කළ ක්‍රියා පටිපාටියක් නොමැතිව කල්තියා පරීක්ෂා කළ හැකි නමුත් ආරක්ෂිත පැත්තේ සිටීම සඳහා, ඒවා භාවිතා කිරීම පරිශීලක දත්ත පෙරීම සහ වලංගු කිරීමෙන් පසුව ආරම්භ වේ.

අවසාන කරුණ නම් වැඩි උත්සාහයක් හා සංකීර්ණත්වයක් අවශ්‍ය වන අනපේක්ෂිත හැසිරීම් හඳුනා ගැනීමයි; සාමාන්‍ය වෙබ් යෙදුම් සඳහා එය නිර්දේශ නොකරයි.

ඉහත පරිශීලක ආදානයේ අනපේක්ෂිත හැසිරීම වන්නේ SELECT, UNION, IF, SUBSTRING, BENCHMARK, SHA සහ root ය. මෙම වචන අනාවරණය වූ පසු, ඔබට ආදානය වළක්වා ගත හැකිය.

යාවත්කාලීන කිරීම 1:

පරිශීලකයෙකු අදහස් දක්වමින් මෙම සටහන නිෂ් less ලයි, හරි! OWASP.ORG විසින් සපයන ලද දේ මෙන්න :

ප්‍රාථමික ආරක්ෂක:

විකල්ප # 1: සකස් කළ ප්‍රකාශ භාවිතා කිරීම (පරාමිතිගත විමසුම්)
විකල්පය # 2: ගබඩා කළ ක්‍රියා පටිපාටි භාවිතා කිරීම
විකල්පය # 3: සියලු පරිශීලක සැපයුම් ආදානයන් මග හැරීම

අතිරේක ආරක්ෂාවන්:

එසේම බලාත්මක කරන්න: අවම වරප්‍රසාදය
ද සිදු කරන්න: සුදු ලැයිස්තු ආදාන වලංගුකරණය

ඔබ දන්නා පරිදි, ලිපියක් ඉල්ලා සිටීම වලංගු තර්කයකින්, අවම වශයෙන් එක් සඳහනකින්වත් සහාය විය යුතුය! එසේ නොමැති නම්, එය ප්රහාරයක් සහ නරක ප්රකාශයක් ලෙස සැලකේ!

යාවත්කාලීන 2:

PHP අත්පොතෙන්, PHP: සකස් කළ ප්‍රකාශ - අත්පොත :

පැන යාම සහ SQL එන්නත් කිරීම

මායිම් විචල්‍යයන් සේවාදායකයා විසින් ස්වයංක්‍රීයව ගැලවී යනු ඇත. ක්‍රියාත්මක කිරීමට පෙර සේවාදායකයා ඔවුන්ගේ ගැලවී ගිය අගයන් සුදුසු ස්ථානවල ප්‍රකාශන අච්චුවට ඇතුළත් කරයි. සුදුසු පරිවර්තනයක් නිර්මාණය කිරීම සඳහා බැඳී ඇති විචල්‍ය වර්ගය සඳහා ඉඟියක් සේවාදායකයට ලබා දිය යුතුය. වැඩි විස්තර සඳහා mysqli_stmt_bind_param () ශ්‍රිතය බලන්න.

SQL එන්නත් කිරීම වැළැක්වීම සඳහා සේවාදායකය තුළ ඇති අගයන් ස්වයංක්‍රීයව ගැලවී යාම සමහර විට ආරක්ෂක අංගයක් ලෙස සැලකේ. ආදාන අගයන් නිවැරදිව ගැලවී ගියහොත් සකස් නොකළ ප්‍රකාශවලින් එකම මට්ටමේ ආරක්ෂාවක් ලබා ගත හැකිය.

යාවත්කාලීන 3:

සූදානම් කළ ප්‍රකාශයක් භාවිතා කරන විට PDO සහ MySQLi විසින් MySQL සේවාදායකයට විමසුම යවන්නේ කෙසේදැයි දැන ගැනීම සඳහා මම පරීක්ෂණ අවස්ථා නිර්මාණය කළෙමි:

PDO:

$user = "''1''"; // Malicious keyword
$sql = 'SELECT * FROM awa_user WHERE userame =:username';
$sth = $dbh->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute(array(':username' => $user));

විමසුම් ලොගය:

    189 Query SELECT * FROM awa_user WHERE userame ='\'\'1\'\''
    189 Quit

MySQLi:

$stmt = $mysqli->prepare("SELECT * FROM awa_user WHERE username =?")) {
$stmt->bind_param("s", $user);
$user = "''1''";
$stmt->execute();

විමසුම් ලොගය:

    188 Prepare   SELECT * FROM awa_user WHERE username =?
    188 Execute   SELECT * FROM awa_user WHERE username ='\'\'1\'\''
    188 Quit

සූදානම් කළ ප්‍රකාශයක් ද දත්ත වලින් ගැලවී යන බව පැහැදිලිය, වෙන කිසිවක් නැත.

ඉහත ප්‍රකාශයේ සඳහන් පරිදි,

SQL එන්නත් කිරීම වැළැක්වීම සඳහා සේවාදායකය තුළ ඇති අගයන් ස්වයංක්‍රීයව ගැලවී යාම සමහර විට ආරක්ෂක අංගයක් ලෙස සැලකේ. ආදාන අගයන් නිවැරදිව ගැලවී ගියහොත්, සූදානම් නොකළ ප්‍රකාශවලින් එකම මට්ටමේ ආරක්ෂාවක් ලබා ගත හැකිය

එබැවින්, intval()ඕනෑම විමසුමක් යැවීමට පෙර පූර්ණ සංඛ්‍යා සඳහා දත්ත වලංගු කිරීම හොඳ අදහසක් බව මෙයින් සනාථ වේ. ඊට අමතරව, විමසුම යැවීමට පෙර අනිෂ්ට පරිශීලක දත්ත වලක්වා ගැනීම නිවැරදි හා වලංගු ප්‍රවේශයකි .

කරුණාකර වැඩි විස්තර සඳහා මෙම ප්‍රශ්නය බලන්න: පීඩීඕ විසින් අමු විමසුම MySQL වෙත යවන අතර මිස්ක්ලි සූදානම් කළ විමසුම යවයි, දෙකම එකම ප්‍රති result ලය ලබා දෙයි

යොමුව:

  1. SQL එන්නත් වංචා පත්‍රය
  2. SQL එන්නත් කිරීම
  3. තොරතුරු ආරක්ෂාව
  4. ආරක්ෂක මූලධර්ම
  5. දත්ත වලංගුකරණය

175

ආරක්ෂක අවවාදයයි : මෙම පිළිතුර ආරක්ෂිත හොඳම භාවිතයන්ට අනුකූල නොවේ. SQL එන්නත් කිරීම වැළැක්වීම සඳහා පැන යාම ප්‍රමාණවත් නොවේ , ඒ වෙනුවට සූදානම් කළ ප්‍රකාශ භාවිතා කරන්න. ඔබේම අවදානමකින් පහත දක්වා ඇති උපාය මාර්ගය භාවිතා කරන්න. (එසේම, mysql_real_escape_string()PHP 7 හි ඉවත් කරන ලදි.)

අවලංගු කරන ලද අවවාදයයි : මෙම අවස්ථාවේදී mysql දිගුව ඉවත් කර ඇත. PDO දිගුව භාවිතා කිරීම අපි නිර්දේශ කරමු

මගේ වෙබ් යෙදුම SQL එන්නත් වලට ගොදුරු වීම වැළැක්වීමට මම ක්‍රම තුනක් භාවිතා කරමි.

  1. භාවිතය mysql_real_escape_string(), දී පෙර අර්ථ කාර්යය වන PHP , සහ, මෙම කේතය පහත අක්ෂර සඳහා backslashes එකතු කරන්න: \x00, \n, \r, \, ', "හා\x1a . SQL එන්නත් කිරීමේ අවස්ථාව අවම කිරීම සඳහා ආදාන අගයන් පරාමිතීන් ලෙස සම්මත කරන්න.
  2. වඩාත්ම දියුණු ක්‍රමය වන්නේ PDOs භාවිතා කිරීමයි.

මෙය ඔබට උපකාරී වනු ඇතැයි මම බලාපොරොත්තු වෙමි.

පහත විමසුම සලකා බලන්න:

$iId = mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

mysql_real_escape_string () මෙහි ආරක්ෂා නොවේ. ඔබේ විමසුම තුළ ඔබේ විචල්යයන් වටා තනි උපුටා දැක්වීම් ('') භාවිතා කරන්නේ නම් මෙයින් ඔබව ආරක්ෂා කරයි. මෙන්න මේ සඳහා විසඳුමක් පහත දැක්වේ:

$iId = (int) mysql_real_escape_string("1 OR 1=1"); $sSql = "SELECT * FROM table WHERE id = $iId";

මෙම ප්රශ්නය මේ පිළිබඳව හොඳ පිළිතුරු කිහිපයක් ඇත.

මම යෝජනා කරන්නේ, PDO භාවිතා කිරීම හොඳම විකල්පයයි.

සංස්කරණය කරන්න:

mysql_real_escape_string()PHP 5.5.0 අනුව ඉවත් කර ඇත. MySQL හෝ PDO භාවිතා කරන්න.

MySQL_real_escape_string () සඳහා විකල්පයක් වේ

string mysqli_real_escape_string ( mysqli $link , string $escapestr )

උදාහරණයක්:

$iId = $mysqli->real_escape_string("1 OR 1=1");
$mysqli->query("SELECT * FROM table WHERE id = $iId");

169

ඒ සරල ක්රමයක් වැනි PHP රාමුව භාවිතා කිරීමට වනු ඇත CodeIgniter හෝ Laravel ඔබ මේ එළඹීමේදී ගැන කරදර වෙන්න ඕනේ නැහැ එසේ ෙපරහන් වැනි සුරකින විශේෂාංග සහ ක්රියාකාරී වාර්තාගත ඇති.


7
මම හිතන්නේ ප්‍රශ්නයේ මුලික කාරණය වන්නේ එවැනි රාමුවක් භාවිතා නොකර මෙය සිදු කිරීමයි.
සන්කේ

147

අවවාදයයි: මෙම පිළිතුරේ විස්තර කර ඇති ප්‍රවේශය ඉතා නිශ්චිත අවස්ථාවන්ට පමණක් අදාළ වන අතර SQL එන්නත් කිරීමේ ප්‍රහාර පමණක් එන්නත් කිරීමේ හැකියාව මත පමණක් රඳා නොපවතින බැවින් එය ආරක්ෂිත නොවේ. X=Y .

ප්‍රහාරකයන් PHP හි $_GETවිචල්‍යය හරහා හෝ URL හි විමසුම් දාමය හරහා පෝරමයට අනවසරයෙන් ඇතුළු වීමට උත්සාහ කරන්නේ නම්, ඔවුන් ආරක්ෂිත නොවේ නම් ඔබට ඒවා අල්ලා ගත හැකිය.

RewriteCond %{QUERY_STRING} ([0-9]+)=([0-9]+)
RewriteRule ^(.*) ^/track.php

නිසා 1=1, 2=2, 1=2, 2=1,1+1=2 , ආදිය ... පහර ක SQL දත්ත ගබඩා කිරීම සඳහා පොදු ප්රශ්න වේ. සමහර විට එය බොහෝ අනවසර යෙදුම් භාවිතා කරයි.

නමුත් ඔබ ප්‍රවේශම් විය යුතුය, ඔබ ඔබේ වෙබ් අඩවියෙන් ආරක්ෂිත විමසුමක් නැවත ලිවිය යුතු නොවේ. ඉහත කේතය ඔබට නැවත ලිවීමට හෝ නැවත හරවා යැවීමට ඉඟියක් ලබා දෙයි (එය ඔබ මත රඳා පවතී) ප්‍රහාරකයාගේ IP ලිපිනය ගබඩා කරන පිටුවකට අනවසරයෙන් විශේෂිත ගතික විමසුම් දාමයක් හෝ ඔවුන්ගේ කුකීස්, ඉතිහාසය, බ්‍රව්සරය හෝ වෙනත් සංවේදී තොරතුරු, එබැවින් ඔබට ඔවුන්ගේ ගිණුම තහනම් කිරීමෙන් හෝ බලධාරීන් සම්බන්ධ කර ගැනීමෙන් පසුව ඔවුන් සමඟ ගනුදෙනු කළ හැකිය.


මොකද 1-1=0වෙන්නේ? :)
රොප්ලි ඇන්ඩ්‍රෙස්

@ RápliAndrás යම් ආකාරයක ([0-9\-]+)=([0-9]+).
සර්ව

127

PHP සහ MySQL සඳහා බොහෝ පිළිතුරු ඇත , නමුත් SQL එන්නත් කිරීම වැළැක්වීම සඳහා මෙන්ම oci8 ධාවක නිතිපතා භාවිතා කිරීම සඳහා PHP සහ Oracle සඳහා කේත මෙහි ඇත :

$conn = oci_connect($username, $password, $connection_string);
$stmt = oci_parse($conn, 'UPDATE table SET field = :xx WHERE ID = 123');
oci_bind_by_name($stmt, ':xx', $fieldval);
oci_execute($stmt);

කරුණාකර oci_bind_by_name පරාමිතීන් පැහැදිලි කරන්න.
ජහන්සෙබ් අවන්

127

හොඳ අදහසක් වන්නේ Idiorm වැනි වස්තු-සම්බන්ධතා සිතියමක් භාවිතා කිරීමයි :

$user = ORM::for_table('user')
->where_equal('username', 'j4mie')
->find_one();

$user->first_name = 'Jamie';
$user->save();

$tweets = ORM::for_table('tweet')
    ->select('tweet.*')
    ->join('user', array(
        'user.id', '=', 'tweet.user_id'
    ))
    ->where_equal('user.username', 'j4mie')
    ->find_many();

foreach ($tweets as $tweet) {
    echo $tweet->text;
}

එය ඔබව SQL එන්නත් වලින් පමණක් නොව සින්ටැක්ස් දෝෂ වලින්ද ගලවා ගනී! එකවර බහුවිධ ප්‍රති results ල සහ බහු සම්බන්ධතා සඳහා ක්‍රියාවන් පෙරීම හෝ ක්‍රියාවට නැංවීම සඳහා ක්‍රම දාමයක් සහිත ආකෘති එකතු කිරීමට ද එය සහාය වේ.


124

අවලංගු කරන ලද අවවාදයයි: මෙම පිළිතුරේ නියැදි කේතය (ප්‍රශ්නයේ නියැදි කේතය වැනි) PHP හි MySQLදිගුව භාවිතා කරයි , එය PHP 5.5.0 හි ඉවත් කර සම්පූර්ණයෙන්ම PHP 7.0.0 වලින් ඉවත් කරන ලදි.

ආරක්ෂක අනතුරු ඇඟවීම : මෙම පිළිතුර ආරක්ෂිත හොඳම භාවිතයන්ට අනුකූල නොවේ. SQL එන්නත් කිරීම වැළැක්වීම සඳහා පැන යාම ප්‍රමාණවත් නොවේ , ඒ වෙනුවට සූදානම් කළ ප්‍රකාශ භාවිතා කරන්න. ඔබේම අවදානමකින් පහත දක්වා ඇති උපාය මාර්ගය භාවිතා කරන්න. (එසේම, mysql_real_escape_string()PHP 7 හි ඉවත් කරන ලදි.)

භාවිතා PDO හා mysqli SQL එන්නත් වැළැක්වීම සඳහා හොඳ ක්රමයක් වන්නේ, නමුත් ඔබ ඇත්තටම MySQL කාර්යයන් හා විමසුම් සමග වැඩ කිරීමට අවශ්ය නම්, එය භාවිතා කිරීමට වඩා හොඳ වනු ඇත

mysql_real_escape_string

$unsafe_variable = mysql_real_escape_string($_POST['user_input']);

මෙය වලක්වා ගැනීම සඳහා තවත් හැකියාවන් ඇත: හඳුනා ගැනීම වැනි - ආදානය නූලක්, අංකයක්, වර්‍ගයක් හෝ අරාවක් නම්, මෙය හඳුනා ගැනීම සඳහා බොහෝ අභ්‍යන්තර කාර්යයන් ඇත. ආදාන දත්ත පරීක්ෂා කිරීම සඳහා මෙම කාර්යයන් භාවිතා කිරීම වඩා හොඳය.

is_string

$unsafe_variable = (is_string($_POST['user_input']) ? $_POST['user_input'] : '');

is_numeric

$unsafe_variable = (is_numeric($_POST['user_input']) ? $_POST['user_input'] : '');

ආදාන දත්ත පරීක්ෂා කිරීම සඳහා එම කාර්යයන් භාවිතා කිරීම වඩා හොඳය mysql_real_escape_string.


10
Is_string () සමඟ $ _POST අරාවෙහි සාමාජිකයන් පරික්ෂා කිරීමේ කිසිදු තේරුමක් නැත
ඔබේ පොදු හැඟීම

21
අවවාදයයි! mysql_real_escape_string() වැරදිසහගත නොවේ .
ఎగ్යාල්

10
mysql_real_escape_stringදැන් අතහැර දමා ඇත, එබැවින් එය තවදුරටත් ශක්‍ය විකල්පයක් නොවේ. එය අනාගතයේදී PHP වලින් ඉවත් කෙරේ. PHP හෝ MySQL පිරිස නිර්දේශ කරන දේ වෙත ගමන් කිරීම වඩාත් සුදුසුය.
jww

2
තේමාව: පරිශීලකයා ඉදිරිපත් කළ දත්ත විශ්වාස නොකරන්න. ඔබ අපේක්ෂා කරන ඕනෑම දෙයක් විශේෂ අක්ෂර හෝ බූලියන් තර්කනය සහිත කසළ දත්ත වේ, එය ඔබ ක්‍රියාත්මක කරන SQL විමසුමේ කොටසක් බවට පත්විය යුතුය. S _POST අගයන් SQL කොටසක් නොව දත්ත ලෙස පමණක් තබා ගන්න.
බිමල් පූඩෙල්

88

මම මීට වසර කිහිපයකට පෙර මෙම කුඩා කාර්යය ලියා ඇත:

function sqlvprintf($query, $args)
{
    global $DB_LINK;
    $ctr = 0;
    ensureConnection(); // Connect to database if not connected already.
    $values = array();
    foreach ($args as $value)
    {
        if (is_string($value))
        {
            $value = "'" . mysqli_real_escape_string($DB_LINK, $value) . "'";
        }
        else if (is_null($value))
        {
            $value = 'NULL';
        }
        else if (!is_int($value) && !is_float($value))
        {
            die('Only numeric, string, array and NULL arguments allowed in a query. Argument '.($ctr+1).' is not a basic type, it\'s type is '. gettype($value). '.');
        }
        $values[] = $value;
        $ctr++;
    }
    $query = preg_replace_callback(
        '/{(\\d+)}/', 
        function($match) use ($values)
        {
            if (isset($values[$match[1]]))
            {
                return $values[$match[1]];
            }
            else
            {
                return $match[0];
            }
        },
        $query
    );
    return $query;
}

function runEscapedQuery($preparedQuery /*, ...*/)
{
    $params = array_slice(func_get_args(), 1);
    $results = runQuery(sqlvprintf($preparedQuery, $params)); // Run query and fetch results.   
    return $results;
}

මෙය එක් ලයිනර් C # -ish String එකක ප්‍රකාශ ක්‍රියාත්මක කිරීමට ඉඩ දෙයි.

runEscapedQuery("INSERT INTO Whatever (id, foo, bar) VALUES ({0}, {1}, {2})", $numericVar, $stringVar1, $stringVar2);

විචල්ය වර්ගය සැලකිල්ලට ගනිමින් එය ගැලවී යයි. ඔබ වගුව, තීරු නම් පරාමිතිකරණය කිරීමට උත්සාහ කරන්නේ නම්, එය වලංගු නොවන සින්ටැක්ස් එකක් වන සෑම නූලක්ම උපුටා දැක්වීම් වලට ඇතුළත් කරන බැවින් එය අසාර්ථක වනු ඇත.

සුරක්ෂිතතා යාවත්කාලීන කිරීම: පෙර str_replaceඅනුවාදය පරිශීලක දත්ත වලට {#} ටෝකන එකතු කිරීමෙන් එන්නත් කිරීමට ඉඩ දී ඇත. preg_replace_callbackආදේශනයේ මෙම ටෝකන අඩංගු නම් මෙම අනුවාදය ගැටළු ඇති නොකරයි.

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.