Web Security 之 Insecure deserialization

news2024/11/25 14:55:18

Insecure deserialization

在本节中,我们将介绍什么是不安全的反序列化,并描述它是如何使网站遭受高危害性攻击的。我们将重点介绍典型的场景,并演示一些 PHP、Ruby 和 Java 反序列化的具体示例。最后也会介绍一些避免不安全的反序列化漏洞的方法。

利用不安全的反序列化通常比较困难。然而,它有时比你想象的要简单得多。如果您不熟悉反序列化,那么本节将包含一些重要的背景信息,您应该首先熟悉这些信息。如果您已经了解反序列化的基础知识,那么可以直接跳到学习如何利用它。

什么是序列化

序列化是将复杂的数据结构(如对象及其字段)转换为“更扁平”的格式的过程,该格式的数据可以作为字节流序列发送和接收。序列化的数据让以下过程更简单:

  • 将复杂数据写入进程间内存、文件或数据库
  • 发送复杂数据,例如,通过网络或API调用,在应用程序的不同组件之间传递复杂数据

关键的是,当序列化一个对象时,其状态也将保持不变。换句话说,对象的属性及其赋值都会被保留。

序列化 vs 反序列化

反序列化是将字节流还原为与原始对象完全相同的副本的过程。然后,网站的逻辑就可以与这个反序列化的对象进行交互,就像与任何其他对象进行交互一样。

许多编程语言提供对序列化的本地支持。具体如何序列化对象取决于具体语言。一些语言将对象序列化为二进制格式,而另一些语言则会序列化为具有不同程度的可读性的字符串格式。请注意,原始对象的所有属性都存储在序列化数据流中,包括所有私有字段。为了防止字段被序列化,必须在类声明中将其显式标记为"transient" 。

请注意,当使用不同的编程语言时,序列化可能被称为 marshalling(Ruby)或 pickling(Python),这些术语与“序列化”同义。

什么是不安全的反序列化

不安全的反序列化是指用户可控制的数据被网站反序列化。这会使攻击者能够操纵序列化的对象,以便将有害数据传递到应用程序代码中。

甚至可以用完全不同类的对象替换序列化对象。令人担忧的是,网站上任何可用的类的对象都将被反序列化和实例化,而不管这个类是不是预期的类。因此,不安全的反序列化有时被称为 “object injection” 对象注入漏洞。

一个意外类的对象可能会导致异常。不过,在此之前,损害可能已经造成。许多基于反序列化的攻击在反序列化结束之前就已经完成。这意味着可以攻击反序列化的过程本身,即使网站的功能不直接与恶意对象交互。因此,其逻辑基于强类型语言的网站也容易受到这些技术的攻击。

不安全的反序列化漏洞是如何出现的

不安全的反序列化出现通常是因为人们普遍缺乏对用户可控数据进行反序列化的危险程度的了解。理想情况下,根本不应该对用户输入进行反序列化。

有些网站所有者认为他们很安全,因为其会对反序列化的数据进行某种形式的附加检查。然而,这种方法通常是无效的,因为几乎不可能验证或预料到所有可能发生的情况。这些检查在根本上也是有缺陷的,因为它们依赖于在数据被反序列化后对其进行检查,在许多情况下,这对于防止攻击来说已经太晚了。

漏洞产生也可能是因为反序列化的对象通常被认为是可信的。特别是在使用二进制序列化格式的语言时,开发人员可能会认为用户无法有效地读取或操作数据。然而,尽管这可能需要更多努力,但攻击者利用二进制序列化对象的可能性与利用基于字符串的格式的可能性是一样的。

由于现代网站中存在大量依赖项,因此基于反序列化的攻击也成为可能。一个站点可能使用许多不同的库,每个库也都有自己的依赖项,这就产生了一个难以安全管理的存在大量类和方法的池子。由于攻击者可以创建这些类中的任何一个实例,因此很难预测可以对恶意数据调用哪些方法。如果攻击者能够将一长串意外的方法调用链接在一起,并将数据传递到与初始源完全无关的接收器中,则尤其如此。因此,几乎不可能预测到恶意数据的流动并堵塞每个潜在的漏洞。

简而言之,安全地反序列化不受信任的输入是不可能的。

不安全的反序列化会造成什么影响

