현재 구형 브라우저를 사용 중입니다.

일부 또는 모든 기능이 작동하지 않을 수 있습니다.
브라우저를 최신으로 업데이트하여 주십시오.

Google Chrome 다운로드

프로그래밍 프로그래밍 PHP의 MySQL/MariaDB 이스케이프 함수 축약하기 mysqlesc();

    2  
(수정 )

함수의 용도

PHP에서 MySQL에 삽입을 할 때 ,

쿼리 에러, 또는 이것을 역이용한 삽입 공격(SQL Injection) 을 방지하기 위해

이 함수를 사용한다.

 

SQL 삽입 공격?

정상 쿼리:

SELECT * FROM tablename WHERE id='myid'

"tablename이란 테이블에서 myid라는 ID를 찾아라."

 

실험

삽입 공격 쿼리를 넣어보자:

ID 란에 ' OR '1'='1 를 삽입한다.

방어(이스케이프) 처리가 되지 않은 쿼리라면 이렇게 작동할 것이다.

SELECT * FROM tablename WHERE id=' ' OR '1'='1 '

"tablename이란 테이블에서 ID 또는 1=1을 찾아라."

1=1이라면 무조건 TRUE값, 즉 모든 ID를 찾는다는 것이다. 

이것은 비밀번호, 혹은 그것이 암호화되어 빼내지 못하더라도, 이메일, 전화번호 등을 빼내어 노출할 수 있는 명령어이다. 

요즘 난무하고 있는 보이스피싱이나 스팸 메일이 이렇게 노출된 신상정보를 바탕으로 오는 것이다.

(여기 이 사이트는 Google 로그인으로 받은 고유번호만 저장하는 시스템이라 이메일이나 전화번호가 노출될 일은 없다.

개인정보를 다뤄야 한다면, 가능하면 Google이나 Kakao 같은 대기업 로그인 시스템을 사용하도록 하자.)

 

 

삽입 공격 방어(이스케이프)

다음 함수로 방어 처리를 하면:

$mysqli->real_escape_string($str);

ID 란에 ' OR '1'='1 를 삽입할 시 다음과 같이 방어가 된다.

문자열을 여는 문자와 닫는 문자인 따옴표에 역슬래시 \ 가 붙어 

따옴표는 전부 일반 문자 따옴표로 취급된다.

SELECT * FROM tablename WHERE id=' \' OR \'1\'=\'1 '

"tablename이란 테이블에서 ID가 ' OR '1'='1인 것을 찾아라."

 

PHP에서 이렇게 활용이 가능하다.

$mysqli->query(
	"INSERT INTO mytable
	(data1, data2, data3)
	VALUES
	('".@$mysqli->real_escape_string($str1)."',
	'".@$mysqli->real_escape_string($str2)."',
	'".@$mysqli->real_escape_string($str3)."');"
);	

여기서 @골뱅이는 함수 안에서 에러가 발생하여도 그냥 에러를 알리지 않고 null 을 반환하겠다는 뜻이다.

 

하지만, 함수명이 길어, 코드가 옆으로 길어지면, 가독성이 매우 떨어진다!

이 함수 이름의 길이가 너무 길어 가독성을 위해 이 함수로 줄여 쓴다.

SQL 이스케이프를 하는 김에, 좌우공백 제거, 그리고 樂(락), 樂(악) 처럼 문자 자체는 같지만, 코드상으로는 다른 글자를 하나로 통합하는 작업도 병행한다.

 

mysqlesc($str);

 

function mysqlesc($str,$trim=true,$nfkd=false){
    global $mysqli;

    if ($trim == true){
        // 앞뒤 공백만 자르기.
        $str = trim($str);
    }
    
    if(method_exists('normalizer','normalize')) {
        
        if ($nfkd == true){
            // 초성검색 용이를 위해 nfkd 변환, 평소에는 nfc 변환 
            $str = Normalizer::normalize($str,Normalizer::NFKD);
        } else {
            // 일반적인 유니코드 평준화. 한자 樂(락), 樂(악) 등을 한개의 코드로 합쳐줘 검색에 최적화.
            $str = Normalizer::normalize($str,Normalizer::NFC);
        }
    }
    
    return $mysqli->real_escape_string($str);
}

 

이러면 코드는 다음과 같아진다:

$mysqli->query(
	"INSERT INTO mytable
	(data1, data2, data3)
	VALUES
	('".@$mysqlesc($str1)."',
	'".@$mysqlesc($str2)."',
	'".@$mysqlesc($str3)."');"
);	

 

 

  



    프로그래밍 프로그래밍 프로그래밍

    프로그래밍 게시판입니다.

    매니저 부매니저