PHP 板


LINE

看板 PHP  RSS
※ 引述《GALINE (天真可爱CQD)》之铭言: 我是原 PO,没想到前几天吃义大利面前的文居然有人这麽详细地回应,甚表感谢。 以下针对一些回应做一下回覆,期待能够抛砖引玉激起更多的高手讨论 <(_ _)> : 想试着来全部回答一下,我本业不是网路安全,所以可能内容会需要被订正... : : 1. 像是 XSS 是什麽?会带来什麽危险?用 htmlentities 跟 htmlspecialchars 这两个函式来防御有什麽差别? : 白话解释 XSS:「别人在你的网站上塞他的 javascript」 : 可能的危害 : - 所有使用者都会看到嘲笑你的对话方块 : - 你的网站被塞别人的广告 : - 别人可以用 javacsript 控制你的使用者做...任何在他在网站上能做的事情 : - 其他很多... : htmlenties 会把「每一个字」都编码成 html entity,htmlspecialchars 只转换 & " ' > < 这五个。 : 在大多数情况下这两者的防御效果差不多,差异在於出来的档案大小会不一样。 : 不过我记得有个 UTF-7 什麽碗糕的的鬼可以打穿 htmlspecialchars,只要 charset 用 utf-8 就没事 : 刚刚一下 Google 找到都是讲 wordpress 烂掉的事情就是了... 这边 G 大应该说反了,用 UTF-7 可以打穿的应该是 htmlentities。 目前主流的 template engine 多采用 htmlspecialchars 作为防御手段。 如 Laravel 的 Blade: https://bit.ly/2HlafbM 或 Symfony 的 Twig: https://bit.ly/2HhILDO XSS 的技术内容我推荐 TDOH 创办人 Hrj 的简报: https://bit.ly/2JfCJWn : : 2. LFI 是什麽?除了被 access 到 /etc/passwd 之外,有没有可能让 source code 泄露? : 白话解释 LFI:「别人可以乱读你的档案」 : a.php?file=aaa.doc => 吐 aaa.doc 的内容给他 : a.php?file=aaa.doc => 把 a.php 的内容(咦,不就自己吗)吐给他 : 我看过比较有趣的搞法是读 .git/ 把整个 repo 拿走,这样还不用暴力硬扫你有哪些档案... LFI 常见於 PHP,但不限於 PHP。 最常见 LFI 出现於 PHP 的四大引入函式 include(_once) 或 require(_once) 它们可能会引入非预期的内容。 如果 allow_url_fopen 的设定有开的话(预设关闭),更可能造成 RCE。 而且也可以引入 php:// 串流,详细可以参见:https://bit.ly/2FN1TNq : : 3. SQL Injection 的原理是?用 PDO 真的可以一劳永逸吗? mysqli_real_escape_string 真的有助於防止 SQL injection 吗? : 组 SQL 字串的时候塞奇怪东西让 SQL 的意思跟你以为的不一样,然後干奇怪的事情 : 例如 : $id = $_POST['id']; // '123or1=1' : $sql = "select * from user where uid where id = {$id}"; : 出来会是 select * from user where uid 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 )模拟的效果够好... mysqli_real_escape_string 其实也不是毫无破绽的。 在 Discuz 某一版中,它会对过长的字串做截断,在截断之前该字串已经先做了一次过滤 造成 mysqli_real_escape_string 过滤後刚好被截断,进而触发 SQL Injection : : 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 我不确定有没有什麽好招可以处理,只能想到黑名单白名单.... 一般来说,在原生 PHP 中处理 URL 下载的话,会使用 curl。 但是 curl 其实不仅支援 HTTP,其实还可以利用 gopher protocal 拿到 reverse shell 如果只要限制用 HTTP/HTTPS 的话,建议用 guzzlehttp 这个套件来处理。 然後用黑名单限制内网 domain。 : : 5. extract 这个函式很好用,但会不会不知不觉间被拿来提权? : extract 把 array 的内容直接拆开变成变数 : 然後有些人会觉得 extract($_GET) 很好用 : 於是别人就可以乱打网址 ?var1=aaa&var2=bbb 来乱改你 code 里面的变数内容,什麽魔法都能变得出来.. : 我觉得啦,这年头还是别这样写... extract 其实还有个风险是:它可以轻易覆盖已宣告变数(预设设定) 它可以覆盖包括但不限於 $_SEVER、$_SESSION 之类的变数。 : : 6. serialize 跟 unserialize 的使用时要注意什麽? : 唔...我原本猜你指的是「unserialize 的东西可能是别人家过料的,然後就可以乱改变数内容」 : 类似 extract 的状况 : 不过为防万一找了一下,发现 PHP 跟 unserialize() 有关的安全漏洞还真不少.... : 我「猜」对 serialize 字串做数位签章(例如 HMAC)验证内容无误,大概还挡得住。 : 不过更好的作法应该会是...不要 unserialize 任何使用者有机会动手脚(不管是网址带入还是 post 进来)的东西。 serialize 跟 unserialize 其实是不限於 PHP 会发生的问题。 像是前阵子 Java Struts 2 的洞很多都是反序列化的问题(当晚很多人不睡觉呢,黑客打站,工程师补洞) unserialize 的问题主要是因为一个 serialized class 在被 unserialize 时,会自动呼叫 __wake 这个魔术方法,就有机会达成 RCE。 所以在 unserialize 时尽量要去验证来源是否完整(HMAC),或是嫌麻烦的话用 json_encode 及 json_decode : : 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[B : 不过理由我一下没找到 : 然後「最好的 hash 演算法」是会随着时间变化的 这边其实已经讲得满详细了,这边多补充一下。 argon2 有针对大量 GPU 破解做防御,如果是个新的专案,不妨试试用 argon2 作为 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 json_encode 及 json_decode 目前使用的是 djb33,它效率很高,但没这麽安全(容易受到 Hash-DoS 攻击)。 目前 PHP Core 社群还没有打算更改为 SipHash,效率也很高,但没有 djb33 这麽高,不过更加安全。 现在为止最好的办法是: 1. 在允许的范围内,用 json 取代 serialize/unserialize 2. 最好可以用一个只有伺服器知道的 key 对 JSON 做 signature 3. 在无法验证来源 JSON 时,应该限制 API Request 的速度 : : 9. 什麽是 XXE?什麽情况可能会出现? : 我我我我我很少用 XML 这个麻烦的小东西所以跟他不熟........ XXE 常出现在跟既有系统介接时可能会发生的情况。 例如 Java 仍有许多系统是以 XML 作为资料交换的媒介。 XXE 其实源自於 XML Spec 下的美丽(?)误会,它可能会造成 RCE。 : : 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 机制要间隔够久 : 不让拉姆跟雷姆有几乎同时揍我的机会,就不会不知道自己被揍时会飞往何方 race condition 也算是个经典议题。 在设计高并发系统或最近很流行的 micro service 时很可能会碰上。 基本上 G 大说的 lock 是个解法,如果有兴趣研究的话可以参考一下计算机组织。 : : 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 要你看哪个(些)栏位 这边其实讲得满详细的,我再补充一项。 因为 HTTP_X_FORWARDED_FOR, HTTP_FORWARDED_FOR 及 HTTP_CLIENT_IP 这三个是可以被窜改的。 所以如果在 Load Balancer 之後,通常来说会设定 trust proxy(symfony),踢除可信赖的 proxy 之後的第一个 IP 就是使用者 IP。 大概是这样罗 _(:3UL)_,因为今天满累的,所以文章写的有点草率。 之後应该会整理成 Medium Post(有空的话),到时再来分享。 --



