OpenSSL – 데이터 암호화



#include <stdio.h>
#include <string.h>
#include <openssl/bio.h>
#include <openssl/err.h>
#include <openssl/bn.h>
#include <openssl/dh.h>
#include <openssl/rand.h>
#include <openssl/pem.h>


 


#define IN_FILE “./plain.txt”   // plain file
#define OUT_FILE “./encrypt.txt”        // cipher file


 


unsigned char* readFile(char *file, int *readLen);
unsigned char *readFileBio(BIO *fileBIO, int *readLen);
unsigned char *addString(unsigned char *destString, int destLen, const unsigned char *addString, int addLen);


 


int main(int argc, char* argv[])
{
        // 키와 IV값은 편의를 위해 직접 만든다.


        unsigned char key[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
        unsigned char iv[] = {1, 2, 3, 4, 5, 6, 7, 8};


        int len;
        unsigned char *readBuffer, *outbuf;
        int outlen, tmplen;



        BIO *errBIO = NULL;
        BIO *outBIO = NULL;


 


        // 에러 발생의 경우 해당 에러 스트링 출력을 위해 미리 에러 스트링들을 로딩.
        ERR_load_crypto_strings();


 


        // 표준 화면 출력 BIO 생성
        if((errBIO = BIO_new(BIO_s_file())) != NULL)
                BIO_set_fp(errBIO, stderr, BIO_NOCLOSE|BIO_FP_TEXT);


 


        // 파일 출력 BIO 생성
        outBIO = BIO_new_file(OUT_FILE, “wb”);
        if(!outBIO) {
                BIO_printf(errBIO, “Can not create file [%s]!”, OUT_FILE);
                ERR_print_errors(errBIO);
                exit(1);
        }


 


        // 파일에서 데이터 읽어오기
        readBuffer = readFile(IN_FILE, &len);


 


        // 암호화 컨텍스트 EVP_CIPHER_CTX 생성, 초기화
        EVP_CIPHER_CTX ctx;
        EVP_CIPHER_CTX_init(&ctx);


 


        // 초기화
        EVP_EncryptInit_ex(&ctx, EVP_bf_cbc(), NULL, key, iv);


 


        // 초기화가 끝난후에 해야 한다. 암호문 저장할 버퍼 생성
        outbuf = (unsigned char*)malloc(sizeof(unsigned char) * (len + EVP_CIPHER_CTX_block_size(&ctx)));


 


        // 업데이트. 마지막 블록을 제외하고 모두 암호화.
        if(!EVP_EncryptUpdate(&ctx, outbuf, &outlen, readBuffer, strlen((char *)readBuffer))) {
                return 0;
        }


 


        // 종료. 마지막 블록을 암호화
        if(!EVP_EncryptFinal_ex(&ctx, outbuf + outlen, &tmplen)) {
                return 0;
        }


 


        // 암호문 길이는 업데이트. 종료 과정에서 나온 결과의 합
        outlen += tmplen;
        EVP_CIPHER_CTX_cleanup(&ctx);


        BIO_printf(errBIO, “Create Cipher Complete.nSaving [%s] filen”, OUT_FILE);


 


        // 파일에 같은 내용을 출력한다.
        BIO_write(outBIO, outbuf, outlen);


 


        // 객체 제거
        BIO_free(outBIO);


 


        return 0;
}


 


 


unsigned char* readFile(char *file, int *readLen)
{
        unsigned char *retBuffer = NULL;
        unsigned char *buffer = NULL;
        int length = 0;


 


        // 파일 BIO 정의
        BIO *fileBIO = NULL;


 


        // 인자로 넘어온 파일을 열고, 파일 BIO 생성
        fileBIO = BIO_new_file(file, “rb”);
        if(!fileBIO) {
                printf(“file open(%s) error!n”, file);
                exit(1);
        }


 


        // 임시로 1000 바이트 만큼의 읽은 데이터를 저장할 버퍼 생성.
        buffer = (unsigned char*)malloc(1001);
        *readLen = 0;


 


        while(1) {


                // 파일 BIO에서 1000 바이트 만큼 읽어서 buffer에 저장 한다.
                length = BIO_read(fileBIO, buffer, 1000);


 


                // 안전을 위해 버퍼의 끝은 NULL로 채운다.
                buffer[length] = 0;


 


                // 임시로 읽은 1000 바이트의 데이터를 리턴 버퍼에 더한다.
                retBuffer = addString(retBuffer, *readLen, buffer, length);


 


                // 지금까지 읽은 데이터의 길이를 더한다.
                *readLen = *readLen + length;


                // 만약 지금 파일에서 읽은 데이터의 길이가 꼭 1000 바이트라면 앞으로 더 읽을


                // 데이터가 있을 것이다. 하지만 1000 바이트보다 작다면 더 이상 읽을 데이터가


                // 없을 것이므로 종료한다.


                if(length == 1000)


                      // 파일 포인터를 1000 바이트 뒤로 옮긴다.
                      BIO_seek(fileBIO, 1000);
                else
                      break;
        }


 


        // 객체 삭제


        BIO_free(fileBIO);


        free(buffer);


 


        return retBuffer;
}


 



unsigned char* addString(unsigned char* destString, int destLen, const unsigned char *addString, int addLen)
{


        // 리턴할 버퍼 정의
        unsigned char *retString;
        int i;


 


        // 만약 덧붙일 대상 버퍼가 NULL, 이거나 길이가 0이면 덧붙일 대상버퍼가 없는 경우


        // 이므로 새로 생성하고, 덧붙일 버퍼의 내용을 복사 한다.


        if((destString == NULL) || (destLen == 0)) {


                // 덧붙일 버퍼 길이 만큼의 버퍼 생성
                retString = (unsigned char*)malloc(sizeof(unsigned char) * (addLen + 1));


 


                // 덧붙일 버퍼의 내용을 새로운 버퍼에 복사
                for(i = 0; i < addLen; i++) {
                      retString[i] = addString[i];
                }


                // 안전을 위해 버퍼의 마지막에 NULL 바이트를 뭍인다.
                retString[i] = NULL;
        }


        // 덧붙일 대상 버퍼가 있는 경우이므로 덧붙일 대상 버퍼의 길이를


        // 더한 만큼의 버퍼를 새로 생성하고, 두 버퍼의 내용을 새로운 버퍼에 복사한다.
        else {


                // 대상 버퍼의 길이와 덧붙일 길이를 더한 만큼의 버퍼 생성
                retString = (unsigned char*)malloc(sizeof(unsigned char) * (destLen + addLen + 1));


                // 덧붙일 대상 버퍼 내용을 새로운 버퍼에 복사
                for(i = 0; i < destLen; i++) {
                      retString[i] = destString[i];
                }


                // 덧붙일 버퍼의 내용을 새로운 버퍼에 복사
                for(i = 0; i < addLen; i++) {
                      retString[i + destLen] = addString[i];
                }


                // 안전을 위해 버퍼의 마지막에 NULL 바이트를 붙인다.
                retString[i + destLen] = NULL;
        }


 


        // 메모리에서 삭제


        free(destString);


        return retString;
}


OpenSSL- 키와 IV 생성 프로그램

 


 


#include <stdio.h>


#include <stdio.h>
#include <string.h>
#include <openssl/evp.h>
#include <openssl/objects.h>
#include <openssl/rand.h>


 


int main(int argc, char* argv[])
{
        int i;


 


        // salt bufer length = 8
        unsigned char salt[8];
        // EVP_CIPHER = Cipher structure
        const EVP_CIPHER *cipher = NULL;
        // password pointer. password = “aaaa”
        char *password = “aaaa”;


        // 키와 IV가 저장될 변수를 정의하고 길이는 OpenSSL에서 알아서 정해준다.
        unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];


 


        int ret = 0;


        // PRNG를 통해 랜덤 수를 만들고 그 값을 Salt에 저장한다. 길이는 8
        ret = RAND_pseudo_bytes(salt, 8);


        // PRNG에서 에러가 발생할 경우 에러 메시지를 출력하고 프로그램을 종료한다.
        if(ret < 0) {
                printf(“Can’t generate random number.n”);
                return 0;
        }


 


        // 암호화 구조체의 인스턴스를 생성. 여기서는 DES의 ECB 모드의 암호화 구조체 생성
        cipher = EVP_des_ecb();


 


        // 키와 IV를 생성함. 인자는 암호화 구조체, 다이제스트 구조체, salt 값, 패스워드


        // 카운트는 생성될 키와 IV를 저장할 변수


        // 다이제스트 구조체는 EVP_md5() 함수를 통해 생성. 카운트는 한번
        EVP_BytesToKey(cipher, EVP_md5(), salt, (unsigned char *)password, strlen(password), 1, key, iv);


        // display salt
        for(i = 0; i < sizeof(salt); i++) {
                printf(“%02X”, salt[i]);
        }


        // Display key
        if(cipher->key_len > 0) {
                for(i = 0; i < cipher->key_len; i++) {
                        printf(“%02X”, key[i]);
                }
        }


 


        // Display IV
        if(cipher->iv_len > 0) {
                for(i = 0; i < cipher->iv_len; i++) {
                        printf(“%02X”, iv[i]);
                }
        }


 


        return 0;
}