不安全的反序列化的影响可能非常严重,因为它提供了一个切入点,从而导致攻击面大幅增加。它允许攻击者以有害的方式重用现有的应用程序代码,从而导致许多其他漏洞,比如远程代码执行.

即使在无法执行远程代码的情况下,不安全的反序列化也可能导致权限提升、访问任意文件和拒绝服务攻击。

如何利用不安全的反序列化漏洞

下文会有详细说明。

如何防止不安全的反序列化漏洞

一般来说,除非绝对必要,否则应该避免用户输入的反序列化。在许多情况下,防御其潜在的高危漏洞的难度超过了其带来的好处。

如果确实需要反序列化来自不受信任的源的数据,请采取强大的措施以确保数据未被篡改。例如,您可以实现一个数字签名来检查数据的完整性。但是,请记住,任何检查都必须在开始反序列化之前进行。否则,检查就没什么用处了。

如果可能,您应该避免使用通用的反序列化功能。这些方法的序列化数据包含了原始对象的所有属性,以及可能包含敏感信息的私有字段。相反,你应该创建自己特定类的序列化方法,以控制公开字段。

最后,请记住,该漏洞是用户输入的反序列化,而不是随后处理数据的工具链的存在。不要依赖于试图消除测试过程中识别的工具链,由于跨库依赖的存在,这是不切实际的。在任何给定的时间,公开记录的内存损坏漏洞也意味着应用程序可能会受到攻击。


利用 insecure deserialization 漏洞

在本节中,我们将通过 PHP、Ruby 和 Java 反序列化的示例来教你如何利用一些常见漏洞场景。我们希望证明利用不安全的反序列化实际上比许多人认为的要容易得多。如果你能够使用预先构建的工具链,那么即使在黑盒测试期间也是如此。

我们还将指导你创建基于反序列化高危漏洞的攻击。尽管这些通常需要访问源代码,但是一旦理解了基本概念,它们也比你想象的更容易学习。我们将讨论以下主题:

  • 如何识别不安全的反序列化
  • 修改网站所需的序列化对象
  • 将恶意数据传递到危险的网站功能中
  • 注入任意对象类型
  • 链式方法调用以控制数据流入危险的接收器中
  • 手动创建自己的高级的漏洞利用
  • PHAR 反序列化

注意:尽管许多实验和示例都基于PHP,但大多数开发技术对其他语言也同样有效。

如何识别不安全的反序列化

识别不安全的反序列化相对来说比较简单,无论你使用白盒测试还是黑盒测试。

在审核过程中,你应该查看网站所有传入数据,并尝试识别出任何类似于序列化的数据。如果你知道不同语言使用的格式,则可以相对容易地识别序列化的数据。在本节中,我们将展示 PHP 和 Java 序列化的示例。一旦确定了序列化的数据,就可以测试是否能够控制它。

PHP 序列化格式

PHP 使用了一种几乎可读的字符串格式,字母表示数据类型,数字表示每个部分的长度。例如,假设一个 User 对象具有以下属性:

$user->name = "carlos";
$user->isLoggedIn = true; 

序列化之后,此对象可能如下所示:

O:4:"User":2:{s:4:"name":s:6:"carlos"; s:10:"isLoggedIn":b:1;} 

其含义是:

  • O:4:"User" - 一个对象,类名是 4 个字符的 “User”
  • 2 - 对象有 2 个属性
  • s:4:"name" - 第一个属性的键是 4 个字符的字符串 “name”
  • s:6:"carlos" - 第一个属性的值是 6个字符的字符串 “carlos”
  • s:10:"isLoggedIn" - 第二个属性的键是 10 个字符的字符串 “isLoggedIn”
  • b:1 - 第二个属性的值是布尔值 true

PHP 序列化的本地方法是 serialize()unserialize() 。如果你有源代码的访问权限,则应该首先在所有位置查找 unserialize() 并进行进一步调查。

Java 序列化格式

有些语言,如 Java ,使用二进制序列化格式。这更难阅读,但如果知道如何识别一些信号,则仍然可以识别序列化的数据。例如,序列化的 Java 对象总是以相同的字节开头,这些字节被编码为十六进制 ac ed 和 Base64 的 rO0

实现接口 java.io.Serializable 的任何类都可以序列化和反序列化。如果你有源代码的访问权限,请注意使用 readObject() 的方法,该方法用于从 InputStream 中读取并反序列化数据。

