upload-labs靶场详解

靶场环境

下载链接:https://codeload.github.com/c0ny1/upload-labs/zip/refs/heads/master
使用小皮集成环境来完成这个靶场 将文件放到WWW目录下就可以进行访问

进入关卡后页面呈现:

Pass-01(前端绕过)

我们先尝试上传一个web.php的文件


这里提示我们只允许上传这三种文件后缀名的文件 我们查看一下源码


发现上传文件中定义了一个checkFile()函数 我们来看一下chekFile()是什么


我们可以用砍出来这是定义了一个白名单 是由前端JS来检测 其中file.lastIndexOf(".")是截取文件最后一个点(.)之后的后缀  也就是截取文件的后缀名来判断是不是在白名单内

既然它是通过JS来检测的那我们可以禁止浏览器运行JS代码来绕过这个检测

刷新页面后再次上传我们的web.php文件

上传成功

Pass-02  (文件类型检测)

我们尝试上传一个web.php文件 显示文件类型不正确


查看一下网页源代码发现一样有checkFile()函数但是在前端页面中没有找到checkfile规则 可能没有在前端进行过滤 大概率是后端验证 再往下看我们能发现 下面有检测文件类型的代码

我们抓包看一下

这个时候我们只需要把类型改成它允许的类型send过去就完成了

Pass-03(php3绕过)

这明显是个黑名单 我们查看源码 

分析代码


$is_upload = false; 和 $msg = null; 初始化了两个变量,其中 $is_upload 用于标记文件是否成功上传,$msg 用于存储可能的错误消息或状态信息。通过 isset($_POST['submit']) 来检查是否有表单提交。然后它定义了一个数组 $deny_ext,包含了不允许上传的文件后缀, 再用deldot()函数去除文件名末尾的点。然后判断如果上传的文件后缀名不在黑名单内则先获取上传文件的临时文件名然后构建新的文件路径再将临时文件移动到指定位置。如果移动成功,$is_upload则将设置为ture,否则将错误信息赋给$msg。

在我们查看Apache中的配置文件我们可以知道

AddType application/x-httpd-php .php .phtml .php3 是指将.php .php3 .phtml的文件当作php文件来执行 这时我们发现.php3不在黑名单内 我们尝试修改文件名再上传

上传成功

Pass-04 (.htaccss重写绕过)


本关还是一个黑名单限制  我们查看一下源代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2","php1",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2","pHp1",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //收尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}


与第三关代码逻辑相同

.htaccess

htaccess可以帮我们实现包括:文件夹密码保护、用户自动重定向、自定义错误页面、改变你的文件扩展名、封禁特定IP地址的用户、只允许特定IP地址的用户、禁止目录列表,以及使用其他文件作为index文件等一些功能。

这个时候我们只需要创建一个.htaccess文件和我们的web.php在同一个目录下 htaccess文件内输入

Sethandler application/x-httpd-php

然后先上传.htaccess文件再更改我们恶意代码的后缀名 上传web.jpg文件即可将我们的php文件上传成功

Pass-05  (大写绕过)


这一关将.htaccess的文件也拉进黑名单了

查看源码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}

这一关我们发现居然没有转小写(PHP不区分大小写) 那我们直接把文件后缀改成.PHP就好了

Pass-06  (Windows特性绕过——空格绕过)

这一关提示没有限制.htaccess文件 尝试上传后还是提示此文件不允许上传 我们查看源码