OpenSSL-RANDOM 함수 사용하기

#include <stdio.h>
#include <openssl/err.h>
#include <openssl/rand.h>


int main(int argc, char* argv[])
{
        int i;
        int retVal = 0;
        // 랜덤 수의 길이는 64로 한다.


        int length = 64;
        // PRNG에 공급할 seed 생성
        RAND_status();
        // 생성할 랜덤 수 길이만큼의 버퍼 생성
        unsigned char *buffer = (unsigned char*)malloc(sizeof(unsigned char) * length);


        // run PRNG
        retVal = RAND_bytes(buffer, length);
        if(retVal <= 0) {
                printf(“error encount!n”);
                return 0;
        }


        // print random number
        printf(“Random number = “);


        for(i = 0; i < length; i++)
                printf(“%c”, buffer[i]);


        return 1;
}


 


 Windows의 경우 RAND_status() 를 RAND_screen() 으로 바꿔주면 된다.


 



5. psad 소개

 * 역사

 psad 소프트웨어 프로젝트는 1999년 가을, 바스티유 개발팀이 바스티유가 경량의 네트워크 침입 탐지 컴포넌트를 제공해야 한다고 결정했을 때 Bastille 리눅스의 일부로 시작했다. 당시 피터 왓킨스는 지금까지도 Bastille 와 함께 제공되는 매우 뛰어난 방화벽 스크립트를 개발 중이었으므로 방화벽 로그가 제공하는 정보에 기반한 IDS 도구를 개발하는 것은 자연스러운 다음 작업이었다. 또 당시 PortSentry(http://sourceforge.net/projects/sentrytools 참조)에는 기본 버리기 전략으로 설정된 방화벽과 함께 사용하기에는 부적절한 구조적 설계 문제가 있었다.

 2001년 마이클 래쉬는 바스티유-NIDS 프로젝트가 바스티유를 설치할 필요 없이 독립적으로 실행될 수 있게 별도의 프로젝트로 분리시키고 포트 스캔 공격 탐지기라고 명명했다. psad의 개발 주기는 매우 활발하며 평균 3~4 달에 한 번씩 새로운 배포판이 나온다.

 * 방화벽 로그를 분석하는 이유
 좋은 네트워크 보안은 기본 네트워크 연결성과 서비스를 허용하기 위해 절대적으로 필요한 만큼만 허용하게 적절히 설정된 방화벽에서 시작된다. 방화벽은 인라인 장치이므로 네트워크 트래픽에 필터링 로직을 적용하기 좋다. 컴퓨터 네트워킹의 문맥에서 인라인 장치란 네트워크를 통해 패킷이 라우팅될 때 패킷의 직접적인 경로에 존재하는 하드웨어를 의미한다. 인라인 장치 내의 하드웨어나 소프트웨어가 오작동해서 기기의 네트워크 트래픽 전달 기능에 영향을 미친다면 네트워크 통신은 더 이상 동작하지 못한다. 인라인 장치의 예로는 라우터, 스위치, 브리지, 방화벽, 네트워크 참입 방지 시스템(IPS)이 있다

 방화벽의 기능이 좀 더 완전해지고 복자배짐에 따라 점차적으로 (애플리케이션 계층 검사와 같이) 전통적으로 침입 탐지 시스템의 점주였던 기능을 제공하고 있다. 이런 기능이 트래픽을 필터링하는 기능에 더해지면서 방화벽은 명백한 침투와 복잡한 정탐 시도로부터 서비스를 보호하고 웜 트래픽으로부터의 잠재적인 피해를 제한할 수 있는 효과적인 기법을 제공할 수 있는 양질의 침입 탐지 데이터를 생성할 수 있게 됐다. 광범위한 로깅과 필터링 기능을 갖춘 iptables 와 같은 방화벽은 무시해선 안 되는 가치 있는 보안 데이터를 제공할 수 있다.

 스노트와 같은 전용 침입 탐지 시스템이 굉장히 많은 기능과 네트워크 공격을 기술하기 위한 광범위한 규칙 언어를 제공하는 반면 iptables 는 항상 네트워크 트래픽에 인라인돼서 자세한 패킷 헤더 로그를 제공한다. 철저한 방어의 원리가 적용되므로 iptables 의 로그를 주의 깊게 보는 것이 좋다.

 * psad 의 기능

 현 버전의 psad는 Nmap과 같은 도구를 이용한 포트 스캔, 다양한 백도어 프로그램을 위한 탐사, 분산 서비스 거부 공격(DDoS) 도구, 네트워킹 프로토콜을 악용하려는 시도와 같이 다양한 유형의 의심스러운 트래픽을 탐지할 수 있다. Psad는 fwsnort와 함께 사용하는 경우 애플리케이션 계층 데이터를 조사해야 하는 규칙을 포함해서 스노트 2.3.3 전체 규칙의 60% 이상을 탐지하고 경고할 수 있다.

 psad 의 좀 더 흥미로운 기능 가운데 하나는 스캔이나 기타 악의적인 트래픽이 시작되는 원격 운영체제를 수동적으로 핑거프린팅할 수 있는 기능이다. psad가 사용하는 핑거프린트는 p0f에서 나온 것이다. 더욱이 psad는 자세한 메일과 syslog 경고, 위험 수준 임계치에 기반한 IP 자동 차단 기능(이 기능은 기본적으로 비활성화돼 있다), 통합된 whois 지원, DShield 보고 등을 제공한다.

 * psad 설치

 psad를 설치하기 전에 우선 http://www.cipherdyne.org/psad/download 에서 최신 버전을 받아야 한다. psad를 포함해서 http://www.cipherdyne.org 에서 배포하는 모든 프로그램은 각 소스 트리에 설치 프로그램인 insatll.pl 이 함께 제공된다. tarball 파일을 받은 다음에는 MD5 합과 GnuPG 서명을 모두 확인하는 것이 좋다.



 install.pl 스크립트는 메일 경고가 전송될 메일 주소, 시스템에서 현재 실행 중인 syslog 데몬의 유형(syslogd, syslog-ng, metalog), psad가 특정 로깅 접두어를 포함하는 iptables 로그 메시지만을 분석하게 할지에 대한 결정, 로그 데이터를 DShield 분산 IDS로 전송할지에 대한 결정 등과 같은 몇 가지 사용자 입력을 필요로 한다. 직접 정보를 입력하거나 기본 값(그냥 엔터 키를 누름)을 그대로 사용할 수 있다. 잠시 후면 psad의 설치가 완료된다.

 데비안 혹은 우분투 리눅스를 사용하는 경우 다음의 명령어를 이용하여 쉽고 같편하게 psad 설치를 진행할 수 있다.
 

 # sudo apt-get install psad

 리눅스에 psad를 성공적으로 설치하고 나면 로컬 파일시스템에 다량의 새 파일과 디렉토리가 생성된다.

 펄은 주요 psad 데몬(나중에 다룰 도우미 데몬 kmsgsd와 psadwatchd는 C로 작성한 것이다)을 개발하는 데 쓰인 프로그래밍 언어로, 핵심 펄 모듈에는 포함되지 않는 몇 개의 펄 모듈이 사용된다. 이러한 펄 모듈을 /usr/lib/psad 에 모두 설치함으로써 psad 는 이미 시스템 펄 라이브러리 트리에 설치된 펄 모듈(주로 /usr/lib/perl5 에 위치)과 psad 가 필요로 하는 모듈을 완전히 분리시켜 유지할 수 있다.

 psad 에는 다음과 같은 모듈이 필요하다.

 * Date::Calc
 * Net::Ipv4Addr
 * Unix::Syslog
 * IPTABLES::Parse
 * IPTABLES::ChainMgr

 psad, kmsgsd, psadwatchd 와 같은 세 개의 시스템 데몬이 psad를 구성한다. 이 데몬은 모두 /usr/sbin 에 설치되며  /etc/psad/psad.conf 파일을 참조한다.

 psad 설치 프로그램은 /etc/psad/archive 디렉토리도 생성해서 현재의 psad 데몬 설정 파일을 복사한다. 이는 psad 를 재설치할 때 이전의 설정을 보존하기 위한 것이다. install.pl 프로그램은 현재의 psad 설정 값을 새로운 설정 파일로 통합할 수 있으며, 이를 통해 업그레이드 비용을 최소화할 수 있다.

 설치 프로그램은 /var 에도 몇 개의 파일과 디렉토리를 생성한다. 우선 /var/lib/psadfifo 에 명명된 파이프를 생성하고 /var/log/psad 디렉토리와 파일 /var/log/psad/fwdata 를 생성한다. 끝으로 install.pl 스크립트는 설치 로그를 /var/log/psad/install.log 에 유지한다. 실행 시 psad 의 주요 동작 디렉토리(수상한 네트워크 트래픽과 관련된 IP 주소를 기록하는 디렉토리)도 /var/log/psad 다.

 psad가 설치되는 디렉토리는 무작위로 선택되는 것이 아니라 파일 시스템 계층 표준(FHS, Filesystem Hierarchy Standard)이라는 문서에서 정의하는 표준 디렉토리 내에 위치한 것이다. 이 문서에는 유닉스 파일시스템 디렉토리 구조 내의 각 디렉토리가 담당할 목적을 분류한다. 이 문서를 따르는 애플리케이션은 리눅스 디렉토리 구조를 예상 가능하게 사용하며 이는 수많은 디렉토리와 파일 속에서 어느 정도 정리된 모습을 유지할 수 있게 해준다. FHS는 http://www.pathname.com/fhs에서 구할 수 있다.XIW0pLyDnJ.pdf

 * psad 관리

 – psad 의 시작과 종료

 psad의 시작과 종료는 매우 간단하다. init 스크립트를 사용하면 된다.
 psad가 init 스크립트를 통해 시작되면 주 psad 데몬, kmsgsd, psadwatchd 와 같은 세 개의 데몬도 시작된다. kmsgsd 는 psad 가 iptables 로그를 실시간으로 분석할 수 있게 /var/lig/psad/psadfifo 명명된 파이프로부터 모든 iptables 로그 메시지를 읽어 와서 별도의 파일인 /var/log/psad/fwdata 에 기록한다. 이를 통해 psad 는 iptables 로그 메시지만을 포함하는 데이터 스트림을 제공받는다.

 psad는 설치 시에 시스템 syslog 데몬이 info 우선순위를 가지는 모든 커널 메시지(또는 syslog 용어로 kern.info 메시지)를 명명된 파이프 /var/lib/psad/psadfifo 에 기록하게 재설정한다.

 psadwatchd 데몬은 단순히 psad와 kmsgsd 데몬이 실행 중인지 확인하고 그렇지 않으면 이들을 재시작한다. psadwatchd 는 두 데몬 중 하나를 재시작해야 하면 /etc/psad/psad.conf 파일에 있는 메일 주소로 경고 메일을 전송한다.

 – 데몬 프로세스의 유일성

 psad 가 시작되면 세 개의 psad 데몬은 각기 자신만의 프로세스 ID(PID)를 /var/run/psad 내의 파일에 기록한다. 명령 행에서 수동으로 데몬을 시작하면 해당 데몬은 우선 다른 인스턴스가 실행 중인지 확인하고 실행 중이라면 새로운 인스턴스는 바로 종료한다. 이를 통해 이미 존재하는 psad 프로세스를 그대로 유지할 수 있다.

 – iptables 정책 설정

 기본적으로 psad 는 로그 분석기다. psad 는 자신이 설치된 시스템상의 iptables 정책이 기록 후 버리기 전략으로 설정됐다고 가정한다. 이는 iptables 가 네트워크의 동작을 위해서 꼭 필요한 패킷만을 수용하게 보장해주며 다른 모든 패킷은 기록 후 버린다. 포트 스캔, 백도어 프로그램을 위한 탐사, 시스템을 전복시키는 애플리케이션 명령, 기타 불법적인 걱듯이 수용 가능한 네트워크 트래픽 목록에서 제외되므로 이런 정책으로부터 나온 iptables 기록은 보통 전용 침입 탐지 시스템에 가치 있는 데이터를 제공할 수 있다.

 psad는 로컬 iptables 정책이 INPUT 과 FORWARD 체인 모두에서 기본 LOG와 DROP 규칙으로 설정됐는지 확인해주는 자동 기법을 제공한다. 이 기법은 /usr/sbin/fwcheck_psad 에 위치한 전용 스크립트로 (psad 실행 시 –no-fwcheck 명령 행 스위치를 주거나 psad 가 별도의 syslog 서버에서 실행 중이지 않는 한) psad 가 시작할 때 실행한다. fwcheck_psad 스크립트는 IPTables::Parse 펄 모듈을 사용해 로컬 iptables 정책의 표현(representation)을 얻어오며 LOG와 DROP 규칙이 포함됐는지 알아보기 위해 이를 해석한다. 포함돼 있지 않다면 psad는 iptables 정책이 알맞게 설정되지 않았다는 것을 알려주기 위해 설정 경고 메일을 전송한다.

 iptables 정책은 매우 복잡할 수 있기 때문에 정책이 로그와 버리기 전략을 가지는지 결정하는데에 IPTables::Parse 모듈의 구문 분석 기능이 항상 충분하지는 않다. 검사가 실패하더라도 psad는 여전히 동작할 수 있으며, psad의 효과는 iptables가 기록하는 패킷의 유형에 따라 달라진다. 실제로 SMB(윈도우에서 사용)와 같은 프로토콜은 필요 없는 내용을 너무 많이 포함하기 때문에 기로하기에 부적절하며, 이런 프로토콜을 통해 전송된 패킷은 주로 LOG 규칙과 일치될 수 있기 전에 받아들이거나 버린다. fwcheck_psad 가 올바로 구문 분석할 수 없을 정도로 복잡한 iptables 정책을 실행 중이라면 /etc/psad/psad.conf 의 ENABLE_FW_LOGGING_CHECK 변수를 N 으로 설정해서 이 검사를 비활성화할 수 있다.

 – syslog 설정

 패킷이 iptables 내에서 LOG 규칙에 매칭되면 커널은 커널 로깅 데몬인 klogd를 통해 이 사실을 보고한다. 이렇게 전달된 커널 로그 메시지는 보통 보고서 파일에 기록되기 위해 명명된 파이프나 버클리 소켓 인터페이스를 통한 별도의 시스템으로 전달된다. 이는 모두 syslog 데몬이 제공하는 기능과 syslog이 어떻게 설정됐는지에 따라 달라진다.

 syslogd와 syslog-ng 데몬은 psad와 호환되며, psad는 metalog도 제한된 방식으로 지원한다. syslogd와 syslog-ng는 명명된 파이프로 로그 메시지를 기록할 수 있으며, psad는 이를 이용하기 위해 모든 kern.info 로그 메시지가 명명된 파이프 /var/lib/psad/psadfifo에 기록되게 설정한다. 이곳으로 전달된 로그 메시지는 kmsgsd가 이용한다. kmsgsd는 psadfifo를 통해 syslog 메시지를 받으면 이 syslog 메시지가 iptables에 의해 생성됐다는 것을 보장하기 위해 두 개의 부분 문자열(IN= 과 OUT=)을 포함하는지 확인한다. 메시지가 이 검사를 통과하면 kmsgsd는 이를 psad가 볼 수 있게 파일 /var/log/psad/fwdata에 기록한다. 많은 kern.info syslog 메시지가 iptables와 아무런 관계도 없는 커널 일부에 의해 생성될 수 있으며, kmsgsd는 iptables 메시지만이 psad에 의해 분석되게 보장한다.

 IN=과 OUT= 문자열은 iptables LOG 타겟을 통해 기록된 패킷의 입력과 출력 인터페이스를 나타낸다. 이러한 문자열은 iptables 로그 메시지에 항상 포함된다.

 — syslogd
 syslogd가 설치된 시스템에서 psad가 실행중이라면 설치 시 /etc/syslog.conf 설정 파일에 다음과 같은 내용이 추가된다. 이는 syslogd가 kern.info 메시지를 /var/lib/psad/psadfifo에 기록하게 설정한다.
 

 – whois 클라이언트
 마르코 디트리(Marco d’itri)가 만든 훌륭한 whois(후이즈) 클라이언트가 psad 소스와 함께 제공된다. 이 클라이언트는 주어진 IP 주소에 대해 거의 항상 올바른 넷블록(netblock)을 질의하며, psad는 (–no-whois 명령 행 스위치를 주지 않는 한) IP 주소 소유 정보를 질의해서 메일 경고에 포함시키기 위해 이 클라이언트를 이용한다. 이런 정보를 가지면 스캔이나 기타 다른 공격이 탐지된 네트워크의 관리자 식별 과정이 단순해진다. 예를 들어 우리학교(http://www.kongju.ac.kr)의 IP(203.253.33.6)의 주소를 whois 탐지하면 다음과 같은 결과가 나온다.

 * psad 설정

 모든 psad 데몬은 /etc/psad에 있는 파일 psad.conf를 참조하며, 이 파일은 간단한 규약을 따른다. 주석은 # 기호로 시작하며 설정 매개변수는 키-값 형식으로 명시한다. 예를 들어 psad.conf의 HOSTNAME 변수는 psad가 설치된 시스템의 호스트명을 정의한다.

### Machine hostname
HOSTNAME                    extreme;

 모든 설정 변수 값은 값을 의미하는 문자열의 끝을 나타내기 위해 세미콜론으로 끝나야 한다. 그러므로 다름과 같이 문서화를 위해 세미콜론 다음에 주석을 포함시킬 수 있다.

### This is used only if ENABLE_PERSISTENCE = “N”;
SCAN_TIMEOUT                3600;  ### seconds

 끝으로 psad 변수 값은 psad가 설정을 구문 분석할 때 확장되는 하위 변수를 포함할 수 있다. 예를 들어 psad의 주요 로깅 디렉토리는 PSAD_DIR 변수가 정의하며, 기본적으로 /var/log/psad로 설정된다. 다른 설정 변수는 다음과 같이 PSAD_DIR 변수를 참조할 수 있다.

PSAD_ERR_DIR                $PSAD_DIR/errs;

 – /etc/psad/psad.conf
 psad.conf 파일은 psad의 주요 설정 파일로 psad 동작의 다양한 면을 제어하기 위한 100개 이상의 설정 변수를 포함한다.

 설정에 관한 더 자세한 내용은 http://www.cipherdyne.org/psad/docs/index.html 에서 확인할 수 있다.

 — EMAIL_ADDRESSES
 EMAIL_ADDRESSES 변수는 psad가 스캔 경고, 정보 메시지, 기타 공지를 전송할 메일 주소를 정의한다. 콤마를 사용해서 여러 개의 메일 주소를 함께 나타낼 수도 있다.

### Supports multiple email addresses (as a comma separated
### list).
EMAIL_ADDRESSES             root@localhost;

—  DANGER_LEVEL{n}
 psad는 경고에 우선순위를 두기 위해 악의적인 모든 활동을 위험 수준에 따라 나눈다. 위험 수준은 1에서 5까지(5가 가장 안 좋은 것)이며, 공격이나 스캔이 탐지된 각 IP 주소에 할당된다. 위험 수준 값은 스캔의 특성(패킷 수, 포트 범위, 시간 간격), 특정 패킷이 /etc/psad/signatures 파일에 정의된 서명과 일치하는지 여부, 패킷이 /etc/psad/auto_dl 파일에 있는 IP나 네트워크로부터 시작됐는지 여부와 같은 세 가지 요소에 기반해 할당된다.

 포트 스캔의 경우 스캔의 패킷 수에 따라 DANGER_LEVEL{n} 변수 값이 달라지며, psad.conf 파일에 다음과 같이 정의돼 있다.

### Danger levels.  These represent the total number of
### packets required for a scan to reach each danger level.
### A scan may also reach a danger level if the scan trips
### a signature or if the scanning ip is listed in
### auto_ips so a danger level is automatically
### assigned.
DANGER_LEVEL1               5;    ### Number of packets.
DANGER_LEVEL2               15;
DANGER_LEVEL3               150;
DANGER_LEVEL4               1500;
DANGER_LEVEL5               10000;

 — HOME_NET
 psad는 의심스러운 네트워크 트래픽을 탐지하기 위해 수정된 스노트 규기을 사용하기 때문에 psad.conf 파일에서 psad가 사용하는 변수는 스노트가 사용하는 변수와 유사하다. HOME_NET 변수는 실행 중인 psad가 설치된 시스템의 로컬 네트워크를 정의한다. 그러나 psad와 스노트가 HOME_NET 변수를 처리하는 데에는 한가지 차이점이 있다. psad는 INPUT 체인에 기록된 모든 패킷의 목적지를 출발지 주소와 무관하게 홈 네트워크로 취급한다. 이는 iptables 방화벽 자체에서 라우팅됐기 때문이다. ENABLE_INTF_LOCAL 변수를 N으로 설정해서 이러한 동작을 재정의할 수 있다.

### Specify the home and external networks.  Note that by default the
### ENABLE_INTF_LOCAL_NETS is enabled, so psad automatically detects
### all of the directly connected subnets and uses this information as
#@@ the HOME_NET variable.
HOME_NET                    any;
EXTERNAL_NET                any;

 — EXTERNAL_NET
 EXTERNAL_NET 변수는 외부 네트워크를 정의한다. 기본 값은 any 이지만 HOME_NET 변수처럼 임의의 네트워크 목록으로 설정할 수 있다. 대부분의 경우 기본 값이 가장 좋을 것이다.

 — SYSLOG_DAEMON
 SYSLOG_DAEMON 변수는 psad 에게 로컬 시스템에서 실행 중인 syslog 데몬이 무엇인지 알려준다. 이 변수는 syslogd, syslog-ng, ulogd, metalog 중 하나의 값을 가진다. psad는 이 변수 값을 이용해서 해당 syslog 설정 파일이 kern.info 메시지를 명명된 파이프 /var/lib/psad/psadfifo에 기록하게 적절히 설정됐는지 확인한다. 단, psad가 ulogd를 통해 iptables 로그 메시지를 얻는 경우는 예외인데 ulogd가 메시지를 직접 디스크에 기록하기 때문에 syslog 데몬이 실행 중이지 않아도 된다. 이 경우 psad는 kmsgsd 데몬을 시작하지 않는다.

### Set the type of syslog daemon that is used.  The SYSLOG_DAEMON
### variable accepts four possible values: syslogd, syslog-ng, ulogd,
### or metalog.
SYSLOG_DAEMON               syslogd;

 — CHECK_INTERVAL
 psad는 대부분의 시간을 대기하면서 보내며 새로운 iptables 로그 메시지가 /var/log/psad/fwdata 파일에 기록될 때만 활성화된다. 확인 시간 간격을 CHECK_INTERVAL 변수로 정의하며 초로 나타낸다. 기본 값은 5초다. 이 간격은 최소 1초까지 설정할 수 있지만 경고가 최대한 빨리 생성되길 원하는 경우가 아니라면 보통 이렇게 작은 값으로 설정할 필요는 없다.

### Set the interval (in seconds) psad will use to sleep before
### checking for new iptables log messages
CHECK_INTERVAL              5;

  — SCAN_TIMEOUT
 기본적으로 SCAN_TIMEOUT 변수는 3600초(1시간)로 설정되며 psad는 이 값을 스캔이 추적되는 시간 간격으로 사용한다. 즉, 특정 IP 주소에서 악의적인 트래픽이 이 시간 간격동안 위험 수준 1에 도달하지 않으면 psad는 경고를 생성하지 않는다. ENABLE_PERSISTENCE를 Y로 설정하면 psad는 SCAN_TIMEOUT 변수를 무시한다.

### This is used only if ENABLE_PERSISTENCE = “N”;
SCAN_TIMEOUT                3600;  ### seconds

 — ENABLE_PERSISTENCE
 포트 스캔 탐지 소프트웨어는 일반적으로 포트 스캔을 잡기 위해 두 개의 임계치를 설정해야 하는데, 조사되는 포트 수와 시간 간격이 그것이다. 공격자는 스캔되는 포트의 수를 줄이거나 스캔의 속도를 줄여서 포트 스캔이 이 임계치에 도달하지 않게 할 수 있다. ENABLE_PERSISTENCE 변수는 psad가 SCAN_TIMEOUT 변수를 스캔 탐지의 요소로 사용하지 않게 해준다. 이는 스캐너가 수일이나 수주에 걸쳐 목표 시스템을 천천히 스캔함으로써 시간 만료 임계치보다 낮은 수준에 머물게 하려는 시도를 무력화하는 데 유용하다. 스캔이 최소 DANGER_LEVEL1 변수에 의해 정의된 패킷수에 도달하면(이 수에 도달하는 데 걸린 시간이 얼마나 긴지에 무관하게) psad는 경고를 전송한다.

### If “Y”, means that scans will never timeout.  This is useful
### for catching scans that take place over long periods of time
### where the attacker is trying to slip beneath the IDS thresholds.
ENABLE_PERSISTENCE          Y;

 — PORT_RANGE_SCAN_THRESHOLD
 이 변수를 통해 psad가 위험 수준을 포트 스캔에 할당하기 전에 스캔돼야 하는 포트의 최소 범위를 정의할 수 있다. 기본적으로 PORT_RANGE_SCAN_THRESHOLD는 1로 설정되며, 이는 위험 수준 1에 이르기 전에 최소한 두 개의 서로 다른 포트가 스캔돼야 함을 의미한다. 한 IP 주소가 한 포트만을 반복적으로 스캔할 수 있는데, 이 경우 psad는 경고를 전송하지 않는다(최소 위험 수준 1이 할당되지 않은 활동에 대해서는 절대 경고가 전송되지 않으며, psad에서는 경고가 전송되는 최소 위험 수준을 1에서 5까지로 설정할 수 있다. “EMAIL_ALERT_DANGER_LEVEL” 참조). psad가 스캔되는 포트의 범위를 탐지 요소로 사용하게 하고 싶지 않다면 PORT_RANGE_SCAN_THRESHOLD를 0으로 설정하면 된다.

### Set the minimum range of ports that must be scanned before
### psad will send an alert.  The default is 1 so that at
### least two port must be scanned (p2-p1 >= 1).  This can be set
### to 0 if you want psad to be extra paranoid, or 30000 if not.
PORT_RANGE_SCAN_THRESHOLD   1;

 — EMAIL_ALERT_DANGER_LEVEL
 이 변수는 어떤 IP 주소가 최소 이 값과 동일한 위험 수준으로 할당되지 않는 한 psad가 메일 경고를 전송하지 않게 하는 위험 수준의 최소 값을 설정하는 데 쓰인다. 기본 값은 1이다.

### Only send email alert if danger level >= to this value.
EMAIL_ALERT_DANGER_LEVEL    1;

 — MIN_DANGER_LEVEL
 MIN_DANGER_LEVEL 임계치는 psad가 수행하는 모든 경고와 추적기능을 위한 전역 임계치다. 예를 들어 MIN_DANGER_LEVEL이 2로 설정되면 psad는 특정 IP 주소가 위험 수준 2에 도달하기 전에는 이를 /var/log/psad/ip 디렉토리에 기록하지도 않는다. 그러므로 MIN_DANGER_LEVEL 변수는 항상 EMAIL_ALERT_DANGER_LEVEL 변수의 값보다 작거나 같게 설정해야 한다. 기본 MIN_DANGER_LEVEL 값은 1이다.

### Minimum danger level a scan must reach before any logging or
### alerting is done.  The EMAIL_ALERT_DANGER_LEVEL variable below
### only refers to email alerts; the MIN_DANGER_LEVEL variable
### applies to everything from email alerts to whether or not the
### IP directory is created within /var/log/psad/.  Hence
### MIN_DANGER_LEVEL should be set less than or equal to the value
### assigned to the EMAIL_ALERT_DANGER_LEVEL variable.
MIN_DANGER_LEVEL            1;

 — SHOW_ALL_SIGNATURES
 이 변수는 psad가 모든 경고에서 IP 주소와 관련된 모든 서명 경고 정보를 포함하게 할지 여부를 결정한다. 이 변수를 활성화할 경우 특정 IP 주소가 오새동안 의심스러운 트래픽으로 한 사이트에 접속할 때 매우 긴 메일 경고가 초래될 수 있기 때문에 이는 기본적으로 비활성화된다. 그러나 SHOW_ALL_SIGNATURES가 비활성화된 경우에도 psad 메일 경고는 마지막 CHECK_INTERVAL에서 새로 촉발된 서명은 모두 포함한다.

### If “Y”, means all signatures will be shown since
### the scan started instead of just the current ones.
SHOW_ALL_SIGNATURES         N;

 — ALERT_ALL
 이 변수가 Y로 설정되면 psad는 어떤 IP 주소로부터의 새로운 악의적인 활동이 위험 수준 1에 도달하는 한 이러한 활동이 탐지될 때마다 메일이나 syslog 경고, 또는 둘 모두를 생성한다. N으로 설정되면 IP 주소에 할당된 위험 수준이 증가할 때만 경고를 생성한다.

### If “Y”, send email for all newly logged packets from the same
### source ip instead of just when a danger level increases.
ALERT_ALL                   Y;

 — SNORT_SID_STR
 이 변수는 어떤 iptables 로그 메시지가 스노트 규칙 하나를 완전하게 기술하는 iptables 규칙에 의해 생성됐는지 알아보기 위해 iptables 로그 메시지와 매칭시킬 부분 문자열을 정의한다. 이런 iptables 규칙은 fwsnort가 생성하며 일반적으로 로깅 접두어 SID{n}을 포함한다. 여기서 {n}은 원본 스노트 규칙에서 얻은 스노트 ID 번호다. SNORT_SID_STR의 기본 값은 단순히 SID다.

### Search for snort “sid” values generated by fwsnort
### or snort2iptables
SNORT_SID_STR               SID;

 — ENABLE_AUTO_IDS
 이 변수는 Y로 설정되는 경우 psad를 수동적 모니터링 데몬에서, (INPUT 체인과 OUTPUT 체인을 통해) 로컬 시스템과 (FORWARD 체인을 통해) 로컬 시스템에 의해 보호되는 모든 시스템과 연동해서 공격자 IP 주소를 차단하기 위해 로컬 iptables 정책을 동적으로 재설정함으로써 공격에 능동적으로 응답하는 프로그램으로 변환한다.

### If “Y”, enable automated IDS response (auto manages
### firewall rulesets).
ENABLE_AUTO_IDS             N;

 — IMPORT_OLD_SCANS
 psad가 포트 스캔과 기타 의심스러운 활동에 대해 수집하는 정보는 /var/log/psad 디렉토리에 기록된다. 위험 수준 1에 도달한 모든 IP 주소에 대해 새 디렉토리 /var/log/psad/ip가 생성된다. 이 디렉토리에 저장되는 다양한 파일에는 가장 최근의 메일 경고, whois 출력, 서명 매칭, 위험 수준, 패킷 수가 포함된다. 처음 시작 시 psad는 보통 기존의 /var/log/psad/ip 디렉토리를 제거하지만 IMPORT_OLD_SCANS를 Y로 설정해서 기존의 디렉토리로부터 모든 데이터를 가져올 수 있다. 이 기능을 통해 이전 psad 인스턴스의 스탬 데이터를 잃지 않고 psad를 재시작하거나 전체 시스템을 재부팅할 수 있다.

### If “Y”, then psad will import old scan source ip directories
### as current scans instead of moving the directories into the
### archive directory.
IMPORT_OLD_SCANS            Y;

 — ENABLE_DSHIELD_ALERTS
 이 변수를 Y로 설정하면 psad는 스캔 데이터를 DSHield 분산 침입 탐지 시스템으로 전송한다. 스캔 정보는 민감한 정보일 수 있기 때문에 스캔 데이터를 DShield로 넘기면 해당 스캔 데이터는 더 이상 여러분의 제어 하에 있지 않으며 상대적으로 열린 데이터베이스로 구문 분석된다는 점을 알아야 한다. 그러나 DShield는 가장 일반적으로 공격당하는 서비스나 현재 대부분의 시스템을 공격하는 어떤 IP 주소가 무엇인지(이런 IP 주소는 엄격한 방화벽 규칙의 좋은 후보가 된다)에 대한 정보를 사용자가 좀 더 잘 이해할 수 있게 해준다. 필자(마이클 래쉬)는 DShield로 스캔 정보를 전송하면 안 된다는 엄격한 요구사항(예를 들어 사이트 보안 정책에서 이를 강제할 수 있다)이 없는 한 psad에서 이 기능을 활성화할 것을 강력히 권장한다. 많은 사람들이 이 기능을 활성화할수록 인터넷은 좀 더 안정해진다.

### Send scan logs to dshield.org.  This is disabled by default,
### but is a good idea to enable it (subject to your site security
### policy) since the DShield service helps to track the bad guys.
### For more information visit http://www.dshield.org
ENABLE_DSHIELD_ALERTS       Y;

 — IGNORE_PORTS
 많은 침입 탐지 시스템의 주요 기능은 관리자가 IDS로 하여금 완전히 무시하게 하고 싶은 데이터 조각을 필터링하는 기능이다. IGNORE_PORTS 변수는 psad가 목적지 포트 번호와 프로토콜(TCP나 UDP)에 기반해서 iptables 로그 메시지를 무시하게 한다. 포트 번위와 다중 포트, 프로토콜 조합은 다음과 같이 지정할 수 있다.

### define a set of ports to ignore (this is useful particularly
### for port knocking applications since the knock sequence will
### look to psad like a scan).  This variable may be defined as
### a comma-separated list of port numbers or port ranges and
### corresponding protocol,  For example, to have psad ignore all
### tcp in the range 61000-61356 and udp ports 53 and 5000, use:
### IGNORE_PORTS        tcp/61000-61356, udp/53, udp/5000;
IGNORE_PORTS                NONE;

 — IGNORE_PROTOCOLS
 IGNORE_PROTOCOLS 변수를 사용하면 psad는 전체 프로토콜을 무시할 수 있다. 대개는 iptables 정책을 조정해서 무시하고 싶은 프로토콜을 기록하지 않는 것이 더 좋지만 예를 들어 psad가 모든 ICMP 패킷을 무시하게 하고 싶다면 다음과 같이 IGNORE_PROTOCOLS를 설정하면 된다.

### allow entire protocols to be ignored.  This keyword can accept
### a comma separated list of protocols.  Each protocol must match
### the protocol that is specified in a Netfilter log message (case
### insensitively, so both “TCP” or “tcp” is ok).
### IGNORE_PROTOCOL             tcp,udp;
IGNORE_PROTOCOLS            icmp;

 — IGNORE_LOG_PREFIXES
 iptables 정책은 매우 복잡할 수 있으며, 다수의 여러 가지 로깅 규칙을 포함할 수 있다. 또 각 로깅 규칙은 자신만의 로깅 접두어를 가질 수도 있다. psad가 특정 로깅 접두어(예를 들어 DROP:INPUT5:eth1)를 무시하게 하고 십다면 IGNORE_LOG_PREFIXES를 다음과 같이 설정하면 된다.

### Ignore these specific logging prefixes
IGNORE_LOG_PREFIXES         DROP:INPUT5:eth1;

 — EMAIL_LIMIT
 어떤 경우에는 Iptables 정책이 특정 트래픽을 기록하게 설정되는데, 이 트래픽이 네트워크상에서 여러 번 반복될 수 있다(예를 들어 특정 DNS 서버로의 DNS 요청). 이러한 트래픽이 스캔이라고 해석되면 해당 트래픽 자체가 반복되기 때문에 psad는 이 트래픽에 대해 다량의 메일 경고를 전송할 수 있다. EMAIL_LIMIT 변수를 사용하면 psad가 스캐닝 IP 주소에 대해 전송되는 메일 경고의 수에 제한을 두게 강제할 수 있다. 기본 값은 0으로 이는 제한이 없다는 것을 의미한다. 그러나 EMAIL_LIMIT 값을 50으로 설정하면 psad는 특정 IP 주소에 대해 50개 이상의 메일 경로를 전송하지 않는다.

### Send no more than this number of emails for a single
### scanning source IP.  Note that enabling this feature may cause
### alerts for real attacks to not be generated if an attack is sent
### after the email threshold has been reached for an IP address.
### This is why the default is set to “0”.
EMAIL_LIMIT                 50;

 — ALERTING_METHODS
 대부분의 관리자는 psad가 제공하는 메일과 syslog 보고 모드를 모두 사용한다. 그러나 ALERTING_METHODS 변소를 이용하면 psad가 메일 경고와 syslog 경고 중 어떤 것을 생성하게 할지 제어할 수 있다. ALERTING_METHODS 변수는 noemail, nosyslog, ALL과 같은 세 가지 값을 가질 수 있다. noemail과 nosyslog 값은 psad가 메일이나 syslog 경고를 전송하지 않게 한다. 이 값들을 조합해서 모든 경고를 비활성화할 수도 있다. 기본 값은 둘 모두를 생성하는 것이다.

### Allow reporting methods to be enabled/restricted.  This keyword can
### accept values of “nosyslog” (don’t write any messages to syslog),
### “noemail” (don’t send any email messages), or “ALL” (to generate both
### syslog and email messages).  “ALL” is the default.  Both “nosyslog”
### and “noemail” can be combined with a comma to disable all logging
### and alerting.
ALERTING_METHODS            ALL;

 — FW_MSG_SEARCH
 FW_MSG_SEARCH 변수는 psad가 iptables 로그 메시지를 어떻게 검색할 지 정의한다. psad가 (iptables에 주는 –log-prefix 인자를 사용해 iptables LOG 규칙에 정의된) 특정 로그 접두어를 포함하는 로그 메시지만을 분석하게 제한하려면 FW_MSG_SEARCH 변수로 접두어를 정의하면 된다. iptables는 패킷에 FW_MSG_SEARCH 변수 값과 다른 로그 접두어를 할당하게 설정할 수 있으며 이 경우 psad는 해당 패킷을 분석하지 않는다.
 예를 들어 psad가 문자열 DROP을 포함하는 iptables 로그 메시지만을 분석하게 하려면 다음과 같이 FW_MSG_SEARCH 변수를 설정하면 된다.

### The FW_MSG_SEARCH variable can be modified to look for logging messages
### that are specific to your firewall configuration (specified by the
### “–log-prefix” option.  For example, if your firewall uses the
### string “Audit” for packets that have been blocked, then you could
### set FW_MSG_SEARCH to “Audit”;  The default string to search for is
### “DROP”.  Both psad and kmsgsd reference this file.  NOTE: You can
### specify this variable multiple times to have psad search for multiple
### strings.  For example to have psad search for the strings “Audit” and
### “Reject”, you would use the following two lines:
#FW_MSG_SEARCH               Audit;
#FW_MSG_SEARCH               REJECT;
FW_MSG_SEARCH               DROP;

 – /etc/psad/auto_dl
 모든 IDS는 항상 높은 확률로 긍정 오류를 범한다. 그러므로 IDS는 특정 시스템, 네트워크, 프토토콜이 모든 탐지 동작과 (가장 중요하게는) 자동화된 모든 응답 기능에서 제외될 수 있게 해주는 허용 목록 기능을 갖춰야 한다. 또 특정 IP 주소나 네트워크가 공격자로 알려질 수도 있으므로 이들을 차단할 차단 목록 기능도 필요하다.

 이러한 요구사항은 다음과 같은 구문을 따르는 psad의 auto_dl 파일이 충족시킨다.

#  <IP address>  <danger level>  <optional protocol>/<optional ports>;

 위험 수준이 0으로 설정되면 psad는 해당 IP 주소나 네트워크를 완전히 무시한다. 반대로 특정 IP 주소나 네트워크가 극도로 악의적이라고 알려지는 경우에는 위험 수준을 5로 설정할 수 있다.

# Examples:
#
#  10.111.21.23    5;          # Very bad IP.
#  127.0.0.1       0;          # Ignore this IP.
#  10.10.1.0/24    0;          # Ignore traffic from this entire class C.
#  192.168.10.4    3    tcp;   # Assign danger level 3 if protocol is tcp.
#  10.10.1.0/24    3    tcp/1-1024;  # Danger level 3 for tcp port range

 – /etc/psad/signatures
 /etc/psad/signatures 파일은 약간 수정된 스노트 규칙을 약 200개 정도 포함한다. 이 규칙들을 psad가 iptables 로그 메시지로부터 바로 탐지할 수 있는 공격을 나타낸다. 이 규칙 중 어떤 것도 네트워크 트래픽에 대한 애플리케이션 계층 검사를 필요로 하지 않는다. 애플리케이션 계층 검사는 fwsnort가 수행한다. 이 파일에 있는 규칙을 하나 예로 들면 다음과 같다.

alert udp $EXTERNAL_NET any -> $HOME_NET 31335 (msg:”DDOS Trin00 Daemon to Master”; reference:arachnids,187; reference:url,www.sans.org/resources/idfaq/trinoo.php; classtype:attempted-recon; psad_dsize:>2; psad_id:100002; psad_dl:2; psad_derived_sids:223,231,232;)

 – /etc/psad/snort_rule_dl
 /etc/psad/auto_dl과 유사하게 snort_rule_dl 파일은 psad가 스노트 규치고가 매칭되는 모든 IP 주소의 위험 수준을 자동으로 설정하게 한다. 이 파일의 구문은 다음과 같다.

# Syntax: Each non-comment line of this file contains a snort ID number, and
#         the corresponding psad danger level like so: <sid> <danger level>.

 위험 수준이 0이라면 psad는 해당 서명 매칭을 무시하고 어떤 경고도 전송하지 않는다. 일부 서명 매칭은 다른 것보다 더 안 좋을 수 있다. 예를 들어 psad가 스노트 규칙 ID 1812(EXPLOIT gobbles SSH exploit attempt)와 매칭되는 트래픽을 탐지 했다면 이는 잠재적으로 스노트 규칙 ID 469(ICMP PING MAP)에 대한 매칭보다 훨씬 더 위험하다. 물론 고블스(Gobbles) SSH 공격의 효과를 제한하는 가장 좋은 전략은 애초에 취약한 SSH 데몬을 실행하지 않는 것이지만 이 공격을 탐지하는 것은 여전히 중요하다. 다음과 같이 스노트 규칙 2284와 매칭되는 IP 주소의 위험 수준을 5로 설정할 수 있다.

### The following example illustrates the syntax for Snort SID 2284
2284   5;

 – /etc/psad/ip_options
 IP 헤더의 옵션 부분이 IP 통신에서 자주 사용되지는 않지만 iptables는 –log-ip-options 명령 행 인자를 이용해서 IP 옵션을 기록할 수 있다. iptables 로그 메시지가 IP 옵션을 포함하는 경우 psad는 소스 라우팅(source routing) 시도와 같은 수상한 활동에 대해 이 옵션을 구문 분석한다. 일부 스노트 규칙은 IP 옵션의 의심스러운 사용을 정의하며, psad는 iptables 로그 메시지의 IP 옵션을 해석하기 위해 /etc/psad/ip_options 파일을 참조한다. 이 파일은 다음 구문에 따라 일반적으로 사용되는 IP 옵션과 이에 대응되는 식별 번호를 정의한다.

#  <option value> <length (-1 for variable)> <ipopts argument> <description>

 아래는 이를 활용한 예문이다.

#  <option value> <length (-1 for variable)> <ipopts argument> <description>
0    1   eol         End of options list
1    1   nop         NOP
130  11  sec         Security
131  -1  lsrr        Loose Source Route
### (lsrre is included in Snort but not documented anywhere else)
132  -1  lsrre       Loose Source Route
68   -1  ts          Timestamp

 – /etc/psad/pf.os
 psad는 원격 운영체제를 수동적으로 핑거 프린팅하기 위해 p0f 프로젝트의 OS 데이터베이스를 사용한다. 이 데이터베이스는 psad가 /etc/psad/pf.os 파일에 설치하며, psad는 처음 시작할 때(또는 Psad가 kill 명령어나 psad -H를 통해 중단(hangup)이나 HUP 신호를 받았을 때) 이를 불러온다.

 다음은 리눅스에 대한 p0f 핑거프린트의 예다.

# S1:64:0:44:M*:A:              Linux:1.2::Linux 1.2.x (XXX quirks support)
512:64:0:44:M*:                 Linux:2.0:3x:Linux 2.0.3x
16384:64:0:44:M*:               Linux:2.0:3x:Linux 2.0.3x

4. 어플리케이션 계층 공격과 방어

 * iptables를 이용한 애플리케이션 계층 문자열 매칭

 모든 IDS가 가지는 가장 중요한 기능 중 하나는 애플리케이션 계층 데이터에서 악의적인 바이트를 암시라는 바이트 나열을 검색하는 것이다. 그러나 일반적으로 애플리케이션의 구조는 네트워크나 전송 계층 프로토콜보다 훨씬 덜 엄격하게 정의되기 때문에 침입 탐지 시스템은 애플리케이션 계층 데이터를 조사할 때 융통성을 가져야 한다.

 네트워크 트래픽에서 애플리케이션 부분 전체에 대해 문자열 매칭을 수행하는 것은 좋은 출발점이며, iptables 의 문자열 매칭 확장이 이를 제공한다.

 – 문자열 매칭 확장의 동작
 다음의 규칙은 TCP 포트 5001에서 대기 중인 Netcat 서버로 문자열 “tester”가 전송될 때 syslog 메시지를 생성하기 위해 iptables LOG 타겟을 사용한다

 #iptables -I INPUT 1 -p tcp –dport 5001 -m string –string “tester” –algo bm -m state –state ESTABLISHED -j LOG –log-prefix “tester”

 # iptables -I INPUT 2 -p tcp –dport 5001 -j ACCEPT

  명령어의 –algo bm 인자에 주목하자. 문자열 매칭 확장은 리눅스 커널의 텍스트 검색 기능 위에서 구현된다. 리눅스 커널의 텍스트 검색 기능은 보이어-무어 문자열 검색 알고리즘(위의 bm)과 크누스-모리스-프랫 문자열 검색 알고리즘(kmp) 등과 같이 다양한 알고리즘을 지원한다.

 * 애플리케이션 계층 공격 정의
 
 애플리케이션 계층 공격은 애플리케이션, 애플리케이션 사용자, 애플리케이션이 관리하는 데이터를 애플리케이션 소유자나 관리자가 허용하는 것 이외의 목적으로 전복하려는 시도로 정의한다.

 애플리케이션 계층 공격은 다음의 세 가지로 분류할 수 있다.

 — 프로그래밍 버그에 대한 공격 : 애플리케이션 개발은 복잡한 과정이며 프로그래밍 오류는 반드시 존재한다. 어떤 경우에는 이런 버그가 네트워크를 통해 원격으로 접근 가능한 심각한 취약점을 유발할 수 있다. 좋은 예로 안전하지 않은 C 라이브러리 함수의 사용으로부터 야기되는 버퍼 오버플로우 취약점, 부적절한 질의를 제대로 제거하지 않고 후단 데이터베이스로 넘기거나(SQL 인젝션 공격으로 이어질 수 있다), 사용자가 입력한 필터링되지 않은 내용을 사이트에 세재하는(크로스 사이트 스크립팅이나 XSS 공격을 야기할 수 있다) 웹서버와 같이 웹 중심 취약점이 있다.

 — 신뢰 관계에 대한 공격 : 어떤 공격은 애플리케이션 프로그래밍 버그 대신 신뢰 관계를 공격한다. 이러한 공격은 애플리케이션 그 자체와의 연동만 고려하면 완전하게 정당한 것처럼 보인다. 하지만 공격은 해당 애플리케이션의 사용자들이 가지는 신뢰를 대상으로 삼는다. 피싱 공격이 대표적이다. 피싱의 목표는 웹 애플리케이션이나 메일 서버가 아니라 피싱 웹사이트나 메일 메시지를 해석하는 사람이다.

 — 자원 소진 : 네트워크나 전송 계층 DoS 공격과 같이 애플리케이션도 때때로 다량의 데이터 입력을 받을 수 있다. 이러한 공격은 모든 사용자가 애플리케이션을 사용할 수 없게 한다.

 * 애플리케이션 계층 악용

 일반적인 네트워크와 전송 계층 프로토콜의 구현이 RFC에 정의된 사항을 거의 따르는 반면 특정 CGI 애플리케이션이 웹서버를 통해 사용자 입력을 처리하는 방법을 제어하거나 애플리케이션이 자동 경계 검사나 메모리 관리를 수행하지 않는 프로그래밍 언어(C 등)로 작성됐는지 제어하는 표준은 없다.

 – 스노트 서명
 애플리케이션 계층 공격을 이해하는 가장 좋은 방법의 하나는 스노트 서명 집합을 살펴보는 것이다. 최근의 스노트 서명은 스노트 소스 코드와 함께 배포되지 않지만 블리딩 스노트(Bleeding Snort) 프로젝트에서 최신 공격에 대한 서명을 스노트 형식으로 생성하고 있다(http://www.bleedingsnort.com 참조)

 – 버퍼 오버플로우 공격
 버퍼 오버플로우 공격은 애플리케이션 소스 코드에서 버퍼에 복사되는 데이터의 양을 충당하기에 버퍼의 크기가 충분하지 않은 부분에서 발생하는 프로그래밍 오류를 이용하는 공격이다. 그러므로 오버플로우라는 용어는 인접한 메모리 위치가 덮어쓰일 때 사용된다. 스택 기반 버퍼 오버플로우의 경우 성공적인 공격은 함수의 복귀 주소(스택에 존재)가 공격자의 코드를 가리키게 덮어 쓴다. 이를 통해 공격자는 그때부터 쭉 프로세스의 실행을 제어할 수 있다. 또 다른 분류의 버퍼 오버플로우 공격은 힙으로부터 동적으로 할당되는 메모리 영역에 적용된다.

 – SQL 인젝션 공격
 SQL 인젝션 공격은 사용자 입력이 데이터베이스 질의에 포함되기 전에 이것이 올바른지 확인하거나 필터링하지 않는 애플리케이션을 공격한다. 영악한 공격자는 새로운 질의를 생성해서 잠재적으로 데이터베이스의 정보를 수정하거나 추출하기 위해 SQL 언어의 충첩(nesting) 기능을 사용할 수 있다. SQL 인젝션 공격의 일반적인 목표는 웹서버를 통해 실행되며, 후단 데이터베이스로의 인터페이스를 제공하는 CGI 애플리케이션이다.

 – 그레이 매터 해킹(Gray Metter Hacking)
 오늘날 인터넷에서 가장 문제가 되는 공격의 일부는 직접 사람들이 사용하는 애플리케이션을 통해서 사람들을 목표로 하는 공격이다. 강력한 시스템, 애플리케이션, 암호화 기법의 취약점을 찾는 것보다 사람을 공격하는 것이 때로는 쉽다.

 — 피싱(Phishing)
 피싱(Phishing)은 사용자가 은행과 같은 온라인 계좌에 대한 인증 정보를 신뢰할 수 없는 곳에 제공하게 속이는 공격이다. 이 공격은 주로 공식적인 것처럼 보이는 메일을 사용자게 전송해서 이뤄지는데, 메일의 내용은 사용자가 온라인 계좌에 접속해서 보안상 “긴급한” 작업(예를 들어 암호 변경)을 수행해야 한다는 것이다. 정상적인 것처럼 보이는 웹 링크가 제공되지만 이는 원래의 웹사이트를 비슷하게 흉내낸 공격자 제어하의 웹사이트로 사용자를 유도하는 교묘한 링크다. 일단 피싱 공격을 당하는 사용자가 사이트에 방문해서 자신의 계정 정보를 입력하는 공격자는 재빨리 계정 정보를 가로챈다.

 — 백도어와 키보드 입력 로깅
 백도어(backdoor)란 공격자는 사용할 수 있지만 정당한 사용자는 사용할 수 없는 기능을 포함하는 실행 파일이다.  예를 들어 Sdbot 트로이목마는 공격자의 명령어 전송을 기자리는 IRC 채널로 연결하기 위해 특정 IRC 클라이언트를 사용해서 백도어를 연다. 하지만 백도어는 어떤 동작도 취하기 전에 공격자가 유효한 암호를 입력하게 만든 프로그램이다. 이는 백도어 통신의 인증 수준을 높여주며, 시스템에 성공적으로 침투한 공격자만이 그 시스템을 제어할 수 있게 해준다.

 * 암호호와 애플리케이션 인코딩

 애플리케이션 계층 공격을 탐지하기 어렵게 만드는 요소로 암호화와 애플리케이션 인코딩 기법의 두 가지를 곱을 수 있다. 암호화는 암호 키가 없는 한 암호를 평문화하는 것이 현실적으로 불가능하게 설계되며, 보통의 IDS, IPS 방화벽 장치는 이러한 키에 접근할 수 없기 때문에 특히 문제가 된다.

 그러나 일부 애플리케이션 계층 공격의 경우에는 성공을 위해 암호화가 필요가 없다. 예를 들어 SSH 서버에 대한 특정 공격을 탐지하는 스노트 서명(“평문 상태”에서 동작해야 함)이 있다. 이러한 서명이 사용되면 스노트는 SSH 암호화 키에 접근하지 않고 페이로드 데이터를 검색한다. 이러한 서명의 존재는 암호화만으로는 완벽한 방어를 할 수 없다는 것을 의미하며, 때때로 공격자는 통상적으로 요구되는 암호화 계층이 어떤 차이도 만들어내지 못하는 애플리케이션 취약점을 공격할 수 있다. 즉, 암호화되지 않은 수단을 통해 접근 가능한 함수 내부에 취약점이 존재할 수도 있다.

 인코딩 기술 역시 IDS가 다루기 어려울 수 있다. 예를 들어 보통 느린 네트워크로 압축하지 않은 데이터를 전송하는 것보다 빠른 CPU로 데이터를 압축하거나 압축 해제하는 것이 빠르기 때문에 많은 웹 브라우저가 네트워크를 통해 전송되는 데이터의 크기를 줄이기 위해 gzip 인코딩을 지원한다. 공격자가 약간의 무작위 데이터를 섞은 후 gzip으로 압축하면 IDS는 공격을 탐지하기 위해 이 데이터가 네트워크로 전송될 때 해당 데이터의 압축을 해제해야 한다. 무작위 데이터는 압축된 공격이 매번 달라 보이게 한다. 이러한 무작위화를 거치지 않으면 IDS는 공격을 식별하기 위해 압축 문자열 자체를 검색할 수 있다. 분주한 네트워크에는 악의적이지 않은 대용량 압축 파일을 다운로드 하는 웹 세션이 매우 많기 때문에 모든 웹 세션을 시시간으로 압축 해제하는 것은 계산상 비현실적이다.

 – IDS가 모든 애플리케이션 인코딩을 디코딩할 수 없는 것은 아니다. 예를 들어 웹 세션에서 URL 인코딩된 데이터는 스노트 서명 언어의 uricontent 키워드를 이용해서 스노트 HTTP 전처리기에 의해 실시간으로 디코딩된다. 이는 URL 인코딩이 16진수 코드와 % 기호를 사용하는 단순한 치환 연산을 통해 수행되기 때문에 가능하다. 예를 들어 A는 %41이 되며, 이는 동일한 방식으로 쉽게 복원할 수 있다. 이러한 인코딩 기법은 많은 계산을 필요로 하지 않는다.

 * 애플리케이션 계층 응답

 기술적으로 애플리케이션 계층 공격에 대한 순수한 애플리케이션 계층 응답은 애플리케이션 계층에 존재하는 구성소만을 포함해야 한다. 예를 들어 사용자가 애플리케이션을 악용하고 있다면 단순히 해당 계정을 비활성해야 되며, 공격자가 웹서버에서 실행되는 CGI 애플리케이션을 통해 SQL 인젝션을 시도한다면 질의를 무시하고 클라이언트로 HTTP 오류 코드를 반환해야 한다. 이러한 응답은 애플리케이션 계층 아래에 존재하는 패킷 헤더 정보의 변경을 필요로 하지 않는다.

 그러나 엄격한 애플리케이션 계층 응답은 방화벽과 네트워크 침입 방지 시스템에 적합하지 않다. 이는 방화벽과 네트워크 침입 방지 시스템이 보통 애플리케이션 자체와 긴밀히 통합돼 있지 않기 때문이다. 더욱이(양방향 통신을 필요로 하는) TCP 세션상에서 특정 IP 주소로부터 매우 악의적인 공격이 발견됐다면 그때부터는 공격자 IP 주소로부터의 모든 통신을 차단하는 것이 좀 더 유용할 수 있다. 이는 애플리케이션 계층 공격에 대한 네트워크 계층 응답이다.