[{"data":1,"prerenderedAt":422},["ShallowReactive",2],{"content:\u002F2026\u002Fphp":3,"surround:\u002F2026\u002Fphp":411},{"id":4,"title":5,"body":6,"categories":378,"date":380,"description":381,"draft":382,"extension":383,"image":384,"meta":385,"navigation":387,"path":388,"permalink":389,"published":389,"readingTime":390,"recommend":389,"references":389,"seo":395,"sitemap":396,"stem":405,"tags":406,"type":408,"updated":409,"__hash__":410},"content\u002Fposts\u002F2026\u002Fphp.md","php伪协议+base64过滤",{"type":7,"value":8,"toc":366},"minimark",[9,12,17,21,32,39,42,52,88,94,264,270,273,279,282,289,293,296,302,306],[10,11],"hr",{},[13,14,16],"h2",{"id":15},"php伪协议base64绕过","php伪协议+base64绕过",[18,19,20],"h3",{"id":20},"php",[22,23,24,25],"p",{},"题目：[",[26,27,31],"a",{"href":28,"rel":29},"https:\u002F\u002Fwww.nssctf.cn\u002Fproblem\u002F2640",[30],"nofollow","SWPUCTF 2022 新生赛]ez_ez_php - CTF 题目 - NSSCTF",[22,33,34],{},[35,36],"img",{"alt":37,"src":38},"Snipaste_2026-10-19_20-42-15","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_20-42-15.png",[22,40,41],{},"拿到这种有php代码的题目，先读代码",[43,44,49],"pre",{"className":45,"code":47,"language":20,"meta":48},[46],"language-php","\u003C?php\nerror_reporting(0);                    \u002F\u002F 关闭所有报错,即使出错页面也不显示错误信息\nif (isset($_GET['file'])) {            \u002F\u002F URL 里传了 file 参数吗?(有没有 ?file=xxx)\n    if ( substr($_GET[\"file\"], 0, 3) === \"php\" ) {   \u002F\u002F 取 file 值的前 3 个字符,和 \"php\" 全等比较\n        echo \"Nice!!!\";                \u002F\u002F 成立 → 打印 Nice!!!\n        include($_GET[\"file\"]);        \u002F\u002F 把 file 的值当作文件名\u002F协议,包含进来\n    } else {\n        echo \"Hacker!!\";               \u002F\u002F 传了 file,但前 3 位不是 \"php\" → 拒绝\n    }\n} else {\n    highlight_file(__FILE__);          \u002F\u002F 完全没传 file 参数 → 显示本页源码(就是你看到的题目页)\n}\n","",[50,51,47],"code",{"__ignoreMap":48},[53,54,55,69,82],"ul",{},[56,57,58,59,62,66,68],"li",{},"第一眼先看到下边有非常显眼的\u002F\u002Fflag.php,先试一下呢",[60,61],"br",{},[35,63],{"alt":64,"src":65},"Snipaste_2026-10-19_21-11-37","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_21-11-37.png",[60,67],{},"题目提示了，这样拿不到flag,并且提示了php伪协议",[56,70,71,72,74,77,78,81],{},"那就仔细看代码所以，整体就是，URL里传的file有值->substr函数，它的作用就是提取字符，substr(要提取的字符串，从哪里开始提取，提取多少个)，",[60,73],{},[50,75,76],{"code":76},"( substr($_GET[\"file\"], 0, 3)","在这里的意思就是，提取file的值，并且是从第0位开始，提取三个字符。—>",[50,79,80],{"code":80},"===","是强等于，在php语法中，===不仅会比较两边的数据，还会比较数据类型，满足则echo，echo是打出的意思，打出Nice->include()的作用就是把传入的file得到的东西包含。大致就是这样",[56,83,84,85],{},"根据代码那我们就传file=php给它 ",[50,86,87],{"code":87},"[node4.anna.nssctf.cn:28133\u002F?file=php",[22,89,90],{},[35,91],{"alt":92,"src":93},"Snipaste_2026-10-19_21-09-13","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_21-09-13.png",[53,95,96,254,261],{},[56,97,98,99,234,236,237,239,241,245,247,248,250],{},"界面只有一个Nice,也没有flag啊？熟悉的就知道这里要用伪协议绕过，不熟悉的话就证实了前边的提示，也能想到伪协议",[53,100,101,125,128],{},[56,102,103,104,108,109,111,112,116,117,120,121,124],{},"为什么明明代码里有include(GET",[105,106,107],"span",{},"file","),但是界面啥也没有，为什么？",[60,110],{},"PHP 最初就是个模板语言。PHP 解析器读任何文件时，默认",[113,114,115],"strong",{},"逐字符当作普通文本原样输出","，只有遇到 ",[50,118,119],{"code":119},"\u003C?php"," 这个起始标签，才切换到“代码模式”，把标签里的内容当代码执行，直到 ",[50,122,123],{"code":123},"?>"," 或文件结尾再切回文本模式。",[56,126,127],{},"include（）只是包含，include(GET(file))，？file=php\u002Fresource=flag.php,这样include切换到代码模式，\u003C?php这个起始标签依旧存在，就只会把flag.php的文件包含进来，但是包含不等于输出，所以我们看不到flag,",[56,129,130,131,134,135,137,140,142,147,155,157,158,166],{},"怎么样才能让它没有",[50,132,133],{"code":133},"\u003C？php","这个起始标签，打印出flag呢？",[60,136],{},[113,138,139],{},"伪协议+base64过滤器",[60,141],{},[113,143,144],{},[50,145,146],{"code":146},"?file=php:\u002F\u002Ffilter\u002Fread=convert.base64-encode\u002Fresource=flag.php",[53,148,149],{},[56,150,151,152],{},"根据代码===需要强等于php,这里其实已经给出了白名单，所以伪协议就用",[50,153,154],{"code":154},"？file=php:\u002F\u002Ffilter...",[60,156],{},"substr()怎么取字符的？",[43,159,164],{"className":160,"code":162,"language":163},[161],"language-text","p  h  p  :  \u002F  \u002F  f  i  l  t  e  r  \u002F  ...  r  e  s  o  u  r  c  e  =  f  l  a  g  .  p  h  p\n    0  1  2  3  4  5  6  7  8  ...                              49 50 51 52 ...\n    └─┬─┘                                                              └─┬─┘\n    substr 取的是这里 → \"php\"                                      \"fla\" 在下标 49\n","text",[50,165,162],{"__ignoreMap":48},[53,167,168,214],{},[56,169,170,173,174,176,179,181,182,184,185,188,189,192,193,196,197,199,200,206,207,210,211],{},[50,171,172],{"code":172},"read=convert.base64-encode","是base64编码，为什么要这么写？不加过滤器会怎样？",[60,175],{},[50,177,178],{"code":178},"?file=php:\u002F\u002Ffilter\u002Fresource=flag.php",[60,180],{},"这样写等于“原样读出文件内容再 include”——内容里 ",[50,183,119],{"code":119}," 标签完好无损，PHP 照样把它当",[113,186,187],{},"代码执行","：执行一次 ",[50,190,191],{"code":191},"$flag = \"flag{xxx}\""," 的赋值，没有任何 echo，页面除了 ",[50,194,195],{"code":195},"Nice!!!"," 什么都不显示。转了一圈回到原点。",[60,198],{},"所以过滤器的作用只有一个：",[113,201,202,203,205],{},"把 ",[50,204,119],{"code":119}," 这几个字符破坏掉","，让 PHP 解析器认不出“这是代码开始”，从而include()就不会只包含不打出flag了。凡是能做到这一点的变换都可以，base64 不是唯一的。还有",[113,208,209],{},"rot13 过滤器"," ",[113,212,213],{},"iconv 编码转换过滤器",[56,215,216,217,219,222,223,226,227,230,231],{},"resource=flag.php",[60,218],{},[50,220,221],{"code":221},"resource="," 是 php:\u002F\u002Ffilter ",[113,224,225],{},"语法里的固定关键字","，",[50,228,229],{"code":229},"flag.php"," 是",[113,232,233],{},"我们自己选的目标文件",[60,235],{},"输入",[50,238,146],{"code":146},[60,240],{},[35,242],{"alt":243,"src":244},"Snipaste_2026-10-19_21-48-00","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_21-48-00.png",[60,246],{},"得到base64编码过的flag,找个解码工具解码就好了",[60,249],{},[35,251],{"alt":252,"src":253},"Snipaste_2026-10-19_21-50-34","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_21-50-34.png",[56,255,256,257,260],{},"代码显示，flag不在这里，",[50,258,259],{"code":259},"real_flag_is_in_'flag'","真正的flag在flag文件下",[56,262,263],{},"改为**?file=php:\u002F\u002Ffilter\u002Fread=convert.base64-encode\u002Fresource=flag**",[22,265,266],{},[35,267],{"alt":268,"src":269},"Snipaste_2026-10-19_21-52-29","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_21-52-29.png",[22,271,272],{},"依旧解码",[22,274,275],{},[35,276],{"alt":277,"src":278},"Snipaste_2026-10-19_21-56-07","https:\u002F\u002Fzelia-avatar-1471520438.cos.ap-guangzhou.myqcloud.com\u002Fblog\u002Fimages\u002FSnipaste_2026-10-19_21-56-07.png",[18,280,281],{"id":281},"更快的解法",[22,283,284,285,288],{},"其实，我在解题的时候漏了，第二张图片的第二行，不然在输入伪协议的时候就可以直接输入**",[50,286,287],{"code":287},"?file=php:\u002F\u002Ffilter\u002Fread=convert.base64-encode\u002Fresource=flag","**就不用，二次解码了",[13,290,292],{"id":291},"拿到flag啦","🎉拿到flag啦！！！",[13,294,295],{"id":295},"梳理流程",[43,297,300],{"className":298,"code":299,"language":163},[161],"① 服务器收到参数字符串 \"php:\u002F\u002Ffilter\u002F...\u002Fresource=flag.php\"\n      ↓  (此刻还没打开任何文件)\n② substr 取下标 0~2 = \"php\" → === \"php\" 成立 → 放行     ← 检测在这里就结束了\n      ↓\n③ include 开始工作 → 认出 php:\u002F\u002Ffilter 协议 → 打开 flag.php\n      ↓\n④ 对 flag.php 的【文件内容】做 base64 编码               ← base64 在这里才登场\n      ↓\n⑤ 编码结果没有 \u003C?php 标签 → 当纯文本输出\n",[50,301,299],{"__ignoreMap":48},[13,303,305],{"id":304},"踩过的坑别学我啊","踩过的坑（别学我啊。。。）",[307,308,309,319,331,337,347,363],"ol",{},[56,310,311,314,315,318],{},[113,312,313],{},"大小写搞反"," —— 黑白名单看反了，白名单题传大写，页面回 ",[50,316,317],{"code":317},"Hacker!!"," 还以为是文件名错",[56,320,321,326,327,330],{},[113,322,323,325],{},[50,324,221],{"code":221}," 漏写"," —— 流不知道读谁，包含失败；又碰上 ",[50,328,329],{"code":329},"error_reporting(0)"," 吞报错，页面空白以为题坏了",[56,332,333,336],{},[113,334,335],{},"页面空白就放弃"," —— 空白可能是：文件名猜错 \u002F resource 少写 \u002F 关键字被 ban。逐个排查而不是换题",[56,338,339,342,343,346],{},[113,340,341],{},"把输出的 base64 直接当 flag 提交"," —— 还要解码一步，解码后的",[113,344,345],{},"源码里","才是 flag",[56,348,349,355,356,358,359,362],{},[113,350,351,354],{},[50,352,353],{"code":353},"read="," 忘写以为错了"," —— 其实 ",[50,357,353],{"code":353}," 可以省略，",[50,360,361],{"code":361},"php:\u002F\u002Ffilter\u002Fconvert.base64-encode\u002Fresource=flag.php"," 等价",[56,364,365],{},"漏了一行提示。。。。",{"title":48,"searchDepth":367,"depth":367,"links":368},4,[369,375,376,377],{"id":15,"depth":370,"text":16,"children":371},2,[372,374],{"id":20,"depth":373,"text":20},3,{"id":281,"depth":373,"text":281},{"id":291,"depth":370,"text":292},{"id":295,"depth":370,"text":295},{"id":304,"depth":370,"text":305},[379],"web","2026-10-19 22:03:29","web-php",false,"md","\u002Fimages\u002Fphp\u002F微信图片_20261019202225_15_6.jpg",{"slots":386},{},true,"\u002F2026\u002Fphp",null,{"text":391,"minutes":392,"time":393,"words":394},"7 min read",6.265,375900,1253,{"title":5,"description":381},{"loc":388,"images":397},[398,399,400,401,402,403,404],{"loc":38},{"loc":65},{"loc":93},{"loc":244},{"loc":253},{"loc":269},{"loc":278},"posts\u002F2026\u002Fphp",[407,20],"Web安全","tech","2026-10-18 23:40:00","uFXOEXJf2HCqGaMJA4MbExfA2ibBSm9p_1C-sM-3kiU",[412,417],{"title":413,"path":414,"stem":415,"date":416,"type":408,"children":-1},"Web基础","\u002F2026\u002Fweb-html","posts\u002F2026\u002FWeb-HTML","2026-10-19 13:44:25",{"title":418,"path":419,"stem":420,"date":421,"type":408,"children":-1},"ctfshow-web-信息搜集","\u002F2026\u002Fctfshow-web","posts\u002F2026\u002Fctfshow-web","2026-10-20 23:09:00",1793524344822]