分析代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = $_FILES['upload_file']['name'];$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATAif (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;if (move_uploaded_file($temp_file,$img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件不允许上传';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}

(我们发现代码中是有过滤.htaccess文件的但上面没显示)

这一关代码和前面的关卡比 没有首位去空了 那我们就可以通过在文件后缀名上加空格来绕过
这里涉及到Windows的特性 它会自动把文件后缀后面的空格删除掉 这样对于我们来说 有空格可以绕过它的黑名单 但对于Windows来说 空格是不存在的 依然可以解析 

Pass-07(Windows特性绕过——加`.`绕过)

分析代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}

这一次他没有去除掉末尾的点  那我们就可以在文件后缀名加个点来绕过 Windows的特性会自动删除后面的空格和点以及::$DATA(非法字符) 所以上传的文件还是可以解析的 

Pass-08(Windows特性绕过——::&DATA绕过)

分析代码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.date("YmdHis").rand(1000,9999).$file_ext;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}

与第七关同理 这一关没有过滤::$DATA 

Pass-09  (Windows特性绕过——综合)

分析源码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array(".php",".php5",".php4",".php3",".php2",".html",".htm",".phtml",".pht",".pHp",".pHp5",".pHp4",".pHp3",".pHp2",".Html",".Htm",".pHtml",".jsp",".jspa",".jspx",".jsw",".jsv",".jspf",".jtml",".jSp",".jSpx",".jSpa",".jSw",".jSv",".jSpf",".jHtml",".asp",".aspx",".asa",".asax",".ascx",".ashx",".asmx",".cer",".aSp",".aSpx",".aSa",".aSax",".aScx",".aShx",".aSmx",".cEr",".sWf",".swf",".htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = deldot($file_name);//删除文件名末尾的点$file_ext = strrchr($file_name, '.');$file_ext = strtolower($file_ext); //转换为小写$file_ext = str_ireplace('::$DATA', '', $file_ext);//去除字符串::$DATA$file_ext = trim($file_ext); //首尾去空if (!in_array($file_ext, $deny_ext)) {$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name;if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = '此文件类型不允许上传!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}

这一关是点 空格 ::&DATA全都过滤了 但我们发现只是末尾的点  那我们可以通过输入一个点一个空格再加一个点的方式来绕过

Pass-10  (双写绕过)

这一关会把这些后缀名全部删掉

分析源码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])) {if (file_exists(UPLOAD_PATH)) {$deny_ext = array("php","php5","php4","php3","php2","html","htm","phtml","pht","jsp","jspa","jspx","jsw","jsv","jspf","jtml","asp","aspx","asa","asax","ascx","ashx","asmx","cer","swf","htaccess");$file_name = trim($_FILES['upload_file']['name']);$file_name = str_ireplace($deny_ext,"", $file_name);$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = UPLOAD_PATH.'/'.$file_name;  //有个upload文件夹        if (move_uploaded_file($temp_file, $img_path)) {$is_upload = true;} else {$msg = '上传出错!';}} else {$msg = UPLOAD_PATH . '文件夹不存在,请手工创建!';}
}

双写问题

那试一下双写php 发现可以上传 且可以解析 只过滤了第一个php 自然而然p和后面的hp又组成了php

Pass-11  (截断漏洞——%00截断GET上传)

分析源码

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');//定义了白名单$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);// 截取文件后缀if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];//获取临时文件名 $img_path = $_GET['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;
//定义了一个save_path 然后把临时文件进行了一次重命名if(move_uploaded_file($temp_file,$img_path)){    //将上传的文件复制到img_path$is_upload = true;} else {$msg = '上传出错!';}} else{$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}

注:此截断漏洞只能在php5.3.x以下的版本才有  因为php底层还是C语言 C语言的截断就是%0

明白代码后我们可以可以进行如下操作 在upload下写一个php 用%00去截断后面的文件名 然后将我们的web.php文件改成.jpg文件 这样绕过上传成功后我们的web.jpg文件的内容会复制给lizhi.php里面去作为php文件执行

Pass-12  (截断漏洞——%00截断POST上传)

源码如下

$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');$file_ext = substr($_FILES['upload_file']['name'],strrpos($_FILES['upload_file']['name'],".")+1);if(in_array($file_ext,$ext_arr)){$temp_file = $_FILES['upload_file']['tmp_name'];$img_path = $_POST['save_path']."/".rand(10, 99).date("YmdHis").".".$file_ext;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上传失败";}} else {$msg = "只允许上传.jpg|.png|.gif类型文件!";}
}

