joomla SQL Injection 漏洞防御

环境搭建

之前在演示SQL注入攻击的时候,使用了xampp应用在window上搭建了集成环境,虽然很方便,但不够灵活,不能根据自己的需求进行环境配置。由于需要在服务器中安装WAF,所以要重新搭建环境,将joomla搭建在ubuntu上。

Step 1: 安装Apache服务器

  • 更新ubunntu源
    apt-get update

  • 安装Apache服务器
    apt-get install apache2

Step 2: 安装MySQL数据库

  • Joomla需要在LAMP的基础环境中运行,首先需要安装MySQL数据库并和PHP连接
    apt-get install mysql-server php7.0-mysql

Step 3: 安装 PHP

  • 安装PHP 7.0 和几个PHP模块
    apt-get install php7.0 libapache2-mod-php7.0 php7.0-mcrypt php7.0-xml php7.0-curl php7.0-json php7.0-cgi

Step 4: 验证LAMP环境安装成功

  • 打开浏览器,输入服务器本机IP,如果看到Apache默认页面,说明Apache服务器已经成功安装了

  • 为了验证PHP安装成功,需要修改默认主页
    rm /var/www/html/index.html

  • 创建新文件
    touch /var/www/html/index.php

  • 编辑文件
    vim /var/www/html/index.php

  • 将下列PHP语句添加到文件中
    <?php
    phpinfo();
    ?>

  • 进入浏览器,刷新刚才的默认Apache页面,如果看到页面显示PHP版本信息,则说明PHP安装成功,最后删除该文件
    rm /var/www/html/index.php

Step 5: 准备Joomla安装文件

  • 成功安装LAMP环境后,就能进行joomla的安装了,切换当前目录到服务器根目录,下载joomla相应版本的安装文件并解压

cd /var/www/html

  • 下载安装文件
    wget https://downloads.joomla.org/cms/joomla3/3-7-5/Joomla_3-7.5-Stable-Full_Package.zip

  • 安装unzip
    apt-get install unzip

  • 解压文件
    unzip Joomla_3-7.5-Stable-Full_Package.zip

  • 修改权限
    chown -R www-data.www-data /var/www/html
    chmod -R 755 /var/www/html

Step 6: 为Joomla创建数据库

  • 在安装joomla之前,需要为joomla在本地创建一个数据库,输入密码进入MySql控制台
    mysql -u root -p

  • 创建名称为joomla的数据库
    mysql>CREATE DATABASE joomla;

  • 为joomla数据库创建用户
    mysql>GRANT ALL PRIVILEGES on joomla.* to 'username'@'localhost' identified by 'password';
    mysql>FLUSH PRIVILEGES;

  • 退出MySql控制台
    mysql>exit

Step 7: 开始安装Joomla

  • 重启Apache服务器
    systemctl restart apache2

  • 进入浏览器,输入服务器IP,会看到joomla欢迎页面,根据提示输入,就能成功安装joomla,注意输入的数据库名称,用户名和密码要和之前第6步创建的数据库的信息一致
    Database Type: MySQLi
    Host Name: localhost
    Username: username
    Password: password
    Database Name: joomla
    Table Prefix: joomla_
    Old Database Process: Remove

WAF安装

Step 1:安装modsecurity模块

  • 使用Ubuntu的包管理器安装libapache2-modsecurity模块及其依赖包
    使用源码安装会出现各种小问题导致安装失败,Ubuntu的包管理器非常好用,在安装过程中基本不会有困难
    apt-get install libxml2 libxml2-dev libxml2-utils libaprutil1
    apt-get install libapache2-modsecurity

Step 2:配置modsecurity,启用拦截模式

  • 重载Apache服务,
    service apache2 reload

  • 修改默认配置,启用拦截模式
    cd /etc/modsecurity/
    mv modsecurity.conf-recommended modsecurity.conf
    vim /etc/modsecurity/modsecurity.conf

  • 修改文件中SecRuleEngine状态为On
    SecRuleEngine On