操纵序列化对象

利用某些反序列化漏洞就像更改序列化对象中的属性一样容易。当对象状态被持久化时,你可以研究序列化数据以识别和编辑感兴趣的属性值。然后,通过反序列化过程将恶意对象传递给网站。这是基本的反序列化攻击的初始步骤。

广义地说,在操纵序列化对象时可以采用两种方法。你可以直接以字节流的形式编辑对象,也可以用相应的语言编写一个简短的脚本来自己创建和序列化新对象。使用二进制序列化格式时,后一种方法通常更容易。

修改对象属性

在篡改数据时,只要攻击者保留一个有效的序列化对象,反序列化过程将使用修改后的属性值创建一个服务器端的对象。

作为一个简单的示例,假设一个网站使用序列化对象 User 在 cookie 中存储有关用户会话的数据。如果攻击者在 HTTP 请求中发现了这个序列化对象,他们可能会对其进行解码以找到以下字节流:

O:4:"User":2:{s:8:"username";s:6:"carlos";s:7:"isAdmin";b:0;} 

这个 isAdmin 属性很容易引起攻击者的兴趣。攻击者只需将这个属性的布尔值更改为 1(true),然后重新编码对象,并用此修改后的值覆盖当前 cookie 。单独来看的话这没啥用。但是,如果网站使用此 cookie 检查当前用户是否有权访问某些管理功能:

$user = unserialize($_COOKIE);
if ($user->isAdmin === true) {
// allow access to admin interface
} 

上述代码将基于来自 cookie 的数据实例化 User 对象,包括攻击者修改后的 isAdmin 属性,并且不会检查序列化对象的真实性。此时,修改后的数据就直接升级了权限。

这种简单的场景并不常见。然而,以这种方式编辑属性值展示了进行攻击的第一步。

修改数据类型

我们除了修改序列化对象中的属性值之外,也可以提供意外的数据类型。

像 PHP 这种弱类型语言,使用松散的比较运算符 == 比较不同的数据类型时特别容易受到这种操作的攻击。例如,如果在整数和字符串之间执行松散比较,PHP 将尝试将字符串转换为整数,这意味着 5 == "5" 计算结果为 true.

特别的是,这也适用于任何以数字开头的字母数字字符串。PHP 会将整个字符串转换为初始数字的整数值,字符串的其余部分将被完全忽略。因此,5 == "5 of something" 实际上被视为 5 == 5

当将字符串与整数 0 进行比较时,这变得更加奇怪:

0 == "Example string" // true 

因为字符串中没有数字,PHP 会将整个字符串视为整数 0 。

考虑这样一种情况:将这个松散的比较运算符与来自反序列化对象的用户可控数据一起使用,这可能导致危险的逻辑缺陷。

$login = unserialize($_COOKIE)
if ($login['password'] == $password) {
// log in successfully
} 

假设攻击者修改了 password 属性,使其为整数 0 而不是预期的字符串。那么只要存储的密码不是以数字开头,就会导致身份验证通过。请注意,这只是一种可能性,因为反序列化可保留数据类型,如果代码直接从请求中获取密码,则 0 将转换为字符串,并且条件的评估结果为 false 。

请注意,在修改任何序列化对象格式的数据类型时,务必记住也要更新序列化数据中的任何类型标签和长度指示符。否则,序列化的对象将损坏,并且不会反序列化。

当直接使用二进制格式时,我们建议使用 Hackvertor 扩展,其可以从 BApp store 中获得。使用 Hackvertor,你可以将序列化数据修改为字符串,它将自动更新二进制数据,并相应地调整偏移量,这可以节省大量的手动操作。

使用应用程序功能

除了简单地检查属性值之外,网站的功能还可能对反序列化对象中的数据执行危险的操作。在这种情况下,你可以使用不安全的反序列化来传递意外的数据,并利用相关功能造成损害。

例如,作为网站“删除用户”功能的一部分,通过访问 $user->image_location 属性可以删除用户的个人资料图片。如果这个 $user 来源于序列化对象,则攻击者可以通过传入一个修改了 image_location 的对象将其设置为任意一个文件路径。删除他们自己的用户帐户也会删除这个任意文件。

