เบื่อมั้ยกับ App ตอบคำถามทายใจใน Facebook เรามีขั้นตอนซ่อนง่ายๆใน 4 วิธี

โพสนี้ เกิดจากการที่ผมรำคาญโพสของแอปทายใจของทาง Dek-D ครับ คือมันเป็นที่นิยมจนเกินไป ไม่ใช่อะไรมันเยอะขนาดหาโพสอื่นไม่ค่อยเจอ เลื่อนมา 2-3 โพสเจออีกแล้ว รวมทั้งผมไม่ได้สนใจโพสพวกนี้อยู่แล้วด้วย ผมเลยแบน App นี้ออกจาก new Feed บน Facebook ผม และผมเชื่อว่าหลายๆคนประสบปัญหาเดียวกันกับผม ผมจึงเขียน blog นี้ขึ้นเพื่อเป็นแนวทางให้หลายๆคน ทำการซ่อนโพสซึ่งเกิดจาก app ทายใจของ Dek-D

วิธีการซ่อนโพสทายใจบน Facebook มีขั้นตอนดังนี้

  1. เข้า หน้า New Feed  บน Facebook จากนั้น หาโพสที่เป็นผลการทายใจ เลื่อนเมาส์ทับโพสทายใจนั้น จากนั้นที่มุมขวาบนจะมีลูกศรขึ้นามาให้กดลงไปครับ
    หาโพสทายใจของ Dek-D แล้วกดลูกศรมุมขวา
  2. จากนั้นกด Hide all from Dek-D (กดให้ถูกนะครับ อย่าไปเผลอกด Hide ของเพื่อนนะครับ) เป็นการบอก Facebook ว่าเราจะซ่อนโพสที่มาจาก Dek-D จาก New Feed ทั้งหมด
    กด Hide all from Dek-D เพื่อซ่อนโพสทายใจ
  3. กด It’s annoying or not interesting (อันแรก) เพื่อบอก Facebook ว่าโพสนี้รบกวนฉันหรือฉันไม่สนใจโพสทายใจเหล่านั้น
    กด it's annoying ot not interesting
  4. กด  It’s advertising something I don’t care about (อันที่ 3) เพื่อบอกว่าโพสทายใจเหล่านี้เป็นการโฆษณาบางอย่างที่เราไม่สนใจครับ
    กด It's advertising something I don't care about เพียงเท่านี้โพสทายใจเหล่านั้นก็จะถูกซ่อนให้น้อยลงแล้วครับ แต่ไม่ได้หมายความว่าจะหมดไปนะครับ ถ้าหากมีเพื่อนเราไปโพสข้างใต้โพสเหล่านั้น มันก็จะเด้งกลับมาหน้า New Feed บน Facebook เหล่านั้นได้ครับ (แต่โดยปกติไม่น่ามีเยอะนะครับ)

บันทึกการซน Thaiware

อันนี้เป็นบันทึกสมัย QA เปิดใหม่ๆนะครับ ผมแจ้ง bug ไปเมื่อ 13 มกราคม 2013 ครับ ผมถือว่านานแล้วเลยเอาออกมาเล่าสู่กันฟัง หลายอย่างกันไปแล้วครับ แต่เอามาแสดงเป็นอุธาหรณ์สำหรับ Programmer ครับ

อันแรกที่เจอ เป็นผลจากการซนของผมครับ ความซนอย่างหนึ่งของผมคือ ถ้ารู้ว่าเป็น custom web ผมจะลองใส่ ‘ or ‘1’=’1 ลงไปครับ ถ้าเป็นหน้า login แล้วผ่านหรือ error ขึ้น ก็ Jackport ครับ เป็น SQL Injection พื้นฐาน ไม่ขออธิบายนะครับ หาตาม Google ได้ทั่วไป จริงๆทำแบบนี้แล้วเกิด memory limit เพราะเค้าไม่ได้ใส่ limit ไว้เลยดึงข้อมูลทั้งหมดมาใส่ ram แต่มันมากเกินไปใส่ไม่หมด วิธีแก้คือใช้ prepare หรืออย่างน้อยใช้ mysql_escape_string ครับ หรือไม่ก็เอา username ไป select อันเดียว แล้วตรวจ password ด้วย php ครับ

อันที่สอง ผมใช้ Dev Console ของ Chrome แก้ Cookie ตัว acc_member_id กับ acc_type ให้เป็นของ admin ได้ (จริงๆได้แค่ดูข้อมูลของ id=1 แต่คิดว่าถ้าลองดีๆ ก็น่าจะได้สิทธิไม่ยาก) ผมคาดว่าเค้าเอา ID จาก Cookie ไปค้นหาข้อมูลตรงๆใน Database เลยก็เป็นได้ ซึ่งไม่ควรทำ โดยทั่วไปเราไม่ควรเชื่อข้อมูลจากฝั่ง client หรือควรมีมาตรการยืนยันมากกว่านี้

