웹사이트 검색

Debian/Ubuntu에서 Apache로 mod_security를 설정하는 방법


전주곡

Mod 보안은 Apache, Nginx 및 IIS에서 작동하는 무료 웹 애플리케이션 방화벽(WAF)입니다. 간단하고 복잡한 작업을 수행하기 위한 유연한 규칙 엔진을 지원하고 SQL 삽입, 교차 사이트 스크립팅, 트로이 목마, 나쁜 사용자 에이전트, 세션 하이재킹 및 기타 많은 익스플로잇에 대한 규칙이 있는 CRS(Core Rule Set)와 함께 제공됩니다. Apache의 경우 설치 및 구성을 쉽게 해주는 추가 모듈입니다.

이 자습서를 완료하려면 서버에 LAMP가 설치되어 있어야 합니다.

mod_security 설치

Modsecurity는 Debian/Ubuntu 리포지토리에서 사용할 수 있습니다.

apt-get install libapache2-modsecurity

mod_security 모듈이 로드되었는지 확인합니다.

apachectl -M | grep --color security

모듈이 로드되었음을 나타내는 security2_module (shared) 모듈이 표시되어야 합니다.

Modsecurity의 설치에는 이름을 변경해야 하는 권장 구성 파일이 포함되어 있습니다.

mv /etc/modsecurity/modsecurity.conf{-recommended,}

아파치 다시 로드

service apache2 reload

Apache 로그 디렉터리에서 mod_security에 대한 새 로그 파일을 찾을 수 있습니다.

root@droplet:~# ls -l /var/log/apache2/modsec_audit.log
-rw-r----- 1 root root 0 Oct 19 08:08 /var/log/apache2/modsec_audit.log

mod_security 구성

기본적으로 modsecurity는 규칙이 작동해야 하므로 아무 작업도 수행하지 않습니다. 기본 구성 파일은 규칙 일치에 따라 요청을 기록하고 아무 것도 차단하지 않는 DetectionOnly로 설정됩니다. 이것은 modsecurity.conf 파일을 편집하여 변경할 수 있습니다.

nano /etc/modsecurity/modsecurity.conf

이 줄 찾기

SecRuleEngine DetectionOnly

다음과 같이 변경합니다.

SecRuleEngine On

프로덕션 서버에서 이것을 시도하는 경우 모든 규칙을 테스트한 후에만 이 지시문을 변경하십시오.

수정할 다른 지시문은 SecResponseBodyAccess입니다. 이것은 응답 본문이 버퍼링되는지 여부를 구성합니다(예: modsecurity에서 읽기). 이는 데이터 유출 감지 및 보호가 필요한 경우에만 필요합니다. 따라서 On 상태로 두면 드롭릿 리소스가 소모되고 로그 파일 크기도 증가합니다.

이것을 찾아라

SecResponseBodyAccess On

다음과 같이 변경합니다.

SecResponseBodyAccess Off

이제 웹 애플리케이션에 게시할 수 있는 최대 데이터를 제한합니다. 두 지시문은 다음을 구성합니다.

SecRequestBodyLimit
SecRequestBodyNoFilesLimit

SecRequestBodyLimit 지시문은 최대 POST 데이터 크기를 지정합니다. 클라이언트가 더 큰 것을 보내면 서버는 413 Request Entity Too Large 오류로 응답합니다. 웹 애플리케이션에 파일 업로드가 없는 경우 이 값을 크게 줄일 수 있습니다.

구성 파일에 언급된 값은

SecRequestBodyLimit 13107200

12.5MB입니다.

이와 유사한 것이 SecRequestBodyNoFilesLimit 지시어입니다. 유일한 차이점은 이 지시문이 POST 데이터에서 파일 업로드를 뺀 크기를 제한한다는 것입니다. 이 값은 "가능한 한 낮아야 합니다.\

구성 파일의 값은

SecRequestBodyNoFilesLimit 131072

128KB입니다.

이러한 지시문과 함께 서버 성능에 영향을 미치는 또 다른 지시문은 SecRequestBodyInMemoryLimit입니다. 이 지시문은 거의 자명합니다. 그것은 얼마나 많은 \요청 본문\ 데이터(POSTed 데이터)가 메모리(RAM)에 보관되어야 하는지를 지정하고, 더 많은 것은 하드 디스크에 배치됩니다(교환과 마찬가지로). 드롭릿은 SSD를 사용하기 때문에 이것은 그다지 중요하지 않습니다. 문제가 있지만 여유 RAM이 있는 경우 적절한 값으로 설정할 수 있습니다.

SecRequestBodyInMemoryLimit 131072

구성 파일에 지정된 값(128KB)입니다.

