PHP Sql注入漏洞
我写了下面的脚本作为我有史以来第一个php mysql应用程序。我自学成才,代码按预期工作。我的主机认为它可能容易受到sql注入攻击,但无法告诉我为什么或者应该改变什么以使其更好。我敢肯定,它不是那么干净,但如果任何人有任何建议或见解,我一定会很感激。PHP Sql注入漏洞
<form method="post" action="search.php?go" id="searchform">
<?php
$db=mysql_connect ("server", "*", "*") or die ('I cannot connect to the database because: ' . mysql_error());
$mydb=mysql_select_db("*");
$category_sql="SELECT distinct category FROM Members";
$category_Options="";
$category_result=mysql_query($category_sql) or die ('Error: '.mysql_error());
while ($row=mysql_fetch_array($category_result)) {
$category=$row["category"];
$category_Options.="<OPTION VALUE=\"$category\">".$category.'</option>';
}
?>
<p>
<SELECT NAME="category"><OPTION VALUE=0>Choose<?=$category_Options?></SELECT>
</p>
<input name="submit" "id="submit" type="submit" value="submit" />
</form>
<?php
if(isset($_POST['submit'])){
if(isset($_GET['go'])){
$category=$_POST['category'];
$category=mysql_real_escape_string($category);
$sql="SELECT category, company, address, city, state, zip, phone, web, addescription, image
FROM Members
WHERE category LIKE '$category'";
$result=mysql_query($sql);
while($row=mysql_fetch_array($result)){
$category2=$row["category"];
$company=$row["company"];
$address=$row["address"];
$city=$row["city"];
$state=$row["state"];
$zip=$row["zip"];
$phone=$row["phone"];
$web = $row["web"];
$addescription = $row["addescription"];
$image = $row["image"];
echo "<blockquote>";
if(@file_get_contents($image))
{
echo "<img src='".$image ."' class='image'/>\n";
}
else
{
}
echo "<p>\n";
echo "</br>".$category2 . "\n";
echo "</br><b>".$company . "</b>\n";
echo "</br>".$address . "\n";
echo "</br>".$city . ", ".$state. " ".$zip . "\n";
echo "</br>".$phone . "\n";
echo "</br><a href=http://".$web .">".$web ."</a>\n";
echo "</br>".$addescription . "\n";
echo "</br><a href=http://www.printfriendly.com style=color:#6D9F00;text-decoration:none; class=printfriendly onclick=window.print();return false; title=Printer Friendly and PDF><img style=border:none; src=http://cdn.printfriendly.com/pf-button.gif alt=Print Friendly and PDF/></a>\n";
echo "</p>";
echo "</blockquote>"
;
}
}
else{
echo "<p>Please select a Category</p>";
}
}
mysql_close($db)
?>
不推荐使用MySQL函数。使用MySQLi函数和预准备语句是防止SQL注入攻击的更好方法。
$stmt = $mysqli->prepare('SELECT category, company, address, city, state, zip, phone, web, addescription, image FROM Members WHERE category LIKE ?');
$stmt->bind_param('s', $category);
的问题是在你的代码
$sql = "SELECT category, company, address, city, state, zip,
phone, web, addescription, image
FROM Members
WHERE category LIKE '$category'";
$result=mysql_query($sql);
如果参数$类别从GET或POST参数读取follwoing部分,它应该是escaped:
$sql = "SELECT category, company, address, city, state, zip,
phone, web, addescription, image
FROM Members
WHERE category LIKE '" . mysql_real_escape_string($category) . "';";
如果你这样做,变量不能用于SQL Injection
顺便说一下(就像Matthew Johnson所说的那样),程序化的mysql扩展从PHP 5.5开始已经被弃用了。您最好使用Mysqli或PDO。
的OOP方式(强烈推荐)看起来像:
$pdo = new PDO($dsn, $user, $password, $options);
$statement = $pdo->prepareStatement(
"SELECT category, company, address,
city, state, zip, phone, web,
addescription, image
FROM Members
WHERE category LIKE :category;");
$statement->bindParam(':category', $category, PDO::PARAM_STR);
$statement->execute();
$categories = $statement->fetchAll();
我带你去一个PDO连接,以及如何与它来查询的执行。它在这里! 首先我们用你的数据库凭证创建连接变量。我们将在$db
中存储此连接。
$username = "root";
$password = "";
$host = "localhost";
$dbname = "my_database";
$options = array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8');
try{
$db = new PDO("mysql:host={$host};dbname={$dbname};charset=utf8"; $username, $password, $options);
}catch(PDOException $ex){
die("Failed to connect: ".$ex->getMessage());
}
现在,你必须存储在一个$db
PDO连接,您可以查询通过。如果你不使用PHP 5.4,你可能想要考虑magic quotes,所以记住这一点。
否则,创建您的查询语句,像这样..
$query = "SELECT category, company, address, city, state, zip, phone, web, addescription, image FROM Members WHERE category LIKE :category"
之后,你想从$_POST['category']
变量的值绑定(或$category
因为你创建的)的参数:category
。做到这一点,像这样:
$query_params = array(':category' => $category);
最后,现在你有语句和参数,使用以前创建$db
变量来准备和执行该语句。
$statement = $db->prepare($query);
$result = $statement->execute($query_params);
由于我们SELECT
荷兰国际集团的数据在可能返回多行(假设你有一个类别中的多个行),我们需要考虑这一点。抓住该语句返回类似这样的行:
$rows = $statement->fetchAll();
现在,你可以通过使用一个foreach语句是指列标题的数据库表的各$row
内。
$citiesArray = array();
foreach($rows as $row){
if(isset($row['city'])){
$citiesArray[] = $row['city'];
}
}
希望有帮助!
你是否检查了这篇文章(http://stackoverflow.com/questions/60174/how-to-prevent-sql-injection-in-php)?它几乎涵盖了它。 –
有很多文章来防止SQL注入。为什么不谷歌;) – tonoslfx
请注意,'mysql_xxx()'函数已被弃用,并被认为已过时多年。如果你从使用它们的教程中学到了东西,那么你几乎肯定会做错事情,因为足够老的推荐使用这些函数的教程也会足够长,以至于不能再使用其他不好的做法。我建议找到一个网站有更多最新的教程来学习。 – Spudley