@mcp.tool
def search_papers(query: str, limit: int = 10) -> str:
    sql = text(f"""
        SELECT *
        FROM papers
        WHERE title LIKE '%{query}%' OR authors LIKE '%{query}%' OR abstract LIKE '%{query}%'
        ORDER BY publication_date DESC
        LIMIT {limit}
    """)  # ← f-string 직접 삽입 (필터 없음, UNION/주입 가능)
    sql_result = db.execute(sql)

# backend/main.py (/chat 에이전트 시스템 프롬프트 일부)
system_message = """... When users ask about papers, use the search_papers tool first ..."""
agent = create_react_agent(model, tools, prompt=system_message)  # 툴 사용 유도 문구로 프롬프트 인젝션 악용

코드 분석 과정에서 mcp_serversearch_papers 함수가 f-string으로 직접 SQL을 구성해 인젝션 가능함을 확인했다. papers 테이블 컬럼 순서를 users 테이블 컬럼과 맞춰 UNION 정렬 전략을 세웠다. /chat 엔드포인트에 ReAct 스타일 프롬프트를 주입해 search_papers 툴 실행을 유도했다. 이어 UNION SELECT로 id, username, password, email, is_admin을 매핑한 JSON 결과를 얻었고 authors 필드에 노출된 admin 해시를 추출했다. verify_password가 단순 평문 비교이므로 그 해시 문자열 자체로 로그인(JWT 발급)이 가능했다. 최종적으로 해당 JWT로 /flag에 접근해 플래그를 획득했다.