Files
2nd/10_Wiki/Topics/Architecture/배수구(Sinks).md
T
koriweb d8a80f6272 chore(wiki): dangling 링크 canonical 정규화 (768파일/1200건)
이름만 다른(표기 변형) [[위키링크]]를 대상 문서의 canonical 제목으로 치환해
끊겼던 1,200개 링크를 연결. 제목/파일명 정규화 일치만 적용하고 별칭 매칭은
과병합 위험으로 제외(애매성 가드). 원본은 _link_reconcile_backup/ 에 백업.
도구: Datacollect/scripts/link_reconcile_apply.mjs

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-08 12:24:15 +09:00

5.7 KiB

id, title, category, status, canonical_id, aliases, duplicate_of, source_trust_level, confidence_score, verification_status, tags, raw_sources, last_reinforced, github_commit, tech_stack
id title category status canonical_id aliases duplicate_of source_trust_level confidence_score verification_status tags raw_sources last_reinforced github_commit tech_stack
wiki-2026-0508-배수구-sinks 배수구 (Sinks) 10_Wiki/Topics verified self
Sinks
Taint Sinks
Dangerous Sinks
Vulnerable Functions
none A 0.9 applied
security
taint-analysis
sast
vulnerabilities
appsec
2026-05-10 pending
language framework
multi Semgrep/CodeQL

배수구 (Sinks)

매 한 줄

"매 untrusted data 의 dangerous 의 reach 한 곳 — 매 taint analysis 의 endpoint.". Source (사용자 input) → Flow (변수, 함수 chain) → Sink (eval, exec, SQL, file write). 2026 SAST tooling (CodeQL, Semgrep, Snyk Code) 은 매 이 source-to-sink graph 의 trace — 매 sanitizer 의 absence 의 vulnerability 의 flag.

매 핵심

매 sink 의 종류

  • Code execution: eval, exec, Function(), os.system, 매 deserialize.
  • SQL: 매 raw query string concat (f"SELECT * FROM u WHERE id={id}").
  • Command: subprocess.Popen(shell=True), child_process.exec.
  • Path: open(path) with 매 user-controlled path → traversal.
  • HTML/DOM: innerHTML, document.write → XSS.
  • SSRF: requests.get(user_url) → 매 internal network access.
  • Log forging / template: 매 user input 의 unescape 된 template.

매 source 의 종류

  • HTTP request body/query/header.
  • 매 file content (untrusted upload).
  • 매 environment variable (in shared env).
  • 매 third-party API response.
  • 매 message queue payload.

매 응용

  1. 매 SAST rule 의 author — 매 custom sink 의 register.
  2. 매 code review 의 checklist — 매 sink 의 list 의 grep.
  3. 매 fuzzing target 의 prioritize — 매 sink 가 most 인 endpoint.

💻 패턴

Semgrep — custom sink rule

rules:
  - id: python-eval-tainted
    pattern-sources:
      - pattern: request.$X
    pattern-sinks:
      - pattern: eval(...)
      - pattern: exec(...)
    pattern-sanitizers:
      - pattern: ast.literal_eval(...)
    message: User input 의 eval 의 reach
    severity: ERROR
    languages: [python]

CodeQL — taint tracking

import python
import semmle.python.dataflow.new.TaintTracking

class UserInputToSqlConfig extends TaintTracking::Configuration {
  override predicate isSource(DataFlow::Node n) {
    n.asExpr().(Attribute).getAttr() in ["args", "form", "json"]
  }
  override predicate isSink(DataFlow::Node n) {
    exists(Call c | c.getFunc().(Attribute).getAttr() = "execute" |
      n.asExpr() = c.getArg(0))
  }
}

SQL sink — parameterize (fix)

# BAD — sink reachable
db.execute(f"SELECT * FROM users WHERE id = {user_id}")

# GOOD — sink 의 sanitize (parameterized)
db.execute("SELECT * FROM users WHERE id = %s", (user_id,))

Command sink — avoid shell

# BAD
subprocess.run(f"ping {host}", shell=True)

# GOOD
subprocess.run(["ping", "-c", "1", host], shell=False)

Path traversal sink — resolve + check

import os
base = "/var/uploads"
path = os.path.realpath(os.path.join(base, user_filename))
if not path.startswith(base + os.sep):
    raise PermissionError("path traversal")
open(path, "rb")

XSS sink — escape

// BAD
el.innerHTML = userBio;

// GOOD — DOM API
el.textContent = userBio;
// 또는 매 DOMPurify 의 sanitize 후
el.innerHTML = DOMPurify.sanitize(userBio);

SSRF — allowlist

from urllib.parse import urlparse
ALLOWED_HOSTS = {"api.partner.com", "img.cdn.com"}
def safe_fetch(url):
    host = urlparse(url).hostname
    if host not in ALLOWED_HOSTS: raise ValueError("blocked host")
    # 매 DNS rebinding 의 also guard — 매 resolve + IP check
    return requests.get(url, timeout=5)

Deserialize sink — never on untrusted

# BAD — pickle 의 RCE
data = pickle.loads(request.body)

# GOOD — JSON only
data = json.loads(request.body)

매 결정 기준

Sink type Sanitizer Notes
SQL Parameterized query, ORM 매 string concat 의 X
Shell argv list, no shell=True 매 quoting 의 trust 의 X
Path realpath + prefix check symlink 의 also handle
HTML textContent or DOMPurify 매 innerHTML 매 last resort
Eval 매 그냥 사용 X 매 alternative 의 find
Deserialize JSON only on untrusted pickle/yaml.load 매 X

기본값: 매 sink 의 see 한 후 매 source 의 trace — 매 sanitizer 의 between 의 verify.

🔗 Graph

🤖 LLM 활용

언제: 매 unfamiliar codebase 의 sink inventory 의 quickly 의 generate, 매 PR 매 new sink 의 introduce 의 spot. 언제 X: 매 production-grade SAST 의 replace — 매 LLM 의 false negative 의 risk, 매 dedicated tooling 의 use.

안티패턴

  • Blacklist sanitizer: 매 known-bad 의 remove — 매 bypass 의 always exist.
  • Sanitize at sink: 매 throughout flow 의 mutate — 매 single point 의 trust 의 X.
  • Trust 매 internal: 매 internal API 의 source 의 also treat — 매 SSRF · Confused deputy.
  • Generic exception: 매 sanitizer fail 의 silent swallow — 매 fail closed.
  • String comparison 의 host check: 매 endswith("trusted.com")evil-trusted.com bypass.

🧪 검증 / 중복

  • Verified (OWASP Source-Sink-Sanitizer model, CodeQL taint tracking docs, Semgrep registry 2026).
  • 신뢰도 A.

🕓 Changelog

날짜 변경
2026-05-08 Phase 1
2026-05-10 Manual cleanup — sink categories, SAST rules, sanitizer patterns