Skip to content
Home » [Update] เข้าใจ Web Security: จัดเก็บ JWT ไว้ใน local storage หรือ cookies ดี? | cookie คือ – NATAVIGUIDES

[Update] เข้าใจ Web Security: จัดเก็บ JWT ไว้ใน local storage หรือ cookies ดี? | cookie คือ – NATAVIGUIDES

cookie คือ: คุณกำลังดูกระทู้

เป็นธรรมดาของระบบทั่วไปที่ต้องมีการตรวจสอบผู้ใช้งานระบบว่าผู้ใช้งานปัจจุบันคือใคร (Authentication) เมื่อทราบแล้วว่าใครคือผู้เข้าใช้ระบบ จึงทำการตรวจสอบสิทธิ์ว่าเขาผู้นั้นสามารถทำอะไรกับทรัพยากรในระบบได้บ้าง (Authorization)

สำหรับการสร้าง API เรามักนิยมใช้ Stateless Token เช่น JWT ในการทำ Authentication (Token-based authentication) โดย token ประเภทนี้จะไม่มีการจัดเก็บในฝั่งเซิฟเวอร์ แต่ยังจำเป็นต้องจัดเก็บทางฝั่งไคลเอ็นต์ เพื่อใช้ส่งไปกับรีเควสให้ทางเซิฟเวอร์ทราบว่าเราเป็นใคร

เมื่อ access token นั้นยังต้องจับเก็บทางฝั่งไคลเอ็นต์ (browser) คำถามจึงเกิดขึ้นว่าเราควรจัดเก็บไว้ใน local storage / session storage หรือ cookies ดีกว่ากัน?

Table of Contents

จัดเก็บ token ด้วย local storage

แรกเริ่มเราต้องลอคอินเข้าสู่ระบบก่อนเพื่อยืนยันว่าเราคือใคร ภายหลังการลอคอินระบบจะส่ง access-token กลับมาให้ เพื่อให้ฝั่งไคลเอ็นต์ใช้จัดเก็บและส่งกลับมาหาเซิฟเวอร์อีกครั้ง เมื่อต้องการทำอะไรซักอย่างกับระบบในนามของผู้ใช้คนนั้น

Code

1

HTTP/1.1 200 OK

2

Content-Type: application/json

3

{

4

"accessToken": "eyJz11a...k23aZWy",

5

"tokenType": "Bearer",

6

"expiresIn": 86400

7

}

หลังจากเราได้รับ response กลับมาแล้ว เราจึงทำการจัดเก็บ access token ไว้ภายใต้ HTML5 Web Storage เช่น localStorage เป็นต้น เมื่อเราทำการร้องขอต่อ API ในครั้งถัดไป หากเราต้องการระบุว่าเราคือใครเราต้องใช้ JavaScript เพื่ออ่าน access token ที่จัดเก็บใน HTML5 Web Storage แล้วทำการส่งไปพร้อมกับรีเควสนั้นๆ

Code

1

HTTP/1.1

2

3

POST /blog/new

4

Host: galaxies.com

5

Authorization: Bearer eyJz11a...k23aZWy

ตัวอย่างข้างต้น เรานำส่ง access token ไปพร้อมกับรีเควสผ่านทาง Authorization Header นั่นเอง

เผชิญหน้ากับ Cross-Site Scripting Attacks

เราสามารถเข้าถึง access token ภายใต้ localStorage ได้ด้วยคำสั่งจาก JavaScript หากแฮกเกอร์สามารถออกคำสั่ง JavaScript บนเว็บเราได้ละ จะเกิดอะไรขึ้น?

สมมติเว็บของเราอนุญาตให้ผู้ใช้โพสต์ข้อความอะไรก็ได้ในช่องสนทนา ผู้ใช้หัวหมอรายหนึ่งจึงใส่โค้ด HTML พร้อมแปะสคริปต์ JavaScript เก๋ๆ ดังนี้

HTML

1

<img src="https://file.not.exist"

2

onerror=alert(localStorage.getItem('access-token'));>

เพราะเราอนุญาตให้ผู้ใช้ใส่อะไรก็ได้ โค้ดดังกล่าวจึงได้รับการประมวลผลในฐานะที่เป็นอีลีเมนต์หนึ่งของ HTML เนื่องจากไฟล์รูปภาพไม่มีอยู่จริง onerror จึงได้รับการทำงาน เป็นผลให้เผย access token ที่จัดเก็บไว้ใต้ localStorage ออกมาด้วย

แน่นอนว่าถ้าคุณเป็นแฮกเกอร์ คุณย่อมไม่เพียงแค่แสดง access token ออกมา แต่คุณคงปรารถนาที่จะทำอะไรพิศดารกว่านั้น เช่นการสำเนา access token ไว้แอบอ้างว่าเป็นผู้ใช้ในครั้งถัดไป

เทคนิคในการแอบฝังโค้ดแปลกปลอมเข้าไป แล้วรอให้เหยื่อมาเปิดหน้าเพจที่มีโค้ดอัปรีย์เช่นนี้ เราเรียกว่าการโจมตีแบบ Cross-Site Scripting (XSS)

การที่ localStorage เข้าถึงได้จาก JavaScript โดยตรงเช่นนี้ จึงมีโอกาสเสี่ยงต่อการโจมตีแบบ XSS นั่นเอง ด้วยเหตุนี้ OWASP องค์กรไม่แสวงหากำไรด้านความปลอดภัย จึงได้ให้คำแนะนำว่าเราไม่ควรจัดเก็บข้อมูลที่เป็นความลับภายใต้ Web Storage

แล้วถ้าเราเปลี่ยนไปจัดเก็บ access token ผ่าน cookies แทนละจะช่วยแก้ปัญหานี้ได้หรือไม่?

รู้จัก HttpOnly Cookies

การจัดเก็บ access token บน cookie ด้วยวิธีธรรมดาก็ไม่ต่างอะไรกับการใช้ localStorage เพราะเรายังคงเข้าถึงได้ผ่าน JavaScript อยู่ดี จึงยังคงเสี่ยงต่อการโจมตีด้วย XSS

cookies นั้นเป็นคนหลายบุคลิกครับ นอกจากจะมีตัวตนแบบธรรมดาเรียบง่ายแล้ว ยังมี secure cookie ที่ใช้ควบคู่กับ HTTPS แต่นางเอกของงานนี้ที่เราจะพูดถึงคือ HttpOnly cookies

หากการเข้าถึง access token ได้จาก JavaScript เป็นปัญหา ก็ตัดปัญหาไม่ให้ JavaScript เข้าถึง access token ภายใต้ cookies ได้ซะซิ เท่านี้ปัญหาก็จบ และจากประโยคบอกเล่าข้างต้นนี้ HttpOnly cookies จึงเข้ามามีบทบาทสำคัญ
a
HttpOnly cookies เป็นคุกกี้ประเภทที่ป้องกันไม่ให้ JavaScript สามารถเข้าถึงข้อมูลมันได้ผ่าน document.cookie เราจึงมั่นใจได้ว่าข้อมูลจากคุกกี้ประเภทนี้ จะปลอดภัยจากการใช้ XSS เพื่อขโมย access token

