Bảo mật web server Apache với mod Security
Giới thiệu:
Mod_security là một opensource web application firewall được Ivan Ristic 
phát triển dành cho Apache Web Server. Ivan Ristic là tác giả quyển sách.Ông là 
một người có rất nhiều kinh nghiệm trong bảo vệ Apache Web Server. Ông đã có 
nhiều thời gian nghiên cứu Web Application Security, Web Intrusion Detection, và 
Security Patterns. Trước khi chuyển sang lĩnh vực security, Ivan đã có nhiều năm 
làm việc như một developer, system architect, technical director trong phát triển 
phần mềm. Ông là người sáng lập ra công ty ThinkingStone làm các dịch vụ liên 
quan đến web application security. 
 Hiện tại mod_security sử dụng giấy phép GPL, hoàn toàn miễn phí. Ngoài ra 
nếu muốn có sự hỗ trợ thì bạn có thể mua nó tại công ty ThinkingStone của ông 
()
Các tính năng của mod_security
• Logging traffic HTTP
• Real-Time Monitoring and attack Detection
• Attack Prevention and just in time patching
• Flexible rule engine
• Embedded-mode Deployment
• Network-based Deployment
• Licensing
Cài đặt và cấu hình mod_security:
Trước khi cài đặt chúng ta cần cài các thư các thư viện apxs, libxml2 và load thêm 
mod_unique_id.so
 Cài đặt thư viện 
yum install httpd-devel libxml2-devel pcre-devel curl-devel apr-devel
Load module mod_unique_id.so 
- mod_unique_id : module của apache có nhiệm vụ phát sinh một unique 
indentifier cho mỗi HTTP request (xem thêm tại 
 e_id.html) . Module này thường 
được compile sẵn khi ta build apache , để sử dụng được cần phải load module này 
lên trong file httpd.conf . Mở file httpd.conf và thêm vào dòng sau ở phần 
LoadModule :
LoadModule unique_id_module modules/mod_unique_id.so
 Download và giải nén source code :
- Download phiên bản stable mới nhất tại  />[root@hungn src]# cd /usr/src
[root@hungn src]# wget ' />apache_2.6.0.tar.gz'
- Giải nén file vừa download : 
[root@hungn src]# ls
debug kernels modsecurity-apache_2.6.0.tar.gz
[root@hungn src]# tar -xvzf 'modsecurity-apache_2.6.0.tar.gz'
Restart httpd và kiểm tra lại :
 [root@hungn src]# httpd -t -D DUMP_MODULES 
unique_id_module (shared) 
 Compile source code :
- cd vào thư mục chứa source code đã giải nén ở bước 1 :
[root@hungn /]# cd /usr/src/modsecurity-apache_2.6.0
[root@hungn modsecurity-apache_2.6.0]# ./configure
[root@hungn modsecurity-apache_2.6.0]# make
[root@hungn modsecurity-apache_2.6.0]# make install
 Tích hợp mod_sec vào apache :
- Khi make xong sẽ tạo ra file mod_security2.so ở thư mục modsecurity-
apache_2.6.0/apache2/.libs . Bạn cần copy file này bỏ vào thư mục modules của 
apache :
[root@hungn modsecurity-apache_2.6.0]# cp apache2/.libs/mod_security2.so 
/etc/httpd/modules
- Thêm dòng sau vào file httpd.conf để load module mod_sec lên :
LoadModule security2_module modules/mod_security2.so
Restart httpd và kiểm tra lại :
 [root@hungn /]# httpd -t -D DUMP_MODULES 
security2_module (shared) 
 Tạo file config :
Chúng ta có thể cấu hình trực tiếp các thông số và rule của ModSecurity vào file 
httpd.conf. Nhưng để cho rõ ràng và đảm bảo không sai sót trong quá trình thực 
hiện - gây ảnh hưởng Apache, Chúng ta nên tạo một file cấu hình riêng và sau đó 
include vào. 
Trong CentOS các file cấu hình riêng mặc định chứa trong /etc/httpd/conf.d/
#vi /etc/httpd/conf.d/modsecurity.conf
Thêm vào các thông số cấu hình cơ bản
<IfModule security2_module> 
 # Bat che do loc cua Modsecurity
 SecRuleEngine On 
 # Thiet lap action mac dinh
 SecDefaultAction "phase:2,deny,log,status:404"
 # rule thu nghiem block tat ca request co uri chua "upload"
 SecRule REQUEST_URI "upload" 
 </IfModule>
 Kiểm tra hoạt động :
