PDO 주입 방지 원리 분석 및 PDO 사용 주의사항 총화

8843 단어 PDO주입 방지
본 고 는 PDO 주입 방지 원리 분석 및 PDO 사용 에 대한 주의사항 을 상세 하 게 설명 하여 여러분 께 참고 하도록 제공 합 니 다.구체 적 인 분석 은 다음 과 같다.
우 리 는 모두 PDO 를 합 리 적 으로 정확하게 사용 하면 SQL 주입 의 발생 을 기본적으로 방지 할 수 있다 는 것 을 알 고 있다.본 고 는 주로 다음 과 같은 두 가지 질문 에 대답한다.
my sql 이 아 닌 PDO 를 왜 사용 합 니까?connect?
왜 PDO 가 주입 을 막 을 수 있 습 니까?
PDO 를 사용 하여 주입 을 방지 할 때 무엇 을 특히 주의해 야 합 니까?
 
1.왜 PDO 를 우선 사용 해 야 합 니까?
PHP 매 뉴 얼 에 명확 하 게 나 와 있 습 니 다.
Prepared statements and stored procedures
Many of the more mature databases support the concept of prepared statements. What are they? They can be thought of as a kind of compiled template for the SQL that an application wants to run, that can be customized using variable parameters. Prepared statements offer two major benefits:
The query only needs to be parsed (or prepared) once, but can be executed multiple times with the same or different parameters. When the query is prepared, the database will analyze, compile and optimize its plan for executing the query. For complex queries this process can take up enough time that it will noticeably slow down an application if there is a need to repeat the same query many times with different parameters. By using a prepared statement the application avoids repeating the analyze/compile/optimize cycle. This means that prepared statements use fewer resources and thus run faster.
 
The parameters to prepared statements don't need to be quoted; the driver automatically handles this. If an application exclusively uses prepared statements, the developer can be sure that no SQL injection will occur (however, if other portions of the query are being built up with unescaped input, SQL injection is still possible).
 
즉,PDO 의 prepare 방식 을 사용 하 는데 주로 같은 SQL 템 플 릿 조회 성능 을 향상 시 키 고 SQL 주입 을 막는다.
이와 함께 PHP 매 뉴 얼 에는 경고 메시지 가 나 왔 다.
Prior to PHP 5.3.6, this element was silently ignored. The same behaviour can be partly replicated with the PDO::MYSQL_ATTR_INIT_COMMAND driver option, as the following example shows.
Warning
The method in the below example can only be used with character sets that share the same lower 7 bit representation as ASCII, such as ISO-8859-1 and UTF-8. Users using character sets that have different representations (such as UTF-16 or Big5) must use the charset option provided in PHP 5.3.6 and later versions.
 
PHP 5.3.6 및 이전 버 전에 서 는 DSN 의 charset 정 의 를 지원 하지 않 고 PDO::MYSQL 을 사용 해 야 한 다 는 뜻 이다.ATTR_INIT_COMMAND 는 초기 SQL,즉 우리 가 자주 사용 하 는 set names gbk 명령 을 설정 합 니 다.
 
저 는 일부 프로그램 을 보고 addslashes 를 사용 하여 주입 을 방지 하 는 목적 을 달성 하려 고 시도 하고 있 습 니 다.이런 사실 문제 가 더 많은 지 모 르 겠 습 니 다.자세 한 내용 은 보 세 요https://www.jb51.net/article/49205.htm
데이터베이스 조 회 를 실행 하기 전에 SQL 의 select,union,...와 같은 키 워드 를 제거 하 는 방법 도 있다.이런 방법 은 분명히 매우 잘못된 처리 방식 이다.만약 에 제출 한 본문 에 the students's union 이 포함 되 어 있다 면 교체 한 후에 원래 의 내용 을 바 꾸 고 무고 한 사람 을 마구 죽 이 는 것 은 바람 직 하지 않다.
 
2.왜 PDO 는 SQL 주입 을 방지 할 수 있 습 니까?
먼저 아래 의 PHP 코드 를 보십시오:

$pdo = new PDO("mysql:host=192.168.0.1;dbname=test;charset=utf8","root");
$st = $pdo->prepare("select * from info where id =? and name = ?");
 
$id = 21;
$name = 'zhangsan';
$st->bindParam(1,$id);
$st->bindParam(2,$name);
 
$st->execute();
$st->fetchAll();
?>
 
환경 은 다음 과 같 습 니 다.
PHP 5.4.7
Mysql 프로 토 콜 버 전 10
MySQL Server 5.5.27
 
