2012-11-02 3 views
2

사용자가 PHP 용 Evernote SDK를 사용하여 Evernote 계정에 로그인 할 수있게 해주는 간단한 PHP 응용 프로그램 (MyApp)을 작성했습니다. 하지만, 내 응용 프로그램에서, 나는이 작업을 수행 할 수 :쿠키에서 PHP 로그인 - 일부 SQL 주입 방지 예

  1. 사용자가 Evernote에 로그인을 승인
  2. 의 MyApp 등 # 1의 requestToken, requestTokenSecret를 수신
  3. 의 MyApp의 쿠키에 저장 # 2 및 $_SESSION
  4. 나중에 사용자가 내 사이트로 돌아 오면 MyApp가 쿠키를 통해 쿠키를 기록합니다.

예, 쿠키 기반 로그인은 안전하지 않습니다. 그러나 내 응용 프로그램은 중요한 데이터를 저장하지 않습니다. 가장 간단한 방법은 무엇입니까?

//if cookie 
if (isset($_COOKIE['requestToken'])) { 
    $m = new mysqli(MYSQL_SERVER, MYSQL_USER, MYSQL_PASS, MYSQL_DB); 
    $q = "SELECT uid FROM users WHERE token={$_COOKIE['requestToken']} and secret={$_COOKIE['requestTokenSecret']}"; 

    // cookie matches db? 
    if ($result = $m->query($q)) { 
     $_SESSION['login']=TRUE; 
     $result->close(); 
} 
    else // no match 
     $_SESSION['login']=FALSE; 
} 
else { //no cookie - create 
    if (EverNoteLogin()) { 
     $year=time()+86400*365; //86400 = 1 day 
     setcookie('requestToken',$_SESSION['requestToken'],$year); 
     setcookie('requestTokenSecret',$_SESSION['requestTokenSecret'],$year); 
    } 
} 

이 개선 사항 버전 ​​

//if cookie 
if (isset($_COOKIE['requestToken'])) { 
    //check db 
    $m = new mysqli(MYSQL_SERVER, MYSQL_USER, MYSQL_PASS, MYSQL_DB); 
    $s=$m->prepare("SELECT uid FROM user WHERE token=? AND secret=?"); 
    $s->bind_param('ss',$rt, $rs); 
    $rt=$_COOKIE['requestToken']; 
    $rs=$_COOKIE['requestTokenSecret']; 
    $s->execute(); 
    $s->store_result(); 
    $n=$s->num_rows; 
    //match db? 
    if ($n) { 
     if ($n==1) { // 1 match 
       $s->bind_result($uid); 
       $_SESSION['uid']=$uid; 
       $_SESSION['login']=TRUE; 
      } 
     else 
      $_SESSION['login']=FALSE; // >1 match not good 
    }else 
     $_SESSION['login']=FALSE; 
} 
else { //no cookie - create 
    if (EverNoteLogin()) { 
     $year=time()+86400*365; //86400 = 1 day 
     setcookie('requestToken',$_SESSION['requestToken'],$year); 
     setcookie('requestTokenSecret',$_SESSION['requestTokenSecret'],$year); 
    } 
} 
+3

이것은 SQL 삽입에 취약합니다. '$ _COOKIE'는 사용자 데이터이며 신뢰할 수 없습니다. MySQLi를 사용하고 있기 때문에 이것은'query()'호출보다는 준비된 문장이어야한다. –

+0

먼저 변수에 $ _COOKIE 정보를 저장 한 다음이를 이스케이프합니다. $ token = mysql_real_escape_string ($ _ COOKIE [ 'requestToken']); –

+1

MySQL 웹 사이트 Juapo2 (http://php.net/manual/en/function.mysql-real-escape-string.php) : "이 확장의 사용은 권장하지 않으며 대신 MySQLi 또는 PDO_MySQL 확장을 사용해야합니다 . " –

답변

0

내가 준비된 문을 사용하여 스크립트의 버전은 SQL 주입 관점에서 적절한 보이는 생각 제안 : 여기 내 시도이다.

쿠키를 안전한 쿠키 (따라서 https 연결 필요)로 설정하고 http 전용 쿠키 (따라서 자바 스크립트에 대한 액세스를 차단하는 것)로 설정하는 것이 좋습니다.

0

bind_param을 사용하면 표시하는 경우 SQL 주입에 대한 효과적인 방어 수단입니다. 이제는 쿠키의 값이 무엇인지는 중요하지 않으며 SQL 문의 의미를 변경할 수 없습니다.

SQL 쿼리의 매개 변수 자리 표시 자 항상은 단일 스칼라 값으로 작동합니다. 값에 SQL 구문이 포함 된 경우 문제가되지 않으며 쿼리에 인용 된 문자열을 넣은 것처럼 모든 특수 문자가 완벽하게 이스케이프 처리 된 것처럼 작동합니다. SQL 인젝션 취약점을 피하기 위해 완전히 안전합니다.

내 프레젠테이션 SQL Injection Myths and Fallacies 또는 내 서적 SQL Antipatterns: Avoiding the Pitfalls of Database Programming에서 SQL 주입에 대해 자세히 읽을 수 있습니다.

그러나 안전한 것은 아니지만 인증 자격 증명을 일반 텍스트로 쿠키에 저장하는 것입니다. 그렇게하지 마십시오.
도 참조 Is it secure to store passwords in cookies? 또는 How to store cookies containing sensitive data securely in PHP?

+0

동의. 내가 틀린 것이 아니라면, oAuth requestToken (쿠키 내)은 oauthVerifier 없이는 정의에 의해 "일시적"이며 어떤 쿠키에도 기록되지 않습니다. 따라서 쿠키 데이터는 본질적으로 이미 임의적입니다. –

+0

그런데 왜 임시 토큰에 대해 1 년 만료를 설정합니까? ;-) –