아래는 Secure Coding 실무에서 바로 적용하는 코드 중심 예시들이다.
언어 구분 없이 웹, API, DB, 파일 처리, 인증·암호화 등 실제로 사고가 많이 나는 포인트만 골라서 정리했다.
모두 “나쁜 코드 → 좋은 코드” 형태로 설명한다.
✅ 1. 입력 검증(Input Validation)
❌ 잘못된 예
// 사용자가 입력한 값을 그대로 사용
const id = req.query.id;
const sql = `SELECT * FROM Users WHERE Id = ${id}`;
db.query(sql);
✅ 안전한 예
// 숫자 검증 + 파라미터 바인딩
const id = parseInt(req.query.id, 10);
if (Number.isNaN(id)) return res.status(400).send('Invalid');
const sql = "SELECT * FROM Users WHERE Id = ?";
db.query(sql, [id]);
핵심 실무 포인트
- 숫자는 parseInt, 문자열 길이/포맷 검증
- SQL은 무조건 파라미터 바인딩
- “검증 실패 = 요청 거절”이 기본 전략
✅ 2. SQL Injection 방지 (Prepared Statement 필수)
❌ 취약한 코드
var sql = "UPDATE Product SET Name = '" + name + "' WHERE Id=" + id;
db.Execute(sql);
✅ 안전한 코드 (Dapper)
var sql = "UPDATE Product SET Name = @Name WHERE Id = @Id";
db.Execute(sql, new { Name = name, Id = id });
실무 사투리 팁
- “문자열 붙이면 끝장난다.”
- Dapper, EFCore, JDBC, PDO, 무엇이든 바인딩이 기본기
✅ 3. XSS 방지 (출력 시 인코딩)
❌ 나쁜 예
<div>사용자 입력: {{ userInput }}</div>
✅ 안전한 예 (Vue/React 기본 escape 기능 활용)
<div>사용자 입력: {{ safeText }}</div>
또는 서버에서 직접 이스케이프:
var safe = System.Net.WebUtility.HtmlEncode(input);
실무 팁
- XSS는 입력이 아니라 출력 시점에서 해결
- 리치 텍스트 필요하면 “화이트리스트 필터링” 필요
✅ 4. 파일 업로드 (디렉토리 탈출 방지)
❌ 취약 코드
var path = "uploads/" + file.FileName;
await File.WriteAllBytesAsync(path, bytes);
❗ 공격 예
../../../web.config → 서버 파일 덮어쓰기
✅ 안전 코드
var safeName = Path.GetFileName(file.FileName); // 디렉토리 제거
var safePath = Path.Combine("uploads", safeName);
await File.WriteAllBytesAsync(safePath, bytes);
추가 보호
- 확장자 화이트리스트 (.jpg, .png, .pdf)
- 실행 가능한 파일 차단 (.exe, .aspx, .js)
✅ 5. 인증 토큰 저장 시 Secure 옵션
❌ 취약 쿠키
Response.Cookies.Append("Token", token);
✅ 보안 쿠키
Response.Cookies.Append("Token", token, new CookieOptions {
HttpOnly = true,
Secure = true,
SameSite = SameSiteMode.Strict
});
실무 팁
- HttpOnly: JS 탈취 방지
- Secure: HTTPS 전송 강제
- SameSite: CSRF 완화
✅ 6. 암호화 – 절대 직접 구현하지 말 것
❌ 직접 만든 암호화(실무에서 절대 금지)
string Encrypt(string s) {
return Convert.ToBase64String(Encoding.UTF8.GetBytes(s)); // 암호화 아님
}
✅ 안전한 암호화 (AES-GCM 예시)
using var aes = Aes.Create();
aes.Mode = CipherMode.GCM;
aes.GenerateKey();
aes.GenerateIV();
using var encryptor = aes.CreateEncryptor(aes.Key, aes.IV);
var cipherText = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
실무 팁
- AES-GCM / RSA / PBKDF2 등 검증된 알고리즘 사용
- “직접 암호화 로직 설계”는 금지
✅ 7. 비밀번호 저장 (Hash + Salt)
❌ 나쁜 예
Password = SHA256('1234')
❗ 해시만 쓰면 rainbow table에 뚫린다
✅ 안전 예
C# 예시(ASP.NET Core 기본)
var hashed = passwordHasher.HashPassword(user, plainPassword);
✅ 8. 예외 메시지 노출 금지 (논리 정보 노출 방지)
❌ 위험한 예
catch (SqlException ex) {
return BadRequest(ex.ToString()); // 내부 DB 정보 노출
}
✅ 안전한 예
catch {
_logger.LogError("DB 오류 발생");
return StatusCode(500, "Server Error");
}
✅ 9. 서버 사이드 요청 위조(SSRF) 방지
❌ 취약 예
var json = await http.GetStringAsync(userInputUrl);
✓ 위험: 내부망 접근, 메타데이터 API 접근 가능
✅ 안전 예
if (!Uri.TryCreate(url, UriKind.Absolute, out Uri? uri))
return BadRequest();
var allowedSchemes = new[] { "http", "https" };
if (!allowedSchemes.Contains(uri.Scheme))
return BadRequest("Invalid Scheme");
// 도메인 화이트리스트
var allowedHosts = new[] { "api.company.com" };
if (!allowedHosts.Contains(uri.Host))
return BadRequest("Blocked Host");
var json = await http.GetStringAsync(uri);
🔥 종합 실무 요약
위험 방지 핵심
| SQL Injection |
파라미터 바인딩 필수 |
| XSS |
출력 인코딩 |
| CSRF |
SameSite/CSRF 토큰 |
| 파일 업로드 |
파일명 정규화 + 확장자 제한 |
| 인증 |
HttpOnly + Secure 쿠키 |
| 비밀번호 |
bcrypt/PBKDF2/Argon2 |
| 예외 처리 |
내부 정보 숨기기 |
| 암호화 |
표준 알고리즘 사용 |