java之文件上传代码审计

1 文件上传漏洞审计

1.1 漏洞原理介绍

大部分文件上传漏洞的产生是因为Web应用程序未对文件的格式和进行严格过滤,导致用户可上传jsp、php等webshell代码文件,从而被利用。例如在 BBS发布图片 , 在个人网站发布ZIP压缩包, 在办公平台发布DOC文件等 , 只要 Web应用程序允许上传文件, 就有可能存在文件上传漏洞。

1.2 审计策略

  • 文件上传可以搜索以下关键词: upload,write,fileName ,filePath

  • 在查看时,主要判断是否有检查后缀和文件的大小

  • 同时要查看配置文件是否有设置白名单或者黑名单(不推荐黑名单,可能被绕过)

1.3 修复方案

  • 通过后端增加对上传文件后缀格式的验证,验证的手段有两种,分别是白名单校验和黑名单校验

  • 推荐使用白名单校验,绕过的危险小,黑名单无法维护全面,极容导致绕过校验成功上传脚本文件

  • 只允许文件上传到固定目录且设置程序对该目录下只有读写权限,不得具有执行权限

  • 推荐存储文件的服务器和应用服务器相互独立

  • 上传成功的文件不得真实的存储路径回显给前端,但是对于我想下载禁止直接使用完整的路径【为了防止直接暴露真实路径到前端】,应该通过key,到服务端或数据库中找到真实的路径下载即可

  • 必要的时候需要重命名文件名,最合理的一定是后端生成的文件的目录

1.4 审计案例

1.4.1 无任何过滤

服务端脚本语言未对上传的文件进行任何限制和过滤,导致恶意用户上传任意文件。

    <form action="/file/upload01" method="post" enctype="multipart/form-data"><input type="file" name="uploadfile" ><input type="submit"></form>

上传文件的后端处理,基于Spring Boot

package com.ms08067.fileupload.controller;
​
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
​
import java.io.File;
import java.io.IOException;
​
@Controller
@RequestMapping("/file")
public class FileUploadController {/*** 未对上传文件进行任何安全处理* @param file* @return*/@PostMapping("/upload01")public String uploadFile01(@RequestParam("uploadfile") MultipartFile file) {//获取文件名String filename = file.getOriginalFilename();//文件保存路径
//        String path = "/";File outfile = new File("D:\\20230222"+filename);try {file.transferTo(outfile);} catch (IOException e) {e.printStackTrace();}return "success";}}

上述代码未对上传的文件进行任何检测,可以上传任意类型的文件,包括exe文件和木马等。

运行页面如下:

成功上传后

1.4.2 客户端检测

JS对文件后缀名检测绕过

通过前端js检测文件名是否合法没有任何意义,因为任意用户都可以对前端js进行任意修改或者通过burp suite抓包修改上传的文件名。

以下代码限制上传文件的后缀名必须为.jpg和.png

<form action="/file/upload02" method="post"  οnsubmit="return judge()" enctype="multipart/form-data"><input type="file" name="uploadfile" id="checkfile" ><input type="submit" value="提交"><p id="msg"></p>
</form>
<script type="text/javascript">
​function judge(){var file=document.getElementById("checkfile").value;if (file==null||file==""){alert("请选择要上传的文件");// location.reload(true);return false;}var isnext=false;var filetypes=[".jpg",".png"];var fileend=file.substring(file.lastIndexOf("."));for (var i=0;i<filetypes.length;i++){if (filetypes[i]==fileend){isnext=true;break;}}if (!isnext){document.getElementById("msg").innerHTML="文件类型不允许";
​// location.reload(true);return false;
​}else {return true;}
​}
</script>

后端没有进行任何限制,将文件存储在src\main\resources\static\upload下