เมื่อเราเปลี่ยนการจัดเก็บ access token จาก localStorage มาเป็น HttpOnly cookies สิ่งที่เราต้องทำก็คือการสื่อสารระหว่างเซิฟเวอร์และไคลเอ็นต์ที่เปลี่ยนมาใช้ cookie ประเภทนี้แทน

เมื่ออ่านมาถึงตรงนี้ เพื่อนๆบางคนอาจเบะปากมองบนว่าทำไมถึงใช้เทคโนโลยีได้โลกที่สามมาก สมัยนี้ใครยังใช้ cookies กันอยู่นอกจากพวกหลังเขาหิมาลัย

หากเรามองให้ดี ไม่ว่าจะเป็นการส่ง access token ผ่าน Authorization Header แบบที่นำเสนอข้างต้น หรือการส่ง access token ผ่าน cookies ทั้งสองล้วนส่งข้อมูลผ่าน Header อยู่ดี นั่นเพราะ cookies ถูกจัดส่งผ่าน Header ที่ชื่อว่า Set-Token นั่นเอง

Code

1

Set-Cookie: access-token=eyJz11a...k23aZWy; Secure; HttpOnly

การจัดส่ง access token ผ่านคุกกี้จึงไม่ได้ลำบากต่อการแงะข้อมูลกลับคืนมาแต่อย่างใด

Cookies และ Cross-Site Request Forgery

ถ้าสมมติเพื่อนๆเป็นแฮกเกอร์ เมื่อเราไม่สามารถขโมย access token ได้แล้ว เราจะโจรกรรมด้วยวิธีไหนต่อไปดี?

เราขโมย access token เพื่อแอบเอาค่านี้ไปใช้บอกระบบว่าเราคือเหยื่อ แต่เมื่อเราแอบขโมย token ไม่ได้ เราก็ให้เหยื่อเป็นคนสร้างธุรกรรมที่เราต้องการด้วยตัวเขาเองซะเลย เช่น เราต้องการให้เหยื่อโอนเงินให้เรา ในเมื่อเราขโมย token เพื่อใช้ทำการโอนในนามของเหยื่อไม่ได้ เราก็แอบล่อให้เหยื่อโอนเงินให้เราโดยไม่ให้เหยื่อรู้ตัว

สมมติเว็บของธนาคารที่เราใช้อยู่ประจำคือ mybank.com แฮกเกอร์อาจสร้างไซต์ใหม่ชื่อ mybamk.com แล้วล่อลวงให้เราเข้าใช้บริการไซต์นี้

ตอนนี้คุณถูกล่อลวงเรียบร้อยแล้ว คุณต้องการโอนเงินคุณจึงไปหน้าเพจสำหรับการโอนเงินคือ /transfer ตามปกติ แต่ที่ไม่ปกติคือคุณถูกล่อลวงมาที่เพจที่ลอกเลียนแบบของจริงอยู่

โดยทั่วไปการโอนเงินของไซต์ที่แท้ทรู จะใช้ฟอร์มแบบ POST พร้อมส่ง accountID ปลายทางและจำนวนเงินไปยังเซิฟเวอร์ แฮกเกอร์แสนฉลาดตอนนี้ก็ได้เลียนแบบฟอร์มดังกล่าวมาไว้ในหน้าเว็บตน

HTML

1

<

form

action

=

"

https://mybank.com/transfer

"

method

=

"

POST

"

>

2

<

input

type

=

"

text

"

name

=

"

accountID

"

value

=

"

HACKER ID

"

/>

3

<

input

type

=

"

text

"

name

=

"

amount

"

value

=

"

AMOUNT

"

/>

4

</

form

>

จะสังเกตเห็นว่าแบบฟอร์มนี้จะยิงกลับไปที่เว็บต้นฉบับพร้อมกับส่ง accountID เป็นไอดีของแฮกเกอร์แทน

การที่เราจะโอนเงินให้ใครซักคนหนึ่ง จำเป็นที่ระบบต้องทราบว่าต้นทางการโอนคือใคร access token จึงเป็นสิ่งสำคัญที่ไคลเอ็นต์ต้องส่งให้กับเซิฟเวอร์เพื่อบอกว่าเราคือใครและมีสิทธิ์ในการโอนหรือไม่

เมื่อแบบฟอร์มนี้อ้างอิงว่าเป็นการส่งรีเควสไปหา mybank.com คุกกี้ที่จัดเก็บไว้ใช้กับ mybank.com จึงถูกส่งไปด้วย เพียงแค่ผู้ใช้ระบบถูกล่อลวงให้ทำธุรกรรมผ่านไซต์ปลอม access token ของเขาก็จะถูกนำไปใช้ในนามของตัวเขาเอง โดยที่แฮกเกอร์ไม่ต้องเปลืองแรงในการขโมยเลย

การโจมตีที่บังคับ (เรียกว่าขืนใจดีกว่า) ให้ผู้ใช้งานที่ลอคอินเข้าสู่ระบบแล้ว ทำอะไรซักอย่างที่เขาไม่ได้ต้องการทำ โดยหมายให้ระบบเข้าใจว่าเป็นการกระทำของผู้นั้นเอง เมื่อเหยื่อเข้าสู่เว็บไซต์จึงล่อลวงให้เกิดการทำธุรกรรมไปยังไซต์เป้าหมาย การโจมตีเช่นนี้เราเรียกว่า Cross-Site Request Forgery (CSRF)

ป้องกันการโจมตีแบบ CSRF ด้วย Origin และ X-Requested-With

การป้องกันการโจมตีแบบ CSRF นั้นสามารถทำได้หลายกระบวนท่า ในหัวข้อนี้ผมจะนำเสนอวิธีหนึ่งแบบคร่าวๆ โดยไม่อธิบายอะไรเป็นพิเศษ เพราะเราจะไปเน้นการแก้ปัญหา CSRF ด้วยอีกสองวิธีในหัวข้อถัดไปแทน

ประการแรกคือการเช็ค Header ที่ชื่อว่า Origin เมื่อรีเควสของการทำธุรกรรมมาถึงเซิฟเวอร์ เพื่อเป็นการยืนยันว่ามาจากแหล่งที่เราอนุญาตหรือไม่ แต่วิธีนี้ก็อาจจะดูตะมุตะมินิดนึงตรงที่เซิฟเวอร์ต้องทราบว่าใครคือไคลเอ็นต์ และไคลเอ็นต์ตั้งอยู่บน URL อะไร

หาก API ของเราอนุญาตให้เข้าถึงได้ผ่าน AJAX เท่านั้น เราสามารถทำการการเพิ่ม header พิเศษ เช่น X-Requested-With: XMLHttpRequest ส่งไปพร้อมกับรีเควส เมื่อเซิฟเวอร์ได้รับก็จะทำการตรวจสอบ header ดังกล่าวว่ามีหรือไม่และมีค่าตามที่กำหนดไหม วิธีการนี้จะช่วยป้องกันไม่ให้ส่งรีเควสจากฟอร์มได้ นั่นเพราะการส่งข้อมูลผ่านฟอร์มจะส่ง header ตามแต่ใจเรากำหนดไม่ได้

