Category Archives: Security

Linux #7 : Dos / DDos 공격에 대한 대처법. #1

수 많은 Site들이 Dos / DDos 공격으로 인해 피해를 보고 있다. 필자도 일본에선 별로 느껴보진 못했지만, 미국에 와서 Dos / Ddos 공격을 여러번 경험하고 실제 지금도 항상 Hacker들을 경계하고 있습니다. 그럼, Dos / DDos 공격이란 무엇인지 먼저 알아보죠.

Dos 공격이란 Daniel of Service attacks의 약자로 Network의 대역을 소비하게 만들거나, 대량의 request를 Server에 보내 connection을 증가시켜 Server를 사용 불능 상태로 만들거나, 더불어 Password를 알아내기 위해 여러 방법을 통해 접근을 시도하는 Brute Force 공격등도 행해지는데,  공격 주체가 1대의 host라면 특정가능하여 해당 IP를 제한하면 되지만 (여기까지가 Dos), 이 공격 주체가 특정할 수 없는 다수일 경우 DDos (Distributed Denial of Service) 공격이라하고, 이를 방지하기 위해선 다른 방법이 필요합니다.

그럼, Dos / DDos와 관련 된 여러 공격에 대한 대처 방법에 대해서 알아보도록 하죠.

SYN Flooding 공격

기본적으로 TCP Packet은 3 Way Handshaking에 의해 초기 Session이 이루어지게 되는데, 즉 SYN -> SYN / ACK -> ACK로 완료가 이루어져야 하지만 정상적인 Session으로 종료가 가능하지만, SYN Packet을 요청하고 SYN / ACK Packet을 Server에서 보내려고 할 때 보내려는 주소가 무의미한 주소여서 Server가 해당 Session을 대기상태 (SYN_RECV)에 놓게 되어 Server 대기 Queue의 증가로 인한 Server Resource가 증가로 정상동작을 할 수 없게 만드는 공격을 말합니다.

확인은 일단 Server가 비정상적으로 느려지고, 접속히 원활하지 않게 되며 netstat 명령어를 통해 SYN_RECV의 수를 체크 했을 시 SYN_RECV의 대기 Queue가 많이 증가하였다고 의심해 볼 필요가 있습니다.

# netstat -an | grep SYN_RECV
...
tcp        0      0 ::ffff:xxx.xxx.xxx.xxx:80    ::ffff:xxx.xxx.xxx.xxx:28719  SYN_RECV
tcp        0      0 ::ffff:xxx.xxx.xxx.xxx:80     ::ffff:xxx.xxx.xxx.xxx:61544   SYN_RECV
...

대처 방법은 아래와 같이 3가지가 있습니다.
첫번째는 Backlog size를 증가시켜 주는 방법으로 Default값에서 1024 ~ 그 이상의 값을 설정합니다.

# SYN Flooding attack block (need to increase backlog size)
net.ipv4.tcp_max_syn_backlog=16000

이 설정을 하게 됨으로 얼마정도 버틸 수 있게 되지만 지속적으로 공격을 당했을 경우 queue가 꽉차게 됨으로 두번째인 SYN Cookies도 활성화를 시켜야 합니다. SYN Cookies가 활성화가 되면 ACK 중에 포함된 확인 응답 번호를 계산하여, 올바른 Session인지를 확인하게 됩니다. Session이 올바른 경우 처리를 행하고, 그렇지 않은 경우의 Connection에 대해서는 System Resource를 낭비하는 걸 막을 수 있습니다.

# Activate SYN Cookies
net.ipv4.tcp_syncookies=1

1인 경우가 활성화된 상태이고, 0인 경우가 비활성 상태입니다. 이 두개의 값은

# echo '16000' > /proc/sys/net/ipv4/tcp_max_syn_backlog
# echo '1' > /proc/sys/net/ipv4/tcp_syncookies

와 같이 설정가능하고 또한,

# sysctl -w net.ipv4.tcp_max_syn_backlog=16000
# sysctl -w net.ipv4.tcp_syncookies=1

또, /etc/sysctl.conf에 추가를 한 뒤

# sysctl -p /etc/sysctl.conf

로도 가능합니다. /etc/sysctl.conf에 넣었을 경우 System Reboot시 자동으로 등록이 되게 됩니다. SYN Cookies를 활성화 하면 확인 응답번호의 계산에 따른 Packet처리에서 Overhead가 발생하게 되고, Packet 량에 따라 CPU 사용량이 증가하여 Bottleneck이 발생 할 가능성이 있습니다.
그리고, 마지막으로 Iptable을 이용하여 비정상적은 IP를 block하면 됩니다.

