任意文件读取你会吗?老网工的私房笔记,看完直呼真香!
哎,兄弟们,干了这么多年网络安全,要是有人突然问我:“任意文件读取你会吗?”——我第一反应绝对是一愣,然后嘴角上扬,心里默念:这问题,问得也太戳心窝子了吧!哈哈,不是吹牛,这玩意儿简直是Web安全领域的“万金油”,你懂我意思吧?今天咱们就坐下来,泡杯茶,好好唠唠这个让人又爱又恨的任意文件读取漏洞,说句掏心窝的话,你要是真把它整明白了,很多看似固若金汤的系统,在你眼里那真是跟透明玻璃房似的,一眼望穿!

啥是“任意”啊?总不能乱来吧?
先别急,咱们得掰扯清楚这个概念,很多新手朋友第一次听到“任意文件读取”,眼睛一亮:这岂不是意味着我能把服务器上的密码本、源码包全都拖回家当枕头?嘿嘿,理论上是这样,但现实总是带点骨感,哈,所谓的“任意”,指的是攻击者能够通过可控的参数,去读取服务器上任意路径、任意权限允许的文件内容,注意啊,我没说“任意权限”,你要非去读 /etc/shadow(Linux密码文件),那大概率是吃闭门羹,除非那服务器管理员喝多了,哈哈,但咱得说,只要能读到配置、源码、日志,这漏洞的价值已经够你喝一壶的了。
你比如说吧,最常见的场景是啥?就是那种老掉牙的下载功能,你看那个URL(网页地址):
https://example.com/download.php?file=report.pdf
哎,是不是很眼熟?正常的话,这代码应该是去服务器上拿 report.pdf 给你下载,但如果你把 report.pdf 改成 ../../../../etc/passwd 呢?这就像你拿着万能钥匙,在人家后门那儿瞎捅咕,服务器那边如果没做好过滤,就会乖乖地把 /etc/passwd 文件内容吐出来给你看。哎呀妈呀,那一刻的感觉,真是比夏天喝冰可乐还爽,对不对?
兄弟我得提醒你,真正的“任意”不是瞎猜路径,而是懂逻辑! 你得知道你在读什么,比如读到了 config.php,里面可能躺着数据库账号密码;读到了 nginx.conf(反向代理配置文件),你能摸清整个内网的路由拓扑;甚至你还能通过读取 /proc/self/environ(进程环境变量)来拿到一些临时会话标识,这可就高级了,直接往代码执行那条路上拐了,是不是想想就流口水?
光会读没用,你得会“演”!
这“任意文件读取你会吗”的灵魂,不仅仅在于“读”,更在于“利用”,哎,这话说到点子上了,你费劲心思读出来一堆乱码,那不是白忙活?所以啊,咱们得学会“见人下菜碟”。
啥意思?就是说,如果目标是PHP(一种编程语言)写的,那你就得琢磨琢磨,能不能通过 php://filter 这个协议(流过滤器),去把源码给读出来,这招儿简直绝了!比如你把请求改成:
https://example.com/download.php?file=php://filter/convert.base64-encode/resource=../../../../etc/passwd
这样一来,服务器会把文件内容转成base64(一种编码格式)输出来,你拿到那串字符,找个在线解码工具一解,哎哟喂,那源代码不就赤裸裸地躺在你面前了吗?那种剥开层层迷雾看到真相的成就感,没有经历过的人真体会不到,真的,朋友们,那种感觉,就像是你在玩密室逃脱,突然找到了一把钥匙,打开了最深处那个保险柜,心里那个扑通扑通跳啊!
再者说了,如果对方是Java应用,那头就得更大了,你不仅能读文件,还能配合反序列化(一种数据还原机制)搞出更大的动静,但咱们今天说的是“读”,那就得说说读了干嘛用,我之前碰到过一目标,拿shell(终端环境)没权限,只能读文件,我就把服务器上的 .bash_history(命令历史记录)给读出来了,好家伙,那里面记着管理员敲过的所有的命令,包括他后来手动改的数据库备份路径!你说这叫什么?这叫顺势而为,雁过拔毛! 看着那些历史命令,我仿佛能感受到那哥们在键盘上敲击的节奏感,太有代入感了。
防御?别光看热闹,咱也得会“守”
既然咱们聊得这么起劲,你要真说“任意文件读取你会吗”只是用来搞破坏,那就太低级了。咱得懂攻防兼备,对不对?作为防守方,我真心建议大家别只在URL(网页地址)上做过滤,那种黑名单策略(就是禁掉一些关键词,如“../”)早就落伍了。
记住咯,最稳妥的防守思路是“白名单”!就是说,你只允许下载指定目录下的、指定格式的文件,你要是想用编码绕过,..%2f 或者 ,在我这白名单机制面前,那都是徒劳,因为压根就不认你这个路径,哎呀,每次看别人穿透层层WAF(防火墙)拿文件,我都觉得刺激,但轮到自己写代码,那真是宁可错杀一千,也不放过一个,哈哈。这种“顽固派”的防守,有时候真能逼疯一群攻击者,你说是不是挺搞笑的?
所以啊,大家伙儿,“任意文件读取”这个课题,真不是背两个Payload(攻击载荷)就完事儿了的,它考验的是你对系统架构、编程语言特性、业务逻辑的综合理解,读到了不该读的,得知道怎么收场;读不到想要的,也得能推断出下一步往哪儿走。
我现在每次看代码审计,看到那些 file_get_contents 这类函数(用于读取文件内容的函数)时,心里的弦都会绷得紧紧的,怎么说呢,这技术就像一把文玩核桃,你得放手里慢慢盘,盘出包浆了,那才叫真本事,哈哈,好了,今儿就聊到这儿,不知道我这份儿“掏心窝子”的经验,诸位听进去几分?下次再有人问你会不会任意文件读取,希望能对答如流,顺便还能反问他一句:“你先说说,你想读啥?我帮你看看路径写得对不对!” ——那咱们这文章,才算真没白写,哈哈!