2013-07-26 3 views
-3

나는 아주 처음으로 PHP mysql 응용 프로그램으로 아래 스크립트를 작성했습니다. 나는 스스로 가르치고 코드는 의도 한대로 작동합니다. 내 호스트는 SQL 주입 공격에 취약 할 수 있다고 생각하지만 왜 더 좋게 만들지, 왜 바꿔야 할지를 알 수 없습니다. 나는 그것이 가능할만큼 깨끗하지 않다고 확신하지만 누군가가 어떤 제안이나 통찰력을 가지고 있다면 분명히 감사 할 것입니다.PHP Sql injection vulnerable

<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 삽입을 방지하는 기사가 많이 있습니다. Why go go it;) – 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

문제는 코드 매개 변수 $ 카테고리가 GET 또는 POST 매개 변수에서 읽을 경우

$sql = "SELECT category, company, address, city, state, zip, 
      phone, web, addescription, image 
     FROM Members 
     WHERE category LIKE '$category'"; 
$result=mysql_query($sql); 

에서 때라도 부분, 그것은 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을 더 잘 사용해야합니다. 내가 PDO 연결하는 방법과 함께 조회하는 방법의 구현을 보여주지

$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가 15 년 전에 수행 된 방법이며 사람들이 이런 식으로 일하는 것을 그만 둘 때가되었습니다. – tadman

+1

내 게시물에서 언급 한 것처럼 절차 적 방법이 폄하됩니다. 나는 PDO의 사용법을 추가했다. –

+0

올바르게 수행하는 방법의 예가 훨씬 향상되었습니다. – tadman

1

: 같은

OOP의 방법 (권장)이 보일 것이다. 여기 간다! 먼저 데이터베이스 자격 증명으로 연결 변수를 만듭니다. 이 연결은 $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 변수를 사용합니다. 우리가 여러 행을 반환 할 수있는 데이터를 SELECT 보내고있어 때문에

$statement = $db->prepare($query); 
$result = $statement->execute($query_params); 

(당신이 범주 내에서 여러 행이 가정), 우리는 차지해야합니다.

$rows = $statement->fetchAll(); 

을 그리고 지금 당신은 foreach 문을 이용하여 데이터베이스 테이블의 각 $row 내에서 열 머리글을 참조 수 : 명령문과 같이 리턴하는 행을 잡아.

$citiesArray = array(); 
foreach($rows as $row){ 
    if(isset($row['city'])){ 
     $citiesArray[] = $row['city']; 
    } 
} 

희망하는 사람!

1

사용자를 절대 신뢰하지 않는 황금률을 기억하십시오. 원시 사용자 입력을 가져 와서 데이터베이스에 삽입하지 마십시오. 보안 문제로 인해 스스로를 열어 두었을 가능성이 있습니다.

코드가 정상적으로 보입니다. 그러나 MySQL은 PHP 5.5.0부터는 더 이상 사용되지 않으며, 더 많은 보안을 제공하는 MySQLi 또는 PDO 확장자를 사용해야합니다.

어쩌면 그게 당신 호스트가 그런 말을 한 이유 일지 모르지만 코드에 대한 빠른 견해에서 그것은 나에게 잘 보였다.

건배.