Thực hiện thử nghiệm để kiểm tra hoạt động của ModSecurity. Tiến hành tạo 2 
floder trong thư mục web, joomla và upload chẳng hạn. Khi chúng ta truy cập vào 
khi chúng ta truy câp vào thư mục joomla thì trình duyệt trả về kết quả bình 
thường 
Còn khi truy cập vào upload thì trình duyệt báo lỗi : 
Đó là kết quả do ModSecurity đã chặn những URI có chứa chuỗi upload và cũng 
đồng nghĩa với việc ModSecurity đã hoạt động.
Cấu trúc của rules
SecRule VARIABLES OPERATOR [ACTIONS]
Variables:
REMOTE_ADDR : Địa chỉ IP của client
REMOTE_HOST : hostname của client (nếu tồn tại) 
REMOTE_USER : Authenticated username (nếu tồn tại) 
REMOTE_IDENT : Remote Username (lấy từ inetd, ít dùng) 
REQUEST_METHOD : Request Method (GET, HEAD, POST ) 
SCRIPT_FILENAME : Đường dẫn đầy đủ của script được thực thi 
404 – Forbidden
PATH_INFO : Phần mở rộng của URI phía sau tên của một script, 
ví dụ: /archive.php/5 thì PATH_INFO là /5
QUERY_STRING : URI phía sau dấu ?. 
Ví dụ /index.php?i=1 thì QUERY_STRING là i=1
AUTH_TYPE : Basic hoặc Digest Authentication 
DOCUMENT_ROOT : đường dẫn đến documentroot 
SERVER_ADMIN : email của Server Administrator 
SERVER_NAME : hostname của Server 
SERVER_ADDR : Địa chỉ IP của Server 
SERVER_PORT : Server port 
SERVER_PROTOCOL : protocol, (ví dụ HTTP/1.1) 
SERVER_SOFTWARE : Apache version 
TIME_YEAR : Năm hiện tại (2006) 
TIME_MON : Tháng hiện tại (2) 
TIME_DAY : Ngày 
TIME_HOUR : Giờ 
TIME_MIN : Phút 
TIME_SEC : Giây 
TIME_WDAY : Thứ tự ngày trong tuần (ví dụ 4 - Thursday) 
TIME : Thời điểm hiện tại được viết theo cấu trúc : YmdHMS 
ví dụ: 20060220144530 : 20/02/2006 14h 45' 30''
API_VERSION 
THE_REQUEST : dòng đầu tiên của request. vd: GET / HTTP/1.1 
REQUEST_URI : Request URI 
REQUEST_FILENAME : Tên file được yêu cầu đến. 
IS_SUBREQ 
Collections 
Một variables có thể bao gồm 1 hay nhiều phần dữ liệu. Khi variable có nhiều hơn 
1 giá trị thì ta gọi nó là collection
Ví dụ: với variable ARGS ta có 2 thông số p, và q
SecRule ARGS:p dirty
SecRule ARGS:q dirty
Có thể dùng 1 hay nhiều variables
SecRule ARGS|REQUEST_HEADERS:User-Agent dirty
Operators:
Sử dụng @ để chỉ ra đây là một operation
Sử dụng !@ để chỉ ra một operation negation 
Toán tử @rx (regular expression) là một toán tử
mặc định, được sử dụng khi không có một toán tử nào khác được chỉ định.
Trên đây chỉ là hướng dẫn cơ bản còn nâng cao thì các bạn tự tìm hiểu
Toán tử Tác dụng Ví dụ
@beginsWith Khớp các chuỗi bắt đầu với chuỗi 
chỉ định
SecRule 
REQUEST_LINE
“!@beginsWith GET”
@containts Khớp các chuỗi có chứa chuỗi chỉ 
định tại bất cứ vị trí nào
SecRule 
REQUEST_LINE
“@contains select”
@containsWord Khớp xâu chứa từ được chỉ định. 
“Từ” ở đây được hiểu là đoạn xâu 
được ngăn bởi một hoặc nhiều ký tự 
không phải chữ,số
SecRule ARGS 
“@containsWord from”
@endsWith Khớp xâu kết thúc bởi xâu chỉ định SecRule ARGS 
“@endsWith ”
@streq Khớp xâu giống hoàn toàn xâu chỉ 
định
SecRule 
REMOTE_HOST
“@streq victim\.com”
@within Khá giống @contains, chỉ khác là 
một so khớp xảy ra khi biến cần so 
xuất hiện bên trong xâu được chỉ 
định
SecRule 
REMOTE_USER
“@within 
cuong,nam,an”
(sẽ khớp nếu remote user 
là cuong, nam hoặc an)
@pm
Khớp với một trong những cụm từ đi 
sau nó
SecRule ARGS "@pm red 
green blue" deny
@pmFromFile
Nếu có quá nhiều chuỗi muốn đặt 
vào, ta có thể liệt kê các chuỗi này 
vào một file và dùng @pmFromFile
SecRule ARGS 
“@pmFromFile 
/usr/log/alo.txt”
Toán tử Toán tử đại số
tương đương
Ví dụ
@eq = SecRule RESPONSE_STATUS “@eq 200”
@ge ≥ SecRule RESPONSE_STATUS “@ge 400”
@gt > SecRule RESPONSE_STATUS “@gt 399”
@le ≤ SecRule RESPONSE_STATUS “@le 199”
@lt < SecRule RESPONSE_STATUS “@lt 200”
Actions
Khi request vi phạm một rule nào đó thì mod_security sẽ thực thi một hành động 
(action). Khi action không được chỉ rõ trong rule thì rule đó sẽ sử dụng default 
action . Có 3 loại actions :
Primary Actions
Primary actions sẽ quyết định cho phép request tiếp tục hay không. Mỗi rule 
chỉ có một primary action. Có 5 primary actions :
deny : Request sẽ bị ngắt, mod_security sẽ trả về HTTP status code 500 
hoặc là status code của bạn thiết lập trong chỉ thị status:
pass : Cho phép request tiếp tục được xử lý ở các rules tiếp theo
Allow: Cho phép truy cập ngay lập tức và bỏ qua các phases khác (trừ 
phases logging). Nếu muốn chỉ cho qua phase hiện tại thì cần chỉ rõ 
allow:phase Khi đó sẽ vẫn được kiểm tra bởi các luật tại các phases sau. Chỉ 
cho phép truy cập tới các request phases: allow:request, nó sẽ cho qua phase 
1,2 và vẫn kiểm tra ở phase 3 trở đi
redirect : Redirect một request đến một url nào đó.
Secondary Actions
Secondary actions sẽ bổ sung cho Primary actions, một rule có thể có nhiều 
Secondary actions
status : n khi một Request vi phạm một rule nào đó thì mod_security có thể 
trả về các HTTP status code n thay vì status code 500 mặc định.
exec : thực thi một lệnh nào đó nếu một request vi phạm 
log : ghi log những request vi phạm rule
nolog : không ghi log
pause : n mod_security sẽ đợi một thời gian n ms rồi mới trả về kết quả.
Flow Actions
chain: kết nối 2 hay nhiều rules lại với nhau
skipnext:n mod_security sẽ bỏ qua n rules theo sau nó
Default Action
Khi một rule không chỉ rõ action thì rule đó sẽ dùng default action được thiết lập 
trong SecDefaultAction. 
Ví dụ : SecDefaultAction "phase:2,deny,log,status:403"
Audit logging
Apache log ít thông tin vì thế nó không cho phép chúng ta có thể lần ngược 
các bước của kẻ tấn công. Mod_security hỗ trợ audit loging với đầy đủ thông tin và 
từ đó có thể lần ngược lại quá trình của kẻ tấn công, cũng như là chỉnh sửa các 
rules cho hợp lý tránh bị “false positive”. Có 2 directives:
SecAuditEngine On : bật audit log lên
SecAuditLog logs/audit.log : chỉ ra file lưu trữ log chính
Ngụy trang Web Server
SecServerSignature “Microsoft-IIS/5.0”
Demo một vài rule cơ bản 
Local Attack
SecRequestBodyAccess On
SecRule REQUEST_BODY "ls" "phase:2,deny,log,status:500"
Rule chống sql
SecRule ARGS "union\s+select" "t:lowercase,deny,msg:'SQL Injection'"
SecRule ARGS "union\s+all\s+select" 
"t:lowercase,deny,msg:'SQLInjection'"
SecRule ARGS "into\s+outfile" "t:lowercase,deny,msg:'SQL Injection'"
SecRule ARGS "drop\s+table" "t:lowercase,deny,msg:'SQL Injection'"
SecRule ARGS "alter\s+table" "t:lowercase,deny,msg:'SQL Injection'"
SecRule ARGS "load_file" "t:lowercase,deny,msg:'SQL Injection'"
SecRule ARGS "select\s+*" "t:lowercase,deny,msg:'SQL Injection'"
SecRule ARGS|REQUEST_HEADERS|REQUEST_URI “@pm select update 
insert alter drop union” 
“deny,status:400,t:lowercase,t:replaceComments,t:removeWhitespace,t:rem
oveNulls”
XSS Attack
SecRule ARGS "alert\s+*\(" "t:lowercase,deny,msg:'XSS'"
SecRule ARGS "<.+>" "t:lowercase,deny,msg:'XSS'"
SecRule ARGS "javascript:" "t:lowercase,deny,msg:'XSS'"
SecRule ARGS "vbscript:" "t:lowercase,deny,msg:'XSS'"
 SecRule ARGS "<script" "deny,t:lowercase"
