2016-08-04 15 views
0

지난 몇 일간 내 웹 사이트에서 MySQL 주입 공격이 몇 번 발생하여 내 사용자 데이터베이스에 손상을 입혔습니다 (대부분 고칠 수 있음). 내 웹 사이트가 사용자 ID와 새 사용자를 기록했기 때문에 나는 이것을 발견 :Google에서 SQL 삽입 방지

999999.9 /**/uNiOn/**/aLl /**/sElEcT 0x39313335313 

(I 전혀 위의 쿼리를 할 수 있도록 설계되었습니다 모르겠어요 내 사용자 테이블의 모든 행을 변경 관련된 실제 피해. 모든 사용자가 최근에 로그인 한 것처럼 보이게합니다. 기괴하지만 내 로그가 선택한 것보다 더 많은 공격을했다고 제안합니다.)

이것은 Google 로그인 버튼을 통해 수행되었습니다. 내 로그인 단추는 자바 스크립트를 사용하여 Google과 통신 한 다음 GET을 통해 반환 된 사용자 ID를 내 다음 페이지로 보냅니다 (여기서 로그인하거나 새 계정을 등록할지 여부를 결정 함). 주입되는이 GET 쿼리입니다.

SQL 쿼리를 만들기 위해 MySQLi를 사용합니다. 저는 PHP에 능숙하며 수년 동안 MySQL을 사용해 왔지만 아마추어 개발자였습니다. 이 방법을 고수하는 방법에 대한 조언을 해주시면 감사하겠습니다. 고맙습니다.

편집 :

여기의 요청에 따라, 내 코드의 예 :하지 보호 문자열 연결 또는 교체를 사용하는 경우

$db = new mysqli('localhost', 'XXX', 'XXX', 'seatingplan'); 

if($db->connect_errno > 0){ 
    die('Unable to connect to database [' . $db->connect_error . ']'); 
} 

$sql = <<<SQL 
    SELECT * 
    FROM `users` 
    WHERE `userid` = '$userid' 
SQL; 

if(!$result = $db->query($sql)){ 
    die('There was an error running the query [' . $db->error . ']'); 
} 


while($row = $result->fetch_assoc()){ 
    $useridcheck = $row['userid'] ; 
    $existingImageUrl = $row['image'] ; 
} 

$lastlogin = date("Y-m-d H:i:s") ; 

$sql = <<<SQL 
    UPDATE `users` 
    SET `lastlogin` = '$lastlogin', 
    `logins` = `logins` + 1 
    WHERE `userid` = '$userid' 
SQL; 


if(!$result = $db->query($sql)){ 
    die('There was an error running the query [' . $db->error . ']'); 
} 
+0

하나의 아이디어를 대체하는 안전한 방법을 제공를 사용하여 바인딩 Google 사용자 ID처럼 보이게하려면 GET의 유효성을 검사하십시오. 이 말은 합리적인 것처럼 들리니? – Rob

+0

우리는 이것에 대해 아무 말도하지 않는 코드가 필요합니다. –

+0

@NorbertvanNobelen 죄송합니다, 예제를 추가했습니다 – Rob

답변

3

SQL 주입이 발생합니다. MySQLi와 (더 나은) PDO는 문자열 교체가 안전한 방식으로 수행되도록주의하여 이러한 문제를 방지 할 수있는 옵션을 제공합니다. 안전은 문자열의 데이터가 악의적 인 코드가 실행되지 않도록 이스케이프 처리된다는 것을 의미합니다.

위의 코드에서 문제 코드는 다음과 같습니다 개발자가 그 값을 확인하지 않은 경우 여기 $lastLogin$userid에서

$sql = <<<SQL 
    UPDATE `users` 
    SET `lastlogin` = '$lastlogin', 
    `logins` = `logins` + 1 
    WHERE `userid` = '$userid' 
SQL; 

는 악용 될 수 있습니다. PHP의 PDO와

쿼리는 다음과 같이 보일 것이다 :

$sql = "UPDATE `users` 
    SET `lastlogin` = :lastlogin, 
    `logins` = `logins` + 1 
    WHERE `userid` = :userid" 

:lastlogin:userid는 PDO 당신의 매개 변수 I가 될 수 했어

+0

mysqli는 이것을 할 수 있지만 named placeholder를 지원하지 않으므로'?'를 사용해야한다. PDO는이 기능으로 인해 훨씬 ​​더 친숙하며, PDO는 MySQL과 관련이 없습니다. – tadman

+0

@tadman 업데이트 할 코드가 많아서 MySQLi의 변경 사항을 줄이기 위해 고수 할 것입니다. 그러나, 나는 아직도이 코드를 사용하여 결과를'$ row [ 'what']'형식으로 반환 할 수 있는지 알 수 없다. while ($ row = $ result-> fetch_assoc()) { $ useridcheck = $ row [ 'userid']; $ existingImageUrl = $ row [ 'image']; }' – Rob

+0

매개 변수화 된 msqli를 사용하여 읽은 모든 가이드는'$ statement-> bind_result (blah)'를 사용하여 결과를 바인드하도록 알려줍니다. 다시 말하지만, 큰 코드 변경을 초래할 수 있으므로이 작업을 피하는 것이 좋습니다. – Rob