วิธีการใช้ Origin ก็ฟังดูแปลก เพราะ API Server ต้องคอยกังวลและรับรู้ว่าไคลเอ็นต์คือใคร ส่วนวิธี X-Requested-With ก็จะยิ่งแปลกเมื่อเราออกแบบ API เราไม่ควรจำกัดให้ใช้งานได้กับ AJAX เท่านั้น

รู้จักการป้องกัน CSRF ด้วย Double Submit Cookie

เซิฟเวอร์นั้นอาจแยกแยะไม่ได้ว่ารีเควสนั้นมาจากความตั้งใจของผู้ใช้งานระบบเองหรือเป็นการแฝงมาจากผู้ไม่ประสงค์ดี ในกรณีของการหลอกล่อด้วยการสร้างฟอร์มบนไซต์อื่น แฮกเกอร์จะไม่สามารถเข้าถึงคุกกี้จากเซิฟเวอร์ใต้ไซต์ต้นฉบับได้เนื่องจากติด same-origin policy

ไซต์ต้นฉบับคือ mybank.com จะส่งคุกกี้เช่นไรจากเซิฟเวอร์ แต่ไซต์ต้มตุ๋นที่ชื่อ mybamk.com แม้กระสันอยากได้ข้อมูลใต้คุกกี้ดังกล่าวก็มิอาจทำได้ นั่นเพราะทั้งสองไซต์อยู่ข้าม origin กัน (คนละ protocol, port หรือ host)

อาศัยความจริงข้อนี้เราจึงแอบส่งค่าบางอย่างที่ได้จากการสุ่มมั่วมากับคุกกี้ พร้อมทั้งทำการฝังค่าตัวนี้ไว้กับฟอร์ม เช่น

HTML

1

<

form

action

=

"

https://mybank.com/transfer

"

method

=

"

POST

"

>

2

<

input

type

=

"

hidden

"

name

=

"

csrfToken

"

value

=

"

CjihIlUp...YQmNcgNb3SSMDn

"

/>

3

<

input

type

=

"

text

"

name

=

"

accountID

"

value

=

"

ID

"

/>

4

<

input

type

=

"

text

"

name

=

"

amount

"

value

=

"

AMOUNT

"

/>

5

</

form

>

จากตัวอย่างข้างต้น เราสุ่มค่ามั่วขึ้นมาคือ CjihIlUp...YQmNcgNb3SSMDn พร้อมส่งค่านี้มากับคุกกี้และส่งค่าเดียวกันนี้มากับฟอร์ม เมื่อใดก็ตามที่รีเควสถูกส่งไป เซิฟเวอร์จะต้องทำการเทียบค่า ว่าค่าของ csrfToken ในคุกกี้เป็นค่าเดียวกันกับในฟอร์มหรือไม่

เพราะว่าแฮกเกอร์ไม่มีทางเข้าถึงคุกกี้ต่างไซต์ได้ จึงมิอาจจำลอง csrfToken ในฟอร์มให้ตรงกับของในคุกกี้ได้นั่นเอง (เว้นแต่จะเดามั่วจนถูกหละนะ – เดาเก่งขนาดนั้นเอาเวลาไปซื้อหวยดีกว่าไหม) วิธีนี้จึงการันตีได้ว่าฟอร์มที่จะได้รับการประมวลผลจะเป็นฟอร์มที่สร้างจากเว็บของเราเองเท่านั้น

ด้วยการใช้ HttpOnly และการทำ Double Submit Cookie จึงปกป้องการโจมตีทั้งแบบ XSS (เฉพาะรูปแบบที่หมายจะขโมย access token) และ CSRF ได้นั่นเอง

ป้องกัน CSRF ด้วย Same-Site Cookies

ปัญหาของการโจมตีแบบ CSRF โดยหลักแล้วมักเป็นการส่งรีเควสมาจากไซต์อื่นที่ไม่ใช่ต้นฉบับ ถ้าเราอยากป้องกันการโจมตีนี้เราก็แค่ป้องกันไม่ให้ส่งคุกกี้มายังเซิฟเวอร์ของเราหากรีเควสนั้นมาจากไซต์อื่น

Same-site cookies เป็นคุกกี้ที่สามารถป้องกันการโจมตีแบบ CSRF ได้ เนื่องจากคุกกี้ประเภทนี้จะไม่ถูกส่งหากมาจากต่างไซต์กัน

Same-site cookies มีสองแบบครับ คือ Strict และ Lax

Strict ตามชื่อเลย เข้มงวดสุดๆ คุกกี้ที่ตั้งค่านี้จะไม่ถูกส่งมายังไซต์ของเรา หากรีเควสนั้นมาจากไซต์อื่น ตรงจุดนี้อาจมีผลต่อความรู้สึกของผู้ใช้ได้ เช่น หากเราเป็น Facebook และตั้งค่าคุกกี้เพื่อจัดเก็บ access token ไว้ด้วย Strict สิ่งที่เกิดขึ้นก็คือ เมื่อมีใครเอาลิงค์เฟสบุคไปแชร์ในไซต์ของเรา เราจะจิ้มเพื่อเข้าไปดูได้แต่เราจะเห็นว่าตัวเราเองยังไม่ได้ลอคอินในเฟสบุค (ทั้งๆ ที่ลอคอินแล้ว) นั่นเพราะรีเควสที่ยิงไปหาเฟสบุคมาจากไซต์อื่น Same-site cookies แบบ Strict จึงไม่ถูกส่งไปด้วย เฟสบุคจึงไม่ทราบว่าเราคือใคร

โดยหลักแล้วเราออกแบบให้เข้าถึงทรัพยากรในเซิฟเวอร์ของเราผ่าน HTTP GET เมื่อการร้องขอนั้นไม่ส่งผลกระทบต่อทรัพยากรในเซิฟเวอร์ หากการร้องขอทำให้เกิดการเปลี่ยนแปลง เช่น สร้างทรัพยากรใหม่ในระบบ (สร้างบทความใหม่ สร้างผู้ใช้งานคนใหม่) เราจะเปลี่ยนไปใช้ HTTP VERBS อื่นแทน เช่น POST

อาศัยความจริงข้างต้น เราจึงกล่าวได้ว่าการเข้าถึงแบบ GET ค่อนข้างปลอดภัยกว่า ด้วยความที่เราก็อยากให้ผู้อื่นแชร์ลิงก์ไซต์เราไปไว้ในเพจเขาได้ด้วย การใช้ Strict จึงไม่ตอบโจทย์มากนั้น ทางเลือกของเราจึงเป็น Same-site cookies แบบ Lax