SQL 인젝션 테스트

규칙 설정을 진행하기 전에 SQL 인젝션에 취약한 PHP 스크립트를 생성하여 사용해 보겠습니다. 이것은 세션 처리가 없는 기본 PHP 로그인 스크립트일 뿐입니다. 데이터베이스에 연결할 수 있도록 아래 스크립트에서 MySQL 암호를 변경해야 합니다.

<코드>/var/www/login.php

<html>
<body>
<?php
    if(isset($_POST['login']))
    {
        $username = $_POST['username'];
        $password = $_POST['password'];
        $con = mysqli_connect('localhost','root','password','sample');
        $result = mysqli_query($con, "SELECT * FROM `users` WHERE username='$username' AND password='$password'");
        if(mysqli_num_rows($result) == 0)
            echo 'Invalid username or password';
        else
            echo '<h1>Logged in</h1><p>A Secret for you....</p>';
    }
    else
    {
?>
        <form action="" method="post">
            Username: <input type="text" name="username"/><br />
            Password: <input type="password" name="password"/><br />
            <input type="submit" name="login" value="Login"/>
        </form>
<?php
    }
?>
</body>
</html>

이 스크립트는 로그인 양식을 표시합니다. 올바른 자격 증명을 입력하면 "A Secret for you.\라는 메시지가 표시됩니다.

데이터베이스에 자격 증명이 필요합니다. MySQL 데이터베이스와 테이블을 만든 다음 사용자 이름과 암호를 삽입합니다.

mysql -u root -p

이렇게 하면 mysql> 프롬프트로 이동합니다.

create database sample;
connect sample;
create table users(username VARCHAR(100),password VARCHAR(100));
insert into users values('jesin','pwd');
insert into users values('alice','secret');
quit;

브라우저를 열고 http://yourwebsite.com/login.php로 이동한 다음 올바른 자격 증명 쌍을 입력합니다.

Username: jesin
Password: pwd

성공적인 로그인을 나타내는 메시지가 표시됩니다. 이제 돌아와서 잘못된 자격 증명 쌍을 입력하십시오. 잘못된 사용자 이름 또는 암호라는 메시지가 표시됩니다.

스크립트가 제대로 작동하는지 확인할 수 있습니다. 다음 작업은 로그인 페이지를 우회하기 위해 SQL 삽입을 시도하는 것입니다. 사용자 이름 필드에 다음을 입력합니다.

' or true -- 

-- 뒤에 공백이 있어야 합니다. 공백이 없으면 이 주입이 작동하지 않습니다. 암호 필드를 비워두고 로그인 버튼을 누르십시오.

짜잔! 스크립트는 인증된 사용자를 위한 메시지를 보여줍니다.

규칙 설정

삶을 더 쉽게 만들기 위해 이미 mod_security와 함께 설치된 많은 규칙이 있습니다. 이를 CRS(Core Rule Set)라고 하며 다음 위치에 있습니다.

root@droplet:~# ls -l /usr/share/modsecurity-crs/
total 40
drwxr-xr-x 2 root root  4096 Oct 20 09:45 activated_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 base_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 experimental_rules
drwxr-xr-x 2 root root  4096 Oct 20 09:45 lua
-rw-r--r-- 1 root root 13544 Jul  2  2012 modsecurity_crs_10_setup.conf
drwxr-xr-x 2 root root  4096 Oct 20 09:45 optional_rules
drwxr-xr-x 3 root root  4096 Oct 20 09:45 util

설명서는 다음에서 사용할 수 있습니다.

root@droplet1:~# ls -l /usr/share/doc/modsecurity-crs/
total 40
-rw-r--r-- 1 root root   469 Jul  2  2012 changelog.Debian.gz
-rw-r--r-- 1 root root 12387 Jun 18  2012 changelog.gz
-rw-r--r-- 1 root root  1297 Jul  2  2012 copyright
drwxr-xr-x 3 root root  4096 Oct 20 09:45 examples
-rw-r--r-- 1 root root  1138 Mar 16  2012 README.Debian
-rw-r--r-- 1 root root  6495 Mar 16  2012 README.gz

이러한 규칙을 로드하려면 Apache에 이러한 디렉터리를 조사하도록 지시해야 합니다. modsecurity.conf 파일을 편집합니다.

nano /etc/apache2/mods-enabled/modsecurity.conf

내부에 다음 지시문을 추가합니다.

Include "/usr/share/modsecurity-crs/*.conf"
Include "/usr/share/modsecurity-crs/activated_rules/*.conf"

activated_rules 디렉토리는 Apache의 mods-enabled 디렉토리와 유사합니다. 규칙은 다음 디렉터리에서 사용할 수 있습니다.

