赞
踩
打开这道题目的网站,页面如下:
发现它直接把网站的源代码给了出来,接下来对源码进行分析:
highlight_file(__FILE__);
这个函数用于将当前脚本的源代码进行高亮显示,并将其输出到浏览器。__FILE__
是 PHP 预定义常量,表示当前脚本的文件名。
error_reporting(0);
这个函数用于设置 PHP 的错误报告级别。在这里,将错误报告级别设置为 0,意味着禁用错误报告。
/*flag in flag.php*/
这是一串注释,也就是告诉我们目标flag在flag.php这个文件里,那么我们的目标确定,就是想办法读取到flag.php文件的内容。
if (!isset($_POST['abc'])) die('i am abc, post it damn you');
首先涉及到了die函数,经过查询die函数的意思就是输出die()中包含的字符串并结束程序的执行.
isset在php中用来判断变量是否声明,该函数返回布尔类型的值,即true/false。
这是一个条件语句,提到了一个POST参数abc,用于检查是否声明了名为 "abc" 的 POST 参数【即是否对abc进行赋值】。如果不存在,那么输出字符串 "i am abc, post it damn you" 并终止脚本的执行。
if (strpos($_POST['abc'],"http")) die('fxck ur rf1 out of shit');
这是另一个条件语句,用于检查名为 "abc" 的 POST 请求参数中是否包含字符串 "http"。如果包含,那么输出字符串 "fxck ur rf1 out of shit" 并终止脚本的执行。
这里解释一下为什么if(strpos($_POST['abc'],"http"))是检查abc的值【字符串】中是否有字符串“http”:
strpos() 函数用于返回第二个字符串在第一个字符串中第一次出现的位置。如果存在,返回数字,如果没有找到该字符串,则返回false。如果abc的字符串值中有"http" strpos($_POST['abc'],"http")返回的值就会是一个数字,而if(数字)只要数字不是0就等于True,因此这串函数可用于检查abc中是否有http
if (strpos($_POST['abc'],"hello123")) die('i am abc! you fxcking hacker');
这是第三个条件语句,用于检查名为 "abc" 的 POST 请求参数中是否包含字符串 "hello123"。如果包含,那么输出字符串 "i am abc! you fxcking hacker" 并终止脚本的执行。
这里有一个问题搞不清楚:按道理来说如果我们给abc传入的值是hello123,那么strpos("hello123","hello123")等于0,而if(0)的值等于False,是不执行这个语句,可是实际测试这道题时if(strpos($_POST['abc'],
"hello123"))给abc以post方式直接传值hello123却会触发这条语句,不知道为什么
if (file_get_contents($_POST['abc']) != 'hello123' ) die('file get contents! FILE! GET! CONTENTS!');
这是第四个条件语句,用于检查名为 "abc" 的 POST 请求参数所表示的文件内容是否等于字符串 "hello123"。如果不等于,那么输出字符串 "file get contents! FILE! GET! CONTENTS!" 并终止脚本的执行。
这里涉及到了file_get_contents()函数
,
file_get_contents() 函数是用于将文件的内容读入到一个字符串中,即把文件内容按照字符串格式输出。
include($_POST['file']);
这串代码提到了一个新的POST参数file,把file的值所指定的文件中的代码进行执行。
file是由我们自己定义,我们可以通过伪协议里的php://协议直接输出flag.php文件的内容
这里include函数不影响php://协议,也就是说假如我们通过php://格式给file赋值,php://协议会直接在网站上输出源码的内容,而之后include函数能不能成功执行都无所谓(因为file不像abc对值有过滤【4个if条件】,没有类似于die函数对file的值进行过滤)
include()函数包含并执行指定文件,如果include所包含的东西里有php代码,你访问的话,它不会显示出php代码是什么,它会直接把这个php代码给执行了。
然后抓取当前网站的数据包,图片如下:
发现当前网站默认的提交方式是GET方式
为了获取到flag,我们结合上面的题目分析,得出了以下思路:
1.把数据包的提交方式从GET方式改为POST方式
2.对abc进行赋值【绕过条件1】,对值进行一定的修改来绕过条件2,3,4
这里可以用到伪协议的data://协议,比如让abc=data://text/plain;base64,aGVsbG8xMjM=
将hello123进行base64编码后得到aGVsbG8xMjM=,而这里base64,aGVsbG8xMjM=相当于一串命令,是把aGVsbG8xMjM=进行base64解码
strpos函数检测的就是strpos(aGVsbG8xMjM=,“hello123”),绕过条件3;
而file_get_contents($_POST['abc'])又等于hello123
以上有不理解的部分可以看附件一,里面是chatgpt的解释
3.对file赋值为php://filter/convert.base64-encode/resource=flag.php,通过伪协议读取flag.php
php://filter/convert.base64-encode/resource=文件名 是标准读取文件源码的格式
上面是对php://filter 读取源代码并进行base64编码输出,如果直接引用php://filter会直接当做php代码执行就看不到源代码内容了。
1.首先打开网站,通过burpsuite进行抓包,图片如下:
2. 然后通过burpsuite自带功能改变提交方式为post:
右击-Change request method
图片如下:
3. 改变后结果如下:
4. 对file和abc进行赋值: abc=data://text/plain;base64,aGVsbG8xMjM=&file=php://filter/convert.base64-encode/resource=flag.php
注意区分请求头和请求体:post方式提交参数需要在请求体进行赋值,区分请求头与请求体的方式是加一行回车
图片如下:
5. 提交数据包,成功读取到经过base64编码加密后的flag.php中的文件内容flag
照片如下:
6. 对这串flag进行base64解码,解码结果如下
<?php
$flag = "flag{pHp_f1lter_123s_d4ngr0us}";
7.得到flag:
flag{pHp_f1lter_123s_d4ngr0us}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。