[ PHP ] - Cookie protection using HTTP Headers [ ป้องกัน Cookie จากช่องโหว่ XSS ]




บทความนี้ขอขอบคุณพี่ยานน่ารัก
ที่นำพาบทความมาไปแปะไว้ในกลุ่ม Owasp Thailand Chapter ครับ :D
ซึ่งเห็นว่าเป็นเรื่องที่น่าสนใจมาก ผมจึงจับมาแปลและเผยแพร่ต่อครับ

Cookie protection using HTTP Headers


เป็นที่รู้กันทั่วไปนะครับว่า Cross Site Scripting คือ 1 ช่องโหว่ที่สามารถขโมยค่าคุ๊กกี้จาก User Browser. HttpOnly คือคำแนะนำที่จะปิดความสามารถในการอ่าน Cookies ที่ใช้ external Javascript

ซึ่ง HttpOnly นี้จะช่วยบรรเทาทุกข์เหมือนคุณริวจิตรสัมผัส ในที่นี้ก็หมายถึงจะช่วยบรรเทาให้ Application ที่มีช่องโหว่ xss แฮกเกอร์จะไม่สามารถอ่าน cookies ได้ เมื่อ HttpOnly flag นั้น enabled.



Example

Http header ของ Application ที่ไม่ปลอดภัย เนื่องจากไม่มี flags เพิ่มเติมใน Set-Cookie header
ซึ่งจะทำให้ "แฮกเกอร์" สามารถอ่าน session id ของเหยื่อได้
ถ้า application มีช่องโหว่ xss

HTTP/1.1 200 OK
Date: Sun, 12 Apr 2015 15:07:14 GMT
Server: Apache/2.2.29 (Unix) mod_fastcgi/2.4.6 mod_wsgi/3.4 Python/2.7.8 PHP/5.6.2 mod_ssl/2.2.29 OpenSSL/0.9.8y DAV/2 mod_perl/2.0.8 Perl/v5.20.0
X-Powered-By: PHP/5.6.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=a2ed2bf468dd811c09bf62521b07a023; path=/
Content-Length: 820
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8


เพื่อหลีกเลี่ยงปัญหานี้, เราสามารถ implement HTTPOnly flag,
ซึ่งจะช่วยให้เราสามารถส่ง cookies ผ่าน http protocol แต่ไม่รวมถึง Javascript

โดยการเพิ่มบรรทัดล่างนี้เข้าไปใน Application
ini_set("session.cookie_httponly", "True");

[code]
http://pastebin.com/7NVHdTSX


เมื่อลอง intercept response headers
โดยใช้ Burp proxy. (หรือ Live HTTP Headers Add-on firefox)

HTTP/1.1 200 OK
Date: Sun, 12 Apr 2015 15:03:15 GMT
Server: Apache/2.2.29 (Unix) mod_fastcgi/2.4.6 mod_wsgi/3.4 Python/2.7.8 PHP/5.6.2 mod_ssl/2.2.29 OpenSSL/0.9.8y DAV/2 mod_perl/2.0.8 Perl/v5.20.0
X-Powered-By: PHP/5.6.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=36cb82e1d98853f8e250d89be857a0d3; path=/; HttpOnly
Content-Length: 820
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8


เมื่อทดสอบโจมตีช่องโหว่ XSS โดยการ alert ค่า cookies
จะป้องกันแฮกเกอร์ ให้จะไม่สามารถอ่านค่า cookie ได้
แม้ Application จะมีช่องโหว่ Xss ก็ตาม




Cookie attribute ต่อไปคือ "secure". 

เมื่อ Application ส่ง cookies ผ่าน HTTP 
พบว่าเป็นไปได้ที่แฮกเกอร์อาจจะยังสามารถ Hijacked 

เนื่องจากข้อมูลที่ส่งอยู่ในรูปแบบ clear text format
ดังนั้นเราจะมาลองเพิ่ม "secure" attribute บน set-cookie header
เพื่อบังคับให้ Application ส่ง cookies ผ่าน HTTPS
โดยการเพิ่มโค้ดนี้ไปในบรรทัดแรกสุดของไฟล์ Application
ini_set("session.cookie_secure", "True");
ทั้งนี้เข้าใจว่า Server ต้อง support https ด้วยเช่นกัน

เมื่อ Intercept Response Header

HTTP/1.1 200 OK
Date: Sun, 12 Apr 2015 15:14:30 GMT
Server: Apache/2.2.29 (Unix) mod_fastcgi/2.4.6 mod_wsgi/3.4 Python/2.7.8 PHP/5.6.2 mod_ssl/2.2.29 OpenSSL/0.9.8y DAV/2 mod_perl/2.0.8 Perl/v5.20.0
X-Powered-By: PHP/5.6.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=f95afc96ecb7acc6c288d31f941e682f; path=/; secure
Content-Length: 820
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8



Kill Session ชั่นเมื่อปิดเบราว์เซอร์


เมื่อเราใช้งาน applications ที่สำคัญๆจำเป็นต้องกำหนดใน Session มีการหมดอายุ
เมื่อเราปิด Browser โดยไม่มีการ logout

example code เมื่อเราปิด Browser จะเหมือนการ Logout อัตโนมัติทันที
session_set_cookie_params(0);
session_start();

สามารถใช้ Cookie editor อย่างเช่น "EditThisCookie" หรือ chrome’s developer tools
บน chrome เพื่อตรวจสอบได้เช่นกัน



นำ 3 เทคนิคนี้มารวมร่างกันก็จะได้

ini_set("session.cookie_secure", "True"); // secure
ini_set("session.cookie_httponly", "True"); //httponly
session_set_cookie_params(3, '/', '.localhost');
// คุ๊กนี้นี้จะสามารถใช้ได้ 3 seconds (max age)
// "/" เพื่อแน่ใจว่า cookie [ paths of this domain ] ถูกต้องทั้งหมด
// ".localhost"  // cookie is accessible from all the subdomains.

session_start();


Response Header

HTTP/1.1 200 OK
Date: Thu, 30 Apr 2015 03:04:11 GMT
Server: Apache/2.2.29 (Unix) mod_fastcgi/2.4.6 mod_wsgi/3.4 Python/2.7.8 PHP/5.6.2 mod_ssl/2.2.29 OpenSSL/0.9.8y DAV/2 mod_perl/2.0.8 Perl/v5.20.0
X-Powered-By: PHP/5.6.2
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Set-Cookie: PHPSESSID=f4d99777d9810bfedb6869acd556bc66; expires=Thu, 30-Apr-2015 03:04:14 GMT; Max-Age=3; path=/; domain=.localhost; secure; HttpOnly
X-XSS-Protection: 1
Content-Security-Policy: script-src 'self'
Content-Length: 820
Keep-Alive: timeout=5, max=100
Connection: Keep-Alive
Content-Type: text/html; charset=UTF-8

จะได้ค่า Set-Cookie header ที่ปลอดภัยดังนี้
Set-Cookie: value[; expires=date][; domain=domain][; path=path][; secure]



Source :
http://resources.infosecinstitute.com/defending-against-web-attacks-using-http-headers-part-3/