DIRECTORY TRAVERSAL Attack
SecRule REQUEST_URI "\.\./" "t:urlDecode,deny"
NULL BYTE Attack
SecDefaultAction 
"phase:2,deny,log,status:403,t:removeNulls"
Mở rộng
Biến thường và các biến tập
ModSecurity sử dụng hai loại biến, loại thứ nhất là các biến chuẩn (standard 
variable) chỉ chứa một giá trị đơn ứng với mỗi biến, và loại thứ hai là các biến tập 
(collection variable) có thể chứa nhiều giá trị ứng với một biến. lấy một ví dụ về 
biến tập như REQUEST_HEADER, nó chứa tất cả giá trị trường header của một 
thông điệp HTTP.
 Để truy cập vào các trường trong biến tập, sử dụng cấu trúc tên_biến:tên_trường, 
ví dụ luật sau:
SecRule REQUEST_HEADER:Referer “victim.com”
Hầu hết các biến tập có thể được sử dụng độc lập mà không cần chỉ định trường cụ 
thể. Khi sử dụng tên biến tập độc lập tương đương với việc truy cập tới mọi trường 
trong tập đó. Ví dụ, querystring gửi lên trong thông điệp POST như 
sau:username=cuongpt&password=123456.
Thì thay vì sử dụng luật:SecRule ARGS:username|ARGS:password “select” Ta có 
thể sử dụng SecRule ARGS “select” deny.
Một số biến tập có các trường cố định (vd: GEO có country_name, city, ) nhưng 
một số lại có các trường không cố định, tùy thuộc vào nội dung client gửi đến. 
Trong các biến tập, có thể truy cập tới các trường không tồn tại hoặc trường đó 
không được gán giá trị mà không phát sinh lỗi. Điều này cần ghi nhớ trong trường 
hợp debug, có thể bỏ qua khả năng trường giá trị trong biến tập không tồn tại hoặc 
không được gán giá trị.
Lưu trữ dữ liệu giữa các request.
Có ba loại biến tập trong ModSecurity có thể được sử dụng để lưu trữ lâu dài. 
Thông thường, các biến sẽ hết hiệu lực mỗi khi request hiện thời được xử lý hoàn 
tất. Tuy nhiên trong một số trường hợp, chúng ta lại cần lưu giữ chúng lại và sử 
dụng chúng khi thao tác với các request sau này. Ba loại biến tập có thể được sử 
dụng cho mục đích lưu trữ là 
IP,
SESSION,
USER.
Biến tập IP được dùng để lưu thông tin về một user thông qua địa chỉ IP.Chúng ta 
có thể sử dụng nó cho một số mục đích như phát hiện ra user nào request nhiều lần 
vào một tài nguyên, hoặc số lần request của một user, giả sử để chống DOS. Trước 
khi sử dụng các biến trên, chúng ta cần khởi tạo chúng cách sử dụng action tên là 
initcol, ví dụ:
SecAction initcol:ip=%{REMOTE_ADDR},nolog,pass
Trong đó, REMOTE_ADD là biến lưu địa chỉ IP của client gửi request. Để lưu trữ 
biến, chúng ta cũng cần cấu hình một thư mục dữ liệu cho ModSecurity thông qua 
chỉ thị SecDataDir, ví dụ:
SecDataDir /var/log/apache2/modsec_data
Điều cần lưu ý đó là thư mục được chỉ định trong chỉ thị nêu trên phải cho phép 
người dùng Apache ghi dữ liệu lên. Sau khi cấu hình thư mục lưu trữ dữ liệu, khởi 
tạo biến, ta có thể thao tác
với giá trị của biến, gán giá trị thông qua action tên là setvar. Trong phần giới thiệu 
biến tập tiếp theo ta sẽ sử dụng action setvar. 
 Biến tập giao tác (transaction collection)
