diff --git a/README.md b/README.md index 6e45a80..978d144 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ 如果你仅仅想测试一下,可以使用 [dynamic_flag/cert.pem](dynamic_flag/cert.pem) 自带的证书,以及这个 Token: -`1:MEUCIQCjK1QcPFro86w3bKPb5zUZZd96ocp3EZDFcwLtJxNNDAIgEPk3Orw0mE+zHLQA7e31kSFupNtG9uepz2H4EqxlKWY=` +`1:MEUCIQC24dB6B24/LDr2O+4cifbzOEFDbkXg3hJIqTXuuvpa1QIgbzMM/F0uUmYIudtM6qEDvOpEHbtTZjSjTWMcA5zhnos=` 在生产环境中,请使用自己生成的证书,方法如下: diff --git a/dynamic_flag/cert.pem b/dynamic_flag/cert.pem index 2a5b34c..b95518c 100644 --- a/dynamic_flag/cert.pem +++ b/dynamic_flag/cert.pem @@ -1,12 +1,12 @@ -----BEGIN CERTIFICATE----- -MIIByjCCAXCgAwIBAgIUTVIbMFuhApks+IlLfPLsIV0rw9cwCgYIKoZIzj0EAwIw -PDELMAkGA1UEBhMCQVUxCjAIBgNVBAgMAScxITAfBgNVBAoMGEludGVybmV0IFdp -ZGdpdHMgUHR5IEx0ZDAeFw0yMTA0MTgxNjU4MzRaFw0yMjA0MTgxNjU4MzRaMDwx -CzAJBgNVBAYTAkFVMQowCAYDVQQIDAEnMSEwHwYDVQQKDBhJbnRlcm5ldCBXaWRn -aXRzIFB0eSBMdGQwVjAQBgcqhkjOPQIBBgUrgQQACgNCAAREnpLsdtmenQf0Iw2Z -5xLOgDYa9VpLU3C1Gxm9TpJi4eAaX8kPpYVkD1rsjE9SOt6/GLnYRTytrlJOGQ/X -nL5Ao1MwUTAdBgNVHQ4EFgQU3BPqL8FbENPzF1rj00aMFzyXXjAwHwYDVR0jBBgw -FoAU3BPqL8FbENPzF1rj00aMFzyXXjAwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjO -PQQDAgNIADBFAiAT/QceAhSZRkiqLh6Udhey2etTr7L08b+G6k2r8HSfswIhAM7Y -TEh3QVp8F5UvzO5g/OtTb0/gS41kvY8OU8AbMI8T +MIIBkTCCATagAwIBAgIUepo+QZi+PQYvqF7ibrFvzz+6IMIwCgYIKoZIzj0EAwIw +HzEdMBsGA1UEAwwUaGFjay5sdWcudXN0Yy5lZHUuY24wHhcNMjIxMDA5MDc0MjUz +WhcNMjIxMTA5MDc0MjUzWjAfMR0wGwYDVQQDDBRoYWNrLmx1Zy51c3RjLmVkdS5j +bjBWMBAGByqGSM49AgEGBSuBBAAKA0IABBfmy8v7pQSGDctgKId1KMpi48hsl1xh +vapAWou6IS6aRwnvE/3Wiy0YfoHEb5xDg/6ExzEbpTeI8Sti9Pw/limjUzBRMB0G +A1UdDgQWBBTifpWQDyGynMhPeRKJQRP1CRYowDAfBgNVHSMEGDAWgBTifpWQDyGy +nMhPeRKJQRP1CRYowDAPBgNVHRMBAf8EBTADAQH/MAoGCCqGSM49BAMCA0kAMEYC +IQCaaTc9FygGgKGbYrTQDV63hj+2ervSlVMlC07M3QeabAIhAJbdPHmQbOBfNHRw +QhYVMt7PEMnspRB2/fUdHfe2H5FM -----END CERTIFICATE----- + diff --git a/dynamic_flag/docker-compose.yml b/dynamic_flag/docker-compose.yml index 890d4b6..69d8c99 100644 --- a/dynamic_flag/docker-compose.yml +++ b/dynamic_flag/docker-compose.yml @@ -19,4 +19,7 @@ services: - hackergame_flag_rule=${flag_rule} - hackergame_challenge_docker_name=${challenge_docker_name} - hackergame_read_only=${read_only} + - hackergame_flag_suid=${flag_suid} + - hackergame_challenge_network=${challenge_network} + - hackergame_shm_exec=${shm_exec} - TZ=Asia/Shanghai diff --git a/dynamic_flag/front.py b/dynamic_flag/front.py index ed681d3..04fd7e6 100644 --- a/dynamic_flag/front.py +++ b/dynamic_flag/front.py @@ -25,10 +25,24 @@ challenge_docker_name = os.environ["hackergame_challenge_docker_name"] read_only = 0 if os.environ.get("hackergame_read_only") == "0" else 1 +# flag_suid sets whether set stricter permission requirements (0400 instead of 0444) to corresponding flag file +flag_suid = os.environ.get("hackergame_flag_suid", "").split(",") +# challenge_network sets whether the challenge container can access other networks. Default = no access +challenge_network = os.environ.get("hackergame_challenge_network", "") +# shm_exec sets /dev/shm no longer be noexec. Default = keep noexec +shm_exec = 1 if os.environ.get("hackergame_shm_exec") == "1" else 0 + + with open("cert.pem") as f: cert = OpenSSL.crypto.load_certificate(OpenSSL.crypto.FILETYPE_PEM, f.read()) +class Flag: + def __init__(self, flag, suid): + self.flag = flag + self.suid = suid + + def validate(token): try: id, sig = token.split(":", 1) @@ -96,9 +110,15 @@ def f(s, method=method): if flag_path: flag = eval(flag_rule, functions, {"token": token}) if isinstance(flag, tuple): - return dict(zip(flag_path.split(","), flag)) + res = dict(zip(flag_path.split(","), flag)) else: - return {flag_path: flag} + res = {flag_path: flag} + for path in res: + if path in flag_suid: + res[path] = Flag(flag=res[path], suid=True) + else: + res[path] = Flag(flag=res[path], suid=False) + return res else: return {} @@ -107,9 +127,12 @@ def generate_flag_files(flags): flag_files = {} for flag_path, flag in flags.items(): with tempfile.NamedTemporaryFile("w", delete=False, dir=tmp_flag_path) as f: - f.write(flag + "\n") + f.write(flag.flag + "\n") fn = f.name - os.chmod(fn, 0o444) + if flag.suid: + os.chmod(fn, 0o400) + else: + os.chmod(fn, 0o444) flag_files[flag_path] = fn return flag_files @@ -139,14 +162,19 @@ def check_docker_image_exists(docker_image_name): def create_docker(flag_files, id): + network = "none" + if challenge_network: + network = challenge_network.split()[0] cmd = ( - f"docker create --init --rm -i --network none " + f"docker create --init --rm -i --network {network} " f"--pids-limit {pids_limit} -m {mem_limit} --memory-swap -1 --cpus 1 " f"-e hackergame_token=$hackergame_token " ) if read_only: cmd += "--read-only " + if shm_exec: + cmd += "--tmpfs /dev/shm:exec " # new version docker-compose uses "-" instead of "_" in the image name, so we try both challenge_docker_name_checked = challenge_docker_name diff --git a/example/example.py b/example/example.py index 5ee09bf..4ec6dee 100644 --- a/example/example.py +++ b/example/example.py @@ -4,3 +4,4 @@ print(open("flag2").read()) else: print("Wrong!") + diff --git a/web_netcat/Dockerfile b/web_netcat/Dockerfile index 65f83e0..7249b1c 100644 --- a/web_netcat/Dockerfile +++ b/web_netcat/Dockerfile @@ -1,6 +1,6 @@ -FROM node:latest +FROM node:lts-bullseye RUN apt update && apt -y upgrade && \ - apt install -y netcat && \ + apt install -y netcat-traditional && \ rm -rf /var/lib/apt/lists/* WORKDIR /srv COPY package-lock.json package.json ./ diff --git a/web_netcat/package.json b/web_netcat/package.json index 3c43c04..4fbe4b6 100644 --- a/web_netcat/package.json +++ b/web_netcat/package.json @@ -1,12 +1,12 @@ { "dependencies": { - "@types/node": "^16.10.3", - "express": "^4.17.1", + "@types/node": "^18.11.2", + "express": "^4.18.2", "express-ws": "^5.0.2", "node-pty": "^0.10.1", - "typescript": "^4.4.3", - "xterm": "^4.14.1", - "xterm-addon-attach": "^0.6.0", - "xterm-addon-fit": "^0.5.0" + "typescript": "^4.8.4", + "xterm": "^5.0.0", + "xterm-addon-attach": "^0.7.0", + "xterm-addon-fit": "^0.6.0" } }