KWONKYU

PHP 시큐어 코딩 #3

May 14th, 2019
380
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.21 KB | None | 0 0
  1. PHP의 주요 역할은 다양한 데이터 소스와 사용자간의 연결 통로를 만드는 일. 여러 데이터베이스와 연결할 수 있으며 이때 데이터베이스에서 가져오는 데이터들 역시 입력으로 보고 필터링해야 한다. 데이터를 지나치게 신뢰하여 심층 방어의 원칙을 위반하는 것보다는 충분한 안전 장치를 설정하는 것이 바람직하다.
  2.  
  3. #1.인증 정보
  4. 데이터베이스 인증 정보(유저 이름, 비밀번호, mysql_connect 등)가 담긴 파일이 웹서버 아래에 위치한다면, 이를테면 /www 아래에 존재한다면 이는 직접 접근으로 데이터가 평문으로 노출(아파치 기본 데이터타입은 text/plain)될 수 있기 때문에 웹서버 외부에 위치시키거나 액세스 인증 정보를 담고 있는 파일에 대한 접근을 거부(아파치 설정)함으로써 예방할 수 있다.
  5.  
  6. #2.SQL Injection
  7. 이 공격이 성공하려면 PHP 코드에 두 가지 취약점이 동시에 존재해야되는데 바로 응용프로그램에 입력하는 데이터를 필터링하지 못하는 것과 데이터베이스에 보내는 데이터를 이스케이프하지 못하는 것이다. 공격자는 데이터베이스의 스키마에 접근할 수 없기 때문에 약간의 추측이 필요하다.이를 추측할 때 만약 이스케이핑이 적절히 이뤄지지 않는다면 입력 폼에 따옴표(')나 쌍따옴표(")를 찍어서 일부러 에러를 내보는 방법도 있다. 예를들어 다음과 같은 쿼리가 있다고 해보자.
  8.  
  9. $sql = "SELECT * FROM users WHERE username = '{$_POST['username']}' AND password = '$password_hash'";
  10.  
  11. 이때 username으로 따옴표 하나를 전달한다면 쿼리의 username은 따옴표 세 개로 바뀌게 된다(''').
  12.  
  13. $sql = "SELECT * FROM users WHERE username = ''' AND password = '$password_hash'";
  14.  
  15. 이는 구문 에러를 일으키며 mysql_error() 같은 함수가 사용되었을 경우 오류문이 출력되어 쿼리가 노출될 수 있으며 공격자는 이를 통해 데이터베이스의 구조를 추측할 수 있다. 이 시점에서 공격자는 "myuser' or 'foo' = 'foo' --" 같은 username을 사용하여 쿼리를 망가뜨릴 수 있다.
  16.  
  17. $sql = "SELECT * FROM users WHERE username = 'myuser' or 'foo' = 'foo' -- AND password = '$password_hash'";
  18.  
  19. SQL문에서 주석은 항상 '--'으로 시작한다. 즉 뒤의 password를 비교하는 구문은 해석되지 않으며 공격자는 유효한 사용자 이름이나 비밀번호를 몰라도 로그인이 가능하게 된다. 혹은 유효한 사용자 이름으로 대체할 수도 있다.
  20.  
  21. 물론 이는 mysql_real_escape_string() 함수나 addSlashes() 등 여러 함수를 통한 입력 필터링 및 출력 이스케이프를 통해 충분히 예방할 수 있다. 바운드 파라미터(bound parameter)나 위치 지정자(placeholder)를 사용하는 데이터베이스를 사용하면 위협이 더욱 줄어든다.
  22.  
  23. #3.Session(Cookie)
  24. HTTP는 Stateless 프로토콜이기 때문에 서버는 클라이언트를 구별할 수 없다. 이는 이 사용자가 장바구니에 물건이 있는지, 이미 로그인을 했는지 등을 파악하는데에 까다로운 문제가 되지만 이는 '쿠키'를 사용하여 보완할 수 있다. 쿠키는 HTTP 프로토콜을 확장한 것으로 정확하게 얘기하면 Set-Cookie 응답 헤더와 Cookie 요청 헤더로 구분되어진다.
  25.  
  26. 먼저 클라이언트가 HTTP Request를 보내면 서버의 Reply는 HTTP Reply 및 Set-Cookie 헤더를 포함시켜 보낸다. 이후 클라이언트는 HTTP Request 시마다 쿠키를 포함시켜 전송하고 서버는 이를 이용하여 클라이언트를 식별, 적절한 Reply를 전송할 수 있게 된다. 헤더에 cookie, query string에 PHPSESSID가 있는지 확인.
  27.  
  28. 세션 관리는 각 클라이언트별로 고유하게 부여된 식별 정보와 데이터를 함께 관리하여 상태를 유지하고자 하는 것에서 고안되었다. 이는 세션 데이터 저장소에 보관되며 Request마다 업데이트 된다. 고유 식별자로 저장소의 특정 레코드를 구별하기 때문에 세션 식별자, 세션 ID라고 부른다.
  29.  
  30. PHP에서는 session_start() 함수 등으로 세션을 관리할 수 있는데 현재 요청에 포함된 세션 ID가 있다면 해당 세션 데이터를 읽어들여 $_SESSION 배열에 저장하고 그렇지 않으면 세션 ID를 생성, 저장소에 레코드를 업데이트한다.
  31.  
  32. 이때 쿠키를 탈취당한다면 사용자가 위험에 노출될 수 있다. 만약 세션ID를 쿠키에 저장한다면 세션 하이재킹 등도 가능하기 때문에 큰 위협이 된다.
  33. 쿠키가 노출되는 일반적인 유형은 XSS, 즉 스크립트를 사용하는 것이 일반적인 경우다. 세션 데이터는 개인 정보나 민감한 데이터로 구성되어 있기 때문에 노출을 피해야 한다(그럴 가능성은 낮다). SSL을 사용하는 것 또한 하나의 방법이다. 세션 데이터 저장소 자체의 보안을 걱정한다면 session_set_save_handler() 등을 사용해서 자신만의 세션 저장소를 작성, 데이터 저장 시 암호화 및 해독하는 함수를 작성함으로써 적절한 키 없이는 세션 데이터를 읽어들이지 못하도록 암호화시킬 수 있다.
  34.  
  35. 세션ID를 숨길 수만 있다면 세션 하이재킹의 위협은 존재하지 않지만.. 공격자는 유효한 세션ID를 얻기 위해 주로 세 가지 방법을 사용한다.
  36. - 예측: PHP는 세션ID를 랜덤하게 생성하기 때문에 이는 큰 위협이 되지 못함.
  37.  
  38. - 캡처: 이것이 일반적인 공격이 될 것이다. 모니터링, 스니핑 등을 통해 헤더에 담겨있는 세션ID를 얻어 적용하는 것.
  39.  
  40. - 고정: 공격자가 선택한 세션ID를 사용해서 희생자를 속이는 공격. 간단한 예로 링크를 사용하거나 프로토콜 레벨에서 방향 재지정을 하는 것.
  41. 세션 주입이라고 하는 편이 더 어울릴 수도 있다. 이는 공격자가 미리 세션을 준비해 둔 후 타겟이 해당 세션을 가진 웹사이트로 접속하도록 유도하여 타겟과 공격자가 같은 세션을 가지도록 함정을 파는 것이다. 자바스크립트로 document.cookie를 조작하거나 준비된 세션ID가 포함된 URL을 클릭하도록 유도하거나 메타 태그를 이용하여 주입(쿠키 몬스터)하는 방법들이 있다.
  42.  
  43. 세션 고정(Fixation) 방법은 타겟과 공격자가 같은 세션을 가지게 된다는 것이 핵심이며 이는 세션 재생성(PHP 함수 session_regenerate_id(). $_SESSION 배열 원소가 isset 되지 않았을 때 재생성)으로 방지할 수 있다. 세션ID가 일정하게 고정된다면 발생하는 취약점이므로 로그인 시마다 새로운 세션 ID를 발행하거나 타임아웃을 설정하는 것도 하나의 방법이다. 혹은 IP를 체크하여 멀티세션을 방지하는 것도 방법이 된다.
  44.  
  45. 이 방법은 세션 하이재킹에 사용할 수 있는 세션ID를 얻기 위한 수단이다. 즉 합법적인 수단으로 얻을 수 있는 것보다 높은 권한을 가진 세션을 하이재킹할 때 유용한 방법이다. 모든 페이지에서 세션ID를 재생성하면 방어효과가 좀 더 높아지겠지만 추천하지 않는다. 일반, 정상적인 사용자도 브라우저 히스토리 등을 통해 돌아갈 때 이전 페이지로 돌아간다면 그 페이지에 있는 링크들은 더 이상 존재하지 않는 세션ID를 가리키게 되는 등의 문제가 있기 때문에...
  46.  
  47. #4.세션 하이재킹
  48. 세션 하이재킹은 공격자가 사용자의 세션에 액세스하기 위해 사용하는 모든 방법을 지칭하는데 이를 막기 위해서는 공격자가 다른 사람인 척 가장하는 것을 방어하는 것이 중요하다. 이의 핵심은 신분 확인을 강화하는 것인데 세션ID 뿐 아니라 HTTP 헤더 내부의 정보들을 활용할 수도 있다(User-Agent 등). 만약 User-Agent를 살펴봤더니 이전에는 Firefox로 접근하던 사용자가 갑자기 Internet Explorer로 접근한다면? 하지만 실제로 사용자가 그렇게 접속했을 수도 있으므로(False Alarm) 비밀번호 입력을 다시 받는 것 또한 하나의 방법이다.
Advertisement
Add Comment
Please, Sign In to add comment