Biến TX là một dạng biến tập giao tác, các biến này được gán giá trị trong một 
vòng đời của một request/response. Chúng ta có thể sử dụng TX để tạo các biến 
của riêng mình nhằm lưu dữ liệu trong vòng một chu kỳ transaction. Xét một số 
luật sau:
SecRule REQUEST_URI “select” “pass,setvar:tx.score=+1”
SecRule REQUEST_URI “passwd” “pass,setvar:tx.score=+2”
SecRule TX:SCORE “@gt 3” deny
Bộ luật trên mô tả như sau, thực hiện kiểm tra các URI trong request, nếu phát hiện 
có chứa “select” thì tăng biến SCORE lên 1, nếu phát hiện thấy có “passwd” thì 
tăng biến SCORE lên 2, và nếu kiểm tra thấy biến SCORE lớn hơn hoặc bằng 3 thì 
chặn request đó lại. 
Cấu trúc action setvar ở trên cho phép tạo và cập nhật một biến. Để hủy một biến, 
cũng sử dụng action setvar nhưng thêm dấu chấm than phía trước biến, cụ thể: 
setvar:!tx.score.
Biến tập TX có thể chứa các trường định nghĩa sẵn (built-in) như TX:0, TX:1, 
cho đến TX:9. Với trường hợp TX:0 đó là giá trị được khớp khi sử dụng toán tử 
@rx hoặc @pm, các biến TX:1 đến TX:9 chứa các giá trị kiểubiểu thức chính quy 
thu được khi ước lượng một biểu thức chính quy kèm theo action capture.
Vài rule nâng cao
BRUTE-FORCE Attack
SecResponseBodyAccess On
SecAction "initcol:ip=%{REMOTE_ADDR},pass,nolog"
SecRule RESPONSE_BODY “login fail"
"phase:4,pass,setvar:ip.failed_logins=+1,expirevar:ip.failed_logins=60"
SecRule IP:FAILED_LOGINS "@gt 3" deny
SecResponseBodyAccess On
SecAction initcol:ip=%{REMOTE_ADDR},nolog
SecRule REQUEST_URI "/dangki\.php" 
"nolog,phase:2,setvar:ip.ddos=+1,deprecatevar:ip.ddos=5/60,expirevar:ip.
ddos=600"
SecRule IP:DDOS "@gt 5" "deny,log,stastus:404,msg:'DDoS'"
 SecRule IP:DDOS "@gt 7" "log,msg:'DDoS from %
{REMOTE_ADDR}',exec:/usr/src /blocker.sh" 
Tham khảo thêm : 
 />apache/2.5.12/html-multipage/index.html
