Skip to content

Commit

Permalink
feat(web/grpc): 添加 README、源码、构建文件以及工作流文件 (#5)
Browse files Browse the repository at this point in the history
* docs(web/grpc): 添加 README

* feat(web/grpc): 添加源码及构建文件

* ci(web/grpc): 添加工作流文件
  • Loading branch information
13m0n4de authored Sep 16, 2024
1 parent 4bca173 commit d37b416
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 0 deletions.
50 changes: 50 additions & 0 deletions .github/workflows/web.grpc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
name: Challenge gRPC

on:
push:
branches: ["main"]
paths:
- "!**/README.md"
- "challenges/web/grpc/build/**"
workflow_dispatch:

env:
TYPE: web
NAME: grpc
REGISTRY: ghcr.io

jobs:
challenge-build:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4

- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3

- name: Log in to the Container registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}

- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ github.repository }}/${{ env.NAME }}
tags: |
latest
- name: Build and push Docker image
uses: docker/build-push-action@v4
with:
context: challenges/${{ env.TYPE }}/${{ env.NAME }}/build
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
push: true
16 changes: 16 additions & 0 deletions challenges/web/grpc/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# gRPC

- 作者:13m0n4de
- 参考:-
- 难度:-
- 分类:Web
- 镜像:-
- 端口:-

## 题目描述

<description>

## 题目解析

<analysis>
11 changes: 11 additions & 0 deletions challenges/web/grpc/build/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM python:3.12-alpine

WORKDIR /app

COPY app/ .

RUN pip install --no-cache-dir -r requirements.txt

RUN python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. *.proto

CMD ["python", "server.py"]
16 changes: 16 additions & 0 deletions challenges/web/grpc/build/app/flag.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
syntax = "proto3";

package flagservice;

service FlagService {
rpc GetFlag (FlagRequest) returns (FlagResponse) {}
}

message FlagRequest {
string token = 1;
}

message FlagResponse {
string flag = 1;
}

4 changes: 4 additions & 0 deletions challenges/web/grpc/build/app/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
grpcio==1.66.1
grpcio_reflection==1.66.1
grpcio_tools==1.66.1
protobuf==5.27.2
151 changes: 151 additions & 0 deletions challenges/web/grpc/build/app/server.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,151 @@
import os
import uuid
from concurrent import futures

import grpc
from grpc_reflection.v1alpha import reflection

import user_info_v2_pb2
import user_info_v2_pb2_grpc
import user_info_v1_pb2
import user_info_v1_pb2_grpc
import flag_pb2
import flag_pb2_grpc

FLAG = os.environ.get("GZCTF_FLAG", "SVUCTF{test_flag}")


class UserInfoServiceV2(user_info_v2_pb2_grpc.UserInfoServiceV2Servicer):
def __init__(self, users):
self.users = users

def GetUserInfo(self, request, context):
user = self.users.get(request.user_id)
if user:
response = user_info_v2_pb2.UserInfoResponseV2(
user_id=user["user_id"],
username=user["username"],
email=user["email"],
role=user["role"],
)
context.set_trailing_metadata(
(
(
"note",
"This version has been updated for security reasons and no longer returns sensitive information like auth tokens.",
),
)
)
return response

context.abort(grpc.StatusCode.NOT_FOUND, "User not found")


class UserInfoServiceV1(user_info_v1_pb2_grpc.UserInfoServiceV1Servicer):
def __init__(self, users):
self.users = users

def GetUserInfo(self, request, context):
user = self.users.get(request.user_id)
if user:
return user_info_v1_pb2.UserInfoResponseV1(
user_id=user["user_id"],
username=user["username"],
email=user["email"],
role=user["role"],
auth_token=user["auth_token"],
)

context.abort(grpc.StatusCode.NOT_FOUND, "User not found")


class FlagService(flag_pb2_grpc.FlagServiceServicer):
def __init__(self, users):
self.users = users

def GetFlag(self, request, context):
token = request.token
user = next((u for u in self.users.values() if u["auth_token"] == token), None)

if user and user["role"] == "admin":
return flag_pb2.FlagResponse(flag=FLAG)

context.abort(
grpc.StatusCode.PERMISSION_DENIED,
"Access denied. Invalid token or insufficient permissions.",
)


def serve():
users = {
0: {
"user_id": 0,
"username": "admin",
"email": "admin@company.internal",
"role": "admin",
"auth_token": str(uuid.uuid4()),
},
1: {
"user_id": 1,
"username": "13m0n4de",
"email": "13m0n4de@svuctf.com",
"role": "user",
"auth_token": str(uuid.uuid4()),
},
2: {
"user_id": 2,
"username": "johndoe",
"email": "johndoe@example.com",
"role": "user",
"auth_token": str(uuid.uuid4()),
},
3: {
"user_id": 3,
"username": "alice",
"email": "alice@example.com",
"role": "user",
"auth_token": str(uuid.uuid4()),
},
4: {
"user_id": 4,
"username": "bob",
"email": "bob@example.com",
"role": "user",
"auth_token": str(uuid.uuid4()),
},
5: {
"user_id": 5,
"username": "guest",
"email": "guest@example.com",
"role": "guest",
"auth_token": str(uuid.uuid4()),
},
}

server = grpc.server(futures.ThreadPoolExecutor(max_workers=10))

# Add services to server
user_info_v2_pb2_grpc.add_UserInfoServiceV2Servicer_to_server(
UserInfoServiceV2(users), server
)
user_info_v1_pb2_grpc.add_UserInfoServiceV1Servicer_to_server(
UserInfoServiceV1(users), server
)
flag_pb2_grpc.add_FlagServiceServicer_to_server(FlagService(users), server)

# Only add V2 and FlagService to reflection
service_names = (
user_info_v2_pb2.DESCRIPTOR.services_by_name["UserInfoServiceV2"].full_name,
flag_pb2.DESCRIPTOR.services_by_name["FlagService"].full_name,
reflection.SERVICE_NAME,
)
reflection.enable_server_reflection(service_names, server)

server.add_insecure_port("[::]:50051")
server.start()
print("Server started on port 50051")
server.wait_for_termination()


if __name__ == "__main__":
serve()
19 changes: 19 additions & 0 deletions challenges/web/grpc/build/app/user_info_v1.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
syntax = "proto3";

package userinfo;

service UserInfoServiceV1 {
rpc GetUserInfo (UserRequestV1) returns (UserInfoResponseV1) {}
}

message UserRequestV1 {
int32 user_id = 1;
}

message UserInfoResponseV1 {
int32 user_id = 1;
string username = 2;
string email = 3;
string role = 4;
string auth_token = 5;
}
18 changes: 18 additions & 0 deletions challenges/web/grpc/build/app/user_info_v2.proto
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
syntax = "proto3";

package userinfo;

service UserInfoServiceV2 {
rpc GetUserInfo (UserRequestV2) returns (UserInfoResponseV2) {}
}

message UserRequestV2 {
int32 user_id = 1;
}

message UserInfoResponseV2 {
int32 user_id = 1;
string username = 2;
string email = 3;
string role = 4;
}

0 comments on commit d37b416

Please sign in to comment.