/usr/share/modsecurity-crs/base_rules
/usr/share/modsecurity-crs/optional_rules
/usr/share/modsecurity-crs/experimental_rules

이를 활성화하려면 activated_rules 디렉토리 내에 심볼릭 링크를 생성해야 합니다. SQL 주입 규칙을 활성화하겠습니다.

cd /usr/share/modsecurity-crs/activated_rules/
ln -s /usr/share/modsecurity-crs/base_rules/modsecurity_crs_41_sql_injection_attacks.conf .

규칙을 적용하려면 Apache를 다시 로드해야 합니다.

service apache2 reload

이제 앞에서 만든 로그인 페이지를 열고 사용자 이름 필드에서 SQL 주입 쿼리를 사용해 보십시오. SecRuleEngine 지시문을 On으로 변경한 경우 403 Forbidden 오류가 표시됩니다. DetectionOnly 옵션에 남겨진 경우 주입은 성공하지만 시도는 modsec_audit.log 파일에 기록됩니다.

나만의 mod_security 규칙 작성

이 섹션에서는 특정 "스팸성\ 단어가 HTML 양식에 입력된 경우 요청을 차단하는 규칙 체인을 생성합니다. 먼저 텍스트 상자에서 입력을 가져와 다시 표시하는 PHP 스크립트를 생성합니다. 사용자.

<코드>/var/www/form.php

<html>
    <body>
        <?php
            if(isset($_POST['data']))
                echo $_POST['data'];
            else
            {
        ?>
                <form method="post" action="">
                        Enter something here:<textarea name="data"></textarea>
                        <input type="submit"/>
                </form>
        <?php
            }
        ?>
    </body>
</html>

사용자 지정 규칙은 모든 구성 파일에 추가하거나 modsecurity 디렉터리에 배치할 수 있습니다. 규칙을 별도의 새 파일에 배치합니다.

nano /etc/modsecurity/modsecurity_custom_rules.conf

이 파일에 다음을 추가합니다.

SecRule REQUEST_FILENAME "form.php" "id:'400001',chain,deny,log,msg:'Spam detected'"
SecRule REQUEST_METHOD "POST" chain
SecRule REQUEST_BODY "@rx (?i:(pills|insurance|rolex))"

파일을 저장하고 Apache를 다시 로드합니다. 브라우저에서 http://yourwebsite.com/form.php를 열고 알약, 보험, 롤렉스 단어가 포함된 텍스트를 입력합니다.

403 페이지와 로그 항목이 표시되거나 SecRuleEngine 설정에 따른 로그 항목만 표시됩니다. SecRule의 구문은 다음과 같습니다.

SecRule VARIABLES OPERATOR [ACTIONS]

여기서 우리는 변수 REQUEST_FILENAME을 form.php, REQUEST_METHOD를 POST, REQUEST_BODY를 정규식(@rx) 문자열 (pills|insurance|rolex)과 일치시키기 위해 연쇄 동작을 사용했습니다. . ?i:는 대소문자를 구분하지 않고 일치합니다. 이 세 가지 규칙이 모두 성공적으로 일치하면 작업은 "스팸이 감지되었습니다.\라는 메시지와 함께 거부하고 기록하는 것입니다. chain 작업은 논리적 AND를 시뮬레이트하여 세 가지 규칙을 모두 일치시킵니다.

호스트 및 디렉토리 제외

때때로 phpMyAdmin과 같은 응용 프로그램을 modsecurity로 실행하고 SQL 쿼리를 차단하는 경우 특정 디렉토리 또는 도메인 이름을 제외하는 것이 좋습니다. WordPress와 같은 CMS 애플리케이션의 관리 백엔드를 제외하는 것도 좋습니다.

완전한 VirtualHost에 대해 모드 보안을 비활성화하려면 다음을 배치하십시오.

<IfModule security2_module>
    SecRuleEngine Off
</IfModule>

섹션 내부.

특정 디렉토리의 경우:

<Directory "/var/www/wp-admin">
    <IfModule security2_module>
        SecRuleEngine Off
    </IfModule>
</Directory>

모드 보안을 완전히 비활성화하지 않으려면 SecRuleRemoveById 지시문을 사용하여 해당 ID를 지정하여 특정 규칙 또는 규칙 체인을 제거하십시오.

<LocationMatch "/wp-admin/update.php">
    <IfModule security2_module>
        SecRuleRemoveById 981173
    </IfModule>
</LocationMatch>

추가 자료

공식 모드 보안 문서 https://github.com/SpiderLabs/ModSecurity/wiki/Reference-Manual

제출자: 제신A