<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Web-Security on IT Comparison</title><link>https://comparison.metacog.co.kr/tags/web-security/</link><description>Recent content in Web-Security on IT Comparison</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Mon, 03 Aug 2026 04:27:16 +0900</lastBuildDate><atom:link href="https://comparison.metacog.co.kr/tags/web-security/index.xml" rel="self" type="application/rss+xml"/><item><title>CSRF vs XSS: Forged Requests or Injected Scripts</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-csrf-vs-xss-forged-requests-or-injected-scripts/</link><pubDate>Mon, 03 Aug 2026 04:27:16 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-csrf-vs-xss-forged-requests-or-injected-scripts/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;CSRF and XSS are both web attacks that abuse a victim&amp;rsquo;s trusted relationship with a site, but they exploit opposite ends of that trust. CSRF forges a request using the victim&amp;rsquo;s own &lt;strong class="kw"&gt;session cookie&lt;/strong&gt; without ever running attacker code in the browser, while XSS smuggles &lt;strong class="kw"&gt;injected script&lt;/strong&gt; into a vulnerable page so it executes directly inside the victim&amp;rsquo;s browser.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;text x="160" y="26" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;CSRF&lt;/text&gt;&lt;text x="480" y="26" text-anchor="middle" font-size="16" font-weight="bold" style="fill:var(--primary)"&gt;XSS&lt;/text&gt;&lt;line x1="320" y1="40" x2="320" y2="345" style="stroke:var(--border)" stroke-width="1"/&gt;&lt;rect x="30" y="45" width="260" height="42" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="62" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Victim Browser&lt;/text&gt;&lt;text x="160" y="76" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;active session cookie&lt;/text&gt;&lt;rect x="30" y="112" width="260" height="42" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="129" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Attacker Site&lt;/text&gt;&lt;text x="160" y="143" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;forged auto-submit form&lt;/text&gt;&lt;rect x="30" y="179" width="260" height="42" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="196" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Target Server&lt;/text&gt;&lt;text x="160" y="210" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;e.g. bank / app backend&lt;/text&gt;&lt;rect x="30" y="246" width="260" height="42" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="160" y="263" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Action Executed&lt;/text&gt;&lt;text x="160" y="277" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;using victim's cookie&lt;/text&gt;&lt;line x1="160" y1="87" x2="160" y2="108" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;polygon points="154,104 166,104 160,113" style="fill:var(--compare-a)"/&gt;&lt;text x="200" y="100" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;visits page&lt;/text&gt;&lt;line x1="160" y1="154" x2="160" y2="175" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;polygon points="154,171 166,171 160,180" style="fill:var(--compare-a)"/&gt;&lt;text x="215" y="167" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;cookie auto-attached&lt;/text&gt;&lt;line x1="160" y1="221" x2="160" y2="242" style="stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;polygon points="154,238 166,238 160,247" style="fill:var(--compare-a)"/&gt;&lt;text x="205" y="234" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;no injected code&lt;/text&gt;&lt;rect x="350" y="45" width="260" height="42" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="62" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Vulnerable Site&lt;/text&gt;&lt;text x="480" y="76" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;renders unsanitized input&lt;/text&gt;&lt;rect x="350" y="112" width="260" height="42" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="129" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Injected &amp;lt;script&amp;gt;&lt;/text&gt;&lt;text x="480" y="143" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;runs in page's own origin&lt;/text&gt;&lt;rect x="350" y="179" width="260" height="42" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="196" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Victim Browser&lt;/text&gt;&lt;text x="480" y="210" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;executes attacker JS&lt;/text&gt;&lt;rect x="350" y="246" width="260" height="42" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="480" y="263" text-anchor="middle" font-size="12" style="fill:var(--content)"&gt;Attacker Server&lt;/text&gt;&lt;text x="480" y="277" text-anchor="middle" font-size="10" style="fill:var(--secondary)"&gt;receives stolen data&lt;/text&gt;&lt;line x1="480" y1="87" x2="480" y2="108" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;polygon points="474,104 486,104 480,113" style="fill:var(--compare-b)"/&gt;&lt;text x="530" y="100" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;input reflected as code&lt;/text&gt;&lt;line x1="480" y1="154" x2="480" y2="175" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;polygon points="474,171 486,171 480,180" style="fill:var(--compare-b)"/&gt;&lt;text x="535" y="167" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;full DOM access&lt;/text&gt;&lt;line x1="480" y1="221" x2="480" y2="242" style="stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;polygon points="474,238 486,238 480,247" style="fill:var(--compare-b)"/&gt;&lt;text x="540" y="234" text-anchor="middle" font-size="9" style="fill:var(--secondary)"&gt;cookie exfiltrated&lt;/text&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;CSRF&lt;/th&gt;
&lt;th&gt;XSS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Attack vector&lt;/td&gt;
&lt;td&gt;Forged cross-site request, e.g. an auto-submitting form or image tag on the attacker&amp;rsquo;s page that targets the victim site&lt;/td&gt;
&lt;td&gt;Malicious script injected into a vulnerable page&amp;rsquo;s HTML or JS output, often via unsanitized user input&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Trust exploited&lt;/td&gt;
&lt;td&gt;Server&amp;rsquo;s trust that any request carrying a valid session cookie came from the legitimate user&lt;/td&gt;
&lt;td&gt;Browser&amp;rsquo;s trust that all script served from the site&amp;rsquo;s origin is safe to execute&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Where the payload runs&lt;/td&gt;
&lt;td&gt;Nowhere on the victim&amp;rsquo;s browser beyond a normal HTTP request; the &amp;lsquo;payload&amp;rsquo; is the request itself&lt;/td&gt;
&lt;td&gt;Attacker&amp;rsquo;s JavaScript executes directly inside the victim&amp;rsquo;s browser, in the vulnerable site&amp;rsquo;s own origin&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Prerequisite for success&lt;/td&gt;
&lt;td&gt;Victim must have an active authenticated session with the target site when the forged request fires&lt;/td&gt;
&lt;td&gt;Vulnerable site must reflect, store, or render attacker-controlled input without proper sanitization or escaping&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Attacker capability&lt;/td&gt;
&lt;td&gt;Limited to whatever action the victim&amp;rsquo;s existing session is authorized to perform, like a transfer or settings change&lt;/td&gt;
&lt;td&gt;Broad: read cookies and localStorage, capture input, deface the page, or pivot into session hijacking&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Primary defense&lt;/td&gt;
&lt;td&gt;Anti-CSRF tokens, SameSite cookies, and origin or referer checks&lt;/td&gt;
&lt;td&gt;Output encoding, Content Security Policy, and strict input sanitization&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical impact scope&lt;/td&gt;
&lt;td&gt;A single forged action, bounded by what the target endpoint allows&lt;/td&gt;
&lt;td&gt;Potential full account takeover or persistent compromise if the injection is stored&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;CSRF forges a request using the victim&amp;rsquo;s existing &lt;strong class="kw"&gt;session cookie&lt;/strong&gt;; XSS injects &lt;strong class="kw"&gt;attacker script&lt;/strong&gt; that runs inside the victim&amp;rsquo;s browser.&lt;/li&gt;
&lt;li&gt;CSRF requires no &lt;strong class="kw"&gt;code injection&lt;/strong&gt; into the target site, while XSS depends entirely on unsanitized input reaching the page.&lt;/li&gt;
&lt;li&gt;XSS can read and exfiltrate data straight from the DOM, whereas CSRF is limited to &lt;strong class="kw"&gt;blind requests&lt;/strong&gt; with no response visibility.&lt;/li&gt;
&lt;li&gt;&lt;strong class="kw"&gt;SameSite cookies&lt;/strong&gt; mitigate CSRF but do nothing against XSS, which is stopped primarily by &lt;strong class="kw"&gt;CSP&lt;/strong&gt; and output encoding.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;CSRF&lt;/strong&gt;&lt;/p&gt;</description></item><item><title>JWT vs Session-Based Authentication: Stateless Tokens or Server-Tracked State</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-jwt-vs-session-based-authentication-stateless-tokens-or-serv/</link><pubDate>Mon, 03 Aug 2026 04:24:11 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-jwt-vs-session-based-authentication-stateless-tokens-or-serv/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;JWT and session-based authentication both prove who a user is on every request, but they disagree about where that proof lives. A &lt;strong class="kw"&gt;JWT&lt;/strong&gt; is a signed, self-contained token the client carries and the server checks locally, while &lt;strong class="kw"&gt;session-based&lt;/strong&gt; auth hands out a small ID that maps to state the server stores and looks up on every call. That single difference in where state lives cascades into how each approach scales, revokes access, and fits different architectures.&lt;/p&gt;</description></item><item><title>HTTP vs HTTPS: Plaintext vs Encrypted Web Traffic</title><link>https://comparison.metacog.co.kr/posts/2026-08-03-http-vs-https-plaintext-vs-encrypted-web-traffic/</link><pubDate>Sat, 01 Aug 2026 20:01:00 +0900</pubDate><guid>https://comparison.metacog.co.kr/posts/2026-08-03-http-vs-https-plaintext-vs-encrypted-web-traffic/</guid><description>&lt;h2 id="overview"&gt;Overview&lt;/h2&gt;
&lt;p&gt;HTTP and HTTPS are the same application-layer protocol for transferring web resources, but HTTPS wraps every request and response in a &lt;strong class="kw"&gt;TLS&lt;/strong&gt; tunnel before it touches the network. That single layer determines whether credentials, cookies, and page content travel as &lt;strong class="kw"&gt;plaintext&lt;/strong&gt; visible to anyone on the path, or as ciphertext only the two endpoints can read.&lt;/p&gt;
&lt;h2 id="comparison-diagram"&gt;Comparison Diagram&lt;/h2&gt;
&lt;div class="compare-diagram"&gt;
&lt;svg viewBox="0 0 640 360" xmlns="http://www.w3.org/2000/svg"&gt;&lt;text x="20" y="32" font-size="18" font-weight="700" style="fill:var(--primary)"&gt;HTTP&lt;/text&gt;&lt;rect x="40" y="70" width="110" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="95" y="100" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Client&lt;/text&gt;&lt;rect x="490" y="70" width="110" height="50" rx="6" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;text x="545" y="100" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;line x1="150" y1="95" x2="490" y2="95" style="stroke:var(--compare-a)" stroke-width="2" stroke-dasharray="5,4" marker-end="url(#arrowA)"/&gt;&lt;text x="320" y="82" font-size="12" text-anchor="middle" style="fill:var(--content)"&gt;GET /login?pwd=hunter2&lt;/text&gt;&lt;circle cx="320" cy="140" r="14" style="fill:var(--compare-a-soft);stroke:var(--compare-a)" stroke-width="1.5"/&gt;&lt;path d="M310 140 Q320 132 330 140 Q320 148 310 140 Z" style="fill:none;stroke:var(--compare-a)" stroke-width="1.3"/&gt;&lt;circle cx="320" cy="140" r="2.5" style="fill:var(--compare-a)"/&gt;&lt;text x="320" y="165" font-size="11" text-anchor="middle" style="fill:var(--secondary)"&gt;visible to anyone on path&lt;/text&gt;&lt;line x1="0" y1="195" x2="640" y2="195" style="stroke:var(--border)" stroke-width="1" stroke-dasharray="3,3"/&gt;&lt;text x="20" y="225" font-size="18" font-weight="700" style="fill:var(--primary)"&gt;HTTPS&lt;/text&gt;&lt;rect x="40" y="260" width="110" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="95" y="290" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Client&lt;/text&gt;&lt;rect x="490" y="260" width="110" height="50" rx="6" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="545" y="290" font-size="13" text-anchor="middle" style="fill:var(--content)"&gt;Server&lt;/text&gt;&lt;line x1="150" y1="285" x2="490" y2="285" style="stroke:var(--compare-b)" stroke-width="2" marker-end="url(#arrowB)"/&gt;&lt;text x="320" y="272" font-size="12" text-anchor="middle" style="fill:var(--content)"&gt;x8f#9a2$qL0e...&lt;/text&gt;&lt;rect x="308" y="296" width="24" height="18" rx="3" style="fill:var(--compare-b-soft);stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;path d="M313 296 v-8 a7 7 0 0 1 14 0 v8" style="fill:none;stroke:var(--compare-b)" stroke-width="1.5"/&gt;&lt;text x="320" y="335" font-size="11" text-anchor="middle" style="fill:var(--secondary)"&gt;TLS-encrypted, tamper-evident&lt;/text&gt;&lt;defs&gt;&lt;marker id="arrowA" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 Z" style="fill:var(--compare-a)"/&gt;&lt;/marker&gt;&lt;marker id="arrowB" markerWidth="8" markerHeight="8" refX="6" refY="4" orient="auto"&gt;&lt;path d="M0,0 L8,4 L0,8 Z" style="fill:var(--compare-b)"/&gt;&lt;/marker&gt;&lt;/defs&gt;&lt;/svg&gt;
&lt;/div&gt;
&lt;h2 id="comparison-table"&gt;Comparison Table&lt;/h2&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Aspect&lt;/th&gt;
&lt;th&gt;HTTP&lt;/th&gt;
&lt;th&gt;HTTPS&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Default port&lt;/td&gt;
&lt;td&gt;80&lt;/td&gt;
&lt;td&gt;443&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Connection establishment&lt;/td&gt;
&lt;td&gt;Single TCP three-way handshake&lt;/td&gt;
&lt;td&gt;TCP handshake plus a TLS handshake to negotiate cipher and exchange keys&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Certificate requirement&lt;/td&gt;
&lt;td&gt;None&lt;/td&gt;
&lt;td&gt;X.509 certificate issued by a trusted CA (or self-signed) required&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data encryption&lt;/td&gt;
&lt;td&gt;Plaintext — headers, cookies, and body sent unencrypted&lt;/td&gt;
&lt;td&gt;Encrypted end-to-end using TLS/SSL symmetric ciphers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Data integrity&lt;/td&gt;
&lt;td&gt;No built-in tamper detection&lt;/td&gt;
&lt;td&gt;MAC/AEAD in TLS detects in-transit tampering&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Browser indicator&lt;/td&gt;
&lt;td&gt;&amp;ldquo;Not secure&amp;rdquo; warning in modern browsers&lt;/td&gt;
&lt;td&gt;Padlock icon; no warning shown&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Performance overhead&lt;/td&gt;
&lt;td&gt;Lower — no crypto or extra round trip&lt;/td&gt;
&lt;td&gt;Slightly higher handshake/CPU cost, largely offset by TLS 1.3 and session resumption&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Typical use case&lt;/td&gt;
&lt;td&gt;Local development, internal tools on trusted networks, legacy static content&lt;/td&gt;
&lt;td&gt;Any production site, especially logins, payments, and APIs handling sensitive data&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="key-differences"&gt;Key Differences&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;HTTPS is HTTP tunneled through &lt;strong class="kw"&gt;TLS&lt;/strong&gt;, not a separate application protocol&lt;/li&gt;
&lt;li&gt;HTTP traffic is readable in plaintext by anyone with network access; HTTPS traffic is &lt;strong class="kw"&gt;encrypted&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;HTTPS requires a valid &lt;strong class="kw"&gt;certificate&lt;/strong&gt; from a trusted CA to establish trust&lt;/li&gt;
&lt;li&gt;Modern browsers flag HTTP sites as &lt;strong class="kw"&gt;not secure&lt;/strong&gt;, pushing HTTPS as the default&lt;/li&gt;
&lt;li&gt;TLS 1.3 has shrunk the historical HTTPS &lt;strong class="kw"&gt;handshake&lt;/strong&gt; cost to near parity with plain TCP&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="when-to-use-each"&gt;When to Use Each&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;HTTP&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>