 import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
​
import java.io.File;
import java.io.IOException;/*** 前端通过JS进行文件名称限制* @param file* @return*/@PostMapping("/upload02")public String uploadFile02(@RequestParam("uploadfile") MultipartFile file) {String filename = file.getOriginalFilename();String path = "D:\\20230222";File fileDir = new File(path);File outfile = new File(fileDir.getAbsolutePath()+File.separator + filename);try {file.transferTo(outfile);}catch (IOException e){e.printStackTrace();}
​return "success";}

绕过js检测方法一:修改前端代码,删除js检测部分或者禁用js

绕过js检测方法二:使用代理Burp Suite上传文件;上传符合要求的文件类型,抓包修改文件类型。例

如要上传1.jsp,先将文件名改为1.jpg,上传,抓包,再修改为1.jsp即可。


成功上传

1.4.3 服务端检测绕过

1.4.3.1 服务器端后缀名检测绕过

主要通过黑白名单进行过滤,如果不符合过滤规则,则不允许上传

一般有个专门的 blacklist 文件,里面会包含常见的危险脚本文件后缀名。

1.4.3.2 大小写绕过

以下后端代码,检测上传的文件的后缀名是否符合要求,不允许上

传".jsp",".php",".exe",".dll","vxd","html"结尾的文件,可通过将文件后缀大写进行绕过

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
​
import java.io.File;
import java.io.IOException;
//基于黑名单大小写绕过的文件上传@PostMapping("/upload03")public String uploadFile03(@RequestParam("uploadfile")MultipartFile file, Model model){boolean flag=true;String filename = file.getOriginalFilename();System.out.println(filename);String suffix=filename.substring(filename.lastIndexOf("."));String[] blacklist={".jsp",".php",".exe",".dll","vxd","html"};//后缀名黑名单for (String s : blacklist) {if (suffix.equals(s)){flag=false;break;}}if (flag){String path="D:\\20230222";File fileDir = new File(path);File outfile = new File(fileDir.getAbsolutePath()+File.separator + filename);try {file.transferTo(outfile);return "success";}catch (IOException e){e.printStackTrace();}
​}else {model.addAttribute("msg","非法文件类型");}return "index";}

通过大小写上传

上述黑名单仅过滤了少数后缀名,可以上传其他后缀类型的恶意文件。

可利用Burp suite截断HTTP请求,利用Intruder模块进行枚举后缀名,寻找黑名单中没有过滤的后缀名。接收HTTP请求,send to intruder,选中变量,在Payloads中加载相应的字典。

1.4.3.3 双写绕过

以下代码判断文件后缀名是否存在黑名单中的字符,若存在则将对应的字符串替换为空

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
​
import java.io.File;
import java.io.IOException;
//基于双写绕过的文件上传(如果后缀名为非法的字符,将替换成空)修复大小写绕过@PostMapping("/upload04")public String uploadFile04(@RequestParam("uploadfile")MultipartFile file){String filename = file.getOriginalFilename();System.out.println(filename);String preFilename=filename.substring(0,filename.lastIndexOf("."));String suffix=filename.substring(filename.lastIndexOf(".")).toLowerCase();String[] blacklist={"jsp","php","exe","dll","vxd","html"};//后缀名黑名单for (String s : blacklist) {if (suffix.indexOf(s)!=-1){suffix=suffix.replace(s,"");//后缀存在黑名单字符串,则将字符串替换为空}}String path="D:\\20230222";File fileDir = new File(path);File outfile = new File(fileDir.getAbsolutePath()+File.separator + preFilename+suffix);try {file.transferTo(outfile);return "success";}catch (IOException e){e.printStackTrace();}return "index";}

可通过双写后缀名进行绕过,例如上传4.jjspsp文件,过滤掉jsp后,文件名正好是我们想要上传的

1.4.3.4 双后缀名绕过

以下代码,后端判断后缀名使用的是filename.indexOf("."),而不是filename.lastIndexOf(".")

可通过双后缀名绕过检测,例如欲上传1.jsp,可将文件名改为1.jsp.jsp,这样后端获得的后缀名

