ป้องกัน xss ใน Codeigniter และ php


หน้าแรก PHP MySQL เกร็ดความรู้ ป้องกัน xss ใน Codeigniter และ php

xss คืออะไร

xss หรือ cross site scripting คือการส่งสคริปข้ามเว็บไซต์ เพื่อโจมตีเหยื่อที่เปิดเข้าไป หรือโจมตีหน้าเว็บเพจ

ยกตัวอย่างเช่น ในเว็บเพจหนึ่ง รับค่าทาง url ดังนี้ page.php?name=myname
แล้วทำการ echo ออกมาทางหน้าเว็บเพจดังนี้ <?php echo $_GET['name']; ?>
ผู้ร้าย ได้ทำการสร้างหน้าเว็บเพจอีกแห่งหนึ่ง โดยมีลิ้งค์ให้คลิกดังนี้ ดูหนังฟรี
เหยื่อเห็นลิ้งค์ดูหนังฟรี จึงคลิกเข้าไป ปรากฏว่ามี javascript alert hello ขึ้นมาในหน้าเว็บเป้าหมาย

นี่เป็นเพียงตัวอย่างง่ายๆของการกลั่นแกล้งแบบทารก ถ้าหากว่าสคริปที่ส่งไปยังเว็บเป้าหมาย เป็นสคริปที่ร้ายแรงล่ะ? เช่น ขโมยคุกกี้, สคริปที่สั่งแก้ข้อมูลสมาชิกในเว็บเป้าหมาย
เรื่องคงไม่สนุกแน่นอน

นอกจากนี้ xss ยังสามารถโจมตีไปที่ stylesheet/css ได้อีกด้วย โดยเป้าหมายคือทำให้หน้าเพจนั้นเละไปเลยด้วยการมั่ว stylesheet เช่น การ xss มาในส่วน comment ทำให้หน้านั้นมี layout comment เละเทะ สีสไตล์ไม่เป็นไปตามที่ควรจะเป็น

การป้องกัน

การป้องกันนั้น หลักการคือ ทำลายแทก <script> ทั้งหลาย และลบล้างคำสั่ง inline script ไม่ว่าจะติดมากับ onclick onload on...สารพัด
นอกจากส่วนของสคริปยังต้องทำลายหรือลบล้างพวก stylesheet, inline style ทั้งหลายให้หมด เพื่อไม่ให้การแสดงผลหน้าเว็บเสียหายจากการ xss

สำหรับ php ธรรมดา สามารถป้องกันได้โดยใช้ vee secured form หรือใช้ htmlpurifier
ส่วน Codeigniter นั้นมีการป้องกันที่ดีมาให้อยู่แล้ว เพียงแค่ใช้ $this->input->get หรือ post แล้วเติม true ใน attribute ที่ 2
ตัวอย่าง $this->input->get("name", true);

ทดสอบการป้องกัน

เราจะมาสร้างหน้าสำหรับทดสอบการป้องกันดูนะครับ ตามสคริปต่อไปนี้

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

class testxss extends CI_Controller {

function __construct() {

parent::__construct();

$this->load->helper(array("form"));

}

function index() {

// for textarea

$output['inputpost'] = htmlspecialchars($this->input->post("inputpost"));

$output['inputget'] = htmlspecialchars($this->input->get("inputget"));

// for html output

$output['resultpost'] = trim($this->input->post("inputpost"));

$output['resultget'] = trim($this->input->get("inputget"));

//

$this->load->view("testxss_view", $output);

}

}

testxss.php ใน controller

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

<!DOCTYPE html>

<html>

<head>

<meta charset="utf-8" />

<title>test xss</title>

<style>

h1, h2, h3, h4 {margin: 0 0 10px 0;}

.test_result {

background: #f5f5f5;

border:1px dotted #ccc;

margin: 0 0 50px 0;

min-height: 50px;

}

</style>

</head>

<body>

<h1>test xss</h1>

<p><a href="http://ha.ckers.org/xss.html" target="_testsheet">test sheet</a></p>

<h3>method post</h3>

