[webhacking.kr] 30번 문제 풀이[PHP,Apache] 오류 해결

2 분 소요

💡 Webhacking.kr challenge(old) 30번 문제에 대한 풀이입니다.

문제

image

  $db = mysqli_connect() or die();
  mysqli_select_db($db,"chall30") or die();
  $result = mysqli_fetch_array(mysqli_query($db,"select flag from chall30_answer")) or die();
  if($result[0]){
    include "/flag";
  }

문제 풀이

문제 코드를 보면 mysql_connect를 통해서 db에 연결을 하고, select flag from chall30_answer 쿼리문을 통해서 결과를 받아온 뒤, 결과 값이 존재하면 플래그를 출력하는 로직으로 되어 있습니다. 이때 주의해서 봐야할 점은 mysql_connect()함수입니다.

원래 mysql_connect() 함수는 다음과 같은 방식으로 DB에 연결을 합니다.

  $servername = "localhost";
  $username = "username";
  $password = "password";

  // Create connection
  $conn = new mysqli($servername, $username, $password);

하지만 문제에서는 mysqli_connect 함수에 인자 값을 넘겨주고 있지 않습니다. 이럴때는 PHP 문서에 따르면 php.ini 파일에 설정된 default 값으로 연결을 시도한다고 합니다. 그리고 초기 php.ini 파일에는 다음과 같이 port 만 3306이 기본으로 설정되어 있고, 나머지 값은 NULL 값으로 되어 있습니다.

image

Apache를 이용해서 php를 운영 할때, .htaccess 파일을 이용해서 해당 폴더 하위의 설정들을 덮어쓸 수 있습니다.

자세한 내용은 PHP 문서에 나와있습니다.

본 문제에서는 이 기능을 이용해서 .htaccess 파일을 업로드 하고, .htaccess 파일에서는 php.ini 설정 값을 덮어쓰도록 하여 DB의 default 값들을 바꿔야 합니다.

.htaccess 파일에서 php.ini 설정 값을 바꾸는 문법은 다음과 같습니다.

  php_value name value

위의 문법에 따라서 .htaccess 파일에는 다음과 같은 설정 값을 넣어줍니다.

  php_value mysqli.default_host "[나의 DB 서버 IP]"
  php_value mysqli.default_user "[DB user]"
  php_value mysqli.default_pw "[DB 사용자 비밀번호]"

이렇게 설정하여 파일을 업로드 한다면, 해당 폴더에서는 자동으로 나의 DB 서버에 접근하여 나의 DB에서 데이터를 읽어 간 뒤 플래그를 출력해 줄 것입니다.

이제 이 쿼리를 받을 DB서버를 구축해 보겠습니다. 저는 AWS Cloud를 이용해서 구축하였으며, 자신의 DB서버가 있으신 분은 해당 서버를 이용하시면 됩니다.

DB서버 구축

  • DB 및 table 생성
  # 데이터베이스 생성
  create database chall30
  use chall30;

  # 테이블 생성
  create table chall30_answer(
    flag int 
  );

  # 데이터 넣기
  insert into chall30_answer values(123);

  # 데이터 확인
  select flag from chall30_answer;

image

이렇게 생성하고 문제를 다시 확인해 보면

  $db = mysqli_connect() or die();
  mysqli_select_db($db,"chall30") or die();
  $result = mysqli_fetch_array(mysqli_query($db,"select flag from chall30_answer")) or die();
  if($result[0]){
    include "/flag";
  }

DB로 연결만 된다면 작동이 된다는 것을 알 수 있습니다.

이제 해당 DB가 외부에서 접근이 가능하도록 다음의 설정을 해줍니다.

  • 사용자 생성 및 권한 설정
      # 사용자 생성
      create user 'test'@'%' identified by 'test1234';
      grant all privileges on *.* to 'test'@'%';
    

image

  • mysqld.cnf 파일 설정 변경
    mysql 서버를 설치하면 기본 값으로 로컬에서만 접근이 가능하도록 설정되어 있습니다. 외부에서 접근 가능하도록 설정을 바꿔 줍니다.

이전 설정 값

image

31-32 번째 라인 변경

image

서버 재시작 후 변경 값 확인

image

추가적으로 방화벽이 있다면 방화벽 설정을 바꿔주고, 로컬에서 연결이 되는지 테스트 해봅니다.

image

여기까지 하면 DB를 구성하고 외부에서 접근이 가능하도록 설정이 완료되었습니다.

이제 .htaccess 파일을 업로드 하여, 문제에서 자동으로 제가 구성한 DB서버로 접근하여 데이터를 읽어가도록 해야 합니다.

저의 서버에 접근 가능하도록 하는 .htaccess 파일은 다음과 같습니다.

image

파일을 업로드 합니다.

image

그리고 업로드 폴더에 index.php에 접근을 해봅니다.

image

원래는 여기까지 했을때, 답이 출력되어야 합니다. 답이 출력되지 않는 사람들은 따로 추가적인 설정을 해줘야 합니다.

오류 원인 및 해결

Mysql이 버전이 업데이트 되면서, 비밀번호를 인증하는 방식에서 차이가 생겼습니다. 옛날의 Mysql 서버에서는 default_authentication_plugin의 값이 mysql_native_password 였는데, Mysql 8.0으로 버전이 업데이트 되면서 default_authentication_plugin 값이 caching_sha2_password로 변경되었습니다.

즉 webhacking.kr 30번 문제에서의 mysql client에서는 구형 library를 사용해서 최신 plugin인 caching_sha2_password 방식을 지원하지 못해서 오류가 나는 것입니다. 저는 원인을 찾느라 삽질을 좀 많이 했습니다 ㅎㅎ..

저 처럼 새로 클라우드를 설치하고, mysql 서버를 최신으로 받으면 plugin 값을 바꿔줘야 합니다. 다음 그림은 mysql 서버에서 plugin정보를 출력한 것입니다. 기본으로 따로 설정해 주지 않았다면 caching_sha2_password로 설정되어 있습니다.

image

이제 이 값을 mysql_native_password로 바꿔주면 됩니다.

  ALTER USER 'test'@'%' IDENTIFIED WITH mysql_native_password BY 'test1234';

image

해당 설정을 해준뒤 다시 접속을 해주면 다음과 같이 flag가 출력됩니다.

image

댓글남기기