此示例依赖于攻击者通过用户可访问的功能手动调用危险方法。然而,当你构造将数据自动传递到危险方法的漏洞利用时,不安全的反序列化将变得更加有趣。这是通过使用“魔术方法”来实现的。

魔术方法

魔术方法是不必显式调用的方法的特殊子集。相反,它们会在特定事件或场景发生时自动调用。魔术方法是各种语言中面向对象编程的一个共同特征。它们有时通过在方法名前面加上前缀或用双下划线包围来表示。

开发人员可以向类中添加魔术方法,以便预先确定在相应的事件或场景发生时应该执行哪些代码。调用魔术方法的确切时间和原因因方法而异。PHP 中最常见的例子之一是 __construct() ,其在实例化类的对象时调用,类似于 Python 的 __init__ 。 通常,像这样的构造函数魔术方法包含初始化实例属性的代码。然而,开发人员可以自定义魔术方法来执行他们想要的任何代码。

魔术方法被广泛使用,其本身并不代表漏洞。但当它们执行的代码对攻击者可控制的数据(例如,来自反序列化对象的数据)进行处理时,它们可能变得危险。攻击者可利用此漏洞在满足相应条件时自动调用反序列化数据上的方法。

在这种情况下,最重要的是,某些语言具有在反序列化过程中自动调用的魔术方法。例如,PHP 的 unserialize() 方法查找并调用对象的 __wakeup() 神奇的方法。

在 Java 反序列化中,这同样适用于 readObject() 方法,它本质上类似于“重新初始化”序列化对象的构造函数。这个 ObjectInputStream.readObject() 方法用于从初始字节流中读取数据。但是,可序列化类也可以声明自己的 readObject() 方法如下:

private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {...}; 

这使得类可以更紧密地控制自己字段的反序列化。最重要的是以这种方式声明的 readObject() 方法充当了在反序列化期间调用的魔术方法。

你应该密切关注包含这类魔术方法的任何类。它们允许你在对象完全反序列化之前,将数据从序列化对象传递到网站代码中。这是利用更高级漏洞的起点。

注入任意对象

正如我们所看到的,偶尔可以通过编辑网站提供的对象来利用不安全的反序列化。然而,注入任意对象可以带来更多的可能性。

在面向对象编程中,对象可用的方法由其类决定。因此,如果攻击者可以操纵作为序列化数据传入的对象类,则可以影响反序列化之后,甚至在反序列化期间执行的代码。

反序列化方法通常不检查反序列化的内容。这意味着你可以传入网站可用的任何可序列化类的对象,并且该对象将被反序列化。这允许了攻击者创建任意类的实例。该对象不是预期类的事实并不重要。意外的对象类型可能会导致应用程序逻辑中的异常,但是恶意对象已经实例化。

如果攻击者有权访问源代码,他们可以详细研究所有可用的类。为了构造一个简单的攻击,他们会寻找包含反序列化魔术方法的类,然后检查其中是否有任何类对可控数据执行危险操作。然后,攻击者将会传入这个类的序列化对象,以使用其魔术方法进行攻击。

包含这些反序列化魔术方法的类也可用于发起更复杂的攻击,这涉及一系列的方法调用,称为 “gadget chain” 调用链。

调用链

“gadget” 是应用程序中存在的一段代码,可以帮助攻击者实现特定目标。单个 gadget 不能直接对用户输入造成任何有害影响。然而,攻击者的目标可能只是调用一个将其输入传递到另一个 gadget 的方法。通过以这种方式将多个 gadget 链接在一起,攻击者可能会将他们的输入传递到一个危险的 “sink gadget”,从而造成最大的破坏。

重要的是要了解,与其他类型的攻击不同,gadget 链不是攻击者构建的链式方法的有效负载。所有的代码都已经存在于网站上。攻击者唯一控制的是传递到 gadget 链中的数据。这通常反序列化期间调用魔术方法来完成,有时称为“启动gadget”。

许多不安全的反序列化漏洞只能通过使用gadget链来利用。这有时可能是一个简单的一步或两步链,但构建高危害性攻击可能需要更精细的对象实例化和方法调用序列。因此,能够构造 gadget 链是成功利用不安全反序列化的关键因素之一。

使用预先构建的 gadget 链

手动识别 gadget 链可能是一个相当艰巨的过程,如果没有源代码访问,几乎不可能。幸运的是,有一些方法可以用来处理预先构建的 gadget 链,你可以先尝试一下。