<?php echo form_open($this->uri->uri_string()."?method=post"); ?>

<textarea name="inputpost" cols="50" rows="10"><?php echo (isset($inputpost) ? $inputpost : ""); ?></textarea>

<input type="submit" value="submit" /> <input type="reset" value="reset" />

<?php echo form_close("n"); ?>

<div class="test_result">

<h4>test result:</h4>

<div>

<?php echo (isset($resultpost) ? $resultpost : ""); ?>

</div>

</div>

<hr />

<h3>method get</h3>

<?php echo form_open($this->uri->uri_string()."?method=post", array("method" => "get")); ?>

<textarea name="inputget" cols="50" rows="10"><?php echo (isset($inputget) ? $inputget : ""); ?></textarea>

<input type="submit" value="submit" /> <input type="reset" value="reset" />

<?php echo form_close("n"); ?>

<div class="test_result">

<h4>test result:</h4>

<div>

<?php echo (isset($resultget) ? $resultget : ""); ?>

</div>

</div>

</body>

</html>

testxss_view.php ใน views

เรียกหน้าทดสอบนี้ขึ้นมา เช่น http://localhost/index.php/testxss
จากนั้นนำโค้ดต่างๆจาก xss cheat sheet มาทำการทดสอบ จะพบว่าสคริปข้างบนไม่ได้ป้องกันไว้เลย ทำให้มี javascript alert ในหลายๆครั้งที่ทดลอง
ให้ทำการเติม ,true เข้าไปใน input->post() และ input->get() ของ controller ดังนี้

?

1

2

$output['resultpost'] = trim($this->input->post("inputpost", true));

$output['resultget'] = trim($this->input->get("inputget", true));


ผลการทดสอบอีกครั้งจะพบว่า ทั้ง javascript และ stylesheet หายไปหมดสิ้น. ถือว่าประสบความสำเร็จในการป้องกัน xss


คำถามบ่อยๆและความเข้าใจผิดๆ

หลายคนอาจมีคำถามว่า ทำไมไม่ใช้ strip_tags ล่ะ?
เพราะว่า strip_tags มันไม่อนุญาตแทกใดๆผ่านได้เลย ในกรณีที่เราต้องการรับ html แบบง่ายๆจาก user ก็ทำไม่ได้เลยเช่นกัน
และแม้ทำได้โดยการเพิ่ม tag ที่อนุญาตลงใน strip_tags มันก็ไม่สามารถกรอง inline style และ inline javascript ได้เลย

แล้วถ้าใช้ htmlspecialchars ล่ะ?
การใช้ htmlspecialchars ก็เช่นเดียวกับ strip_tags คือมันจะไม่อนุญาตให้ใช้ html ได้เลย
หลายๆกรณีเราอาจต้องการการกรอก html แบบง่ายๆจาก user เช่น การกรอก comment ที่อาจอนุญาตให้ user แทรกรูปภาพด้วยแทก <img> ได้
ถ้าใช้ strip_tags หรือ htmlspecialchars การกรอก html ก็หมดสิทธิ

ดังนั้นเราควรเข้าใจและยอมรับว่า มันควรต้องมีทางที่จะอนุญาตให้ html แบบง่ายๆที่ไม่เป็นพิษเป็นภัยผ่านเข้าไปได้
ด้วยเหตุนี้สคริปในการป้องกัน xss จึงจำเป็นและควรใช้ในที่ๆต้องใช้ครับ

ป้องกัน xss ใน Codeigniter ได้แล้ว แต่ html ที่กรอกเข้ามาแบบมั่วๆไม่สมบูรณ์ทำให้หน้าเว็บเสียหาย แก้อย่างไร?
การ ตรวจสอบแทก html ต่างๆให้เปิดและปิดถูกต้องครบถ้วน ผมแนะนำว่ามอบหน้าที่นี้ให้กับ htmlpurifier ครับ เพราะมันทำงานได้ยอดเยี่ยมมากจริงๆ Cool


ขอบคุณ: http://okvee.net/th/post/php-codeigniter-xss-prote...



ขึ้นไปด้านบน