Lax อนุญาตให้ส่งคุกกี้นี้ได้เมื่อทำการร้องขอจากไซต์อื่น เพียงแต่การร้องขอนี้ต้องเกิดขึ้นบน HTTP GET เช่น จิ้มลิงก์ เท่านั้น โดยเงื่อนไขสำคัญของการทำงานคือการกระทำนี้ต้องทำให้เกิดการเปลี่ยน URL บน address bar (top-level navigation) ความหมายคืออะไร? นั่นคือการร้องขอแบบ GET ผ่าน iframe หรือ AJAX จะทำไม่ได้นั่นเอง เพราะการใช้ AJAX หรือ iframe นั้น URL บน address bar จะไม่เปลี่ยน

Code

1

Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Lax;

2

Set-Cookie: <cookie-name>=<cookie-value>; SameSite=Strict;

ด้วยการผสานระหว่าง HttpOnly, Secure และ SameSite การโจมตีแบบ XSS และ CSRF ก็เหมือนแมลงสาบโดนฉีดไบกอน… แม้อาจไม่ตายซะทีเดียว แต่ก็คงดิ้นกระแด่วๆคาขวดเขียว

Code

1

Set-Cookie: <cookie-name>=<cookie-value>; Secure; HttpOnly; SameSite=Strict;

ช่างน่าเสียดายนักที่ Same-site cookies ยังไม่สามารถใช้งานได้ในทุกเบราเซอร์… บาย

เข้าใจวิถีแห่ง Cookies

HTTP นั้นเป็น stateless protocal อารมณ์ว่าสมองกลวงไม่เคยจำอะไรเลย แต่บางครั้งเราก็อยากให้การสื่อสารระหว่าง client และ server นั้นรู้เรื่อง ไม่ใช่ต้องมาลอคอินใหม่ทุกครั้งของการใช้งาน

Cookies เข้ามาแก้ปัญหานี้เพื่อให้บราวเซอร์จำค่าบางอย่างได้และใช้มันเพื่อส่งไปในทุกๆครั้งของการร้องขอข้อมูลกับเซิฟเวอร์

หลายครั้งที่เราต้องการใช้ข้อมูลจาก Cookies ในไซต์อื่น เช่น การฝังโฆษณาลงบนเว็บของเรา เมื่อผู้ใช้เว็บเราทำการคลิกโฆษณาต้องทำการส่งรีเควสไปผู้ให้บริการ ถ้าไม่ทำเช่นนี้เราก็อดได้ตังค่าโฆษณาใช่ไหมละ ฉะนั้นแล้วคุกกี้ซึ่งจัดเก็บ ID ของเรา (ต้นทางที่อนุญาตให้ลงโฆษณา) ต้องถูกส่งกลับไปที่เว็บโฆษณาด้วย ตรงจุดนี้จึงกล่าวได้ว่า Cookie ออกแบบมาเพื่อให้ไม่ปลอดภัยตั้งแต่แรก

Cookies นั้นเชื่อถือได้ยาก การตั้งค่าทั่วไปอาจทำให้ต่าง subdomain เข้าถึงคุกกี้ของกันและกันได้ นอกจากนี้คุกกี้บน https://example.com ยังสามารถเข้าถึงจาก http://example.com อีกด้วย จึงกล่าวได้ว่าคุกกี้ไม่ได้ตามหลักการ Same Origin Policy แบบที่ localStorage เป็น เมื่อเป็นเช่นนี้เราจึงต้องมี Domain, Path, Secure และ Http-Only flags เพื่อทำให้คุกกี้ปลอดภัยมากขึ้น

ฟังๆดูแล้วคุกกี้ดูมีแต่รูที่เราปะจนกลับมาปลอดภัย แล้วถ้าเราหันกลับมาใช้ Web Storage แบบ localStorage หละ มันจะดีขึ้นไหม?

HTML Sanitizer

localStorage นั้นป้องกัน CSRF ได้อย่างสมบูรณ์ นั่นเพราะค่าต่างๆที่เก็บอยู่ภายใต้ localStorage จะไม่ถูกส่งไปกับทุกรีเควสเช่นเดียวกับคุกกี้ นอกจากนี้ค่าของ localStorage ยังไม่สามารถเข้าถึงได้จากไซต์ต่าง origin (same-origin policy)

ทว่า localStorage อาศัยการอ่านและเขียนค่าด้วย JavaScript เมื่อแฮกเกอร์ได้สิทธิ์ของการใช้ JavaScript เขาจึงเขาถึงค่า access token ภายใต้ localStorage ได้

มีความเป็นไปได้ที่แฮกเกอร์จะแอบฝังโค้ดไว้ในเพจของเราผ่านช่องทางต่างๆ เช่น ช่องสนทนา

HTML

1

<img src="https://file.not.exist"

2

onerror=alert(localStorage.getItem('access-token'));>

เพื่อดับฝันของแฮกเกอร์ เราจึงควรแปลงโค้ดอัปรีย์ (sanitize) นี้เสียก่อนทำการบรรจุหีบห่อลงเว็บของเรา หลังการแปลงผลลัพธ์ที่ได้อ่านเป็นเช่นนี้

HTML

1

&lt;

img src=

&quot;

http://file.not.exist

&quot;

2

onerror=alert(localStorage.getItem(

&#039;

access-token

&#039;

));

&gt;

ช่างโชคดีจนน้ำตาไหล frontend libs สมัยใหม่ไม่ว่าจะเป็น Angular หรือ React ต่างก็ป้องกัน XSS ด้วยการ sanitize ให้กับเราอยู่แล้ว

ในความโชคดีก็ยังมีฝันร้าย การโจมตีแบบ XSS ไม่ได้มาในรูปแบบของการแปะโค้ดลงช่องสนทนาเท่านั้น หากแต่การโจมตีดังกล่าวอาจฝังอยู่ใน lib ที่เรานำมาใช้ร่วมด้วยก็ได้ โดยเฉพาะอย่างยิ่งกับการใช้ CDN

Content Security Policy

เพื่อป้องกันไม่ให้เราโดนโจมตีด้วย XSS สิ่งหนึ่งที่เราควรทำคือ การใช้เฉพาะไลบรารี่ที่เชื่อถือได้ รวมถึงใช้งานสคริปต์จากลิงก์หรือ CDN ที่ปลอดภัยเท่านั้น

สมมติหน้าเว็บเราต้องการมีปุ่ม Like ของเฟสบุค หากใครชอบใจหน้าเว็บนี้ย่อมสามารถกดปุ่ม Like ได้ ด้วยเหตุนี้เราจึงต้องใช้สคริปต์จากเฟสบุคคือ https://connect.facebook.net/en_US/sdk.js#xfbml=1 ในเพจเรา

เรามั่นใจว่าเพจเราใช้แต่สคริปต์ที่กำหนดเท่านั้น เราจึงไม่ต้องการให้แฮกเกอร์หาช่องโหว่แล้วนำสคริปต์จาก https://connect.evil.net มาวางเพื่อทำงาน นี่คือเป้าหมายที่เราต้องการ