อันที่สาม เป็น ผลมาจากครั้งที่ 2 ครับ ผมคาดว่าเค้าใช้ session ยืนยันตัวตนแทนในกรณีที่มี session ผมก็ใช้วิธีเดียวกับวิธีที่ 2 แต่คราวนี้ผมไม่แน่ใจว่าแก้พวก id กับ type ได้ไหม ใน mail ผมไม่ได้มีข้อมูลด้านนี้ แต่มีข้อมูลอีกแบบคือ ผมสามารถใส่ sql injection ลงไปในช่อง acc_member_id แล้วเกิด error memory limit ขึ้น ซึ่งผมเดาว่ามันคงไปดึงข้อมูลทั้งหมดใน DB ออกมาแน่ๆเลย ในตอนนั้นผมแนะนำให้เค้าใช้ mysqli (หรือ PDO) เพื่อให้ใช้ prepare statement เพื่อป้องกัน sql injection ครับ แต่จริงๆผมลืมแนะนำไปว่า ควรใส่ limit 1 ไว้ด้วย เพื่อประสิทธิภาพที่ดีครับ คือถ้าเจอ 1 ตัวแล้วมันจะหยุดหาไม่หาต่อ แล้วก็หากไม่มี session ควรยืนยันตัวตนผ่านวิธีอื่นไม่ใช่เอา id อย่างเดียวไปหาตรงๆ อย่างเช่นเอา pass มาก md5 หลายๆชั้นใส่ cookie แล้วเวลายืนยันก็ไป select id ออกมา แล้วเอา pass มาทำด้วยวิธีเดียวกันถ้าตรงกับ pass ที่เข้ารหัสใน cookie ค่อยเอาข้อมูลใส่ session [ref to mysqli.prepare]

อันสุดท้าย [สถานะวันที่ 22/11/13 คือยังไม่ได้รับการแก้ไข]  ดังนั้นผมยังไม่บอกไรมาก บอกได้แค่ XSS จ้า

การลบ Mail Queue ทั้งหมดออกจาก server

คือพอดี server ผมมีปัญหาว่าผมลง vBulletin ไว้ แล้วทีนี้ผมตั้งว่าถ้าเกิด error ให้ email หาผม แล้วปัญหามันเกิดเมื่อ วันนึง MySQL มันล่ม และช่วงนั้นคนเข้าเยอะ ผลคือ Mail จำนวนมากถูกส่งมาให้ผม และอีกจำนวนมากค้างอยู่ใน Mail Queue ผมรอ 3 วันมันก็ไม่หมดสักที ผมเลยต้องหาวิธีลบเมลขาออกให้หมด ผลที่ได้คือเจอเว็บนี้ครับ แล้วทำตามคำสั่งนี้ (สำหรับ DirectAdmin นะครับ ตัวอื่นผมไม่ชัวร์)

cd /var/spool
mv exim exim.old
mkdir -p exim/input
mkdir -p exim/msglog
mkdir -p exim/db
chown -R mail:mail exim
/sbin/service exim restart

#หากทำงานได้ปกติ ให้ทำข้างล่างนี้ต่อครับ
rm -rf exim.old

 

วิธีการสุ่มค่าจาก SQL ที่ดีกว่าการใช้ ORDER BY RAND()

โดยทั่วไปเท่าที่ผมเห็น การจะสั่ง sql ให้ดึงแถวที่ต้องการมาโดยเรียงลำดับแบบสุ่มจะใช้วิธี ORDER BY RAND() เช่น

SELECT * FROM `table` WHERE 1 ORDER BY RAND()

แต่วิธีนี้ไม่ใช่วิธีที่ดีเลย เพราะสมมุตว่าข้อมูลมีจะนวน 100000 แถว จะต้องเกิดการ random ค่าทั้งหมด 100000 ครั้ง นอกจากนั้นเมื่อ random เสร็จ ก็ต้องเอาข้อมูลนั้นมาเรียงลำดับใหม่อีกครั้ง ซึ่งในขั้นตอนการเรียง โดยมากแล้ว ตัว Database จะไม่ยอมให้ใช้เนื้อที่เกินจำนวนหนึ่งใน RAM แต่ถ้าข้อมูลเยอะๆแบบนี้ จะใช้การเขียนลง file ก่อน แล้วค่อย sort ซึ่งทำให้ช้ากว่าใน RAM มาก

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

SELECT  * FROM    (
        SELECT  @cnt := COUNT(*) + 1,
                @lim := 10
        FROM    `table`
) vars
STRAIGHT_JOIN
 (
        SELECT  r.*,
                @lim := @lim - 1
        FROM    `table` r
        WHERE   (@cnt := @cnt - 1)
                AND RAND(20090301) < @lim / @cnt
) i

โดย `table` หมายถึงชื่อตาราง และตรง @lim := 10 หมายถึงต้องการ 10 ตัว ส่วนตัวเลข 20090301 เค้าบอกเป็นเลขอะไรก็ได้ เค้าเอาเลขนี้มาจากวันที่โพส และควรเปลี่ยนทุกครั้ง เพื่อให้ผลไม่เหมือนเดิม

หลักการทำงานคือเหมือนเค้าใช้หลักความน่าจะเป็นแทนการสุ่มมั้งครับ

จริงๆในเว็บต้นฉบับ เค้าบอกมีวิธีสำหรับแถวเดียวอยู่ด้วย แต่ผมไม่สามารถทำความเข้าใจได้ครับ