有几种可用的工具可以帮助你以最小的工作量构建 gadget 链。这些工具提供了一系列预先发现的 gadget 链,这些 gadget 链在其他网站上被利用过。在目标站点上发现了不安全的反序列化漏洞后,即使你无权访问源代码,也可以使用这些工具尝试并利用它。由于包含可利用 gadget 链的库的广泛使用,这种方法成为可能。例如,如果一个依赖 Java 的 ApacheCommons Collections 库的 gadget 链可以在某个网站上被利用,那么使用该库的任何其他网站也可以使用同一个链进行攻击。

其中一个用于 Java 反序列化的工具是 “ysoserial” 。你只需指定一个你认为目标应用程序正在使用的库,然后提供一个要尝试并执行的命令,该工具就会根据已知的给定库的 gadget 链创建适当的序列化对象。这仍然需要一定量的尝试,但它比手工构建自己的 gadget 链要轻松得多。

大多数经常遭受不安全反序列化攻击的语言都有匹配的 proof-of-concept 工具。例如,对于基于 PHP 的站点,可以使用 “PHP Generic Gadget Chains”(PHPGGC)。

需要注意的是,网站代码或其任何库中存在的 gadget 链并不是导致该漏洞的原因。该漏洞是用户可控制数据的反序列化,gadget 链只是在数据被注入后操纵数据流的一种手段。这也适用于依赖于非可信数据反序列化的各种内存破坏漏洞。因此,即使他们设法管理每一个可能插入的 gadget 链,网站可能仍然是脆弱的。

使用有记录的 gadget 链

你可以看看是否有任何记录在案的漏洞利用,可以拿来攻击你的目标网站。即使没有用于自动生成序列化对象的专用工具,你仍然可以为流行框架找到有记录的 gadget 链并手动调整它们。

如果你找不到一个可以使用的 gadget 链,你仍然可以获得有价值的知识,你可以利用这些知识创建自己的自定义漏洞利用程序。

创建自己的漏洞利用

当现成的 gadget 链和有记录的漏洞攻击不成功时,你需要创建自己的漏洞利用。

为了成功地构建自己的 gadget 链,你几乎肯定需要访问源代码。第一步是研究此源代码,以识别包含反序列化期间调用的魔术方法的类。评估这个魔术方法执行的代码,看看它是否直接使用用户可控制的属性做任何危险的事情。

如果魔术方法本身不可利用,它可以作为你的 gadget 链的启动点。研究启动 gadget 调用的任何方法。这些操作是否会对你控制的数据造成危险?如果不是,请仔细查看它们随后调用的每个方法,依此类推。

重复此过程,跟踪你可以访问的值,直到你到达死胡同或识别出一个危险的 sink gadget ,你的可控数据被传递到其中。

一旦解决了如何在应用程序代码中成功地构造 gadget 链,下一步就是创建一个包含有效负载的序列化对象。这只需研究源代码中的类声明并创建一个有效的序列化对象,该对象具有利用漏洞所需的适当值。正如我们在以前的实验室中看到的,使用基于字符串的序列化格式时,这一点相对简单。

使用二进制格式,例如在构建 Java 反序列化漏洞时,可能会特别麻烦。在对现有对象进行小的更改时,直接使用字节可能会很舒服。但是,当进行更重要的更改时,例如传入一个全新的对象,这很快就变得不切实际了。为了自己生成和序列化数据,用目标语言编写自己的代码通常要简单得多。

在创建自己的 gadget 链时,要注意利用这个额外的攻击面触发次要漏洞的机会。

通过仔细研究源代码,你可以发现更长的 gadget 链,这些 gadget 链可能允许你构建高危险性攻击,通常包括远程代码执行.

PHAR 反序列化

到目前为止,我们主要研究了如何利用反序列化漏洞,即网站显式地反序列化用户输入。然而,在 PHP 中,有时即使没有明显使用 unserialize() 方法,也有可能可以利用反序列化漏洞。

当你访问不同的文件时,PHP 提供了不同的处理方式。其中之一是 phar:// ,它提供了一个流式接口来访问 PHP Archive (.phar) 文件。

