Web中間件學習篇
本篇主要從IIS、Apache、Nginx、Tomcat四種常見中間件的Nginx入手,介紹相關安全知識,遵循“中間件簡介→如何搭建網站→安全配置分析→安全日志分析”的順序進行學習,旨在梳理常見Web中間件的知識點,為Web安全學習打好基礎。
Nginx篇
作者:古月藍旻@安全之光
Nginx簡介
Nginx(發音同engine x)是一個網頁服務器,它能反向代理HTTP, HTTPS, SMTP, POP3, IMAP的協議鏈接,以及一個負載均衡器和一個HTTP緩存。 Nginx是一款面向性能設計的HTTP服務器,相較於Apache、lighttpd具有占有內存少,穩定 性高等優勢。與舊版本(<=2.2)的Apache不同,nginx不采用每客戶機一線程的設計模型, 而是充分使用異步邏輯,削減了上下文調度開銷,所以並發服務能力更強。 起初是供俄國大型的門戶網站及搜索引擎Rambler(俄語:Рамблер)使用。此軟件BSD-like 協議下發行,可以在UNIX、GNU/Linux、BSD、Mac OS X、Solaris,以及Microsoft Windows 等操作系統中運行。
Nginx站點搭建
Nginx站點的搭建其難點在於安裝Nginx,不同於Apache可以直接使用yum或者apt-get的方式安裝,Nginx不在系統標准源中,因此常見的安裝方式主要有兩個:編譯安裝和第三方yum源安裝。由於編譯安裝Nginx需要安裝的拓展比較多,此次我們使用第三方yum源方式安裝Nginx,同時以此為基礎,搭建Linux+Nginx+Mysql+Php的站點,分為以下幾步:
- 配置第三方yum源;
- 安裝Nginx;
- 安裝Mysql、php、配置phpmyadmin;
- 部署php站點;
下面開始詳細介紹如何搭建一個完整的Nginx站點:
環境介紹
操作系統:CentOS release 6.5 (Final) Nginx版本: nginx-1.6.2-23.el6.art.x86_64 站點類型:php
搭建步驟
配置第三方yum源
由於CentOS標准yum源中不提供Nginx的安裝包,所以需要第三方yum源來補充一下,而第三方源的選擇同樣需要謹慎,不僅要保證軟件要兼容本系統同時版本較新,最重要的是要保證安全,否則安裝的軟件可能都帶着后門。此次我們選擇的是Atomic源
Atomic支持哪些軟件可以到這個地址查看:http://www.atomicorp.com/channels/atomic/ 最常見的有php、mysql、nginx、openvas、memcached、php-zend-guard-loader等軟件。
配置步驟如下:
wget http://www.atomicorp.com/installers/atomic sh ./atomic yum check-update
其中在sh ./atomic一步,一路yes即可,同時安裝相關拓展和依賴
yum -y install ntp make openssl openssl-devel pcre pcre-devel libpng libpng-devel libjpeg-6b libjpeg-devel-6b freetype freetype-devel gd gd-devel zlib zlib-devel gcc gcc-c++ libXpm libXpm-devel ncurses ncurses-devel libmcrypt libmcrypt-devel libxml2 libxml2-devel imake autoconf automake screen sysstat compat-libstdc++-33 curl curl-devel
如果之前有安裝過mysql、apache、php,需要先全部卸載
yum remove httpd yum remove php yum remove mysql
安裝Nginx
配置了第三方yum源后,安裝就方便了很多
yum install nginx service nginx start chkconfig --levels 235 nginx on ////設置2、3、5級別開機啟動
此時去訪問localhost或者127.0.0.1或者本機訪問本機ip就可以看見nginx界面
由於Atomic源的軟件不是特別新,該版本是2014年4月發行,但是也足夠使用了
此時其他主機還是無法通過ip的方式訪問該主機的,和apache類似,需要開啟80端口的訪問規則
/sbin/iptables -I INPUT -p tcp --dport 80 -j ACCEPT //添加開啟80端口規則 /etc/rc.d/init.d/iptables save //保存配置 /etc/rc.d/init.d/iptables restart //重啟iptables /etc/init.d/iptables status //查看開放的端口,出現80
此時其它主機已經可以正常訪問
安裝Mysql、php、配置phpmyadmin
這些其實和apache是基本相同的
yum -y install mysql mysql-server mysql-devel //安裝mysql和其相關拓展 chkconfig mysqld on //設置其開機啟動 service mysqld start //啟動mysqld服務 /usr/bin/mysql_secure_installation //設置mysql的一些安全配置 這一步還是很重要的,主要是設置mysql的root密碼,是否需要刪除匿名賬號等等,根據實際需要設置
此時我們可以登錄一下mysql
yum -y install php //安裝php yum -y install php-mysql gd php-gd gd-devel php-xml php-common yum -y install php-mbstring php-ldap php-pear php-xmlrpc php-imap php-mcrypt //安裝php常用拓展 yum install php-tidy php-common php-devel php-fpm //安裝php-fpm service php-fpm start //啟動php-fpm chkconfig --levels 235 php-fpm on //設置php-fpm2、3、5級別開機啟動 service nginx restart //重啟nginx服務,這一步非常重要
完成之后可以簡單測試一下,在/usr/share/nginx/html/目錄下新建phpinfo.php文件內容為phpinfo(),讓其輸出一下相關信息,然后發現。。。現在還是無法解析php文件,訪問的話會直接下載該文件
因此我們需要配置一下Nginx支持解析php,配置文件名稱為nginx.conf,具體路徑的尋找方式有多種方法:
方法一: updatedb locate nginx.conf 方法二: ps aux |grep nginx
還有更簡單的配置文件路徑的查看方法,會在日志篇進行詳細說明
具體的配置步驟如下:
mv /etc/nginx/nginx.conf /etc/nginx/nginx.confbak
//將配置文件改為備份文件
cp /etc/nginx/nginx.conf.default /etc/nginx/nginx.conf
//由於原配置文件要自己去寫因此可以使用默認的配置文件作為配置文件
//修改nginx配置文件,添加fastcgi支持
vi /etc/nginx/nginx.conf
index index.php index.html index.htm;
//加入index.php,大約在45行左右
location ~ .php$ {
root /usr/share/nginx/html;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /usr/share/nginx/html$fastcgi_script_name;
include fastcgi_params;
}
//將65行--71行處關於.php文件規則的注釋符號刪去
//配置/etc/php.ini,在文件末尾添加cgi.fix_pathinfo = 1
最后重啟nginx和php-fpm service nginx restart service php-fpm restart
此時再訪問/usr/share/nginx/html/目錄下的phpinfo.php,可以正常顯示服務器信息
下一步就是安裝phpmyadmin,這個其實是可選步驟,只是為了方便圖形化管理mysql,下載官網:phpmyadmin下載官網
在官網下載了phpMyAdmin-4.0.10.20-all-languages.tar.gz
和Apache一樣,由於安裝的php版本為5.4.45,低於php5.5,因此安裝低版本的phpMyAdmin
tar -xvzf phpMyAdmin-4.0.10.20-all-languages.tar.gz mv phpMyAdmin-4.0.10.20-all-languages /usr/share/nginx/html/phpmyadmin cd /usr/share/nginx/html/phpmyadmin cp libraries/config.default.php config.inc.php
然后修改一下相關配置vi config.inc.php,一般改這些
$cfg['PmaAbsoluteUri'] = '';這里填寫 phpMyAdmin 的訪問網址。 $cfg['Servers'][$i]['host'] = 'localhost'; // MySQL hostname or IP address $cfg['Servers'][$i]['port'] = ''; // MySQL port - leave blank for default port $cfg['Servers'][$i]['user'] = 'root'; // 填寫 MySQL 訪問 phpMyAdmin 使用的 MySQL 用戶名,默認為 root。 $cfg['Servers'][$i]['password'] = ''; // 填寫對應上述 MySQL 用戶名的密碼。 $cfg['blowfish_secret'] = '1qaz2wsx3edc';//隨意,長度不要太短
實際過程中其實我也只是修改了password一處為我的mysql密碼,blowfish_secret其實也可以修改,否則登錄后會給個警告,但是不影響使用最后重啟一下nginx和php-fpm服務
service nginx restart service php-fpm restart
打開瀏覽器訪問http://localhost/phpmyadmin 或者 http://ip/phpmyadmin
部署php站點
還是將apache中配置好的php源碼包直接拿來使用,和apache不同,此時的db_config.php文件,主機host使用127.0.0.1不會報錯
但是登錄頁面login.php顯示亂碼,登錄成功后的頁面index.php正常,這個很顯然是編碼的問題
於是在login.php的<?php下發第一行添加
header("Content-Type: text/html;charset=utf-8");
重啟一下nginx和php-fpm,再次訪問,可以登錄,一切正常,至此nginx下的php站點搭建完成
nginx日志分析
和apache非常類似,nginx的主要日志也是access.log和error.log,那么該如何確認詳細的路徑?
執行以下命令即可
nginx -V
其實里面有很多詳細的路徑信息,可以在其中查到,同時順便一提,關於一些配置信息可以查看phpinfo界面,不要忽略它
根據上圖,我們可以得到訪問日志和錯誤日志的具體路徑
access.log=/var/log/nginx/access.log
error.log=/var/log/nginx/error.log
在打開這兩種日志前,我們還是去配置文件/etc/nginx/nginx.conf里看看關於nginx日志的配置情況,直接搜索關鍵字log_format,結果…
看起來比apache詳細多了,而且還解釋了各個字段的含義。但是…所有和日志有關的內容全被注釋了…所以日志是怎么記錄的?難道雖然被注釋了,但是還是生效的?打開/var/log/nginx/access.log看一下
這個完全和apache的日志一樣啊,根本沒有什么http_x_forward_for字段嘛,這個問題我困惑了很久,找了半天才發現原因:
也就是說:nginx默認使用了和apache相同的組合日志格式(Combined Log Format),但是它省略了,這個就比較坑了
其實一般情況下nginx日志記錄格式會如上圖所示,不會注釋,但是可能是我安裝的方式使用第三方yum源,有些配置被修改了
如果想自定義日志的不同字段,可以參考這篇文章:nginx系列-04-nginx日志配置
同時error.log的格式在nginx.conf中若未定義,同樣使用apache對於錯誤日志的記錄級別,該句亦省略
error_log /var/log/nginx/error.log warn;
還有一點很重要:查看一下/var/log/nginx下的文件
可以看見訪問日志和錯誤日志均會按照天壓縮成.gz文件,這個在nginx.conf中並未定義,是在哪里設置的?
其實類似這種log分片壓縮成不同文件的,往往由logrotate完成
logratate根據不同應用生成多個log配置文件,路徑在/etc/logrotate.d/目錄下
兩處關鍵點:
- daily 代表log按照天划分;
- compress 代表日志以gzip壓縮轉儲以后的日志(.gz文本文件亦可直接使用vim打開)
如果對logrotate中nginx的配置比較感興趣,可以看這篇文章:Nginx日志切割之Logrotate篇
Nginx日志分析Web攻擊行為
Nginx日志同樣可以用於分析Web攻擊行為,本次使用AWVS掃描搭建的站點,然后查看日志情況
一切使用默認配置即可,稍等片刻即可完成掃描
打開日志看一下,內容挺多的,這次和IIS和Apache的web日志分析不同,這次主動查找AWVS的常用攻擊行為
sql注入攻擊
直接在access日志中搜索關鍵字“SELECT”
典型的GET型sql注入攻擊,目的是獲取數據庫中所有的表
xss攻擊
也非常簡單,直接在access日志中搜索關鍵字“script”
如圖所示,以上4處xss均為dom-xss,且添加測試字段均為wvstest
shellshock漏洞攻擊
這個發現的比較偶然,自己之前甚至不怎么留意,因為在access日志中發現了一處16進制編碼payload
配合前面的echo -e ,基本可以判斷這是一處測試RCE漏洞的payload,於是乎想看看這個payload的原文
echo -e \x22\x5C0141\x5C0143\x5C0165\x5C0156\x5C0145\x5C0164\x5C0151\x5C0170\x5C0163\x5C0150\x5C0145\x5C0154\x5C0154\x5C0163\x5C0150\x5C0157\x5C0143\x5C0153\x22
\x是典型的16進制,\x22是雙引號"的16進制,\5C是反斜杠\的16進制,所以轉換一下上述字符串就是
echo -e”\0141\0143\0165\0156\0145\0164\0151\0170\0163\0150\0145\0154\0154\0163\0150\0157\0143\0153″
\0又是典型的8進制,所以接下來的問題是把8進制轉換為對應字符串即可,直接轉有點麻煩先轉換為16進制吧
echo -e “6163756e657469787368656c6c73686f636b”
越來越短了,看見希望了,最后就是16進制轉字符串,得到
echo -e “acunetixshellshock”
果然是awvs在測試shellshock(破殼漏洞),在測試命令執行,從最后漏洞掃描結果看,在我的服務器確實沒找到這個漏洞,但是服務器真的沒有這個漏洞嗎?畢竟我是CentOS 6.5,自己跑下POC好了
env x='() { :;}; echo vulnerable' bash -c "echo this is a test "
如果輸出vulnerable就說明有該漏洞,且該漏洞常見於bash版本低於4.2的主機,看一下結果
顯然是有該漏洞的,但是為什么AWVS沒掃出來?查了一些資料,應該是服務器的bash解釋器修復了該漏洞,關於該漏洞的相關知識,可以參考以下文章:
目錄遍歷漏洞
除了access日志外,error日志中亦包含很多攻擊信息,最常見的便是目錄遍歷導致服務器出錯
典型的目錄遍歷查看/etc/passwd文件的,順便一提由於變量會加上php后綴,所以我們要用%00來截斷后綴這樣才能正常顯示文件內容
關於目錄遍歷漏洞,推薦一篇文章
嘗試修改php.ini配置
還是error.log,這個payload就有點膽大妄為了,在嘗試直接修改php.ini配置
典型的url編碼,解密看下結果好了
-d allow_url_include=on -d safe_mode=off -d suhosin.simulation=on -d disable_functions="" -d open_basedir=none -d auto_prepend_file=php://input -d cgi.force_redirect=0 -d cgi.redirect_status_env=0 -n
真是敢做敢擔當,直接把php默認的安全配置全改了,允許遠程url包含,關閉安全模式…直接降低站點的安全系數
其實access日志和error日志中還有大量漏洞利用的payload,時間有限,就不過多介紹了
post方式訪問
nginx默認情況下還是不記錄POST方式提交的內容的,那么如何開啟呢?其實非常簡單,修改一下nginx.conf關於日志的部分,添加一個記錄字段 "$request_body"(請求體),啟用一下access_log的配置為main中的配置
順便一提access_log的路徑為logs/access.log,完整路徑為nginx根路徑+logs/access.log,在我本機為/usr/share/nginx/logs/access.log,需要創建一下/usr/share/nginx/logs/目錄,並改一下屬主和權限
mkdir /usr/share/nginx/logs chown -R nginx:root /usr/share/nginx/logs chmod 644 /usr/share/nginx/logs
此時訪問任意界面,POST傳入相應數據,可以發現,POST請求體被記錄在案啦
補充知識點
1. 如何修改Nginx默認端口號?
這個問題非常簡單,打開nginx.conf文件,
找到Listen 80 一行,將80修改為想要設置的端口號,保存,重啟nginx即可
測試時在本機瀏覽器輸入http://127.0.0.1:新端口號 即可
注:外網主機此時可能無法通過http://IP:新端口號 方式訪問,記得修改iptables,添加新端口號規則。
2. 以root身份啟動nginx,該服務以什么用戶運行?
使用ps aux|grep nginx|grep -v grep查看一下
第一列中既有root,又有nginx,Nginx在以Linux service腳本啟動時,通過start-stop-domain啟動,會以root權限運行master進程。
然后master進程讀取/etc/nginx/nginx.conf文件中的user配置選項,默認這里的user=nginx,也就是用nginx用戶啟動worker process。且nginx.conf中會定義worker process的數量