为.jsp.jsp,可通过检测。

   //文件后缀名双写绕过-未修复大小写绕过@PostMapping("/upload05")public String uploadFile05(@RequestParam("uploadfile")MultipartFile file,Model model){boolean flag=true;String filename = file.getOriginalFilename();System.out.println(filename);String suffix=filename.substring(filename.indexOf("."));String[] blacklist={".jsp",".php",".exe",".dll",".vxd",".html"};//后缀名黑名单for (String s : blacklist) {if (suffix.equals(s)){flag=false;break;
​}}if (flag){String path="D:\\20230222";File fileDir = new File(path);File outfile = new File(fileDir.getAbsolutePath()+File.separator + filename);try {file.transferTo(outfile);return "success";}catch (IOException e){e.printStackTrace();}
​}else {model.addAttribute("msg","非法文件类型");
​}return "index";
​}

上传不符合windows文件命名规则的文件名

上述代码可以通过抓包,修改文件名为如下形式:

  • 点绕过1.jsp.

  • 空格绕过1.jsp(空格)

  • 1.jsp:1.jpg

  • 1.jsp::$DATA

1.4.4 白名单检测

在jdk低版本(1.7及以下)中可以使用%00截断。图片木马

1.4.4.1 MIME类型检测绕过

以下代码限制上传文件的MIME类型需为"image/jpeg","image/png"或"image/gif",可通过抓包,

修改Content-Type为合法类型绕过MIME类型检测

 @PostMapping("/upload07")public String uploadFile07(@RequestParam("uploadfile")MultipartFile file,Model model){boolean flag=false;String filename = file.getOriginalFilename();String contentType = file.getContentType();System.out.println(filename);String preFilename=filename.substring(0,filename.lastIndexOf("."));String suffix=filename.substring(filename.lastIndexOf(".")).toLowerCase();//基于文件头类型进行白名单校验String[] whiteList={"image/jpeg","image/png","image/gif"};for (String s : whiteList) {if (contentType.equals(s)){flag=true;}}if (flag){String path="D:\\20230222";File fileDir = new File(path);File outfile = new File(fileDir.getAbsolutePath()+File.separator + filename);try {file.transferTo(outfile);return "success";}catch (IOException e){e.printStackTrace();}
​}else {model.addAttribute("msg","非法文件类型");}return "index";}

例如上传1.jsp文件,可修改Content-Type值为 image/jpeg

1.4.4.2 文件头检测绕过

根据文件的前面几个字节,即常说的魔术数字进行判断,不同文件类型的开头几个字节不同。

常见文件头:

以下代码,通过检测文件头部分判断上传的文件是否为图片,可利用如下两种方法绕过

package com.ms08067.fileupload.controller;
​
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
​
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
​
@Controller
@RequestMapping("/file1")
public class FileUploadController1 {public final static Map<String,String> FileType=new HashMap<String,String>();static {getAllFileType();//初始化文件类型信息}@PostMapping("/upload")public static String upload(@RequestParam("uploadfile") MultipartFile file, Model model){String filename = file.getOriginalFilename();boolean flag=false;byte[] b=new byte[50];try {InputStream inputStream = file.getInputStream();inputStream.read(b);System.out.println(b.toString());StringBuilder stringBuilder=new StringBuilder();if (b==null ||b.length<0){flag=false;}for (int i = 0; i < b.length; i++) {int v=b[i]&0xff;String hv=Integer.toHexString(v);//十六进制stringBuilder.append(hv);}System.out.println("stringBuilder"+stringBuilder.toString());String fileTypeHex = String.valueOf(stringBuilder.toString());Iterator<Map.Entry<String, String>> iterator = FileType.entrySet().iterator();while (iterator.hasNext()){//判断文件前几个字节是否为FileType中三种类型之一Map.Entry<String, String> next = iterator.next();System.out.println(fileTypeHex.toUpperCase(Locale.ROOT));if (fileTypeHex.toUpperCase(Locale.ROOT).startsWith(next.getValue())){flag=true;}
​}
​inputStream.close();}catch (FileNotFoundException e){e.printStackTrace();}catch (IOException e){e.printStackTrace();
​}
​if (flag){String path="D:\\20230222";File fileDir = new File(path);File outfile = new File(fileDir.getAbsolutePath()+File.separator + filename);try {file.transferTo(outfile);return "success";}catch (IOException e){e.printStackTrace();}
​}else {model.addAttribute("msg","非法文件类型");
​}return "index";
​}private static void getAllFileType(){FileType.put("jpeg","FFD8FF");FileType.put("png","89504E47");FileType.put("gif","47494638");FileType.put("jpg","GIF89a");}}
1.4.4.3 添加合法文件头绕过