※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 59.115.34.119
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/PHP/M.1528122524.A.24B.html
1F:推 GALINE: 唔,我记反啦 XDDDD 06/05 01:50
2F:→ MoMoShota: 没事没事,以前我也记反了 06/05 06:58
3F:推 shvanta: 学到新东西 感谢 06/05 09:35
4F:推 TFnight: 推 06/06 14:28
5F:推 DirtyVegas: 推推 06/07 19:29
6F:推 MOONRAKER: 赞 06/08 11:46
7F:推 kasimEnix: 赞 07/02 15:06







like.gif 您可能会有兴趣的文章
icon.png[问题/行为] 猫晚上进房间会不会有憋尿问题
icon.pngRe: [闲聊] 选了错误的女孩成为魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一张
icon.png[心得] EMS高领长版毛衣.墨小楼MC1002
icon.png[分享] 丹龙隔热纸GE55+33+22
icon.png[问题] 清洗洗衣机
icon.png[寻物] 窗台下的空间
icon.png[闲聊] 双极の女神1 木魔爵
icon.png[售车] 新竹 1997 march 1297cc 白色 四门
icon.png[讨论] 能从照片感受到摄影者心情吗
icon.png[狂贺] 贺贺贺贺 贺!岛村卯月!总选举NO.1
icon.png[难过] 羡慕白皮肤的女生
icon.png阅读文章
icon.png[黑特]
icon.png[问题] SBK S1安装於安全帽位置
icon.png[分享] 旧woo100绝版开箱!!
icon.pngRe: [无言] 关於小包卫生纸
icon.png[开箱] E5-2683V3 RX480Strix 快睿C1 简单测试
icon.png[心得] 苍の海贼龙 地狱 执行者16PT
icon.png[售车] 1999年Virage iO 1.8EXi
icon.png[心得] 挑战33 LV10 狮子座pt solo
icon.png[闲聊] 手把手教你不被桶之新手主购教学
icon.png[分享] Civic Type R 量产版官方照无预警流出
icon.png[售车] Golf 4 2.0 银色 自排
icon.png[出售] Graco提篮汽座(有底座)2000元诚可议
icon.png[问题] 请问补牙材质掉了还能再补吗?(台中半年内
icon.png[问题] 44th 单曲 生写竟然都给重复的啊啊!
icon.png[心得] 华南红卡/icash 核卡
icon.png[问题] 拔牙矫正这样正常吗
icon.png[赠送] 老莫高业 初业 102年版
icon.png[情报] 三大行动支付 本季掀战火
icon.png[宝宝] 博客来Amos水蜡笔5/1特价五折
icon.pngRe: [心得] 新鲜人一些面试分享
icon.png[心得] 苍の海贼龙 地狱 麒麟25PT
icon.pngRe: [闲聊] (君の名は。雷慎入) 君名二创漫画翻译
icon.pngRe: [闲聊] OGN中场影片:失踪人口局 (英文字幕)
icon.png[问题] 台湾大哥大4G讯号差
icon.png[出售] [全国]全新千寻侘草LED灯, 水草

请输入看板名称,例如:BabyMother站内搜寻

TOP