Content-Security-Policy เป็น HTTP header ที่กำหนดมาจากเซิฟเวอร์เลยว่าสิ่งใดคือสิ่งที่เราเชื่อถือได้บ้าง (whitelist) ด้วยการใช้งาน CSP บราวเซอร์จะทำการประมวลผลเฉพาะสคริปต์ใน whitelist ที่เรากำหนดเท่านั้น สคริปต์ประหลาดที่แฮกเกอร์แฝงมากไม่ได้อยู่ใน whitelist ก็จะไม่ถูกประมวลผล ทำให้เราปลอดภัยจาก XSS ได้ระดับนึง

Code

1

Content-Security-Policy: script-src 'self' https://connect.facebook.net

หมายเหตุ: ไม่ใช่เฉพาะ script-src เท่านั้นที่สามารถกำหนดได้ ยังมีค่าอื่นๆอีกมาก เช่น connect-src font-src img-src เป็นต้น ที่เพื่อนๆสามารถลองตั้งค่าได้ครับ

เก็บ access token ใน cookies หรือ localStorage ดีกว่ากัน?

แม้ในปี 2017 OWASP จะจัดให้การโจมตีแบบ XSS (Server XSS + Client XSS) อยู่ลำดับสาม และการโจมตีแบบ CSRF อยู่ลำดับแปด แต่ถ้าเพื่อนๆเป็นแฮกเกอร์ จะใช้วิธีใดในการโจมตี?

หากเราเลือกโจมตีแบบ XSS (เพื่อเข้าถึง access token) เพื่อนๆอาจได้ access-token ไปก็จริง แต่โดยปกติแล้วเรามักตั้งให้ token ประเภทนี้มีอายุสั้นมาก ถึงเราได้มาก็ไม่แน่ว่าจะใช้งานได้ เพราะ token อาจหมดอายุไปเสียก่อน นอกจากนี้การโจมตีแบบ XSS ยังต้องรอเหยื่อมาตกหลุมพลางอีก

เมื่อเป็นเช่นนี้ เพื่อนๆจึงคิดว่างั้นโจมตีแบบ CSRF ดีกว่าเพราะได้ผลที่แน่นอนกว่า ด้วยการปลอมแปลงนิดหน่อยเหยื่อก็ทำธุรกรรมให้กับเราแล้ว

หากอาศัยจากสมมติฐานนี้ เราอาจมองว่า CSRF ควรได้รับการป้องกันระดับสูง ในขณะที่ XSS ก็ต้องได้รับการป้องกันเช่นกัน เราจึงใช้ localStorage ที่ป้องกัน CSRF ได้แน่นอน แล้วทำ CSP + Sanitize เพื่อป้องกัน XSS ระดับ 99.99% (เป็ดโปรยังฆ่าเชื้อได้ 99.99% เลย)

คุกกี้ก็เป็นอีกหนึ่งทางออกที่สามารถเลือกใช้ได้ เพียงแต่การจัดเก็บ access token บนคุกกี้ เพื่อนๆควรใช้คู่กับ Secure + HttpOnly พร้อมทำ Double Submit Cookie (ไม่แนะนำ Same-Site cookies เพราะยังไม่รองรับอย่างกว้างขวาง)

XSS ไม่จำกัดอยู่แค่การขโมย token

XSS นั้นไม่เพียงแต่เป็นรูปแบบการโจมตีเพื่อหมายขโมย access token เท่านั้น เพจสอนแฮกเว็บแบบแมวๆ – เพจดังด้านความปลอดภัย ได้ขยายความรูปแบบการโจมตีด้วย XSS ไว้ว่า

การโจมตีเว็บแบบ XSS เราไม่ได้ใช้โจมตีแต่การขโมย session token (ไม่ว่าจะอยู่ใน cookie/local storage) อย่างเดียว แฮกเกอร์สามารถใช้ทำอย่างอื่นได้ เช่นใช้ JavaScript ดักคีย์บอร์ด หรืออ่านค่าใน textfield เช่นเลขบัตรเครดิต หรือแก้ไขหน้าตาเว็บ แก้เลขบัญชีเว็บใน HTML หรือถ้าเป็น XSS ใส่เว็บที่ user สิทธิ์สูงรัน command ผ่านฟีเจอร์เว็บได้ก็อาจจะได้ RCE ฯลฯ

เมื่อพิจารณาจากรูปแบบการโจมตีที่เกิดขึ้นได้ XSS จึงดูร้ายแรงและเป็นอันตรายมากกว่า CSRF โดยแอดมิน เพจสอนแฮกเว็บแบบแมวๆ ได้ให้เหตุผลไว้ว่า

ถ้าเว็บใด ๆ มีช่องโหว่ XSS แล้วละก็ การป้องกัน CSRF เกือบทุกอย่างที่เขียนมา 99% ไร้ความหมายทันทีเพราะ

  • ถ้าทำ XSS สร้าง form แล้ว submit ค่าทำ CSRF (จริง ๆ ควรชื่อ Same-Site Request Forgery มากกว่าในเคสนี้)
    เราสามารถใช้ JavaScript อ่านค่า csrf token ใน textfield ได้ (bypass ในหัวข้อ double submit cookie)

  • ถ้าใช้ XSS ทำ CSRF ค่า Origin ที่ติดมาเป็นค่าเหมือนเว็บเดิม Same-Origin Policy ช่วยไม่ได้ (bypass ในหัวข้อ ป้องกันการโจมตีแบบ CSRF ด้วย Origin)

มุมมองของผู้เขียน

สำหรับผม – ผู้เขียน เลือกการใช้ localStorage เพราะเป็นวิธีที่นิยมใช้กันมากกว่า เราเชื่อมั่นในโค้ดที่เราเขียนและสคริปต์ที่เราใช้ เราใช้ frontend เฟรมเวิร์กที่ดีและอัพเดทสม่ำเสมอ อีกทั้งเรามั่นใจว่าปัญหาจากการใช้ localStorage จะยุ่งยากน้อยกว่าคุกกี้

ผู้เขียนเชื่อว่าไม่มีระบบใดจะสมบูรณ์ 100% จึงอย่าไว้ใจช่องโหว่ที่อาจเกิดขึ้นได้ สิ่งสำคัญของการใช้ access token คือช่วงอายุที่สั้น และเราต้องทำให้มั่นใจว่าธุรกรรมที่สำคัญควรได้รับการยืนยันเสมอ เช่น ให้กรอกพาสเวิร์ดอีกครั้ง นอกจากนี้อะไรที่เป็นพื้นฐานที่ดีก็อย่าละเลย เช่น sanitize ข้อมูลทุกครั้งก่อนจัดเก็บ เป็นต้น

เมื่อ Local Storage คือความยุ่งยากของการทำ Server-Side Rendering

