Vulnerability Patterns — 코드 취약점 패턴 데이터베이스
security-analyst 에이전트가 보안 리뷰 시 활용하는 취약 코드 패턴, CWE 분류, 안전한 대안 레퍼런스.
대상 에이전트
security-analyst — 이 스킬의 취약점 패턴을 코드 보안 분석에 직접 적용한다.
취약점 분류 체계 (CWE Top 25)
최우선 검출 대상
| CWE |
이름 |
심각도 |
빈도 |
| CWE-79 |
XSS (Cross-Site Scripting) |
High |
매우 높음 |
| CWE-89 |
SQL Injection |
Critical |
높음 |
| CWE-78 |
OS Command Injection |
Critical |
중간 |
| CWE-22 |
Path Traversal |
High |
중간 |
| CWE-352 |
CSRF |
High |
높음 |
| CWE-798 |
Hardcoded Credentials |
Critical |
높음 |
| CWE-862 |
Missing Authorization |
Critical |
높음 |
| CWE-306 |
Missing Authentication |
Critical |
중간 |
| CWE-502 |
Deserialization |
Critical |
중간 |
| CWE-918 |
SSRF |
High |
중간 |
언어별 취약 코드 패턴
Python
SQL Injection (CWE-89)
# 취약
query = f"SELECT * FROM users WHERE name = '{user_input}'"
cursor.execute(query)
# 안전
cursor.execute("SELECT * FROM users WHERE name = %s", (user_input,))
# 또는 ORM 사용 (SQLAlchemy, Django ORM)
Command Injection (CWE-78)
# 취약
os.system(f"ping {user_input}")
subprocess.call(f"ls {user_input}", shell=True)
# 안전
subprocess.run(["ping", user_input], shell=False)
# shlex.quote()로 이스케이프 (부득이한 경우)
Path Traversal (CWE-22)
# 취약
file_path = os.path.join(BASE_DIR, user_input)
open(file_path).read()
# 안전
file_path = os.path.realpath(os.path.join(BASE_DIR, user_input))
if not file_path.startswith(os.path.realpath(BASE_DIR)):
raise ValueError("Invalid path")
YAML Deserialization (CWE-502)
# 취약
data = yaml.load(user_input) # 임의 코드 실행 가능
# 안전
data = yaml.safe_load(user_input)
JavaScript/TypeScript
XSS (CWE-79)
// 취약 (React)
<div dangerouslySetInnerHTML={{__html: userInput}} />
// 안전
<div>{userInput}</div> // React 자동 이스케이프
// 필요 시 DOMPurify
import DOMPurify from 'dompurify';
<div dangerouslySetInnerHTML={{__html: DOMPurify.sanitize(userInput)}} />
Prototype Pollution (CWE-1321)
// 취약
function merge(target, source) {
for (let key in source) {
target[key] = source[key]; // __proto__ 오염 가능
}
}
// 안전
function merge(target, source) {
for (let key of Object.keys(source)) {
if (key === '__proto__' || key === 'constructor') continue;
target[key] = source[key];
}
}
// 또는 Object.create(null) 사용
ReDoS (CWE-1333)
// 취약 (Catastrophic Backtracking)
const regex = /^(a+)+$/;
regex.test("aaaaaaaaaaaaaaaaaaaaaaaaaaaaab"); // 지수적 시간
// 안전: 비백트래킹 패턴 사용
const regex = /^a+$/; // 중첩 반복 제거
eval/Function 실행 (CWE-95)
// 취약
eval(userInput);
new Function(userInput)();
setTimeout(userInput, 1000);
// 안전: eval 사용 금지, 대안 로직 사용
Java
SQL Injection (CWE-89)
// 취약
String query = "SELECT * FROM users WHERE id = " + userId;
Statement stmt = conn.createStatement();
stmt.executeQuery(query);
// 안전
PreparedStatement ps = conn.prepareStatement("SELECT * FROM users WHERE id = ?");
ps.setInt(1, userId);
ps.executeQuery();
XXE (CWE-611)
// 취약
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
db.parse(userInput);
// 안전
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
Deserialization (CWE-502)
// 취약
ObjectInputStream ois = new ObjectInputStream(userInputStream);
Object obj = ois.readObject(); // 임의 코드 실행 가능
// 안전: JSON/XML 직렬화 사용 (Jackson, Gson)
// ObjectInputFilter 사용 (Java 9+)
Go
SQL Injection (CWE-89)
// 취약
query := fmt.Sprintf("SELECT * FROM users WHERE name = '%s'", userInput)
db.Query(query)
// 안전
db.Query("SELECT * FROM users WHERE name = $1", userInput)
SSRF (CWE-918)
// 취약
resp, err := http.Get(userProvidedURL)
// 안전: URL 화이트리스트 + 내부 IP 차단
parsedURL, _ := url.Parse(userProvidedURL)
if isInternalIP(parsedURL.Hostname()) {
return errors.New("internal IP not allowed")
}
시크릿/민감정보 패턴
탐지 대상 패턴
| 유형 |
정규식 패턴 (간략) |
심각도 |
| AWS Access Key |
AKIA[0-9A-Z]{16} |
Critical |
| AWS Secret Key |
[A-Za-z0-9/+=]{40} (AKIA와 함께) |
Critical |
| GitHub Token |
gh[ps]_[A-Za-z0-9_]{36,} |
Critical |
| Google API Key |
AIza[0-9A-Za-z_-]{35} |
High |
| Slack Token |
xox[baprs]-[0-9a-zA-Z-]+ |
High |
| JWT |
eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+ |
High |
| Private Key |
`-----BEGIN (RSA |
EC |
| 비밀번호 변수 |
password\s*=\s*['"][^'"]+['"] |
Critical |
| DB Connection String |
`(mysql |
postgresql |
심각도 판정 매트릭스
| 요소 |
Critical |
High |
Medium |
Low |
| 공격 용이성 |
네트워크, 인증 불필요 |
네트워크, 일부 조건 |
로컬, 인증 필요 |
물리적 접근 |
| 영향 |
시스템 완전 장악 |
데이터 유출 |
서비스 저하 |
정보 노출 (제한적) |
| 데이터 범위 |
전체 DB |
사용자 개인정보 |
비민감 데이터 |
공개 데이터 |
| 기밀성 |
전면 노출 |
부분 노출 |
간접 노출 |
미미 |
보안 리뷰 체크리스트
인증/인가
입력 처리
데이터 보호
의존성