운영상의 편의를 위해 아래와 같이 Script를 작성해 보았습니다.

### Block_SYN_Flooding.sh
#!/bin/sh
# ================================================================
# -script name
# Block_SYN_Flooding.sh
# -script desc
# Block DDos Attack through the SYN Flooding
# -how to use
# ./Block_SYN_Flooding.sh $1 $2
# $1 Type
# $2 List File
# -NOTE
#
# -directory
# /home/scripts/security
# -create date
# 2010/06/22 NHN USA)Jeff KIM
# -Update
#
# ----------------------------------------------------------------
# -internal variable
# BASE Common lib directory
# LIB_ENV Location of env file
# FUNCTION Location of function file
# SCRIPT_NAME Script name
# APP_VERSion Application & History Number
# ================================================================
BASE=/home/scripts
SCRIPT_NAME="Block_SYN_Flooding.sh"
LIB_ENV=$BASE/setenv.conf
FUNCTION=$BASE/function
APP_VERSION=$BASE/app_version
. $LIB_ENV
. $FUNCTION
. $APP_VERSION
##################################################################
# start script
Startscript
Whoamiroot
MENU_INIT="[ start | stop | start_pp | stop_pp ]"
function Read_Iplist_File {
if [ "${IPS}" == "" ];then
Printmsg "ERROR" "Please, Input IP List File Path!"
Endscript
else
if test -r ${IPS};then
iRC=$?
if [ ${iRC} -eq 0 ];then
chkFile=1
else
chkFile=0
Printmsg "ERROR" "${2} File is not existed."
fi
fi
fi
}
if [ "${1}" == "" ];then
Printmsg "ERROR" "Please, Input Type (Usage: ${MENU_INIT} ) correctly!"
Endscript
else
TYPE=${1}
IPS=${2}
case ${TYPE} in
start)
PRC_NAME="Start IPtables to block ${2}.........."
Startprocess
Read_Iplist_File
if [ "${chkFile}" == "1" ];then
for ipaddress in `cat ${2}`;do
Printmsg "NOTICE" "/sbin/iptables -A INPUT -s ${ipaddress} -j DROP"
/sbin/iptables -A INPUT -s ${ipaddress} -j DROP
done
/sbin/iptables -L
fi
/etc/init.d/iptables save
/etc/init.d/iptables restart
Endprocess
;;
stop)
PRC_NAME="Stop IPTables to remove ${2}.........."
Startprocess
Read_Iplist_File
if [ "${chkFile}" == "1" ];then
for ipaddress in `cat ${2}`;do
Printmsg "NOTICE" "/sbin/iptables -D INPUT -s ${ipaddress} -j DROP"
/sbin/iptables -D INPUT -s ${ipaddress} -j DROP
done
/sbin/iptables -L
fi
/etc/init.d/iptables save
/etc/init.d/iptables stop
Endprocess
;;
start_pp)
PRC_NAME="Start IPtables to block SYN,FIN,RST from ALL IPs.........."
Startprocess
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP"
/sbin/iptables -A INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
/sbin/iptables -L
/etc/init.d/iptables save
/etc/init.d/iptables restart
Endprocess
;;
stop_pp)
PRC_NAME="Stop IPTables to remove SYN,FIN,RST from ALL IPs.........."
Startprocess
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags FIN,RST FIN,RST -j DROP
Printmsg "NOTICE" "/sbin/iptables -D INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP"
/sbin/iptables -D INPUT -p tcp --tcp-flags ACK,FIN FIN -j DROP
/sbin/iptables -L
/etc/init.d/iptables save
/etc/init.d/iptables stop
Endprocess
;;
*)
Printmsg "ERROR" "Please, Input Type (Usage: ${MENU_INIT} ) correctly!"
Endscript
;;
esac
fi
Endscript

위 Script에서 4개의 선택 메뉴가 있는데, MENU_INIT=”[ start | stop | start_pp | stop_pp ]”
start / stop은 Block_SYN_Flooding.sh start [IP_List_file]과 같이 IP List File을 지정하면 각 IP를 Block 할 수 있도록 되어 있습니다.
Stop을 하면 해제가 되구요. start_pp / stop_pp에 대해서는 IP가 너무많아 대응하기 힘든 경우 SYN Flooding과 관련 된 것들을 Iptable에서 몽땅 Drop 해버리는 겁니다. 실제 Web Service에서 문제없이 사용하고 있습니다. 그러나, 제가 다른 서비스에 대해서는 보장 못 해드립니다. ^ ^;