这一关我们发现传参方式变成POST了 与上一关同理我们可以通过抓包修改参数 用%00来截断文件名 

Pass-13  (文件包含绕过头部检测)

这一关给我们的提示是上传一个图片马

分析源码

function getReailFileType($filename){$file = fopen($filename, "rb"); //以二进制方式打开我们的文件$bin = fread($file, 2); //只读2字节fclose($file);$strInfo = @unpack("C2chars", $bin);    $typeCode = intval($strInfo['chars1'].$strInfo['chars2']);    $fileType = '';    switch($typeCode){      // 根据前两个字节判断我们的文件是什么内容格式case 255216:            $fileType = 'jpg';break;case 13780:            $fileType = 'png';break;        case 7173:            $fileType = 'gif';break;default:            $fileType = 'unknown';}    return $fileType;
}$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$temp_file = $_FILES['upload_file']['tmp_name'];$file_type = getReailFileType($temp_file);if($file_type == 'unknown'){$msg = "文件未知,上传失败!";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").".".$file_type;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上传出错!";}}
}

注:文件包含是php的一种机制 一共有四个函数  include、require、include_once、require_once 它们的特性——包含的所有文件 都被当成php文件来执行

我们找到这个include知道他GET传的文件名是file之后 我们找一个.jpg文件 再自己写一个php文件 将两个文件融合 

这个时候我检查一下我们融合的jpg文件 php代码有没有融合进去

OK这个时候我们把这个文件上传进去 还没结束 我们上传的依旧是一个.jpg文件 没法执行php代码 这个时候我们只需要复制图片地址然后在url里面粘贴赋值给file即可 其他格式同理

Pass-14  (图片检测)

查看源码

