1/13/2007

[Linux] Apache Security (Linux Server Security)

1. Practical httpd.conf Configuration


1.1 Directory Listing

- 웹 브라우저에서 사용자가 URL을 입력했을 경우, Apache 웹 서버는 3가지 방법 응답한다. 정상적으로 웹 내용을 보여주든지, 디렉토리 리스트를 보여주든지, 에러 메시지를 보여준다.

- 원격의 공격자가 시스템에 대한 많은 정보를 획득할수록 보안 허점을 발견하기가 용이해 진다. 디렉토리 리스트를 보여주는 것 또한 불필요한 정보를 공격자에게 제공하여 공격에 이용될 수 있다. 백업 데이터, CGI 소스코드들, 필요에 의해 만들어 놓은 심볼릭 링크 등 서버 관리자가 실수로 지우지 않은 파일들이 공격자의 손에 들어갈 수 있다.

- DocumentRoot 디렉토리 내의 모든 파일들이 리스팅되는 것을 방지하기 위해서 “Options” 지시자에서 Indexes 옵션을 제거하여야 한다.


1.2 FollowSymLinks

- 몇몇 서버는 심볼릭 링크를 이용해서 기존의 웹 문서 이외의 파일시스템에 접근 가능하도록 하고 있다. 이러한 방법은 편리할 수는 있지만 심각한 보안 문제를 야기시킬 수 있다. 가령 시스템 자체의 root 디렉토리(/ )를 링크 걸게 되면 웹 서버 구동 사용자 권한(nobody)으로 모든 파일시스템의 파일에 접근할 수 있게 된다. 즉, /etc/passwd와 같은 대단히 민감한 파일까지 누구나 열람 가능하게 된다.

- “Options” 지시자에서 심볼릭 링크를 가능하게 하는 옵션인 FollowSymLinks 를 제거함으로써 이를 막을 수 있다.


1.3 DirectoryIndex

- DirectoryIndex는 사용자가 디렉토리 이름 끝에 슬래쉬(/)를 붙여서 디렉토리의 인덱스를 요구한 경우, 리턴할 자원의 목록을 지정하는 지시자 이다. 예를 들어 DirectoryIndex 지시자가 다음과 같이 설정되어 있고 클라이언트가 디렉토리 인덱스 http://www.domain.com/info/ 를 요구한 경우, 아파치는 제일 먼저 info 디렉토리에서 index.cgi 파일을 찾아서 리턴해준다. 그 파일이 없으면index.shtml 파일, index.html 순으로 찾게 된다.

DirectoryIndex index.cgi index.shtml index.html

- 그런데 여기서 리스트의 순서에 주의해야 한다. Index.html 파일이 존재한다 하더라도 공격자가 index.cgi 파일을 업로드 한다면, index.html 대신 index.cgi 파일이 처리될 것이다.
따라서 DirectoryIndex의 목록이 적절하게 배열되어 있는지 점검해야 한다.


1.4 ServerTokens

- 클라이언트가 Apache 웹 서버에 접속했을 때 웹 서버에서는 응답 메시지의 헤더에 웹 서버 버전, 설치된 응용프로그램 등과 같은 정보를 전달한다.

[root@mitnik conf]# telnet 192.168.152.129 80
Trying 192.168.152.129...
Connected to 192.168.152.129.
Escape character is '^]'.
GET / HTTP/1.1
HTTP/1.1 400 Bad Request
Date: Mon, 03 Jan 2005 03:04:03 GMT
Server: Apache/2.0.50 (Unix)
Content-Length: 301
Connection: close
Content-Type: text/html; charset=iso-8859-1
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>400 Bad Request</title>
</head><body>
<h1>Bad Request</h1>
<p>Your browser sent a request that this server could not understand.<br />
</p>
<hr />
<address>Apache/2.0.50 (Unix) Server at 192.168.152.129 Port 80</address>
</body></html>
Connection closed by foreign host.

- 이 정보는 공격자에 의해 Apache 웹 서버 버전별 또는 구동되고 있는 응용프로그램에 잘 알려진 취약점을 공격하는데 유용하게 이용될 수 있으며, 인터넷 웜과 같은 자동화된 공격에서도 이러한 banner 정보가 사용되어지기도 한다. 따라서 공격자에게 웹 서버의 버전과 같은 banner 정보를 숨기는 것이 안전하다.