<IfModule security2_module>
# Bat che do loc cua Modsecurity
 SecRuleEngine On
 # Thiet lap action mac dinh
 SecDefaultAction "phase:2,deny,log,status:404" 
SecAuditEngine On
SecAuditLog logs/audit_log
SecDataDir /tmp/modsec_data
SecResponseBodyAccess On
# Khoi tao collection ip
 SecAction "initcol:ip=%{REMOTE_ADDR},pass,nolog"
# Phat hien dang nhap khong thanh cong
SecRule RESPONSE_BODY "fail" 
"phase:4,pass,setvar:ip.failed_logins=+1,expirevar:ip.failed_logins=300"
# Khoa dang nhap khi so lan dang nhap khong thanh cong bang 3
SecRule IP:FAILED_LOGINS "@gt 3" deny
</IfModule>
Code chống dos
SecDataDir /tmp/modsec_data
SecAction "initcol:ip=%{REMOTE_ADDR},nolog"
SecRule REQUEST_URI "/data\.php" 
"nolog,setvar:ip.ddos=+1,deprecatevar:ip.ddos=5/60,expirevar:ip.ddos=600"
SecRule IP:DDOS "@gt 5" "deny,log,status:404,msg:'DDoS'"
SecRule IP:DDOS "@gt 7" "log,msg:'DDoS from %
{REMOTE_ADDR}',exec:/path/to/a/script/blocker.sh"