localstorage นั้นจำเป็นต้องใช้ JavaScript ในการเข้าถึง หากเราต้องการทำ Server-Side Rendering (SSR) ด้วยการเลือกแสดงผลข้อมูลอิงกับผู้ใช้งานในขณะนั้นจึงเป็นไปไม่ได้ นั่นเพราะทุกครั้งของการทำ SSR เราไม่ได้ส่งข้อมูล access-token ที่เก็บอยู่ภายใต้ localstorage ไปด้วยนั่นเอง แต่สำหรับการจัดเก็บผ่าน cookie นั้นไม่เป็นปัญหา เพราะ cookie จะถูกจัดส่งไปพร้อมกับทุกการร้องขอ เป็นผลให้ access-token ได้รับการจัดส่งตามไปด้วย เมื่อมองในมุมของการทำ SSR cookie จึงมีภาษีที่เหนือกว่าเยอะ

ของแถม – ป้องกัน Clickjacking ด้วย X-Frame-Options

แม้เราจะป้องกันการโจมตีด้วย CSRF เป็นอย่างดี แต่การโจมตีที่เรียกว่า Clickjacking ก็อาจทำให้คุณหงายเงิบไปเลย

สมมติเราอยากล่อให้คนกดถูกใจเพจในเฟสบุคเราจะทำไงดี?

แน่นอนว่าถ้าเราสร้างเว็บแล้วแปะปุ่มให้เขากดไลค์ ถ้าเขาไม่อยากกด เขาก็คงไม่มากดหลอก จริงไหมครับ? แล้วถ้าเป็นแบบนี้หละ เราสร้างเว็บไซต์ขึ้นมา แล้วแสดงข้อความว่า “ฟรี iPhone X คลิกเลย” พร้อมทั้งแอบซ่อน iframe แบบโปร่งใส (มองไม่เห็น) ไว้ด้านหลัง iframe ดังกล่าวให้ทำการโหลดหน้าเพจเฟสบุคของเรา โดยกำหนดให้ตำแหน่งของคำว่า “ฟรี iPhone X คลิกเลย” ตรงกับปุ่ม Like Page

เมื่อเหยื่อเห็นคำว่าฟรี ต่อมกระสันก็จะทำงาน พร้อมพลาดเอามือไปกดปุ่มดังกล่าว ป๊ะเข้าให้ ปุ่ม Like Page ก็จะถูกกดตามไปด้วย เพราะมันซ่อนอยู่ข้างหลัง ฉลาดไหมละ?

และนี่หละครับคือการโจมตีแบบ Clickjacking ซึ่งเป็นวิธีการโจมตีที่ล่อให้เหยื่อคลิกอะไรซักอย่างแล้วไปทำอีกอย่างที่ซ่อนอยู่โดยที่เหยื่อไม่ตั้งใจ

แน่นอนว่าต่อให้คุณป้องกัน CSRF มาเป็นอย่างดี ก็ยังไม่รอดพ้นการโจมตีเช่นนี้ นั่นเพราะการคลิกเกิดขึ้นโดยตรงบนหน้าเพจของคุณที่ถูกฝังอยู่กับ iframe ที่ซ่อนอยู่

ถ้าคุณเป็นเฟสบุค คุณคิดว่าจะป้องกัน Clickjacking อย่างไรดี? ใช่แล้วครับ ถ้าไม่อยากให้เพจของเราซ่อนอยู่เบื้องหลังด้วย iframe ก็อย่าอนุญาตให้เพจเราแสดงเนื้อหาใน iframe ได้ซะซิ!

สิ่งที่เราควรทำจึงเป็นการตั้งค่า response ของเพจให้มี X-Frame-Options header เป็น DENY ด้วยวิธีนี้จะเป็นการป้องกันไม่ให้เพจของเราถูกฝังบน iframe ใดๆได้ แต่หากเราต้องการให้ฝังเพจได้เฉพาะกับ iframe ในไซต์เดียวกัน ก็ให้ตั้งค่า header ตัวนี้เป็น SAMEORIGIN แทน

เอกสารอ้างอิง

Abhinav Sejpal (2014). Why am I anxious about Clickjacking?. Retrieved December, 5, 2017, from https://www.linkedin.com/pulse/20141202104842-120953718-why-am-i-anxious-about-clickjacking

Mike West and Joseph Medley. Content Security Policy. Retrieved December, 5, 2017, from https://developers.google.com/web/fundamentals/security/csp/

James Kettle (2016). Web Storage: the lesser evil for session tokens. Retrieved December, 5, 2017, from http://blog.portswigger.net/2016/05/web-storage-lesser-evil-for-session.html

OWASP. Top 10 2017-A3-Cross-Site Scripting (XSS). Retrieved December, 5, 2017, from https://www.owasp.org/index.php/Top_10_2017-A3-Cross-Site_Scripting_(XSS)

[NEW] ทำความรู้จัก PDPA และการเตรียม Cookie และ Universal Consent | cookie คือ – NATAVIGUIDES

By

By

By

สรุป พ.ร.บ.คุ้มครองข้อมูลส่วนบุคคล พ.ศ. 2562

สาระสำคัญของ PDPA คืออะไร และมีส่วนคล้ายคลึงกับ EU Data Protection Directive หรือ GDPR เช่น
1. การแจ้งให้ทราบเรื่องการจัดเก็บข้อมูล
2. การขอความยินยอม (Consent) ทั้งผ่านแบบฟอร์มและVerbal
3. การระบุวัตถุประสงค์ในการเก็บรวบรวม (Purpose Specification)
4. การรักษาความปลอดภัยของข้อมูล ต้องมีมาตรการรักษาความปลอดภัยของข้อมูลที่ถูกเก็บรักษา Integrity and confidentiality (security)
5. การกำหนดผู้ควบคุมข้อมูล (Data Controller) และผู้ประมวลผลข้อมูลส่วนบุคคล (Data Processor)
6. สิทธิของเจ้าของข้อมูล โดยเจ้าของมีสิทธิในการขอเคลื่อนย้ายข้อมูลส่วนบุคคลของตน
7. ความรับผิดชอบของบุคคลซึ่งทำหน้าที่ควบคุมข้อมูล (Accountability)

สิ่งที่จะต้องเตรียมก็คือ

  • List data touchpoints ทั้งหมดออกมาดู
  • ออกแบบแบบระบบ consent ต่างๆทั้ง offline/online
  • ตั้งกรรมการหรือคนที่ทำหน้าที่โดยตรง DPO (Data Protection Officer)
  • ทำ Master Database เพื่อ Single Source of Customer Data
  • ทำ Preference Center, Unsubscribe center เพื่อสิทธิที่จะถูกลบข้อมูลออก
  • ทำ Data Gorvernance ให้ชัดเจน ใครควรView/Edit/Deleteข้อมูลลูกค้าแค่ไหน

ข้อมูลส่วนบุคคล หรือ Customer Data คืออะไร แบ่งเป็นกี่ประเภท

ประเภทของข้อมูลลูกค้า แบ่งเป็น 3 ประเภทได้แก่
1. ข้อมูลส่วนบุคคล (Personal Data)
ในที่นี้จะรวมทั้ง ข้อมูลที่ยืนยันตัวตนได้(Personally Identifiable Information) และยืนยันตัวตนไม่ได้ (Non-PII)