function isImage($filename){$types = '.jpeg|.png|.gif';if(file_exists($filename)){$info = getimagesize($filename);    //这里判断了图片的大小格式  $ext = image_type_to_extension($info[2]);if(stripos($types,$ext)>=0){return $ext;}else{return false;}}else{return false;}
}$is_upload = false;
$msg = null;
if(isset($_POST['submit'])){$temp_file = $_FILES['upload_file']['tmp_name'];$res = isImage($temp_file);if(!$res){$msg = "文件未知,上传失败!";}else{$img_path = UPLOAD_PATH."/".rand(10, 99).date("YmdHis").$res;if(move_uploaded_file($temp_file,$img_path)){$is_upload = true;} else {$msg = "上传出错!";}}
}

和13关相同的技巧可以解决 

Pass-15  (图片检测)

function isImage($filename){//需要开启php_exif模块$image_type = exif_imagetype($filename);   //检测格式switch ($image_type) {case IMAGETYPE_GIF:return "gif";break;case IMAGETYPE_JPEG:return "jpg";break;case IMAGETYPE_PNG:return "png";break;    default:return false;break;}
}

13、14、15关同理

Pass-16  (图片渲染绕过)

这一关我们再尝试上传我们的带有php代码的图片的时候发现 图片虽然上传成功了但是我们发现 我们写的php代码不存在了 消失了   这个时候我们只能去看一下源码

分析源码

$is_upload = false;
$msg = null;
if (isset($_POST['submit'])){$filename = $_FILES['upload_file']['name'];//获取文件名$filetype = $_FILES['upload_file']['type'];//获取文件类型$tmpname = $_FILES['upload_file']['tmp_name'];//获取临时文件路径$target_path=UPLOAD_PATH.'/'.basename($filename);//获取文件路径$fileext= substr(strrchr($filename,"."),1);// 获得上传的文件的后缀名//判断文件后缀名类型if(($fileext == "jpg") && ($filetype=="image/jpeg")){if(move_uploaded_file($tmpname,$target_path)){$im = imagecreatefromjpeg($target_path);//使用上传的图片生成新的图片 这个很重要 把我们上传的图片打散了if($im == false){$msg = "该文件不是jpg格式的图片!";@unlink($target_path);}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".jpg";//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagejpeg($im,$img_path);@unlink($target_path);$is_upload = true;}} else {$msg = "上传出错!";}}else if(($fileext == "png") && ($filetype=="image/png")){if(move_uploaded_file($tmpname,$target_path)){//使用上传的图片生成新的图片$im = imagecreatefrompng($target_path);if($im == false){$msg = "该文件不是png格式的图片!";@unlink($target_path);}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".png";//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagepng($im,$img_path);@unlink($target_path);$is_upload = true;               }} else {$msg = "上传出错!";}}else if(($fileext == "gif") && ($filetype=="image/gif")){if(move_uploaded_file($tmpname,$target_path)){//使用上传的图片生成新的图片$im = imagecreatefromgif($target_path);if($im == false){$msg = "该文件不是gif格式的图片!";@unlink($target_path);}else{//给新图片指定文件名srand(time());$newfilename = strval(rand()).".gif";//显示二次渲染后的图片(使用用户上传图片生成的新图片)$img_path = UPLOAD_PATH.'/'.$newfilename;imagegif($im,$img_path);@unlink($target_path);$is_upload = true;}} else {$msg = "上传出错!";}}else{$msg = "只允许上传后缀为.jpg|.png|.gif的图片文件!";}
}

这个时候我们就要想了 这个图片可能有很多数据块 imagecreatefromjpeg()这个函数它是把这些数据块全都打散了 还是只打散了一部分 如果只打散了一部分 那我们把一句话木马插入到它没打散的部分 那就行的通了

既然我们有思路了 把上传的图片保存到本地 然后用beyond compare来对比原图和渲染之后的图 对比查看哪里没有被渲染 找到没有被渲染的地方加入我们的php代码 修改后再重新上传

Pass-17 (条件竞争漏洞/时间竞争)

代码审计

$is_upload = false;
$msg = null;if(isset($_POST['submit'])){$ext_arr = array('jpg','png','gif');//白名单$file_name = $_FILES['upload_file']['name'];//获取上传文件名$temp_file = $_FILES['upload_file']['tmp_name'];//获取临时文件名$file_ext = substr($file_name,strrpos($file_name,".")+1);//获取文件后缀$upload_file = UPLOAD_PATH . '/' . $file_name;//获取上传路径if(move_uploaded_file($temp_file, $upload_file)){//把上传的临时文件上传到想要上传的目标路径里if(in_array($file_ext,$ext_arr)){  //判断是否在白名单内$img_path = UPLOAD_PATH . '/'. rand(10, 99).date("YmdHis").".".$file_ext;rename($upload_file, $img_path);//在的话对文件进行重命名$is_upload = true;}else{$msg = "只允许上传.jpg|.png|.gif类型文件!";unlink($upload_file);//如果不在白名单内就删除文件}}else{$msg = '上传出错!';}
}

注:访问php文件的时候 php文件可以自动生成其他的php文件 我们就可以利用这个特性将新生成的php文件生成到上一级目录

我们注意到是先上传再删除的 那我们就可以在他删除前的那短时间内将我们的php文件进行操作 让我们的php文件在它的上一级目录生成一个新的一句话木马

我们写一个恶意代码 在我们访问成功的时候在他上级目录生成我们新的恶意代码 

<?php file_put_contents('../web.php','<?php phpinfo(); ?>');?>

然后打开我们的burpsuite暴力破解一下

然后我们抓住他删除前的时间内执行我们的php文件就可以将一句话木马放到它的上级目录

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

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

相关文章

[svelte]属性和逻辑块

属性 / Default values • Svelte 教程 | Svelte 中文网 属性 Declaring props 到目前为止&#xff0c;我们只处理了内部状态——也就是说&#xff0c;这些值只能在给定的组件中访问。 在任何实际应用程序中&#xff0c;都需要将数据从一个组件向下传递到其子组件。为此&…

【Spring】-编程式事务和声明式事务

spring中控制事务的方式有两种&#xff1a;编程式事务和声明式事务&#xff0c;今天我以两种事务出发&#xff0c;对spring中实现事务的EnableTransactionManagement和Transaction两个注解的底层原理进行讨论。 一、编程式事务 什么是编程式事务&#xff1f; 硬编码的方式实现…

Adobe将Sora、Runway、Pika,集成在PR中

4月15日晚&#xff0c;全球多媒体巨头Adobe在官网宣布&#xff0c;将OpenAI的Sora、Pika 、Runway等著名第三方文生视频模型&#xff0c;集成在视频剪辑软件Premiere Pro中&#xff08;简称“PR”&#xff09;。 同时&#xff0c;Adob也会将自身研发的Firefly系列模型包括视频…

【Python】高级进阶(专版提升3)

Python 1 程序结构1.1 模块 Module1.1.1 定义1.1.2 作用1.1.3 导入1.1.3.1 import1.1.3.2 from import 1.1.4 模块变量1.1.5 加载过程1.1.6 分类 1.2 包package1.2.1 定义1.2.2 作用1.2.3 导入1.1.3.1 import1.1.3.2 from import 2 异常处理Error2.1 异常2.2 处理 3 迭代3.1 可…

Three.js 入门——核心概念和坐标系理解

Three.js 是什么&#xff1f; 一个封装了 WebGL 的库&#xff0c;简化 WebGL 的使用 WebGL vs OpenGL OpenGL 主要被认为是一种 API&#xff08;应用程序编程接口&#xff09;&#xff0c;它为我们提供了大量可用于操作图形和图像的函数&#xff0c;主要用 C语言编写的。 然…

python辅助QQ登入

python辅助QQ登入 import pyautogui import time import random from pyautogui import ImageNotFoundException# 生成随机等待时间&#xff0c;范围在1到3秒之间 random_time random.uniform(1, 3)def find_and_click(image_path, moveFalse, execute_nextTrue):try:image_l…

【QT学习】7.事件,把文本显示在页面中(文本可变),鼠标指针切换,鼠标左键右键按下,qt设置背景样式

0.创建项目&#xff0c;事件的创建 1.事件的位置 2.这就是多态&#xff0c;子类重写父类函数&#xff0c;子类调用子类函数&#xff0c;也可以调用父类函数。但同函数名 1.要求&#xff1a;文本显示在页面中&#xff08;文本可变&#xff09; 1.文本显示在页面的核心代码 主要步…

DRF requets源码分析

【四】requets源码分析 【1】查看request传递的数据 &#xff08;1&#xff09;视图层 编写传输数据的接口查看request方法的参数 class BookAPIView(APIView):def get(self, request, *args, **kwargs):return Response({body: request.body, data: request.data, post: r…

【Web】DASCTF X GFCTF 2022十月挑战赛题解

目录 EasyPOP hade_waibo EasyLove BlogSystem EasyPOP 先读hint.php sorry.__destruct -> secret_code::secret() exp: $anew sorry(); $bnew secret_code(); $a->password"suibian"; $a->name"jay"; echo serialize($a); 真暗号啊&…

web项目中jsp页面不识别el表达式

如果使用el表达式出现下图问题 ** 解决办法 ** 这是因为maven创建项目时&#xff0c;web.xml头部声明默认是2.3&#xff0c;这个默认jsp关闭el表达式 修改web.xml文件开头的web-app的版本 <?xml version"1.0" encoding"UTF-8"?> <web-app x…

Python爬取猫眼电影票房 + 数据可视化

目录 主角查看与分析 爬取可视化分析猫眼电影上座率前10分析猫眼电影票房场均人次前10分析猫眼电影票票房占比分析 主角查看与分析 爬取 对猫眼电影票房进行爬取&#xff0c;首先我们打开猫眼 接着我们想要进行数据抓包&#xff0c;就要看网站的具体内容&#xff0c;通过按F12…

Postman之安装

Postman工具之介绍与安装 Postman是什么&#xff1f;Postman有几种安装方式&#xff1f; Postman是什么&#xff1f; postman是一款http客户端的模拟器&#xff0c;它可以模拟发出各种各样的网络请求&#xff0c;用于接口测试。 Postman有几种安装方式&#xff1f; 两种&…

4.17 网络编程

思维导图 select实现TCP并发服务器 #include <myhead.h> #define SER_IP "192.168.125.26" #define SER_PORT 8888int main(int argc, const char *argv[]) {int sfd socket(AF_INET,SOCK_STREAM,0);if(sfd -1){perror("socket error");return -1…

基于Java+SpringBoot+Mybaties-plus+Vue+elememt 小区物业管理系统 的设计与实现

一.项目介绍 系统分为管理员 和 业主 两块&#xff1a; 管理员点击进入到系统操作界面&#xff0c;可以对首页、业主信息管理、管理员信息管理、 楼栋和房屋信息管理、物业费管理、地下停车位管理、公告信息管理、报修信息管理、 投诉管理以及个人信息等功能模块 …

libftdi1学习笔记 5 - SPI Nor Flash

目录 1. 初始化 2. CS控制例子 3. 读ID 3.1 制造商 3.2 容量大小 3.3 设置IO类型 3.3.1 setQSPIWinbond 3.3.2 setQSPIMxic 3.3.3 setQSPIMicrochip 3.3.4 setQSPIMicron 4. 写保护 5. 等待空闲 6. 擦除扇区 7. 页编程 8. 页读 9. 写 10. 读 11. 验证 基于M…

cesium加载高层级离线影像地图瓦片(天地图、19级Arcgis)

实际加载效果如图&#xff1a; 1、下载离线地图瓦片方式&#xff08;多种任选其一&#xff0c;个人倾向于Qgis工具&#xff09;&#xff1a; 方式1、采用第三方下载工具如&#xff1a;91卫图、水经注、全能电子地图下载器、bigemap等等。&#xff08;这些有的下载层级不够&…

Spring Boot:Web应用开发之登录与退出的实现

Spring Boot 前言实现登录功能配置拦截器 实现退出功能 前言 登录与退出功能作为 Web 应用中的基础且重要的组成部分&#xff0c;直接关系到用户的安全和隐私保护。通过实现登录与退出功能&#xff0c;可以对用户的身份进行验证和授权&#xff0c;确保只有合法的用户才能访问特…

Qwen1.5大语言模型微调实践

在人工智能领域&#xff0c;大语言模型&#xff08;Large Language Model&#xff0c;LLM&#xff09;的兴起和广泛应用&#xff0c;为自然语言处理&#xff08;NLP&#xff09;带来了前所未有的变革。Qwen1.5大语言模型作为其中的佼佼者&#xff0c;不仅拥有强大的语言生成和理…

vue3【详解】选项式 API 实现逻辑复用

抽离逻辑代码到一个函数函数命名约定为 useXxxx格式 ( React Hooks 也是 )在 setup 中引用 useXxx 函数 演示代码&#xff1a;实时获取鼠标的坐标 逻辑封装 useMousePosition.js // 导入 ref, onMounted, onUnmounted import { ref, onMounted, onUnmounted } from "vue…

锐捷云桌面的安装

按下 <DEL> 键进入 BIOS setup 界面&#xff08;初始密码为 admin &#xff09;。 输入密码之后就进入 BIOS 的 Main 界面 设置服务器 BMC IP 地址。 a 云服务器启动后&#xff0c;在 BIOS 的主页面&#xff0c;把光标移到 [Server Mgmt] 项。 b 选择 [BMC Network C…