作者GALINE (天真可爱CQD)
看板PHP
标题Re: [请益] 网站资安需注意哪些?
时间Mon Jun 4 19:23:27 2018
想试着来全部回答一下,我本业不是网路安全,所以可能内容会需要被订正...
: 1. 像是 XSS 是什麽?会带来什麽危险?用 htmlentities 跟 htmlspecialchars 这两个函式来防御有什麽差别?
白话解释 XSS:「别人在你的网站上塞他的 javascript」
可能的危害
- 所有使用者都会看到嘲笑你的对话方块
- 你的网站被塞别人的广告
- 别人可以用 javacsript 控制你的使用者做...任何在他在网站上能做的事情
- 其他很多...
htmlenties 会把「每一个字」都编码成 html entity,htmlspecialchars 只转换 & " ' > < 这五个。
在大多数情况下这两者的防御效果差不多,差异在於出来的档案大小会不一样。
不过我记得有个 UTF-7 什麽碗糕的的鬼可以打穿 htmlspecialchars,只要 charset 用 utf-8 就没事
刚刚一下 Google 找到都是讲 wordpress 烂掉的事情就是了...
(EDIT: 我弄错了,是 htmlenties 会被 UTF7 攻击打穿...)
: 2. LFI 是什麽?除了被 access 到 /etc/passwd 之外,有没有可能让 source code 泄露?
白话解释 LFI:「别人可以乱读你的档案」
a.php?file=aaa.doc => 吐 aaa.doc 的内容给他
a.php?file=a.php => 把 a.php 的内容(咦,不就自己吗)吐给他
我看过比较有趣的搞法是读 .git/ 把整个 repo 拿走,这样还不用暴力硬扫你有哪些档案...
: 3. SQL Injection 的原理是?用 PDO 真的可以一劳永逸吗? mysqli_real_escape_string 真的有助於防止 SQL injection 吗?
组 SQL 字串的时候塞奇怪东西让 SQL 的意思跟你以为的不一样,然後干奇怪的事情
例如
$id = $_POST['id']; // '123or1=1'
$sql = "select * from user where id = {$id}";
出来会是 select * from user where id = 123or1=1
然後所有的使用者资料就一起喷出来了
而且这个例子用 mysqli_real_escape_string 正好搞不定
理想的做法是不要自己组 SQL 字串,用 prepared statement 然後 bind 参数。背後做的事情大约像这样
mysql> PREPARE stmt FROM "SELECT * FROM user WHERE uid = ?";
「DB 哥哥,我等下要跑『select * from user where uid where id = ?』,问号我等下再跟你说是什麽」
Statement prepared
「好喔,我准备好了等你的参数」
mysql> SET @param='123or1=1'; EXECUTE stmt USING @param;
「DB 哥哥,参数是 '123or1=1' 喔,麻烦把结果跑给我」
Query OK, 0 rows affected (0.00 sec)
Empty set (0.00 sec)
「喔, id 是『123or1=1』吗?我看看...一个都没有喔!」
是说看到上面推文才知道 PDO 的 mysql driver 预设是模拟的,不是真的叫 DB 做 prepared statement。
可以用 PDO::ATTR_EMULATE_PREPARES 这个选项切换...
爬了一下别人的 code
Laravel 内部做 PDO 的时候会强制设定用真的 prepared statement
doctrine 的 dbal 跟 maghead 乍看之下没有管这件事
希望 PHP(或该说 MySQL Driver )模拟的效果够好...
: 4. 什麽是 SSRF?会让系统服务遭受什麽样的风险?
白话解释 SSRF:「别人让你的 server 帮他送 request 给其他机器」
例如抓档案的 URL 如果可以自己乱填
upload_image.php?url=
https://example.com/porn.png
然後你正好知道人家内部的网路状况,或是刚好灵光一闪,就可以拿来打看看(?
upload_image.php?url=
https://dashboard.example.com/
upload_image.php?url=
http://127.0.0.1/
等於是让人家间接钻进内网干乱连机器干事情,而且你会以为是你的内部机器要连所以不一定挡得下来。
SSRF 我不确定有没有什麽好招可以处理,只能想到黑名单白名单....
: 5. extract 这个函式很好用,但会不会不知不觉间被拿来提权?
extract 把 array 的内容直接拆开变成变数
然後有些人会觉得 extract($_GET) 很好用
於是别人就可以乱打网址 ?var1=aaa&var2=bbb 来乱改你 code 里面的变数内容,什麽魔法都能变得出来..
我觉得啦,这年头还是别这样写...
: 6. serialize 跟 unserialize 的使用时要注意什麽?
唔...我原本猜你指的是「unserialize 的东西可能是别人家过料的,然後就可以乱改变数内容」
类似 extract 的状况
不过为防万一找了一下,发现 PHP 跟 unserialize() 有关的安全漏洞还真不少....
我「猜」对 serialize 字串做数位签章(例如 HMAC)验证内容无误,大概还挡得住。
不过更好的作法应该是...别 unserialize 任何使用者有机会动手脚(不论是网址带入或 post 进来)的东西。
: 7. Hash 用户的密码是用什麽演算法好呢?bcrypt
: ?argon2?它们又有什麽差别?
简单的答案:
什麽演算法都不要管,PHP(5.5+)都包好了
把密码这样存
$hash = password_hash("password", PASSWORD_DEFAULT);
然後这样比对密码是否正确(别在 DB 比对)
$passwordOK = password_verify($input, $storedHash);
然後用这里的范例检查有没有需要更新密码 hash
http://php.net/manual/en/function.password-needs-rehash.php
最後,PHP 升级你尽量跟着升级。
真正的答案:
现代 hash 演算法的敌人主要有几种
## 从数学,相对容易算出碰撞值
例如数学方法可以快速算出其他值的 hash 跟你密码的 hash 一样
对应法:
选没有已知攻击的演算法
- md5 阵亡(2004的论文)
- sha1 进棺材了(同一个人写过 sha1 的论文,Google 做过示范攻击)
还有,没事就看一大堆讲这种事情的文章....
## 从实作上被攻击
有些实作有 side channel attack 的问题,例如可以从计算时间推算数值
甚至有些比较夸张的,可以录你电脑的声音推断 CPU 多忙,猜出在算的值是什麽...
对应法:
常常更新系统套件,用 libsodium 或是 PHP 5.5+ 的 password_ 系列 function 来算 hash
还有,没事就看一大堆讲这种事情的文章....
## 预先算好巨大的对应表(所谓 rainbow table)
就是有人会先算好一大堆字串的 hash,做成查询表方便对照。
所以看到 7c4a8d09ca3762af61e59520943dc26494f8941b 可以直接查出这是 123456 的 sha1
是说,有个网站叫做 CrackStation,线上让你查 hash 对应表..
对应法:
内容加盐或是给 iv,每笔资料的盐或 iv 都要都不一样,而且要够长
这会让对应表很难做
也可以用 PHP 5.5+ 的 password_ 系列算,他预设会随机产盐撒进资料来算 hash
## 用巨大的运算力量暴力硬算
通常是云端出租 GPU,也有靠 ASIC 之类的专门机器。
感谢数位挖矿产业,这方面的技术突飞猛进...
对应法:
选难以平行化运算的,记忆体使用量大的,计算效能差的
然後也许因此不该选 sha256,因为 bitcoin 挖矿就是在算 sha256,有利可图就有专门产业...
bcrypt 是前几年的佼佼者,而 argon2 是最近几年的国际 hash 比赛冠军。
PHP 预设的密码 hash PASSWORD_DEFAULT 应该还是 bcrypt
有找到 PHP 的 RFC 提到「暂时不把 PASSWORD_DEFAULT 改成 ARGON2」
https://wiki.php.net/rfc/argon2_password_hash
不过理由我一下没找到
然後「最好的 hash 演算法」是会随着时间变化的
: 8. json_encode 跟 json_decode 有什麽潜在问题吗?有没有可能造成 DoS?
其实我直觉想到的是「爬 log 的时候用 json_decode 好慢,我都用 jq 先 parse 过」...
不过我猜你指的是可以恶搞 json 的内容,故意制造一大堆 hash collision,导致 hash table 效率低落。
这解释起来得把 hash table 从头讲一次...简中连结,不过讲得还满清楚的
http://www.cnblogs.com/yangecnu/p/Introduce-Hashtable.html
: 9. 什麽是 XXE?什麽情况可能会出现?
我我我我我很少用 XML 这个麻烦的小东西所以跟他不熟........
: 10. 什麽是 race codition?在 PHP + MySQL 这样的经典组合中有没有可能出现?要如何解决?
雷姆揍我右脸,我会往左边飞
拉姆揍我左脸,我会往右边飞
他们揍我的速度够快,我被揍飞另一个挥拳就会落空
当雷姆跟拉姆几乎同时出拳揍我,我可能往左边飞,也可能往右边飞,难以预测
race condition 就是指这种状况
PHP 本身原则上是单一 Process 在跑的,所以只有 PHP 不太容易碰到
(我知道有 fork 或 pthreads,但是网页上还是尽量别这麽干,跑後端 job 就是另外一件事...)
MySQL 比较常碰到是当 DB 规模大的时候,通常会读写分离到不同台机器上。
如果先做 update 然後又马上 select,有可能 select 不到更新後的资料(还没同步到所有机器
另外一个状况是来自系统外部,例如 client 同时发两个取 token 的 request
然後你不确定 client 会觉得自己取到哪个
race condition 有一些正面解法,例如说设置 lock 确保一次只有一个人通过
不过我的经验是,非硬解不可的状况并不多,比较建议的作法是调整工作流程
例如既然都 update 了表示你有资料,那就别再 select 了
或是跪求 client 不要同时发一样的 request 上来,如果有 re-try 机制要间隔够久
不让拉姆跟雷姆有几乎同时揍我的机会,就不会不知道自己被揍时会飞往何方
: 11. 如何正确取得使用者的 IP?$_SERVER['REMOTE_ADDR']?如果商业逻辑伺服器是放在 LoadBalancer 之後呢?
$_SERVER 里面有很多栏位跟 client IP 有关
REMOTE_ADDR
这是 server 看到当下 request 的来源 IP
HTTP_X_FORWARDED_FOR
HTTP_FORWARDED_FOR
HTTP_CLIENT_IP
这堆(或是其他类似的栏位)则是 http header 里面写的 client IP
如果你的伺服器是放在外面直接让 client 打,那麽 HTTP_ 系列的栏位全部不可信
因为 http header 很容易伪造,人家可以随便乱塞 127.0.0.1 之类的鬼东西
但如果机器放在 Load Balancer 後面,那麽送 request 给你的机器是 LB,REMOTE_ADDR 只会拿到 LB 的 IP
通常 LB 会确保 HTTP_X_FORWARDED_FOR 是原始的 client ip ,外部恶搞这个栏位的时候会也把他洗掉
这部分细节请参照 LB 的说明书
所以如何正确取得使用者 IP,要看你的的服务架构
- 机器直接对外,看 $_SERVER['REMOTE_ADDR']
- 机器在 LB 後面,看 $_SERVER['HTTP_X_FORWARDED_FOR'],或是看你的 LB 要你看哪个(些)栏位
--
顶天立地:爱孩子就要支持萝莉控
https://goo.gl/Zmk62o
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 60.248.122.206
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PHP/M.1528111425.A.0A8.html
※ 编辑: GALINE (60.248.122.206), 06/04/2018 19:38:12
1F:推 Kenqr: 推 06/04 20:38
2F:推 MoMoShota: 推详细好文! 06/04 22:30
3F:推 zx4109: 感谢分享,解释的很仔细! 06/04 23:06
4F:推 Nonsense8: 受小弟一拜 06/05 03:12
5F:推 Nancy010006: race condition那边太好笑了吧xD 06/05 07:05
6F:推 shvanta: 好文 06/05 09:30
7F:推 onininon: 推 06/05 11:56
※ 编辑: GALINE (60.248.122.205), 06/05/2018 15:09:40
8F:推 JohnRoyer: 推拉姆跟雷姆 XD 06/06 12:51
9F:推 ailio: 丢你拉姆 06/06 14:10
10F:推 TFnight: 丢你雷姆 06/06 14:22
11F:推 jimmy010679: 受益良多 06/06 19:34
12F:推 DirtyVegas: 有答案有推 而且够白话 06/07 13:24
13F:推 kevinheyo: 推 06/09 10:38
14F:推 phoenixcx: 跪... 06/25 11:32
15F:推 chocho1981: 推 07/05 16:43
16F:推 agda: 推 07/11 22:10
17F:推 crow1270: 推 10/16 23:01
18F:推 mahou1942: 推 12/02 00:02
19F:推 newhandfun: 真神人也 01/03 23:28
20F:推 OmegaDeath: 猛!! 03/17 19:07
21F:推 nick03008: 推 06/06 19:35