php 와 my sql server 통신 의 세부 사항 을 철저히 파악 하기 위해 저 는 특히 wireshark 스냅 백 을 사용 하여 연 구 했 습 니 다.wireshak 를 설치 한 후에 저 희 는 여과 조건 을 tcp.port==3306 으로 설정 합 니 다.다음 그림:
 
 
 
이렇게 하면 my sql 3306 포트 와 의 통신 데이터 만 표시 하여 불필요 한 방 해 를 피한다.
특히 wireshak 는 wincap 구동 을 기반 으로 로 컬 링 인터페이스 에 대한 검색 을 지원 하지 않 습 니 다.(즉,phop 으로 로 컬 my sql 을 연결 하 는 방법 은 검색 할 수 없습니다)다른 기계(브리지 네트워크 의 가상 컴퓨터 도 가능 합 니 다)의 MySQL 을 연결 하여 테스트 하 십시오.
 
그리고 우리 의 PHP 프로그램 을 실행 합 니 다.검색 결 과 는 다음 과 같 습 니 다.우 리 는 PHP 가 단순히 SQL 을 MySQL Server 에 직접 보 내 는 것 임 을 발 견 했 습 니 다.
 
 
 
사실,이것 은 우리 가 평소에 사용 하 는 mysql 과real_escape_string 문자열 을 전의 로 연결 하고 SQL 문 구 를 연결 하 는 것 은 차이 가 없습니다.(PDO 로 컬 드라이브 로 전 의 를 완성 하 는 것 일 뿐)이러한 상황 에서 SQL 주입 을 초래 할 수 있 습 니 다.즉,phop 로 컬 에서 Pdo prepare 의 my sql 을 호출 하 는 것 입 니 다.real_escape_string 은 query 를 조작 합 니 다.로 컬 단일 바이트 문자 집합 을 사용 합 니 다.다 중 바이트 인 코딩 변 수 를 전달 할 때 SQL 주입 구멍(phop 5.3.6 이전 버 전의 문제 중 하나 입 니 다.PDO 를 사용 할 때 phop 5.3.6+로 업그레이드 하고 DSN 문자열 에 charset 를 지정 하 는 이 유 를 설명 합 니 다.
 
php 5.3.6 이전 버 전에 대해 다음 코드 는 SQL 주입 문 제 를 일 으 킬 수 있 습 니 다.
$pdo->query('SET NAMES GBK'); 
$var = chr(0xbf) . chr(0x27) . " OR 1=1 /*";
$query = "SELECT * FROM info WHERE name = ?";
$stmt = $pdo->prepare($query);
$stmt->execute(array($var));
 
원인 은 위의 분석 과 일치한다.
 
정확 한 전 의 는 my sql Server 에 문자 집합 을 지정 하고 변 수 를 MySQL Server 에 보 내 문자 에 따라 전 의 를 완성 해 야 합 니 다.
 
그렇다면 어떻게 해야만 PHP 로 컬 전의 가 MySQL Server 에 의 해 전달 되 는 것 을 금지 할 수 있 습 니까?
PDO 에는 PDO:ATTR 라 는 인자 가 있 습 니 다.EMULATE_PREPARES 는 PHP 로 컬 시 뮬 레이 션 prepare 를 사용 할 지 여 부 를 표시 합 니 다.이 매개 변 수 는 기본 값 을 알 수 없습니다.그리고 우리 가 방금 캡 처 분석 결 과 를 보면 phop 5.3.6+기본 값 은 로 컬 변 수 를 사용 하여 SQL 로 연결 하여 MySQL Server 에 보 낸 것 입 니 다.우 리 는 이 값 을 false 로 설정 하고 효 과 를 시험 합 니 다.예 를 들 어 다음 코드 와 같 습 니 다.

$pdo = new PDO("mysql:host=192.168.0.1;dbname=test;","root");
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);//
 
$st = $pdo->prepare("select * from info where id =? and name = ?");
$id = 21;
$name = 'zhangsan';
 
$st->bindParam(1,$id);
$st->bindParam(2,$name);
$st->execute();
$st->fetchAll();
?>
 
프로그램 을 실행 하고 wireshark 캡 처 분석 을 통 해 얻 은 결 과 는 다음 과 같 습 니 다.


보이 시 나 요?이것 이 바로 신기 한 점 입 니 다.이번 PHP 는 SQL 템 플 릿 과 변 수 를 두 번 으로 나 누 어 MySQL 에 보 낸 것 입 니 다.MySQL 에서 변수의 전의 처 리 를 완 료 했 습 니 다.변수 와 SQL 템 플 릿 이 두 번 으로 나 누 어 보 낸 이상 SQL 주입 에 문제 가 없 지만 DSN 에서 charset 속성 을 지정 해 야 합 니 다.예 를 들 어:
$pdo = new PDO('mysql:host=localhost;dbname=test;charset=utf8', 'root');
 
