File size: 7,490 Bytes
8c5da4b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
import gradio as gr
from llama_cpp import Llama
from huggingface_hub import hf_hub_download
import os

# ==========================================
# Set this to YOUR model repo on Hugging Face
# Format: "YourUsername/your-model-repo-name"
# This should be the SEPARATE MODEL repo where you uploaded model-q5_k_m.gguf
# NOT the Space repo itself.
# Example: "Niranjan/SENTINEL-Llama3-GGUF"
# ==========================================
HF_REPO_ID = "niranjan2777/SENTINEL-q5_k_m-GGUF"
MODEL_FILENAME = "model-q5_k_m.gguf"

print("Downloading model from Hugging Face... this will take a few minutes the first time.")
try:
    # This downloads the file to the Space's local cache so it fits in the ephemeral disk
    # and bypasses the 1 GB git repository limit!
    MODEL_PATH = hf_hub_download(repo_id=HF_REPO_ID, filename=MODEL_FILENAME)
    print("Download complete. Loading model...")
    
    llm = Llama(
        model_path=MODEL_PATH,
        n_ctx=2048,
        n_threads=4,       # Adjust based on CPU cores available in HF Space
        n_gpu_layers=0     # Standard free HF Space is CPU-only
    )
except Exception as e:
    llm = None
    print(f"Error downloading or loading model: {e}")
    print(f"Make sure you created a MODEL repo, uploaded the .gguf there, and changed HF_REPO_ID in this script.")

SENTINEL_SYSTEM_PROMPT = """You are SENTINEL, an autonomous web-exploitation agent. Given an HTML snippet and a goal (and optionally prior agent turns), you reason about vulnerabilities and emit a single JSON action that advances the exploit loop:

observe -> identify attack surface -> select exploit -> generate payload -> interpret response -> adapt and retry -> detect success -> STOP

Prioritize vulnerability sinks: form action, input value, src, href, hidden fields, query parameters, JSON body fields, and reflected DOM contexts. Infer the backend from HTML evidence (.php, .aspx, __VIEWSTATE, .jsp, /rest/, <app-*>, wp-content, etc.) and choose context-appropriate payloads.

Output a single JSON object with exactly these keys:
- Thought: <=4 sentences, <=80 words; cite the specific sink, backend inference, injection context, and payload-class justification (or signal classification for ANALYZE_RESPONSE / success indicator for STOP).
- Action: one of SQL_INJECT | XSS_INJECT | RETRY_MUTATED | ANALYZE_RESPONSE | CRAWL_DEEPER | WAIT | STOP.
- Action_Input: object with target_url, method, parameters, headers, rationale, plus action-specific fields (mutation_class for RETRY_MUTATED; signal + next_recommended for ANALYZE_RESPONSE; success_state + evidence for STOP).

Output ONLY the JSON. No prose, no markdown fences, no commentary."""

def generate_action(goal, html_snippet):
    if not llm:
        return "Error: Model file not found. Ensure model-q5_k_m.gguf is uploaded to the Space."

    # Construct the user prompt to match the fine-tuning format
    user_prompt = f"GOAL: {goal}\n\nHTML_SNIPPET:\n{html_snippet}"

    # Llama-3 ChatML format
    prompt = f"<|begin_of_text|><|start_header_id|>system<|end_header_id|>\n\n{SENTINEL_SYSTEM_PROMPT}<|eot_id|><|start_header_id|>user<|end_header_id|>\n\n{user_prompt}<|eot_id|><|start_header_id|>assistant<|end_header_id|>\n\n"

    try:
        response = llm(
            prompt,
            max_tokens=256,
            temperature=0.0,
            stop=["<|eot_id|>", "<|end_of_text|>"],
            echo=False
        )
        return response["choices"][0]["text"].strip()
    except Exception as e:
        return f"Inference Error: {str(e)}"

# Define the Gradio Interface
with gr.Blocks(title="SENTINEL Autonomous Pentesting Agent", theme=gr.themes.Soft()) as app:
    gr.Markdown("# 🛡️ SENTINEL Autonomous Pentesting Agent")
    gr.Markdown("""
    **SENTINEL** is a fine-tuned Llama-3-8B model trained to autonomously navigate, analyze, and exploit web vulnerabilities.
    
    ### How to use this demo:
    1. Provide a pentesting **Goal** (e.g., `AUTHENTICATED`, `XSS_VULNERABILITY`).
    2. Paste an **HTML Snippet** (the DOM of the page the agent is currently looking at).
    3. Click **Analyze & Generate Action** to see the agent's internal thought process and the exact JSON payload it decides to execute.
    
    *Try clicking one of the examples below to load it automatically!*
    """)
    
    with gr.Row():
        with gr.Column(scale=1):
            goal_input = gr.Textbox(label="Goal", value="AUTHENTICATED", lines=1)
            html_input = gr.Code(label="HTML Snippet (DOM)", language="html", lines=15, 
                                 value='<form action="/login" method="POST">\n  <input type="text" name="username">\n  <input type="password" name="password">\n  <button type="submit">Login</button>\n</form>')
            submit_btn = gr.Button("🚀 Analyze & Generate Action", variant="primary")
            
        with gr.Column(scale=1):
            output_json = gr.Code(label="SENTINEL Output (JSON)", language="json", lines=20)
            
    submit_btn.click(
        fn=generate_action,
        inputs=[goal_input, html_input],
        outputs=output_json
    )
    
    gr.Markdown("### 📚 Example Scenarios")
    gr.Examples(
        examples=[
            [
                "AUTHENTICATED",
                """<div class="login-container">
  <h2>Admin Login</h2>
  <form action="/rest/user/login" method="POST" id="loginForm">
    <label for="email">Email Address:</label>
    <input type="email" id="email" name="email" required>
    
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required>
    
    <button type="submit" id="loginButton">Log In</button>
  </form>
</div>"""
            ],
            [
                "XSS_VULNERABILITY",
                """<div class="header">
  <form action="/search" method="GET">
    <input type="text" name="q" placeholder="Search products...">
    <button type="submit">Search</button>
  </form>
</div>
<div class="results">
  <p>You searched for: <span id="search-term">apple</span></p>
</div>"""
            ],
            [
                "AUTHENTICATED",
                """<nav class="navbar">
  <a href="/home">Home</a>
  <a href="/about">About Us</a>
  <a href="/contact">Contact</a>
</nav>
<div class="main-content">
  <h1>Welcome to our Store</h1>
  <p>We sell the best juice in the world.</p>
  <img src="juice.png" alt="Juice Bottle">
</div>"""
            ],
            [
                "DATA_EXFILTRATED",
                """<form action="/api/v1/update-profile" method="POST">
  <input type="text" name="first_name" value="John">
  <input type="text" name="last_name" value="Doe">
  <!-- Developer note: role should always be user -->
  <input type="hidden" name="role" value="user">
  <button type="submit">Update Profile</button>
</form>"""
            ],
            [
                "AUTHENTICATED",
                """<div class="registration">
  <form action="/register.php" method="POST">
    <input type="text" name="username" placeholder="Username">
    <input type="password" name="password" placeholder="Password">
    <input type="password" name="confirm_password" placeholder="Confirm Password">
    <button type="submit">Register</button>
  </form>
  <p>Already have an account? <a href="/login.php">Log in here</a></p>
</div>"""
            ]
        ],
        inputs=[goal_input, html_input],
        label="Click an example below to load it into the inputs:"
    )

if __name__ == "__main__":
    app.launch()