PHP 암호화 방법 분석

들어가며

웹 서버와 데이터베이스를 관리하던 도중, PHP 언어를 다루는 일도 적지 않았다. 특히 데이터베이스 Query 작성에서 SQL Injection 공격에 대한 위험성도 인지하였다. 이에 따라 특별하지 않은 SQL Query 부분을 변경하려고 한다. 또한 PHP 암호화 방법도 알아보려고 한다.
이와 함께 PHP 코드 자체를 암호화하는 방법을 찾아보던 중, 온라인으로 PHP 코드를 암호화해 주는 사이트를 찾을 수 있었다. 여기에서는 간단한 PHP 코드의 암호화 방법을 알아보고, 이를 분석해 본다.

PHP 암호화 예제

위 링크에서 PHP 코드를 입력하면 Base64 인코딩 문구와 함께 암호화 결과를 제공한다. 여기에서는 인코딩만 제공하며, 디코딩은 제공하지 않는다. 설명을 보면 불필요한 구문을 제거하고 암호화 과정을 거친다고 한다. PHP 암호화 예시는 아래와 같다.

PHP
/* Input */
<?php
$x = 2018 ** 4;
echo "DDManager\n$x\n";
PHP
/* Output */
<?php eval(gzinflate(base64_decode('BcHJcoIwAADQz1GHAzvidHpgryyyC/TSARIiBYI2yPb1fQ/OZX9Ee4ubvpzgsSoJlIQfAOsRwOOhr0WQjN6iKDoSlr1FHINqOSEIyKOmJs4W6GaokGuxkr8eOJAnYUXZPCovQGLwyPLu6ym++Iw13ufb+TLGlMSweYFlYZRJkXqXbb59jx4Tp9h079UQMwutdVo0s0gbFZt9NU6jxw4GauLV3leC5KK1f7mw2GTv3uRxDnwDmozgYsdn9MHnrMaOsnwGJktXDV3FgbY80yF6oKwwcLaGPZJ2EiVdQMlsbXpJ7/vz5kHRWPzNzXILUPNG+VkN0hQ99LWauzBcWxRytKH65u39mLqpWJzL6ohsbmNGn3aeSgSi9zJerEF9I+PqBpNAWzOtkM/D6XT6+Ac=')));

여기에서 eval 함수를 사용하였다. 문자열로 표현된 코드를 실행하는 함수인데, JavaScript 등에서는 보안 상의 위험을 이유로 절대 사용하지 말라고 한다. 제3자가 악의적인 코드를 실행할 수도 있기 때문이다.

PHP 암호화 과정 분석

이제 암호화 예제의 출력을 분석해본다. 먼저 eval 함수 내부를 출력해보면 아래와 같다.

PHP
/* Decode : Step 1 */
eval(gzinflate(base64_decode('lc5dToMwAADg4wzig20gc8Tsgd8oCBTKyPDFQAsIYxsrldKe3sQb+J3ga9d60no13Lqp5q3W1Eu7N79oS+601XYn84o8sYUM9yvNZoM0SUnFLVbmS0w/CkCRv1gCoAJ1qfKfDSKndBTMcMHTg8YiJj2QYy8MVfXSXdOEeF04LnKO0DmO2GfJRWXvdF1/bf/bSPCwpUmRhgWYEnWxQlg6zsRTkP+81cFMTlOOvyMe5EwOyLWXGd+vy+OWcdUUghDxbvkQQxigQ2/EBOFNuhtktYwK9xK51XJn0Dtz3+T4sDl8nwGmBugEILPt4/Gv/As=')));

1단계의 출력에서 eval 함수 내부를 다시 출력해보면 아래와 같다.

PHP
/* Decode : Step 2 */

// Code 1
eval(gzinflate(base64_decode('U4mPDwxJrSgvdQp3cbNVdwnMz47MdLT0dPEs9w0PTPfOzE/3cylOjwr3C0+qdMwMcg0yjgw3zYgyCvONcDfJjsypKPXMKrZVtwYA')));

// Code 2
eval(gzinflate(base64_decode('U4mPDwxJrSgvdQp3cbNNSixONTOJT0lNzk9J1VBBltO0RuHaFpcUlRShKtFRryiPCAspSomsqnQtzbTwccwI9E1S11FP8g3McPSxyCx1rayKTCkKCYsor1DXtE4tS8xBt6Q0rzi1BF0QAA==')));

이번에는 eval 함수 구문 2개가 생성되었다. 이들을 디코딩하면 아래와 같다.

PHP
/* Decode : Step 3 */

// Code 1
$__QTexwuBWDF='DQokYiA9IDIwMWQgKiogNDsgZWNWbyAiRER3YW5hZ2VMXG4kYlxuIjs=';

// Code 2
$__QTexwuBWDF=base64_decode($__QTexwuBWDF);
$__QTexwuBWDF=strtr($__QTexwuBWDF,'xwXVTrdYzyEui8LAhQMb','bMQhAL8iuEyzYdrTVXwx');
eval($__QTexwuBWDF);
unset($__QTexwuBWDF);

난독화된 변수 하나와 인코딩 문자열이 등장한다. 위 코드를 분석하면 다음과 같다.

  • 먼저 변수에 저장된 Base64 문자열의 디코딩을 수행한다.
  • 디코딩된 Base64 문자열에 strtr 함수를 적용한다. 이 함수는 문자열을 바꾸는 함수로, 바이트 단위로 문자열을 치환한다. 예시 코드는 잠시 후에 설명한다.
  • eval 함수에 치환 결과를 대입하고 변수 할당을 해제한다.

PHP의 strtr 함수 사용 예시를 들면 아래와 같다. 아래 코드에서는 ‘DDManager’ 문자열을 입력받아 ‘aegn’을 ‘bfho’로 순서대로 치환하여 ‘DDMbobhfr’ 문자열을 생성한다.

PHP
/* Example : strtr */

<?php
$str = strtr('DDManager', 'aegn', 'bfho');
echo($str); // 'DDMbobhfr'

변수에 저장된 Base64 문자열을 디코딩하면 아래와 같다. 원본 코드와 비교했을 때 비슷하면서도 다르다. 디코딩 결과에 strtr 함수를 적용하면 원본 코드를 확인할 수 있다.

PHP
/* Decode : Step 4 */
$b = 201d ** 4; ecVo "DDwanageL\n$b\n";

/* Decode : Final Step */
$x = 2018 ** 4; echo "DDManager\n$x\n";

PHP 암호화 구현

위의 설명을 바탕으로 PHP 암호화를 구현해 보았다. 차이점이 있다면 Base64가 아닌 Hex 인코딩을 사용하였고 디코딩 작업을 지원한다는 점이다.

물론 공개적인 방법 외에도 상용 프로그램을 사용할 수도 있다. 하지만 간단한 테스트 용도로 사용하는 것에는 굳이 상용 프로그램을 사용할 필요가 있을까 하는 생각도 든다. 필자가 제작한 PHP 암호화 사이트를 남기며 이 글을 맺는다.

댓글 남기기