PHP 文档揭示了 PHAR 清单文件包含序列化的元数据。至关重要的是,如果你对 phar:// 流执行文件系统操作,其元数据会被隐式的反序列化。这意味着 phar:// 流可能是利用不安全的反序列化的潜在点,前提是可以将此流传递到文件系统方法中。

对于明显危险的文件系统方法,例如 include()fopen(),网站很可能已经实施了反制措施,以减少它们被恶意使用的可能性。然而,诸如 file_exists() 这类看起来没有明显危险的方法可能没有得到很好的保护。

此技术要求你通过某种方式将 PHAR 上传到服务器。例如,一种方法是使用图像上传功能。如果你能够将 PHAR 伪装成一个简单的 JPG 文件,你有时可以绕过网站的验证检查。如果你能强迫网站加载这个伪装成 JPG 的 PHAR 流,则任何通过 PHAR 元数据注入的有害数据都将被反序列化。由于 PHP 读取流时不检查文件扩展名,因此文件是否使用图像扩展名并不重要。

只要对象的类是由网站支持的,则 __wakeup()__destruct() 魔术方法可以用这种方式调用,从而允许你使用这种技术启动一个 gadget 链。

通过内存破坏利用反序列化

即使不使用 gadget 链,也有可能利用不安全的反序列化。如果所有其他方法都失败,通常会有公开记录的内存损坏漏洞,可以通过不安全的反序列化来利用这些漏洞。这些通常会导致远程代码执行。

反序列化方法,例如 PHP 的 unserialize() 很少对这类攻击进行强化,暴露出大量的攻击面。其本身并不总会被认为是一个漏洞,因为这些方法一开始并不打算处理用户可控制的输入。

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

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

相关文章

14正交向量与子空间

正交向量与子空间 本章研究的重点还是之前提到过的子空间,但是本章我们主要从正交的角度来探讨这些子空间具有的性质,主要内容见下图。 注意,上图指出了我们之前没有关注到的子空间的一些性质:对于一个矩阵,其零空间…

微信推送消息给女友提醒每天天气情况,本文讲解流程,附带代码,可快速上手。

实现的效果图 此模板为自己添加的,各位看客可以自行添加,如何添加接着往下看。备注在数据库自定义设置。如果你非专业人士,可以联系作者给你专属设置。如果需要代为设置跳转到文章结束位置。 完整的代码 代码下载地址 微信公众号设置 申…

《Linux Shell脚本攻略》学习笔记-第八章

8.1 简介 TCP/IP网络的运作过程就是在节点之间传递分组。每一个分组中都包含了目标的IP地址以及处理分组中数据的应用程序端口号。 当节点接收到分组时,它会查看自己是否就是改分组的目的地。如果是,节点会再检查端口号并调用相应的应用程序来处理分组数…

Cookie 会话身份验证是如何工作的?

在 Web 应用程序中,Cookie-Session 是一种标准的身份验证方法。饼干,也被称为“sweet cookies”。类型为“小文本文件”,是指一些网站为了识别用户身份而存储在客户端的数据。Session的主要功能是通过服务器记录用户的状态。 在典型的在线购物…

类与类之间关系的表示方式

1.关联关系 关联关系是对象之间的一种引用关系,用于表示一类对象与另一类对象之间的联系,如老师和学生,师傅和徒弟,丈夫和妻子等。关联关系是类与类之间最常用的一种关系,分为一般关联关系,聚合关系和组合…

郭天祥十天入门单片机学习笔记

电子元件 排阻 有两种: nn1 二极管 几个概念 限流电阻:与二极管串联,防止电流过大烧毁二极管导通压降:二极管亮起的最小电压 贴片式绿色为阴极,插入式短脚为阴极 数码管 共阴极:对应段选信号置1亮…

测试开发 | 这些常用测试平台,你们公司在用的是哪些呢?

测试管理平台是贯穿测试整个生命周期的工具集合,它主要解决的是测试过程中团队协作的问题。在整个测试过程中,需要对测试用例、Bug、代码、持续集成等等进行管理。下面分别从这四个方面介绍现在比较流行的管理平台。 图片108091 50.2 KB 测试用例管理平台…

Doris 使用记录(随机更新(ง •_•)ง)

文章目录知识点常见数据分布方式使用表动态分区Hash分桶知识点 常见数据分布方式 分布式数据库中常见的数据分布方式。 轮询:Round-Robin,假设分桶数为3,数据按顺序依次写入桶1、桶2、桶3,然后继续循环。 区间:Ran…