- Apache 웹 서버에서는 ServerTokens 지시자를 수정함으로써 헤더에 의해 전송되는 정보를 바꿀 수 있다.

Syntax : ServerTokens Minimal ProductOnly OS Full

- ServerTokens 지시자에서 설정할 수 있는 각 키워드에 의해 나타나는 정보는 다음과 같다.
(키워드) (제공하는 정보) (예)
Prod[uctOnly] -- 웹 서버 종류 -- Apache
Min[imal] -- 웹 서버 종류 + 버전 -- Apache/2.0.50
OS -- 웹 서버 종류 + 버전 + 운영체제 -- Apache/2.0.50(Unix)
Full -- 웹 서버 종류 + 버전 + 운영체제 + 설치된 모듈(응용 프로그램) 정보 -- Apache/2.0.50(Unix)PHP/4.3.0

- ServerTokens는 Apache 1.3 이상에서 가능하고 ProductOnly 키워드는 1.3.12 이상의 버전에서 사용 가능하다. 일반적으로 ServerToken은 httpd.conf에서 명시되어 있지 않는 경우가 많은데 이럴 경우에는 기본값인 ServerTokens Full 이 적용되어 운영체제 정보, 웹 서버 정보, 버전정보, 설치된 모듈 정보 등이 모두 서버의 응답 헤더에 포함되어 클라이언트에게 전송된다.

- 최소한의 정보를 주기 위해서 ServerTokens Prod 를 설정하는 것이 바람직하다. 혹자는 공격자를 속이기 위해서 서버의 헤더 정보를 앞에서 명기한 내용과는 전혀 다른 내용으로 조작하여 클라이언트에 보내기를 원할 수도 있는데 이 경우에는Apache 소스코드를 수정해서 재 컴파일 하여야 하므로 권고하지 않는다.


1.5 ServerSignature

- ServerSignature는 서버가 만든 문서의 꼬리말(trailing footer)을 설정하다. 이러한 꼬리말이 필요한 이유는 프락시 체인 형성시, 사용자가 실제로 어느 서버가 에러 메시지를 리턴 했는지 알 수 있도록 하기 위해서다. 이 값이 on으로 설정되어 있으면 아파치 버전과 가상호스트의 ServerName, ServerAdmin이 노출된다.

- ServerSignature를 off로 설정하면 아무런 정보를 보여주지 않는다.


1.6 PUT 과 POST 제한

- 원격 사용자는 DocumentRoot 디렉토리 구조에 파일을 업로드 하거나 수정하는 행위가 제한되어야 한다. 물론 DocumentRoot의 파일/ 디렉토리 퍼미션을 사용해서도 웹을 통한 파일 업로드 및 수정을 막을 수는 있다. 하지만, 적절한 제한이 이루어지지 않을 경우 홈페이지가 변조되거나 웹 사이트가 침해 당할 수 있으므로 태그를 이용하여 각 디렉토리별로 HTTP Method의 사용여부를 통제할 수 있다. 파일 업로드 및 파일의 수정을 위해서 사용되는 HTTP Method는 PUT과 POST이다.

- 다음의 예는 개인 사용자 홈디렉토리에서 POST, PUT, DELETE Method를 패스워드 파일에 등록된 사용자만이 이용 가능 하도록 제한한 것이다.