通过抓包,添加合法文件头,例如GIF89a(jpg格式文件头)


上传两个注意事项:

(1)编码前空格、编码上边空一行

1.4.4.4 制作图片木马绕过

copy 2.jpg/b+1.jsp 3.jpg,或者使用记事本等软件打开图片,在末尾添加jsp木马数据,将攻击脚本隐藏到图片中。

单纯的图片马并不能直接和蚁剑连接,因为该文件依然是以image格式进行解析,需要结合文件包含漏洞

1.4.4.5 ImageIO判断上传图片文件

通过ImageReader解码file并返回一个BufferedImage对象,如果找不到合适的ImageReader则会返回null,我们可以认为这不是图片文件。

如果能够正常的获取到一张图片的宽高属性,那么该文件一定是图片,因为非图片文件获取不到它的宽高属性的。

但若是在可以正常打开的图片里面加入非法代码或者病毒,那就非常危险了

@Controller
public class UploadImg {
//ImageIO判断上传的文件是否为图片
@PostMapping("/upload")
public static String uploadImg(@RequestParam("uploadfile")MultipartFile file , Model model){
boolean flag=false;
String filename = file.getOriginalFilename();
String suffix = filename.substring(filename.lastIndexOf("."));
String path="src\\main\\resources\\static\\upload";
File fileDir = new File(path);
File outfile = new File(fileDir.getAbsolutePath()+File.separator + filename);
String[] whiteList={".jpg",".png"};
for (String s : whiteList) {
if (suffix.toLowerCase(Locale.ROOT).equals(s)){
flag=true;
break;
}
}
File tmpFile=null;
if (flag){
tmpFile = new File(System.getProperty("java.io.tmpdir"), filename);
​
try{
file.transferTo(tmpFile);
BufferedImage read = ImageIO.read(tmpFile);
read.getWidth();
read.getHeight();
}catch (Exception e){
e.printStackTrace();
flag=false;
}finally {
if (flag){
try {
FileCopyUtils.copy(new FileInputStream(tmpFile),
Files.newOutputStream(Paths.get(path,filename), StandardOpenOption.CREATE_NEW));tmpFile.delete();
return "success";
}catch (FileNotFoundException e){
e.printStackTrace();
}catch (IOException e){
e.printStackTrace();
}
}else {
model.addAttribute("msg","请上传图片文件!");
}
}
}else {
model.addAttribute("msg","文件后缀名不符合要求");
}
return "index";
}
}

1.5 文件上传漏洞总结

文件上传漏洞的原因:

  • 未对文件做任何过滤,可上传任意文件类型,如木马、可执行文件等;

  • 在js端检验文件后缀,可通过删除js或禁用js或抓包修改文件后缀等方法绕过;

  • 后端后缀过滤使用黑名单,过滤不全,可通过使用未过滤的后缀名、大小写变换、双写后缀名、双后缀名、文件名结尾加”.“或空格、%00截断等方式绕过;

  • 后端判断文件类型,只判断Content-type,可通过抓包修改Content-type字段的值进行绕过;

  • 后端检查文件内容仅检查文件头内容,可通过抓包添加合法文件头,或使用其他工具添加合法文件头进行绕过。

1.6 文件上传漏洞修复

  • 服务器端的检查最好使用白名单过滤的方法,黑名单极不可靠

  • 使用随机数**改写文件名和文件路径**。文件上传如果要执行代码,需要用户能够访问到这个文件。应用了随机数改写了文件名和路径,可防止大小写绕过、双后缀、多后缀等手段,将极大地增加攻击的成本;

  • 文件上传目录设置为不可执行,只要web容器无法解析该目录下面的文件,即使攻击者上传了脚本文件,服务器本身也不会受到影响。

  • 使用安全设备防御,恶意文件千变万化,隐藏手法也不断推陈出新,对普通的系统管理员来说可以通过部署安全设备来帮助防御。

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

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