Step 3:选择modsecurity规则

  • 将希望启用的规则放入下列文件夹中
    cd /usr/share/modsecurity-crs/activated_rules/

  • 选择启用下列规则,包含了基本的SQL注入攻击拦截规则
    modsecurity_crs_41_sql_injection_attacks.conf

  • 修改apache模块配置,启用规则集
    vim /etc/apache2/mods-available/security2.conf

  • 修改文件内容如下
    <IfModule security2_module>
    # Default Debian dir for modsecurity's persistent data
    SecDataDir /var/cache/modsecurity
    # Include all the *.conf files in /etc/modsecurity.
    # Keeping your local configuration in that directory
    # will allow for an easy upgrade of THIS file and
    # make your life easier
    IncludeOptional /etc/modsecurity/*.conf
    IncludeOptional /usr/share/modsecurity-crs/*.conf
    IncludeOptional /usr/share/modsecurity-crs/activated_rules/*.conf
    </IfModule>

Step 4:启用modsecurity模块

a2enmod headers
a2enmod security2

Step 5:测试真实的攻击payload

发起下列HTTP请求,未开启WAF前,该请求会导致构造的SQL语句被执行

http://192.168.254.130/index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(500)))test))

可以看到,服务器拦截了这次攻击请求,返回了403页面,SQL注入攻击失败

image.png

可以查看服务器日志文件来查看具体的拦截信息

第一段记录了HTTP请求的相关信息,包括发起请求的时间,客户端IP,还有整个完整的HTTP请求头部信息都完整的记录了下来。

--60c14f24-A--
[03/Jul/2018:06:06:00 --0700] Wzt0uO5VTqHWiSTB7HaLtQAAAAM 192.168.254.1 7204 192.168.254.130 80
--60c14f24-B--
GET /index.php?option=com_fields&view=fields&layout=modal&list[fullordering]=if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(500)))test)) HTTP/1.1
Host: 192.168.254.130
Connection: keep-alive
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Cookie: c40b869f52497e9591df3658e267d1ba=e9kqsd8kenepp0gekrfihodt21
X-Forwarded-For: 113.55.110.2

这一段记录的是服务器对该异常HTTP请求的响应,包含响应的头部信息和内容。可以看到,服务器返回的HTTP状态码为403 Forbidden,表示该条请求被服务器拒绝,而响应内容是HTML代码,简单的显示了禁止访问的提示。

--60c14f24-F--
HTTP/1.1 403 Forbidden
Content-Length: 299
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=iso-8859-1

--60c14f24-E--
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>403 Forbidden</title>
</head><body>
<h1>Forbidden</h1>
<p>You don't have permission to access /index.php
on this server.<br />
</p>
<hr>
<address>Apache/2.4.29 (Ubuntu) Server at 192.168.254.130 Port 80</address>
</body></html>

最后一段记录了WAF拦截本次请求的原因等相关信息。第一个字段Message中,显示出服务器对该请求的响应是拒绝服务并返回403错误。后面给出了拦截发生的阶段,(phase 2) 表示在服务器读取到请求内容时执行了拦截操作。Pattern match给出了所匹配的规则,匹配到了modsecurity_crs_41_sql_injection_attacks.conf文件中第80行id 950901 号规则,显示了该规则的部分正则表达式。消息中给出了可能的web攻击的种类,在该次请求中为SQL Injection Attack: SQL Tautology Detected,也就是SQL注入攻击。还显示出了在请求内容中匹配到规则的那一部分数据, 即(1=1 ,正是因为请求内容有这部分数据,才被特定规则识别出来。下面两个参数muturity和accuracy用来判断该次拦截的准确率。

--60c14f24-H--
Message: Access denied with code 403 (phase 2). Pattern match "(?i:([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)\\b([\\d\\w]++)([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)(?:(?:=|<=>|r?like|sounds\\s+like|regexp)([\\s'\"`\xc2\xb4\xe2\x80\x99\xe2\x80\x98\\(\\)]*?)\\2\\b|(?:!=|<=|>=|<>|<|>|\\^|is\\s+not ..." at ARGS:list[fullordering]. [file "/usr/share/modsecurity-crs/activated_rules/modsecurity_crs_41_sql_injection_attacks.conf"] [line "80"] [id "950901"] [rev "2"] [msg "SQL Injection Attack: SQL Tautology Detected."] [data "Matched Data: (1=1 found within ARGS:list[fullordering]: if(1=1,1,(SELECT(1)FROM(SELECT(SLEEP(500)))test))"] [severity "CRITICAL"] [ver "OWASP_CRS/2.2.9"] [maturity "9"] [accuracy "8"] [tag "OWASP_CRS/WEB_ATTACK/SQL_INJECTION"] [tag "WASCTC/WASC-19"] [tag "OWASP_TOP_10/A1"] [tag "OWASP_AppSensor/CIE1"] [tag "PCI/6.5.2"]
Action: Intercepted (phase 2)
Apache-Handler: application/x-httpd-php
Stopwatch: 1530623160351414 2841 (- - -)
Stopwatch2: 1530623160351414 2841; combined=1194, p1=529, p2=634, p3=0, p4=0, p5=30, sr=74, sw=1, l=0, gc=0
Response-Body-Transformed: Dechunked
Producer: ModSecurity for Apache/2.9.0 (http://www.modsecurity.org/); OWASP_CRS/2.2.9.
Server: Apache/2.4.29 (Ubuntu)
Engine-Mode: "ENABLED"

下面是请求触发的规则的具体定义,在modsecurity规则的核心是建立在正则匹配上的,可以看到下面的规则对SQL注入的检测依赖于一段很长的正则表达式,如果正则匹配成功,则说明检测到攻击。

#
# -=[ SQL Tautologies ]=-
#
SecRule REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/* "(?i:([\s'\"`´’‘\(\)]*?)\b([\d\w]++)([\s'\"`´’‘\(\)]*?)(?:(?:=|<=>|r?like|sounds\s+like|regexp)([\s'\"`´’‘\(\)]*?)\2\b|(?:!=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)([\s'\"`´’‘\(\)]*?)(?!\2)([\d\w]+)\b))" \
        "phase:2,rev:'2',ver:'OWASP_CRS/2.2.9',maturity:'9',accuracy:'8',capture,multiMatch,t:none,t:urlDecodeUni,t:replaceComments,ctl:auditLogParts=+E,block,msg:'SQL Injection Attack: SQL Tautology Detected.',id:'950901',logdata:'Matched Data: %{TX.0} found within %{MATCHED_VAR_NAME}: %{MATCHED_VAR}',severity:'2',tag:'OWASP_CRS/WEB_ATTACK/SQL_INJECTION',tag:'WASCTC/WASC-19',tag:'OWASP_TOP_10/A1',tag:'OWASP_AppSensor/CIE1',tag:'PCI/6.5.2',setvar:'tx.msg=%{rule.msg}',setvar:tx.sql_injection_score=+%{tx.critical_anomaly_score},setvar:tx.anomaly_score=+%{tx.critical_anomaly_score},setvar:tx.%{rule.id}-OWASP_CRS/WEB_ATTACK/SQL_INJECTION-%{matched_var_name}=%{tx.0}"

先来看一下在modsecurity中配置规则的主要指令SecRule,这个命令用于分析数据并根据分析结果执行相应动作。

下面是该指令的格式,VARIABLES描述哪些数据会被检测,例如REQUEST_HEADERS表示检测HTTP请求头中的内容, ARGS表示请求中的参数。第二部分的OPERATOR表示如何检测数据,一般会用一个正则表达式作为规则的第二个参数。第三个参数[ACTIONS]是可选的,因为在modsecurity配置文件中指定了默认动作列表。如果这个值被设定了,会联合预设的默认动作列表最终产生一个执行的动作,来对检测结果做出响应。

SecRule VARIABLES OPERATOR [ACTIONS]

在上述规则中,VARIABLES的值为REQUEST_COOKIES|!REQUEST_COOKIES:/__utm/|REQUEST_COOKIES_NAMES|ARGS_NAMES|ARGS|XML:/ *
就是需要检测HTTP请求的cookie内容和cookie名字,以及HTTP请求中包含的参数和参数名字,如果是GET请求,则参数和参数名称在请求头部的URL中;如果是POST请求,那参数和参数名称就在请求的载荷中。此外,对cookie排除了__utm的值,经过搜索,这个参数来自于google的网站统计,可以过滤。

然后我们再来详细分析一下规则中作为OPERATOR的正则表达式

(?i:( 
    [\s'\"`´’‘\(\)]*?)  # 匹配各种引号和括号
    \b([\d\w]++)  # 匹配数字
    ([\s'\"`´’‘\(\)]*?)  # 匹配各种引号和括号
    (?:(
        ?: =|<=>|r?like|sounds\s+like|regexp)  # 匹配关系运算符
        ([\s'\"`´’‘\(\)]*?)\2\b|  # 匹配各种引号和括号
        (?:
            !=|<=|>=|<>|<|>|\^|is\s+not|not\s+like|not\s+regexp)  # 匹配关系运算符
        ([\s'\"`´’‘\(\)]*?)
        (?!\2)([\d\w]+)\b)  # 匹配数字,和第1个分组的数字要相同
)

可以从匹配结果看出,这条正则能够匹配到通过关系运算实施的SQL注入攻击

image.png

最后,看一下这条规则的动作,在modsecurity配置文件/usr/share/modsecurity-crs/modsecurity_crs_10_setup.conf中,设定的默认动作列表如下,即,默认拒绝检测到异常的HTTP请求,并形成记录写入日志。 所以这条规则检测到攻击后,会按默认动作拒绝请求,并记录日志

SecDefaultAction "phase:1,deny,log"
SecDefaultAction "phase:2,deny,log" 

我们看到在动作列表中有一个phase参数,这个参数说明了规则生效的阶段,在 ModSecurity中,规则可以在五个阶段执行,,分别为:

  1. 请求头(REQUEST_HEADERS)
  2. 请求体(REQUEST_BODY)
  3. 响应头(RESPONSE_HEADERS)
  4. 响应体(RESPONSE_BODY)
  5. 记录(LOGGING)

下图是标准的 apache 请求流程,5 个 ModSecurity 处理阶段显示在其中

image.png

大多数规则在下列两个阶段执行

请求头阶段

这个阶段的规则会在 apache 完成HTTP请求头的读取后立即被执行,这时,还没有读取请求体,意味着不是所有的参数都可用。如果你必须让规则尽早运行,应把规则放在这个阶段(在 apache 使用这个请求做某些事前),在请求体被读取前做些事情,从而决定是否缓存这个请求体,或者决定你将希望这个请求体如何被处理(如是否以 XML 格式解析或不解析)。

请求体阶段

这个阶段,服务器完成对请求载荷的解析,服务器端可以拿到所有请求的参数,上面的那条规则就是在本阶段执行的

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,736评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,167评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,442评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,902评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,302评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,573评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,847评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,562评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,260评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,531评论 2 245
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,021评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,367评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,016评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,068评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,827评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,610评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,514评论 2 269

推荐阅读更多精彩内容