【Lp-CVT and Applications】

Lp-CVT and Applications 论文笔记 本文是论文 Lp Centroidal Voronoi Tessellation and its Applications 的学习笔记。有不足之处,请指出!非常感谢! 1 主要工作 解决问题:推广CVT以适用各向异性和六面体网格划分。推广 CVT &am…

如何模拟实现一个“缓存”?

目录 前言 一、LRU Cache是什么 二、模拟实现 2.1、通过继承 LinkedHashMap 模拟实现 2.2、自主模拟实现LRU Cache 2.2.1、LRU Cache的定义 2.2.2、存放结点 2.2.3、访问结点 2.2.4、LRU Cache 完整模拟代码 小结 前言 这次主要实现一个类似缓存的一种数据结构&#xf…

day49 业务逻辑水平垂直越权访问控制脆弱验证

前言: #知识点: 1、水平越权-同级用户权限共享 2、垂直越权-低高用户权限共享 3、访问控制-验证丢失&取消验证 4、脆弱验证-Cookie&Token&Jwt等 #前置知识: 1、逻辑越权原理- -水平越权:用户信息获取时未对用户…

NTP(Network Time Protocol)协议详解

一、NTP的基本概念: NTP(Network Time Protocol)------网络时间协议-----应用层协议,用来在分布式时间服务器和客户端之间进行时间同步。 二、采用NTP的目的: 是对网络内所有具有时钟的设备进行时钟同步,使网络内所有设备的时钟…

JDY-06蓝牙透传无天线模块介绍

JDY-06蓝牙透传无天线模块简介JDY-06透传模块是基于蓝牙4.0协议标准,工作频段为2.4GHZ范围,调制方式为GFSK,最大发射功率为0db,最大发射距离60米,采用TICC2541芯片设计,支持用户通过AT命令修改设备名、服务…

Alkyne maleimide,Mal-Alkyne,炔烃-马来酰亚胺

中英文别名:CAS号:N/A | 英文名:Alkyne maleimide,Mal-Alkyne |中文名:炔烃-马来酰亚胺物理参数:CASNumber:N/AMolecular formula:C12H14N2O3Molecular weight:234.26Pur…

什么是前后端分离?

当前,数字化发展速度越来越快,前后端分离已经成为今后的发展趋势。在现代化办公管理中,不少企业倾向于使用低代码开发平台实现高效协作办公,那么,什么是前后端分离?都有哪些特点?本文就围绕这个…

【网络安全】渗透测试之linux信息收集

前言 在内网中linux的服务器是占大多数的,主要原因分为以下几点 1.便宜,linux大多为免费的,Windows Server是收费的,对于企业来说为了节约成本,大量采用linux服务器。 2.轻便,linux主要是对服务器进行服务的…

递归算法实例应用(三)

递归算法实例应用(三) 四则运算表达式求值 Description 给你一个字符串表达式 str ,请你实现一个基本计算器来计算并返回它的值。 注意:不允许使用任何将字符串作为数学表达式计算的内置函数 。 Input 一行,一个四则运算表达…

编写设备驱动之i2c_client

编写设备驱动之i2c_client 文章目录编写设备驱动之i2c_client参考资料:一、I2C总线-设备-驱动模型二、 编译i2c_driver三、编写测试程序四、多种方法生成i2c_client并测试4.1 在用户态生成4.2 编写代码4.3 使用设备树生成2. IMX6ULL4.4 上机测试致谢参考资料&#x…

prometheus的remotewrite解析

特性 目的是为了向远端的存储写入数据。 为了提高写入效率,Prometheus在将采集到的samples写入远程存储之前,会先缓存在内存队列中,然后打包发送给远端存储。而这个内存队列的配置参数,对于Prometheus写入远程存储的效率影响较大…

《MySQL高级篇》十一、事务基础知识

文章目录1. 数据库事务概述1.1 存储引擎支持情况1.2 基本概念1.3 事务的ACID特性1.4 事务的状态2. 如何使用事务2.1 显式事务2.2 隐式事务2.3 隐式提交数据的情况2.4 使用举例1:提交与回滚2.5 使用举例2:测试不支持事务的Engine2.6 使用举例3&#xff1a…