相关文章

高阶图神经网络 (HOGNN) 的概念、分类和比较

图神经网络&#xff08;GNNs&#xff09;是一类强大的深度学习&#xff08;DL&#xff09;模型&#xff0c;用于对相互连接的图数据集进行分类和回归。它们已被用于研究人类互动、分析蛋白质结构、设计化合物、发现药物、识别入侵机器、模拟单词之间的关系、寻找有效的交通路线…

Vue70-路由的几个注意点

一、路由组件和一般组件 1-1、一般组件 1-2、路由组件 不用写组件标签。靠路由规则匹配出来&#xff0c;由路由器渲染出来的组件。 1-3、注意点1 一般组件和路由组件&#xff0c;一般放在不同的文件夹&#xff0c;便于管理。 一般组件放在components文件夹下。 1-4、注意点…

河南大学24计算机考研数据,有三个学院招收计算机相关专业,都是考的408!

河南大学&#xff08;Henan University&#xff09;&#xff0c;简称“河大”&#xff0c;是河南省人民政府与中华人民共和国教育部共建高校&#xff0c;国家“双一流”建设高校&#xff0c;入选国家“111计划”、中西部高校基础能力建设工程、卓越医生教育培养计划、卓越法律人…

怎么用二维码在线下载视频?视频用二维码下载的制作方法

怎么把视频转换成二维码之后还可以下载视频呢&#xff1f;现在使用二维码的方式来分享视频内容在很多行业和场景中都有应用&#xff0c;这种方式能够更加简单快捷的完成视频的传播分享&#xff0c;那么怎么让扫码者可以自由选择下载视频呢&#xff1f;下面来给大家分享扫码下载…

深入探索C++中的AVL树

引言 在数据结构和算法的世界里&#xff0c;平衡二叉搜索树&#xff08;Balanced Binary Search Tree, BST&#xff09;是一种非常重要的数据结构。AVL树&#xff08;Adelson-Velsky和Landis发明的树&#xff09;就是平衡二叉搜索树的一种&#xff0c;它通过自平衡来维护其性质…

zookeeper + kafka消息队列

zookeeper kafka 消息队列 一、消息队列简介 1、什么是消息队列 消息队列&#xff08;Message Queue&#xff09;是一种用于跨进程或分布式系统中传递消息的通信机制。消息队列在异步通信、系统解耦、负载均衡和容错方面具有重要作用。 &#xff08;1&#xff09;特性 异步…

c++ 里构造函数的形参与数据成员的同名问题

如题&#xff0c;这时&#xff0c;或许在 java 里&#xff0c;会报语法错误。但在 c vs2019 开了 c20语法规范。这不再是错误。这样的好处是解决了咱们的起变量名的麻烦&#xff1a;重名现在已不是错误&#xff0c;编译器可以解决了。测试如下&#xff1a; 我们看看 c 编译器是…

如何正确理解和评估品牌价值?

在当今这个品牌林立的商业世界里&#xff0c;我们常常听到企业家们满怀憧憬地谈论品牌梦想。 但究竟是什么驱使这些企业去打造一个品牌&#xff0c;到底是市场的激烈竞争&#xff0c;还是内心的情感寄托&#xff1f;亦或是社会发展的必然趋势&#xff0c;引领我们追求超越产品…

1969python房屋租赁管理系统mysql数据库Flask结构BootStrap布局计算机软件工程网页

一、源码特点 python Flask房屋租赁管理系统是一套完善的web设计系统mysql数据库 &#xff0c;对理解python编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。 python flask 房屋租赁管理系统 开发环境pycharm mysql …

鸿蒙正在跨越“生态繁荣阈值”

