PHP 에는 DB 연결 라이브러리가 대표적으로 두가지가 많이 쓰이는데 mysqli , PDO 가있다.
이번에 PHP src 엔진저장소의 이슈를 보다가 sql 인젝션 관련 글이 올라왔다.
https://github.com/php/php-src/issues/19777
Pdo MySQL prepared sqli · Issue #19777 · php/php-src
Description https://slcyber.io/assetnote-security-research-center/a-novel-technique-for-sql-injection-in-pdos-prepared-statements/ Maybe someone of authors can solve this problem PHP Version Php ma...
github.com
해당이슈의 링크를 보면 올해 어느 해킹대회에서 SQL 인젝션 취약점을 찾았고 상세한 내용이 나와있다.
Novel SQL Injection Technique in PDO Prepared Statements
Searchlight Cyber's Security Research team details a Novel Technique for SQL Injection in PDO's Prepared Statements.
slcyber.io
해당글의 취약점에 관해 나와있는데 요지만 보면
<?php
$dsn = "mysql:host=127.0.0.1;dbname=demo";
$pdo = new PDO($dsn, 'root', '');
$col = '`' . str_replace('`', '``', $_GET['col']) . '`';
$stmt = $pdo->prepare("SELECT $col FROM fruit WHERE name = ?");
$stmt->execute([$_GET['name']]);
$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach($data as $v) {
echo join(' : ', $v) . PHP_EOL;
}
이런 코드가 있다고 했을때
col 을 입력받으므로 해커가 null 바이트 \0 와 원하는 문자열 'x' 를 넣음
SELECT `'x'#\0` FROM fruit WHERE name = ?
널바이트 뒤엣것은 무시하는것을 이용하는것이다.
PHP 의 PDO 의 바인딩 쿼리를 만드는 파서 버그로 인해
바인딩 쿼리를 사용하더라도 해커가 null 바이트 코드를 넣을수 있다면 SQL 인젝션이 가능하다는것이다.
PDO 에는
PDO::ATTR_EMULATE_PREPARES
이라는 속성을 지정할수있는데 기본값은 true 라서 켜져있는 상태다
? , :문자 등 바인딩 대상을 DB 에서 하는게 아니라 PHP 에서 하게되고
PHP 8.3 까지는 해당 파서가 mysql 기준으로만 되어있을 뿐더러 위에서 해커들이 찾은 취약점까지있다는것이다.
해당 보고서에 따르면 이를 막을 방법은 두가지 인데
1. PDO::ATTR_EMULATE_PREPARES = false 로 지정한다 - php 엔진이 업뎃될때까지 최선
pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
나온대로 패치하고나니 for update 쿼리에서 오류가 나오는데
같은이름의 바인딩을 할수없다고 해서 이름을 바꾸어 주니 모두 정상동작하였다.
2 . 널바이트를 필터링한다. 라고 나와있다.
부랴부랴 널바이트 필터링을 하기위해 아래 함수를 만들어 sql 실행하는 함수에 넣었다.
// 파라미터 타입을 쓰면 좋겠지만 php 5 등 구버전에서도 호환되게 is_string 씁니다.
function sanitize_null_bytes($input) {
if (is_string($input)) {
return str_replace(["\x00", "\0", '%00'], '', $input);
}
return $input;
}
orm 이나 db 쿼리 빌더를 사용하지않아서 쿼리문자열을 실행하는 함수안에서 실행되게 했다.
어차피 널바이트를 검색하는 사람도 없을뿐더러 그런 행위부터가 의심스럽기에
권고하는 사항대로 쿼리 문자열통으로 치환하기로 했다.
쿼리빌더나 orm 사용하는 프로젝트의 경우 입력값에서 필터링 하면 되겠다.
PHP 8.4 부터는 PDO 쿼리파서가 각 DBMS 별로 맞춤형으로 제작하는 RFC 가 통과되었지만
이것도 취약점이 패치되기전까지는 동일하다.
어서 취약점이 패치되면 좋겠고 지금 보안 패치를 받는 PHP 버전은 8.4~ 8.1 만해당되서
옛날버전들은 저렇게 하는 수밖에 없겠다.
'PHP' 카테고리의 다른 글
| PHP 에 jemalloc 적용하기 (0) | 2026.01.14 |
|---|---|
| PHP 비동기 i/o 공식지원 요구를 보며... (0) | 2025.10.17 |
| 그누보드5 성능 이슈 겪은 것들 정리 (1) | 2025.07.01 |
| PHP 로 된 프로젝트는 왜 유독히... (0) | 2025.02.17 |
| 라라벨의 파사드 찬성/반대 측면 (0) | 2023.06.08 |