이렇게 하면 SQL 주입 문 제 를 근본적으로 근절 할 수 있다.만약 당신 이 이것 에 대해 잘 모른다 면,메 일 로 보 낼 수 있 습 니 다[email protected]함께 토론 하 다.
 
3.PDO 사용 주의사항
상기 몇 가 지 를 알 게 된 후에 우 리 는 PDO 를 사용 하여 SQL 주입 을 근절 하 는 몇 가지 주의사항 을 정리 할 수 있다.
1.  pp 는 5.3.6+로 업그레이드 되 었 으 며,생산 환경 은 pp 5.3.9+phop 5.4+로 업그레이드 하 는 것 을 강력 히 권장 합 니 다.phop 5.3.8 에는 치 명 적 인 hash 충돌 구멍 이 있 습 니 다.
 
2.php 5.3.6+를 사용 하면 PDO 의 DSN 에서 charset 속성 을 지정 하 십시오.
3.PHP 5.3.6 및 이전 버 전 을 사용 했다 면 PDO::ATTR 설정EMULATE_PREPARES 인 자 는 false(즉 MySQL 에서 변수 처리)이 고 php 5.3.6 이상 버 전 은 이 문 제 를 처 리 했 습 니 다.로 컬 아 날로 그 prepare 를 사용 하 든 my sql server 를 호출 하 는 prepare 를 사용 하 든 모두 가능 합 니 다.DSN 에서 charset 를 지정 하 는 것 은 무효 이 며,set names의 실행 은 필수 입 니 다.
 
4.PHP 5.3.6 및 이전 버 전 을 사용 했다 면 Yii 프레임 워 크 는 기본적으로 ATTR 을 설정 하지 않 았 기 때 문 입 니 다.EMULATE_PREPARES 의 값 입 니 다.데이터베이스 설정 파일 에 emulatePrepare 의 값 을 false 로 지정 하 십시오.
 
질문 이 있 습 니 다.DSN 에서 charset 를 지정 하면 set names를 실행 해 야 합 니까?
네,아 낄 수 없어 요.set names는 사실 두 가지 역할 을 합 니 다.
A.  my sql server,클 라 이언 트(PHP 프로그램)가 제출 한 인 코딩 이 무엇 인지 알려 줍 니 다.
B.  my sql server 에 게 클 라 이언 트 가 필요 로 하 는 결과 의 인 코딩 이 무엇 인지 알려 줍 니 다.
즉,데이터 시트 에 gbk 문자 집합 을 사용 하고 PHP 프로그램 이 UTF-8 인 코딩 을 사용 하면 검색 을 실행 하기 전에 set names utf 8 을 실행 하고 my sql server 에 정확 한 인 코딩 을 알려 주면 됩 니 다.프로그램 에서 인 코딩 하지 않 아 도 됩 니 다.이렇게 하면 우 리 는 utf-8 인 코딩 으로 my sql server 에 제출 하여 조회 한 결과 도 utf-8 인 코딩 이 될 것 입 니 다.프로그램의 인 코딩 전환 문 제 를 줄 이 고 의문 을 갖 지 마 세 요.이렇게 하면 혼란 이 생기 지 않 습 니 다.
 
그렇다면 DSN 에서 charset 를 지정 하 는 역할 은 무엇 입 니까?다만 PDO 에 게 로 컬 구동 전의 시 지정 한 문자 집합(my sql server 통신 문자 집합 을 설정 하 는 것 이 아 닙 니 다)을 사용 하고 my sql server 통신 문자 집합 을 설정 하 며 set names명령 을 사용 해 야 합 니 다.
 
나 는 새로운 프로젝트 들 이 왜 PDO 를 사용 하지 않 고 전통 적 인 my sql 을 사용 하 는 지 정말 이해 가 되 지 않 는 다.XXX 함수 라 이브 러 리 는?만약 에 PDO 를 정확하게 사용 하면 SQL 주입 을 근본적으로 차단 할 수 있 습 니 다.저 는 각 회사 의 기술 담당자,일 선 기술 연구 개발 자 에 게 이 문 제 를 중시 하고 가능 한 한 PDO 를 사용 하여 프로젝트 의 진도 와 안전 품질 을 가속 화 할 것 을 강력 히 건의 합 니 다.
 
더 이상 SQL 을 만들어 서 필터 함수 라 이브 러 리 에 주입 하려 고 하지 마 세 요.
본 논문 에서 말 한 것 이 여러분 의 PHP 프로 그래 밍 에 도움 이 되 기 를 바 랍 니 다.

좋은 웹페이지 즐겨찾기