又一次搬家囉! https://blog.inndy.tw

about 4 years ago

網站安全那些大小事

如果你正在學習使用PHP(其實任何語言都通用)開發網站...

請務必要注意到安全性的問題

特別是有開放留言、註冊功能之類的網站!

有留言板,就有人想 <script> ...

有登入系統,就有人想 'or''=' ...

可以寫<script>的留言板,黑客就可以偷走你的cookie

甚至偷走你的密碼,進入後台搞破壞

萬一你的密碼是萬用密碼,拿到之後每個網站都可以登入

那你就損失慘重了!

至於可以寫單引號的系統呢?

如果你寫了...

$query = mysql_query("DELETE FROM `messages` WHERE " .  
                     "`mid` = '{$_POST['id']}' AND " .  
                     "`del_code` = '{$_POST['code']}'");  

像這樣具有刪除留言功能的留言板

那麼我只要搞破壞,在code欄位輸入了 ' or '' = ' ...

整個 SQL 命令就會變成

DELETE FROM `messages` WHERE `mid` = '' AND `del_code` = '' or '' = ''
看清楚了嗎?

or '' = ''

然後你整張資料表的內容就...

萬一這是使用者刪除帳號的功能呢?

只要把握一個原則,就可以寫出很安全的網頁

Never Trust User Input, Forever.

就算是在後台也一樣

不管是前台還是後台,都要要檢查使用者輸入資料格式、範圍是否正確

並且正確的 escape 掉所有的 SQL 和 HTML

如此一來,你的網站安全就能夠大大的提升了

好了,我已經講完了

「等等,這不是有講跟沒講一樣嗎?」

摁,所以來講些實作上的東西

Never Trust User Input Data

  • 取得使用者IP?
    • HTTP_X_FORWARDED_FORHTTP_CLIENT_IPREMOTE_ADDR請全部記下來...
    • 如果我要限制使用者IP呢?
      • 只能相信REMOTE_ADDR,因為其他的通通都能輕易偽造

登入系統絕對不能只靠cookie判斷

  • if ($_COOKIE['user_login'] == "admin") { echo "歡迎回來,管理員大大"; }
    • javascript: document.cookie = "user_login=admin"; // Hi, I'm cracker.
  • SESSION是你的好夥伴
    • SESSION ID請使用 http-only 的cookie來存,確保JS讀不到
  • SESSION內存放登入有效期限,超過就強制登出

 組合 SQL 前,檢查並且escape所有放進去的參數

  • mysqli_real_escape_string // mysql_* 要廢棄了,全面改用mysqli
  • mysqli::prepare
  • PDO
  • ORM framework
  • IP位址也要escape...
  • HTTP_X_FORWARDED_FOR 也能注
  • 如果你要把資料從DB query出來,再存進去,記得也要再次escape
  • 延伸閱讀:2nd sql injection
  • 絕對要使用正確的方式做escape

絕對不要 認為 htmlentities 可以保護你的資料庫

  • But... XSS還是要靠他

輸出前記得要escape html擋XSS

  • htmlentities
  • 使用 ENT_IGNORE時請小心
  • 可以利用文字編碼繞過 escape
  •  統一入資料庫前或者輸出前escape一次就好

我遇過被資料escape兩次的,然後編輯資料我就要手動unescape一次
...

幹....

CAPTCHA 的內容絕對不要放 cookie 或者img的alt...

  • <img src="captcha.php?code=dr5gh" alt="請輸入:dr5gh" id="img_captcha" />
    • var captcha = document.querySelector("#captcha").alt.substr(4);
  • 乖乖用SESSION啦

重要的操作請勿使用GET方法

  • <img src="http://your.website.com/user/delete_my_account.php?confirm=yes" />
    • 你看你又悲劇了
    • POST + one time token + check referer
    • <input type="hidden" name="token" value="blablablabla_store_in_session" />

避免不安全的使用eval()

Server儲存密碼的時候請使用hash處理過

if (!DEBUG) error_reporting(0);

  •  error噴出來的資料可能會洩漏一些資訊
    • Ex: username, path...
    • 為了安全,不顯示錯誤

就先寫到這裡吧,最後來個留言板Demo...

http://pastebin.com/z77Tx3ra

← 重灌Windows之後,修復Linux Mint(Ubuntu)的開機選單(grub2) ToS那些大小事 →
 
comments powered by Disqus