1.1 ข้อมูลที่ยืนยันตัวตนได้(Personally Identifiable Information)
คือข้อมูลที่ทราบแล้ว เราสามารถเชื่อมโยงได้ ว่าเจ้าของข้อมูลคนๆนั้นเป็นใคร โดยกลุ่มนี้สามารถแยกได้ย่อยเป็นอีก 2 กลุ่มได้แก่

(1) เชื่อมโยงได้โดยทันที (Linked Information) ได้แก่

  • ชื่อเต็ม (Full name)
  • ที่อยู่จริง (Physical address)
  • Email address

(2) เชื่อมโยงได้เมื่อนำข้อมูลมาประกอบกัน Linkable Information ได้แก่

  • ชื่อ หรือ นามสกุล (Firstname or lastname)
    ตำแหน่งที่อยู่  ประเทศ จังหวัด รหัสไปรษณีย์
    เพศ (Gender)

1.2  ข้อมูลที่ยืนยันตัวตนไม่ได้ (Non-PII)
คือข้อมูลที่ทราบแล้ว เราไม่สามารถเชื่อมโยงได้ ว่าเจ้าของข้อมูลคนๆนั้นเป็นใคร จัดอยู่ในกลุ่มข้อมูล (anonymous) ได้แก่

  • เลขไอพี (IP address)
  • Cookies
  • เลข Device IDs

* ข้อมูลส่วนบุคคล (Personal Data) กลุ่มนี้จัดว่าเป็น”ข้อมูลส่วนบุคคล”ตาม General Data Protection Regulation (GDPR)

อ่านรายละเอียดเรื่อง Customer Data คืออะไร แบ่งเป็นกี่ประเภท

สำหรับการจัดการ Consent มีทั้งระดับ Cookie Consent และระดับสูงกว่าคือ (Universal Consent & Preference Management)

คุกกี้ หลักๆมีกี่รูปแบบ
1.คุกกี้ที่มีความจำเป็นอย่างยิ่ง (Strictly Necessary Cookies) เพื่อให้ Website ของเราทำงานได้ถูกต้อง, เพื่อระบบ Log-In หรือระบบ KYC  หรือเป็นคุกกี้เพื่อการตรวจเช็คความปลอดภัยด้านE-Payment

2.คุกกี้สำหรับฟังก์ชั่นการทำงาน (Preferences หรือ Functional Cookies) คุกกี้สำหรับใช้เพื่อประสบการณ์ที่ดีในการใช้งาน website เช่น จดจำสินค้าล่าสุดที่เราเคยดู ภาษาที่เราเลือกใช้ หรือการจดจำ Log-In  ก็ได้

3. คุกกี้เก็บข้อมูลการใช้งาน (Analytic หรือ Statistics หรือ Performance Cookies) คุกกี้พวกนี้สำหรับจัดเก็บพฤติกรรมการใช้งานwebsite ทั้งหมด และรวมถึง 3rd Party Cookie เช่น Google Analytic  เป็นต้น

4. คุกกี้สำหรับการโฆษณา (Marketing cookies ) คุกกี้สำหรับใช้เพื่อการทำ Advertising ทั้งการ Re-marketing  หรือการ Track จำนวน frequency

การจัดการ Cookie Consent Management

ตัวอย่าง Cookie  Banner Flow ที่จะทำหน้าที่ขวางการ Tracking ของ User จนกว่าจะมีการกดรับ Cookie

โดยเราสามารถเลือกความเข้มข้นในการขอ Consent ได้หลายแบบ เช่น

Notice Only ทึกทัก – Track ไปแล้ว และแจ้งให้ทราบเท่านั้นว่า Web ของเรามีการใช้คุกกี้อะไรบ้าง User ไม่สามารถ Disable Cookie ของเราได้ทำได้แค่ปิด Dialog / Banner Cookie เท่านั้น
Implied Consent แค่โอเคก็ทะลุทะลวง –  ยังไม่ Track แต่ทันทีที่ User กด OK  ระบบจะ Enable Cookie ทุกตัว
Opt-out ลากเข้าไปก่อน – Track ไปแล้ว และแจ้งให้ทราบว่า Web ของเรามีการใช้คุกกี้อะไรบ้าง มีPage ให้ User เข้าไป disable cookie บางตัวได้
Opt-in ปลอดภัยฝุดๆ – ยังไม่ Track นอกจากคุกกี้ที่จำเป็นกับการใช้งาน (Strictly Necessary) User เข้าไป Enable cookie แต่ละตัวเอง

การจัดการ Universal Consent & Preference Management
1. ระบุวัตถุประสงค์การเก็บและประมวลผล (purpose of processing) เช่น
– เพื่อการบริหารความสัมพันธ์, การทำ Email Marketing, การวัดผลแคมเปญ

  1. การกำหนดจุดที่จะเก็บข้อมูล Points of Interaction หรือ Collection Point เช่น
    – Web Form, Email, APP SDK หรือ Custom API อื่นๆ
    โดยในส่วนนี้เราสามารถบังคับ User  ให้ Double Opt-in  ได้ เช่นการให้ User click confirmation link ใน Email

3. การสร้าง Preference Center เพื่อให้ User เข้ามาจัดการช่องทางการติดต่อ, และหมวดหมู่ที่ต้องการรับข่าวสารจากเรา

ตัวอย่าง Preference Center ของ spotify

อ่านสรุป พ.ร.บ.คุ้มครองข้อมูลส่วนบุคคล พ.ศ. 2562 หรือ PDPA

Reference อื่นๆ
https://gdpr.eu/cookies
https://www.onetrust.com/
https://www.slideshare.net/mediapostlive/onetrust-sponsored-coffee-break
https://www.nivea.co.th/system-pages/cookies#CookieDescription

หากมีคำถามเพิ่มเติม สามารถสอบถามผมได้ที่กลุ่ม >> Marketing Tech Thailand

ติดตาม Marketing Tech Thailand ใน Social Media ได้ที่
🔥 Facbook Page : Marketing Tech Thailand
🔥 Facebook Group : Marketing Tech Thailand – Group
📺 Youtube : Marketing Tech Thailand
🌎 Linkedin Group (Global Community) : Marketing Tech Community in Thailand


COOKIE RUN NFT CONTROVERSY – All you need to know


I thought this was an important video to make. I am just one, small voice in this large discussion, but the more voices stand up in protest to this new NFT venture proposal, the better we serve our community and most importantly, our environment. I encourage you to do the same.
Below I list some resources to get you started if you wish to research onwards:
‘WHAT IS AN NFT?’:
https://www.youtube.com/watch?v=Oz9zw7_vhM
https://mashable.com/article/nftcryptocurrencybadenvironmentart
https://www.nftsstreet.com/howarenftsbadfortheenvironment/
COOKIE RUN NFT DISCUSSIONS:
https://twitter.com/koffeebeecookie/status/1458389909354553345
https://www.reddit.com/r/Cookierun/comments/qqrun4/devsisters_plans_on_making_cookie_run_nfts_thats/
https://twitter.com/search?q=%23StopCookieRunNFTs

นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูความรู้เพิ่มเติมที่นี่

COOKIE RUN NFT CONTROVERSY - All you need to know

เจ้าหมี กับตุ๊กตา Huggy Wuggy!


บุกโรงงานตุ๊กตาสุดสยอง Huggy Wuggy

คลิปที่แล้ว ► https://youtu.be/D9sc2_GUc1g
TORtorpedo GMOD trevorhenderson
▬▬▬
ช่องทางติดตาม TOR Torpedo :
🚀 Fanpage : https://www.fb.com/torpedo702
📷 IG : https://www.instagram.com/torpedo702
🎵 TikTok : https://www.tiktok.com/@702torpedo
💼 ติดต่องาน : [email protected]

เจ้าหมี กับตุ๊กตา Huggy Wuggy!

The chemistry of cookies – Stephanie Warren


View full lesson: http://ed.ted.com/lessons/thechemistryofcookiesstephaniewarren
You stick cookie dough into an oven, and magically, you get a plate of warm, gooey cookies. Except it’s not magic; it’s science. Stephanie Warren explains via basic chemistry principles how the dough spreads out, at what temperature we can kill salmonella, and why that intoxicating smell wafting from your oven indicates that the cookies are ready for eating.
Lesson by Stephanie Warren, animation by Augenblick Studios.

The chemistry of cookies - Stephanie Warren

Five Little Ducks – Great Songs for Children | LooLoo Kids


The best collection of kids songs featuring the most popular “Five Little Ducks” The best songs for kids created by LooLoo KIDS📢Listen on SPOTIFY http://listento.loolookids.com/ 📢Download our app: http://onelink.to/looloo
🔔Subscribe to our channel because new videos are uploaded every week! http://bit.ly/Subscribe_to_LooLooKids
👍Follow us on Facebook for new updates! https://www.facebook.com/LooLooKids/
🐦Tweet to us! https://twitter.com/loolookids
🎵Instagram: https://instagram.com/loo.loo.kids
🎵👍 Watch the LooLoo Kids Playlist: http://bit.ly/310qEOk
🎵 Go to your favorite song by selecting a title below! 👇
0:00 Five Little Ducks 1:40 Five Little Monkeys 3:59 Twinkle, Twinkle, Little Star 6:28 Bingo 8:52 Johny Johny Yes Papa 10:28 Old MacDonald Had a Farm 11:46 Once I Caught A Fish Alive 13:54 If You’re Happy And You Know It 15:54 Five Little Ducks 18:17 Head, Shoulders, Knees and Toes 20:18 PataCake 21:19 Twinkle, Twinkle Little Star 23:30 The ABC Song 24:55 Old MacDonald Had a Farm 26:23 Humpty Dumpty 27:44 Five Little Ducks 29:24 BINGO 31:26 Three Little Kittens 33:51 The Finger Family 34:58 Miss Polly Had a Dolly 36:26 Baa, Baa, Black Sheep 37:41 Incy Wincy Spider 39:23 Row, Row, Row Your Boat 41:20 Head, Shoulders, Knees and Toes 42:53 Rain, Rain Go Away 45:12 If You’re Happy And You Know It 46:57 Mary Had a Little Lamb 49:16 Hush, Little Baby 51:41 The Wheels on the Bus 53:29 Happy Birthday
Five Little Ducks Lyrics
Five little ducks went swimming one day,
Over the hills and far away.
Mommy duck said: \”Quack, quack, quack, quack.\”
But only four little ducks came back.
Four little ducks went swimming one day,
Over the hills and far away.
Mommy duck said: \”Quack, quack, quack, quack.\”
But only three little ducks came back.
Three little ducks went swimming one day,
Over the hills and far away.
Mommy duck said: \”Quack, quack, quack, quack.\”
But only two little ducks came back.
Two little ducks went swimming one day,
Over the hills and far away.
Mommy duck said: \”Quack, quack, quack, quack.\”
But only one little duck came back.
One little duck went swimming one day,
Over the hills and far away.
Mommy duck said: \”Quack, quack, quack, quack.\”
But no little ducks came swimming back.
No little ducks went swimming one day,
Over the hills and far away.
Daddy duck said: \”Quack, quack, quack, quack.\”
And all the five little ducks came back.
Watch the LooLoo Kids Playlist: https://youtu.be/ccCPcujnys?list=PLFkIjhjdbaAdmPyradNYGNG5vbbPQBuuw
Enjoy other LooLoo Kids nursery rhymes:
Johny, Johny Yes Papa https://youtu.be/F4tHL8reNCs
The Wheels on the bus https://youtu.be/6X3AQe4lPg
Rain, Rain Go Away https://youtu.be/nCqUYAnQF0o
Ten in a Bed https://youtu.be/jk7N3bKvgvg
Five Little Ducks https://youtu.be/ccCPcujnys
Are You Sleeping Brother John https://youtu.be/ptXUH9vhCmA
PeekaBoo https://youtu.be/3pzyUMVI_qQ
Drawing Song https://youtu.be/4_TANGFW43k
Seven Days https://youtu.be/iXtPqJEylVk
Baby Shark https://youtu.be/sUxTSW4hW2g
Enjoy educational songs and stories for preschool kids created by experts in children’s education!
Nursery rhymes in English, canciones en inglés para niños, barnvisorna på engelska, Músicas em inglês para crianças, Gyerekzene, Kinderlieder in Englisch, 英文兒歌, Písničky v angličtině, أناشيد أطفال باللغة الإنجليزية, अंग्रेजी में नर्सरी कविताएं, Comptines en anglais, Lagulagu anak berbahasa Inggeris, Musik Untuk Anak, Barnerim på engelsk, Canzoni per bambini in inglese, Engelse kinderliedjes, Piosenki dla dzieci po angielsku, เพลงภาษาอังกฤษสำหรับเด็ก loolookids looloonurseryrhymes loolookids looloonurseryrhymes looloo
LooLoo Kids is a registered trademark of MORA TV. For distribution and more information, visit and contact us at https://loolookids.com

Five Little Ducks - Great Songs for Children | LooLoo Kids

เพื่อนสนิท | ขี้เลียนแบบ


เพื่อนที่คอยทำตามเราทุกอย่าง จนเราทนต่อไปไม่ไหว
เพจเฟสบุ๊ค https://www.facebook.com/epookz/
ติดต่องาน
https://www.facebook.com/epookz/
[email protected]
///////////////

เพื่อนสนิท | ขี้เลียนแบบ

นอกจากการดูบทความนี้แล้ว คุณยังสามารถดูข้อมูลที่เป็นประโยชน์อื่นๆ อีกมากมายที่เราให้ไว้ที่นี่: ดูบทความเพิ่มเติมในหมวดหมู่LEARN FOREIGN LANGUAGE

ขอบคุณมากสำหรับการดูหัวข้อโพสต์ cookie คือ

Leave a Reply

Your email address will not be published. Required fields are marked *