作者 | 曾响铃 文 | 响铃说 先讲一个故事。 一个朋友曾经做了一个本地互联网装修平台&#xff0c;一边是装修服务的提供者——各工种工人等&#xff0c;一边是有装修需求的业主。这个平台要做独立生态&#xff0c;绕过旧有的装修公司渠道垄断&#xff0c;直接提供服务&#…

Android开发系列(六)Jetpack Compose之Box

Box是一个用来组合和控制子元素布局的组件。它可以在一个矩形区域内排列一个或多个子元素&#xff0c;并根据所提供的参数来控制它们的位置、大小和样式。 Box的功能类似传统的FrameLayout。 下面通过示例了解Box的使用方法&#xff0c;首先看一个最简单的示例&#xff0c;如下…

永磁同步电机驱动死区补偿

1 死区效应及补偿 1. 1 死区效应 在本文的电机控制嵌入式系统中,逆变器为三 相电压型桥式逆变电路,如图 1 所示。 在理想状态 下,上桥臂和下桥臂的控制信号满足互补通断原则, 即上桥臂开通时,下桥臂关断,反之亦然。 而在实际 应用中,开关管的通断需要一定的开通时…

Nginx HTTPS(证书) 部署实战

一、申请证书与认证 要搭建https服务首先需有SSL证书&#xff0c;证书通常是在第三方申请&#xff0c;在阿里云的安全服务中有SSL证书这一项&#xff0c;可以在里面申请免费的证书。也可以在自己电脑中生成&#xff0c;虽然也能完成加密&#xff0c;但是浏览器是不认可的&…

美创科技入选“2024年度浙江省工业信息安全服务支撑单位”

近日&#xff0c;浙江省经济和信息化厅公布“2024年度浙江省工业信息安全服务支撑单位”名单。 经单位自愿申报、各市经信主管部门初审推荐、专家评审等环节&#xff0c;凭借在工业数据安全领域长期深耕和产品服务实力&#xff0c;美创科技成功入选&#xff01; “2024年度浙江…

理解 JTBD 框架和EJ 理念:深挖以用户为中心的设计

在与用户的交流中&#xff0c;我们发现对用户需求的精准洞察普遍困扰着产品经理、设计、企划人员&#xff0c;因为当今消费者行为已经由单品消费转向场景消费&#xff0c;千人千面的个性化需求出现&#xff0c;消费者数据维度极大丰富&#xff0c;这对把握用户体验造成了很大挑…

工具与技术:如何使用工具创建和实现导航栏图标动效

这篇教程的目的主要是带领大家做UI交互的入门引导,让大家理解做交互动效的一些基本逻辑思维,利用原型交互动画做导航栏icon动画效果。 导航栏icon动效的详细教程&#xff1a; 即时设计 - 可实时协作的专业 UI 设计工具即时设计是一款支持在线协作的专业级 UI 设计工具&#x…

2024年道路运输企业主要负责人证模拟考试题库及道路运输企业主要负责人理论考试试题

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2024年道路运输企业主要负责人证模拟考试题库及道路运输企业主要负责人理论考试试题是由安全生产模拟考试一点通提供&#xff0c;道路运输企业主要负责人证模拟考试题库是根据道路运输企业主要负责人最新版教材&#…

【算法训练记录——Day32】

Day32——贪心算法Ⅱ 1.leetcode122买卖股票的最佳时机II2.leetcode55跳跃游戏3.leetcode45跳跃游戏II4.eetcode1005K次取反后最大化的数组和 目标&#xff1a; leetcode122买卖股票的最佳时机IIleetcode55跳跃游戏leetcode45跳跃游戏IIleetcode1005K次取反后最大化的数组和 1…

掌握数据魔方:Xinstall引领ASA全链路数据归因新纪元

一、引言 在数字化时代&#xff0c;数据是App推广和运营的核心驱动力。然而&#xff0c;如何准确获取、分析并应用这些数据&#xff0c;却成为了许多开发者和营销人员面临的痛点。Xinstall作为一款专业的App全渠道统计服务商&#xff0c;致力于提供精准、高效的数据解决方案&a…