<directory /home/*/public_html>
<limit POST PUT DELETE>
Require valid-user
</limit>
</directory>


1.7 CGI Script Execute Limitatioin

- 사용자들이 CGI 스크립트들을 어느 디렉토리에서나 실행할 수 있도록 할 경우 악의적인 사용자가 CGI 프로그램을 업로드 한 후 이를 실행하여 임의의 명령을 실행시킬 수 있다. 따라서, CGI 프로그램의 실행은 관리자가 지정한 특정 디렉토리에서만 가능하도록 제한할 필요가 있다.

- CGI 실행은ScriptsAlias 지시자에 의해서 실행 가능한 디렉토리를 제한할 수 있다. ScriptsAlias 지시자 문법은 다음과 같다.

Syntax : ScriptAlias URL-path file-path directory-path

- 예를들어 cgi-bin이라는 디렉토리에서만 실행 가능 하도록 할 경우 다음과 같이 지정할 수 있다.

ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/ "

- 앞서 언급한 디렉토리 리스팅, 심블릭 링크, SSI 등에 대한 제어는 “Options” 지시자에 의해 제어가 가능하다.

Syntax : Options [+-]option [[+-]option]...

- Options지시자에 ExecCGI를 설정하는 방법은 다음과 같다. CGI스크립트의 실행을 허용할 디렉토리의 디렉토리 섹션에서 Options 지시자 옆에 ExecCGI를 명시하고, AddHandler로 CGI스크립트로 처리할 파일의 확장자를 지정해주면 된다.

<directory “/home/httpd/html/cgi-bin”>
Options ExecCGI …
...
</directory>
...
AddHandler cgi-script .cgi

- 운영중인 웹 서버의 경우 설정 파일을 분석하여 CGI스크립트가 실행될 필요가 없는 디렉토리에 대해 위와 같은 방법으로 CGI스크립트가 실행 가능하도록 설정되어 있는지 점검해볼 필요가 있다.


2. Authentication & Access Control


- 접근을 허락하기에 앞서 사용자나 호스트 인증과 접근통제를 위한 몇몇 기능이 Apache에 있다. 이는 특정한 IP 주소나 서브넷에 따라서 접속을 허락하거나 거부할 수 있고, 사용자 이름과 패스워드에 의해서 사용자를 인증할 수도 있다.

- 아파치에서 일반적인 인증 절차는 다음과 같다. 클라이언트가 특정 자원을 요청하고 그 자원이 인증 기능을 통해서 보호되었다면, 아파치는 클라이언트의 요청에 대한 응답으로 401 Authentication Required 헤더를 보내서 클라이언트에게 사용자 증명서(credential)를 요구한다. 클라이언트는 401 response 헤더를 받으면, 위 그림과 같이 사용자에게 아이디와 패스워드를 요구한다. 사용자가 아이디와 패스워드를 입력하면, 클라이언트는 그 값을 서버에게 전송한다. 그러면 서버는 아이디와 패스워드가 정확한지 점검한 후에, 요청된 자원을 클라이언트에게 전달한다.

■ Basic Authentication
HTTP는 stateless 프로토콜이므로 기본적인 사용자인증에 의해 보호되는 자원에 접근하기 위해서는 매번 사용자 이름과 패스워드와 같은 인증서를 서버에 보내야만 한다. 하지만 초기 인증을 거친 후 다른 페이지에 접근하기 위해서 매번 사용자 이름과 패스워드를 서버에 전송하는 것은 일반적으로 클라이언트 소프트웨어나 웹 브라우저에 의해서 자동으로 이루어진다. 만약 사용자 이름이 웹 서버의 리스트에 있고, 패스워드가 일치하면 보호된 자원에 접근을 허락 받게 된다.
기본적인 인증에서는 패스워드가 암호화되어서 저장되지만 클라이언트에서 서버로 전송되는 도중에는 암호화되지 않아 제 3자에 의해서 도청될 수 있다. 보호된 자원에 접속하는 매 순간마다 ID와 패스워드가 전송되므로 telnet, ftp 등 인증을 하는 다른 서비스보다 쉽게 도청이 가능하다. 뿐만 아니라 서버에서 클라이언트로 전송되는 어떠한 데이터에 대해서도 암호화가 제공되지 않으므로 내용도 가로채기가 용이하다. 따라서 기밀성이 중요시되는 웹 서버에서는 이러한 인증은 권장할 수 없다.

■ Digest Authentication
두 번째 인증 방법으로는 다이제스트 인증이 있는데 기본적인 인증과의 차이점은 네트워크 등 전송로 상에서 패스워드가 평문으로 전송되지 않는다는 점이다. 패스워드는 MD5 암호화 해쉬를 시킨 후 전송한다. 다이제스트 인증은 패스워드를 암호화해서 전송하고는 있지만 데이터는 평문으로 전송되므로 문제점을 가지고 있고, 또한 모든 웹 브라우저가 다이제스트 인증을 지원하지는 않는다는 문제점이 있다.

■ Database Authentication
DB 인증 모듈은 사용자 이름과 패스워드를 보다 신속하게 확인할 수 있도록 한다. 서버에 다수의 사용자 이름과 패스워드가 저장되어 있을 경우 사용자가 데이터에 접근하기 위한 인증과정에 많은 시간이 소모될 수 있다. 일반 파일 시스템이 아닌 DB를 이용할 경우 사용자 이름과 패스워드 확인 시간을 대단히 단축할 수 있다.


3. Basic Authentication


- 기본 사용자 인증과 다이제스트 사용자 인증의 설정 방법은 대단히 유사한데 다음과 같은 절차를 거쳐서 설정할 수 있다.

* 패스워드 파일 생성
* 패스워드 파일을 사용할 수 있도록 Apache 환경 설정

** 패스워드 파일 생성
- 패스워드 파일은 외부에서 외부에서 접근이 불가능한 곳에 위치해야 한다. 파일 내부에는 암호화가 되어 있기는 하지만 패스워드 파일 획득시 복호화가 가능하기 때문이다.

- 다음 과정은 htpasswd 프로그램을 이용하여 패스워드 파일을 생성하는 과정이다.

# htpasswd -c /usr/local/.passwd demantos
New password:
Re-type new password:
Adding password for user demantos

- 새로운 사용자를 추가하고자 할 때는 -c 옵션을 빼고 해야 한다. -c 옵션은 패스워드 파일을 새로 생성하기 때문에 사용자 추가시 이 옵션을 사용하면 기존 사용자에 대한 패스워드가 사라지게 된다.

# htpasswd /usr/local/.passwd mitnik
New password:
Re-type new password:
Adding password for user mitnik

- 패스워드 파일은 최소한의 퍼미션만 있어야 한다.

# chown root.nobody /usr/local/.passwd
# chmod 640 /usr/local/.passwd

- 이 때 패스워드 파일에 대한 퍼미션을 수정하지 않으면 정상적으로 패스워드를 입력하여도 접근이 불가능하다. 웹을 통해 접근하는 사용자는 nobody의 권한을 가지고 있으므로 nobody라는 사용자나 그룹이 적어도 읽기는 가능해야 한다. 퍼미션을 644로 할 수도 있지만 root 사용자나 nobody 그룹 이외에는 접근을 하지 못하게 하기 위해서 위와 같이 설정을 해주는 것이다.

** httpd.conf 수정
- 패스워드 파일을 사용하기 위해 httpd.conf 파일을 수정한다. 인증을 원하는 경로를 지정하고 다음과 같이 쓸 수 있다.
<directory "/usr/local/httpd/htdocs/admin">
AuthType Basic
AuthName "SecuBits"
AuthUserFile /usr/local/.passwd
Require user demantos
</directory>
􀁹 AuthType : 인증 타입. 여기서는 Basic
􀁹 AuthName : 인증영역 식별자(realm)
􀁹 AuthUserFile : 패스워드 파일의 위치
􀁹 AuthGroupFile : 그룹 파일의 위치 (선택사항)
􀁹 Require : 허가를 주기 위해 만족시켜야 하는 요구사항들

- 위의 예제는 /admin 이라는 경로는 demantos 만이 접근이 가능하게 설정되어 있다. 패스워드 파일에 지정되어 있는 모든 사용자에 대해서 접근을 허가하고자 한다면 다음과 같이 쓸 수 있다.

<directory "/usr/local/httpd/htdocs/admin">
AuthType Basic
AuthName "SecuBits"
AuthUserFile /usr/local/.passwd
Require valid-user
</directory>

4. Digest Authentication


- Digest Authentication은 mod_auth_digest 모듈에 의해 구현되었다. 이 인증방식의 특징은 패스워드가 MD5 digest 형태로 전송된다는 것이다. 이 방식을 사용하기 위해서는 mod_auth_digest가 설치되어야 한다.

- 이 모듈은 아파치 설치시 --enable-auth-digest 옵션을 주어 아파치를 설치해야 한다.

- 기본 인증 방식과 패스워드 파일 생성 방법은 비슷하다. 다른 점은 인증영역 식별자가 인자 값으로 들어간다는 것이다.

# htdigest -c /usr/local/.digest_passwd secubit demantos
Adding password for demantos in realm secubit.
New password:
Re-type new password:

- secubit은 인증영역 식별자로, httpd.conf 파일에서 AuthName 지시자를 사용해서 지정되는 이름과 동일해야 한다. 기존 패스워드 파일에 추가하는 경우에는 -c 플래그를 생략하도록 한다.

- 생성된 패스워드 파일은 반드시 문서 디렉토리 밖에 저장하여 외부에서 접근이 불가능하도록 해야 한다. 비록 내용이 암호화되어 있더라도 우선 접근이 가능하면 패스워드를 알아낼 수 있는 기회가 주어질 수 있기 때문이다. 또한 사용자들로 하여금 웹사이트의 패스워드와 다른 중요한 것들의 패스워드를 다르게 사용하도록 권장한다.

<directory "/usr/local/httpd/htdocs/digest">
AuthType Digest
AuthName "secubit"
AuthDigestFile /usr/local/.digest_passwd
Require valid-user
</directory>

5. Database Authentication


- Basic authentication과 digest authentication은 둘 다 인증 정보를 저장하는데 텍스트 파일을 사용하는 단점이 있다. 텍스트 파일은 인덱싱이 안되기 때문에 검색 속도가 느리다. 또한 HTTP가 stateless이기 때문에 컨텐츠가 요청될 때마다 인증이 수행되어야 하고 텍스트 파일에서 검색을 수행해야 한다. 최악의 경우 사용자 이름 이 텍스트 파일에 없으면 파일의 모든 라인을 점검해야 한다.

- 사용자가 적은 경우에는 이것이 큰 문제가 되지 않지만, 사용자가 많은 경우 웹 서버의 응답이 매우 느려진다. 실제로 많은 경우 정상적인 사용자 이름과 패스워드를 입력해도 인증 모듈이 그 파일에서 사용자를 찾는데 시간이 엄청나게 걸리기 때문에 아파치가 인증 실패를 리턴 할 수 있다. 이런 경우에 다른 대안으로 데이터베이스를 사용하는 것이 좋다. 아파치는 다양한 데이터베이스를 사용해서 인증을 수행할 수 있도록 많은 모듈을 제공한다.

- mod_auth_dbm 모듈은 사용자이름과 패스워드를 DBM 파일에 저장할 수 있게 한다.

- 만약 사용하고 있는 플랫폼에서 DB 지원을 하지 않는다면 설치를 해야 한다. Berkeley 데이터 베이스 파일로 알려진 DB 파일은 가장 간단한 형태의 데이터베이스로서 HTTP 인증에 적합하다. DB 파일은 키와 값의 페어를 저장한다. 즉, 변수의 이름과 변수의 값을 저장한다. 다른 데이터베이스는 한 레코드에 많은 필드가 저장될 수 있지만, DB 파일은 키와 값의 페어만을 저장한다. 이것은 사용자 이름과 패스워드를 요구하는 인증에 아주 적합하다.

- 이 방식도 digest 방식과 같이 사용하기 위해서는 mod_auth_dbm가 설치되어야 한다. 이 모듈은 아파치 설치시 다음 옵션으로 설치 할 수 있다.

--enable-auth-dbm

사용자 파일 생성

- 여기서 사용되는 파일은 일반 텍스트 파일이 아니라 DB 파일이다. dbmmanage 라는 유틸로 파일을 생성할 수 있다.

# dbmmanage /usr/local/.passwd.dat adduser demantos
New password:
Re-type new password:
User demantos added with password encrypted to I3kmoSjOBRtGQ using crypt

- 아파치 설정은 다음과 같다.

<directory "/usr/local/httpd/htdocs/dbm">
AuthType Basic
AuthName "SecuBits - DBM Authentication"
AuthDBMUserFile /usr/local/.passwd.dat
AuthDBMType GDBM
Require user demantos
</directory>

6. Access Control


- 아파치에서의 접근 제어는 탄력이 있다. 이 말은 관리자가 어떻게 설정하느냐에 따라서 그 결과는 천차만별이라는 것을 뜻한다. 자세한 설정을 보기 전에 먼저 영역이나 범위를 설정하는 지시어에는 다음과 같은 것이 있다.

<directory></directory>
<directorymatch></directorymatch>
<files></files>
<filematch></filematch>
<location></location>
<locationmatch></locationmatch>
<limit></limit>
<limitexcept></limitexcept>

- 위의 지시어들은 접근을 제어할 영역이나 범위 혹은 패턴을 정의한다. 이런 지시어들을 사용하여 특정 디렉토리나 특정 파일들에 대해서만 접근을 제어할 수 있다. 아주 간단한 예제 하나를 보면

<filematch ^(.*\.pl | .*localconfig.* | check.sh)$>
deny from all
</filematch>

- 이것은 확장자가 .pl이거나 localconfig라는 문자열을 포함하거나 check.sh와 파일이름이 매치가 되면 모든 접근을 거부한다는 것이다. ^는 시작을 의미하고 $는 끝을 의미한다.

- 위의 예제에서 보이는 영역 내부에 들어 있는 접근 제어 지시어에 대해서 알아보면

** mod_access에 의한 접근 제어
- 클라이언트가 사용하는 호스트의 IP 주소나 도메인에 의해서 웹 서버의 데이터에 대한 접근을 통제할 수 있다. 기본적인 서버 설정은 DocumentRoot의 내용에 대해 누구나 접속을 허락하도록 설정되어 있다. Apache의 Allow 와 Deny 지시자는 사용자 시스템의 호스트 이름과 호스트 주소를 근간으로 접속을 허락 또는 차단할 수 있도록 지정할 수 있다. 또한, Allow와 Deny 지시자를 동시에 사용할 경우 그 순서를 정하는 Order 지시자를 사용하여 보다 정교한 정책설정을 할 수 있다.

- 또한 이 지시자들은 위의 인증방식들과 함께 사용하여 더욱 강력한 인증 정책을 수립할 수 있다.

􀁹 Order Deny, Allow : deny 지시자가 allow 지시자보다 먼저 검사된다. 접근은 기본적으로 허용된다. 즉, deny 지시자나 allow 지시자에 일치하지 않는 클라이언트의 접속은 허용한다.
􀁹 Order Allow, Deny : allow 지시자가 deny 지시자보다 먼저 검사된다. 접근은 기본적으로 차단된다. 즉, deny 지시자나 allow 지시자에 일치하지 않는 클라이언트의 접속은 차단한다.
􀁹 Order Mutual-failure : allow 리스트에 있고 deny 리스트에 없는 호스트만 접근을 허용한다. 순서는 allow, deny 일 때와 같다.

- ex)
Order Allow,Deny
Allow from all
Deny from 203.238.110.121
- 이 설정은 203.238.110.121 이라는 아이피만 차단한다.

Order Deny,Allow
Deny from all
Allow from .company.com
- 이 설정은 .company.com 도메인 즉, 회사내부에서만 접속이 가능하도록 하는 설정이다.

deny from 192.110.50
deny from domain.com attacker.com
deny from tld
- 이 설정은 192.110.50 C 클래스의 아이피나 domain.com attacker.com 그리고 탑 레벨 도메인으로부터 접근을 막는 설정이다. tld는 Top Level Domain의 약자로 .com 이나 .gov, .net 과 같은 탑 레벨 도메인을 의미한다.

- 여기에 추가적으로 Satisfy 라는 지시자가 있는데 인증방식과 접근 제어 방식을 같이 사용할 때 사용된다.

- 권한 부여는 특정한 자원에 접근할 사용자 퍼미션이 유효한지를 확인하는 과정이다. 어떤 퍼미션에 의해 허락되고 거부될지는 자원과 그 자원과 관련된 규칙들에 따라 서 대단히 다양하다. 각 파일과 디렉토리 구조는 다른 접근통제나 사용자 인증 방법을 가질 수 있다. 접근통제와 사용자 인증 방법을 사용하여 각 자원에 대한 다양한 권한을 부여할 수 있다. 가령 인터넷에서 접속 시에는 사용자 이름과 패스워드를 확인하고 인트라넷에서 접속시에는 요구하지 않도록 설정할 수도 있다. 이는Satisfy 지시자를 통해서 구현할 수 있다. 즉, Satisfy 지시자는 사용자 인증(Require에 의한)과 클라이언트 호스트 주소에 따른 접근통제(Allow에 의한)를 동시에 사용하여 정책설정을 할 때 쓰인다.

Syntax : Satisfy any all

- 다음 예는 인트라넷 밖에서의 모든 접속시 패스워드를 요구하고 인트라넷 내부의 사용자들은 패스워드 없이 접속을 허용하도록 설정한 예이다.

order deny ,allow
deny from all
allow from 172.16.5
AuthType Basic
AuthName "Welcome SecuBits"
AuthUserFile /usr/local/.passwd
Require valid-user
Satisfy Any

- AuthType 에 의해 인증을 거치거나 혹은 내부사용자일 경우 두 가지 조건 중 하나만 맞으면 정상적으로 접근이 가능하다. 하지만 이 방법은 추천되는 방법은 아니다. 정말 중요한 네트워크라면 두 가지 조건을 모둔 만족하게 하는 Satisfy All로 설정을 해주어야 한다. 물론 인증 방식 또한 기본 인증 방식이 아닌 다이제스트 인증 방식이나 데이터베이스 인증 방식을 채택하는 것이 안전하다.

- 이외에도 Extended Access Control 모듈이나 Realtime Blackhole List 모듈에 의해서 접근을 제어할 수 있다.

** 확장자별 접근 제어
- 디렉토리 인섹싱이 되지 않는다면 공격자들은 절대경로를 사용하여 원하는 파일을 얻어낼려고 할 것이다. 이 때 사용되는 파일의 확장자 중 특정 확장자는 웹을 통해서 접근을 못하게 할 수 있다.

<directory /usr/local/httpd/htdocs>
Order deny, allow
Deny from all
<filematch “\.(html?|jpe?g|bmp|gif)$”>
Order deny, allow
Allow from all
</filematch>
ErrorDocument 403 /access_deny.html
</directory>

- 위의 설정은 html, jpg, bmp, gif 파일 이외의 파일은 접근이 허용되지 않으며, 이외의 파일에 접근시 접근 에러 메시지가 담긴 access_deny.html의 내용을 보여주게 된다.

- 위의 내용을 약간 변경시켜서 다음과 같이 사용할 수 있다.

<directory /usr/local/httpd/htdocs>
Order deny, allow
Allow from all
<filematch “\.(conf(ig)?|bak|tmp)$”>
Order deny, allow
Deny from all
</filematch>
ErrorDocument 403 /access_deny.html
</directory>

- config, conf, bak, tmp의 확장자를 갖는 파일들에 대해서는 접근을 제한하게 된다.

- rewrite 모듈을 사용하여 접근을 제한할 수도 있지만 만약 rewrite 모듈을 설치하지 않았을 경우 mod_access는 기본적으로 설치되는 모듈이기 때문에 이렇게 지정할 수도 있다.

** 환경 변수별 접근 제어
- 클라이언트의 환경에 따라 접근을 허용할지 안할지를 결정할 때 사용된다. 보통 브라우저에 많이 적용을 시키게 되는데 클라이언트가 MSIE로 접속할 때만 허용하고 다른 웹 브라우저인 경우에는 접근을 제한하게 한다. 이것은 보안보다는 서버의 성능과 환경이 MSIE에 맞추어져 있기 때문에 최대의 성능 위해서 사용하는 경우가 많다.

BrowserMatch ^MSIE InternetExplorer
<directory /msie_html>
Order deny, allow
Deny from all
Allow from env=InternetExplorer
</directory>

- ^MSIE 는 HTTP 헤더 중 User-Agent에 클라이언트의 브라우저에 대한 정보가 있는 부분을 이야기한다. 시작이 MSIE일 경우를 InternetExplorer라는 환경 변수에 지정을 하고 이 환경 변수와 일치할 때만 접근을 허용하는 정책이다.