SYN Flooding 공격에 대한 대처법은 여기까지입니다.  Linux : Dos / DDos 공격에 대한 대처법. #2에서는 Smurf 공격 및 Spoofing 대처법 등에 대해서 다루도록 하겠습니다.

Linux #5 : System File Protection

Linux는 Windows만큼이나 Security에 취약성을 보이지는 않는다고 하지만 그렇다고 해서 그냥 두고 볼 일은 아니죠. Security 침해를 방지하기 위한 최소한의 아니 될 수 있는 한 많은 부분에 대해서 강화를 해야 합니다. 그럼, 먼저 System File Protection 부분에서 Security를 강화 해 보도록 하죠.

System File Protection이라고 하면, Linux System 안에서 사용되고 있는 각 종 File 및 System Directory에 대한 Permission, Ownership, Attribute 등이 될 것 입니다.

1. Boot Loader

chmod 600 /boot/grub/grub.conf
chmod 600 /boot/lilo.conf
chattr +i /boot/grub/grub.conf

2. /tmp, /var/tmp에 1777 permission

chmod 777 /tmp /var/tmp
chmod +t /tmp /var/tmp
chgrp 0 /tmp

3. /, /usr, /var에 755 Permission

755이상의 Permission이 할당되어 있다면 문제의 여지가 많습니다.

chmod 755 / /usr /var

4. User Home Directory Permission

해당 User ID에 대해서만 User Read, Write, Execute만 부여하고 (700), Group, Other에 대해서는 어떠한 Permission도 부여하지 않는 것이 중요합니다.

chmod 700 /home/*

여기서 중요한 건 1회성에 그치지 않도록 User가 생성될 때 자동으로 700을 부여 할 필요가 있는데 이는 아래와 같이 하면 됩니다. UMASK 022가 Default 일텐데, 077로 고쳐주세요.

# vi /etc/login.defs
..
UMASK 077
..

여기서 UMASK는 Permission을 다르게 표기하는데, 그냥 777 – 022 => 755 , 777 – 077 => 700 이렇게 생각하시면 되요.

5. 각종 System File에 각각의 Permission 및 Attribute 부여

/var 관련 부분

chmod 751 /var/log
chmod 644 /var/log/messages
chmod 660 /var/log/wtmp #Who is logged in now. Use who to view
chmod 640 /var/log/lastlog #Who has logged in befor. Use last to view
chmod 600 /var/spool/cron/root

/etc 관련 부분

chmod 600 /etc/crontab
chmod 640 /etc/syslog.conf
chmod 640 /etc/logrotate.conf
chmod 600 /etc/ftpusers
chmod 644 /etc/passwd
chmod 400 /etc/shadow
chmod 400 /etc/gshadow
chmod 750 /etc/pam.d
chmod 600 /etc/hosts.allow /etc/hosts.deny
chmod 600 /etc/securetty #TTY interfaces that allow root logins
chmod 700 /etc/security
chmod 750 /etc/rc.d/init.d /etc/init.d
chmod 751 /etc/sysconfig
chmod 400 /etc/cron.allow /etc/cron.deny
chmod 400 /etc/ssh
chmod 400 /etc/sysctl.conf
chmod 600 /etc/xinetd.conf /etc/inetd.conf
chmod 600 /etc/login.defs
chmod 644 /etc/services /var/run/syslogd.pid
chmod -R g-w /etc

6. System Binary File에 Permission & Attribute 부여

chmod 4750 /bin/su
chattr +i /bin/su
chmod 750 /usr/sbin/useradd
chmod 750 /usr/bin/top
chmod 750 /sbin/fdisk
chmod 750 /sbin/mfs*
chmod 750 /sbin/fsck*
chattr +i /usr/sbin/useradd
chattr +i /usr/bin/top
chattr +i /sbin/fdisk
chattr +i /sbin/mkfs*
chattr +i /sbin/fsck*
chmod 100 /bin/ping /bin/ping6
chmod g-s /usr/bin/wall
chmod g-s /usr/bin/write
chmod u-s /usr/bin/rlogin
chmod u-s /bin/umount
chmod g-s /sbin/netreport
chmod u-s /usr/bin/rsh

필요에 따라서 설정을 잘 조정 해야하니 주의하세요.