chore(brain): ASTRA 성장 자산 동기화 — 기능 인벤토리·growth(약점프로필/학습큐)·일화기억·장기기억·회의록 원문
This commit is contained in:
@@ -0,0 +1,179 @@
|
||||
---
|
||||
id: wiki-2026-0508-배수구-sinks
|
||||
title: 배수구 (Sinks)
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [Sinks, Taint Sinks, Dangerous Sinks, Vulnerable Functions]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [security, taint-analysis, sast, vulnerabilities, appsec]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: multi
|
||||
framework: 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
|
||||
```yaml
|
||||
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
|
||||
```ql
|
||||
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)
|
||||
```python
|
||||
# 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
|
||||
```python
|
||||
# BAD
|
||||
subprocess.run(f"ping {host}", shell=True)
|
||||
|
||||
# GOOD
|
||||
subprocess.run(["ping", "-c", "1", host], shell=False)
|
||||
```
|
||||
|
||||
### Path traversal sink — resolve + check
|
||||
```python
|
||||
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
|
||||
```javascript
|
||||
// BAD
|
||||
el.innerHTML = userBio;
|
||||
|
||||
// GOOD — DOM API
|
||||
el.textContent = userBio;
|
||||
// 또는 매 DOMPurify 의 sanitize 후
|
||||
el.innerHTML = DOMPurify.sanitize(userBio);
|
||||
```
|
||||
|
||||
### SSRF — allowlist
|
||||
```python
|
||||
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
|
||||
```python
|
||||
# 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
|
||||
- 부모: [[Application_Security]]
|
||||
- 변형: [[SAST]] · [[보안_및_시스템_신뢰성_표준|DAST]] · [[IAST]]
|
||||
- 응용: [[OWASP_Top_10]]
|
||||
- Adjacent: [[Fuzzing]]
|
||||
|
||||
## 🤖 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 |
|
||||
Reference in New Issue
Block a user