2013-07-26 89 views
-3

我寫了下面的腳本作爲我有史以來第一個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) 
?> 
+3

你是否檢查了這篇文章(http://stackoverflow.com/questions/60174/how-to-prevent-sql-injection-in-php)?它幾乎涵蓋了它。 –

+1

有很多文章來防止SQL注入。爲什麼不穀歌;) – tonoslfx

+0

請注意,'mysql_xxx()'函數已被棄用,並被認爲已過時多年。如果你從使用它們的教程中學到了東西,那麼你幾乎肯定會做錯事情,因爲足夠老的推薦使用這些函數的教程也會足夠長,以至於不能再使用其他不好的做法。我建議找到一個網站有更多最新的教程來學習。 – Spudley

回答

3

不推薦使用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); 
0

的問題是在你的代碼

$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開始已經被棄用了。您最好使用MysqliPDO

的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(); 
+0

這是十五年前PHP如何完成的,是時候人們停止這樣做了。 – tadman

+1

就像我在我的文章中提到的:程序化的方式被剝奪了。我已經添加到PDO的使用。 –

+0

用正確的方法做了很多改進。 – tadman

1

我帶你去一個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']; 
    } 
} 

希望有幫助!

1

只要記住永不相信用戶的黃金法則。切勿接受任何原始用戶輸入並將其插入到數據庫中,因爲您有可能因安全問題而自行放棄。

你的代碼似乎很好。但是請注意,從PHP 5.5.0開始不推薦使用MySQL,而應該使用MySQLiPDO擴展,從而提供更高的安全性。

也許這就是你的主機說這樣的事情的原因,但從快速瀏覽你的代碼看起來對我來說很好。

乾杯。