๊ฐ์
๋ณด์์ ํตํฉํ QueryPie์ ํ์ดํ๋ผ์ธ
QueryPie๊ฐ ์ค์ํ๊ฒ ์๊ฐํ๋ ๋ถ๋ถ, ๋น ๋ฅธ ๊ฐ๋ฐ ์๋์ ์์ ์ฑ์ ๋๋ค. QueryPie ํ์ ๋น ๋ฅธ ์ฑ์ฅ์ ์ํฉ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ณํ์ ๋ฏผ์ฒฉํ๊ฒ ๋์ํ๊ธธ ์ํฉ๋๋ค. ๊ทธ๋ฌ๋ ๊ฐ๊ณผํ๋ฉด ์๋๋ ๋ถ๋ถ์ด ์์ต๋๋ค. ์ฐ๋ฆฌ๋ ๊ฐ๋ฐ ์๋๋ฅผ ๋์ด๋ค ๋ณด๋ฉด ๋ณด์ ๊ฒํ ๊ฐ ๋ค๋ก ๋ฐ๋ฆฌ๊ฑฐ๋ ๊ฐ๊ณผ๋๋ ๊ฒฝ์ฐ๋ฅผ ์ด๊ธฐ์ ๋ง์ด ๊ฒฝํํ์์ต๋๋ค. ์ด๋ก ์ธํ์ฌ ์ถ์ ํ ๋ณด์ ์ทจ์ฝ์ ์ด ๋ฐ๊ฒฌ๋๋ฉด ๊ธด๊ธ ํจ์น, ๋์ ๋น์ฉ, ๊ทธ๋ฆฌ๊ณ ๋ธ๋๋ ์ ๋ขฐ๋ ์์ค๋ก ์ด์ด์ง ์ ์๋ค๋ ์ํ์ ์ถฉ๋ถํ ์ธ์งํ๊ณ ์์ต๋๋ค.
DevSecOps๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ๊ทผ๋ณธ์ ์ผ๋ก ํด๊ฒฐํ๊ธฐ ์ํ ์ ๊ทผ ๋ฐฉ์์ ๋๋ค. ๊ฐ๋ฐ(Dev)๊ณผ ์ด์(Ops) ๊ณผ์ ์ ๋ณด์(Security)์ ํตํฉํ์ฌ, ๊ฐ๋ฐ ์ด๊ธฐ๋ถํฐ ์ด์ ๋จ๊ณ๊น์ง ๋ณด์์ ์๋ํํ๊ณ ํ์คํ๋ ๋ฐฉ์์ผ๋ก QueryPie๋ ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถ ์ด์ํ๊ณ ์์ต๋๋ค.
QueryPie์ ๊ฐ๋ฐ ๋ผ์ดํ์ฌ์ดํด ์ ๋จ๊ณ ๋ณด์์ฑ ๊ฒํ ํ๋ก์ธ์ค
QueryPie๋ Privileged Access Management(PAM) ์๋ฃจ์ ์ผ๋ก์, Database Access Control(DAC), System Access Control(SAC), Kubernetes Access Control(KAC) ๋ฑ ์ค์ํ ์์ฐ๊ณผ ์ ๋ณด๋ฅผ ๋ณดํธํ๊ธฐ ์ํด ๊ณ ๋์ ๋ณด์์ ์๊ตฌํ๋ ์ ํ์ ๋๋ค. ์ด์ ๋ฐ๋ผ ๋์ฑ๋ ์ฒ ์ ํ ๋ณด์ ๊ด๋ฆฌ๋ฅผ ์ํ์ฌ QueryPie๋ ๊ฐ๋ฐ ๋ผ์ดํ์ฌ์ดํด ์ ๋ฐ์ ๊ฑธ์ณ ์ผ๊ด๋ ๋ณด์ ๊ฒํ ๋ฐ ์ ๊ฒ์ด ์ด๋ฃจ์ด์ง๋๋ค. ๊ฐ๋ฐ ์ด๊ธฐ ๋จ๊ณ์ ์๊ตฌ์ฌํญ ์๋ฆฝ๋ถํฐ, ์ค๊ณ, ๊ตฌํ, ํ ์คํธ, ๋ฐฐํฌ, ์ด์์ ์ด๋ฅด๊ธฐ๊น์ง ๊ฐ ๋จ๊ณ์์ ๋ค์ธต์ ์ธ ๋ณด์ ๊ฒํ ํ๋ก์ธ์ค๋ฅผ ์ ์ฉํ์ฌ ์ ์ฌ์ ์ธ ๋ณด์ ์ํ์ ์ฌ์ ์ ๋ฐฉ์งํ๊ณ ์์ต๋๋ค. ์ด๋ฅผ ๊ตฌํํ๊ธฐ ์ํด์ ์ ํฌ๋ DevSecOps ์ ๊ทผ ๋ฐฉ์์ ์ฑํํ์ฌ ๊ฐ๋ฐ๊ณผ ๋ณด์์ ํตํฉํ์ฌ ๊ธด๋ฐํ ์ฐ๊ณํ๊ณ ์๋ํ๋ ๋ณด์ ๊ฒ์ฌ์ ์ง์์ ์ธ ๋ชจ๋ํฐ๋ง์ผ๋ก ์ทจ์ฝ์ ์ ์ ์ํ๊ฒ ์๋ณํ๊ณ ๋์ํจ์ผ๋ก์จ, ์ ํ์ ์์ ์ฑ๊ณผ ์ ๋ขฐ์ฑ์ ๋์ฑ ๊ฐํํ๊ณ ์์ต๋๋ค. ์ด์ฒ๋ผ, ์ฐ๋ฆฌ์๊ฒ ๋ณด์์ ๋จ์ํ ๊ธฐ๋ฅ์ ๋์ด ์ ํ์ ํต์ฌ ์์๋ก ์๋ฆฌ ์ก๊ณ ์์ต๋๋ค.

DevSecOps์ ํ์์ฑ๊ณผ ํด๋ผ์ฐ๋ ํ๊ฒฝ์์์ ๋ณด์ ๊ณผ์
๊ธฐ์กด์ ๋ณด์ ์ ๊ทผ๋ฒ์ ๋ณด์์ ๋ํ ๊ฒํ ๋ฅผ ๊ฐ๋ฐ ์๋ฃ ํ์ ์ํํ๋ ๊ฒฝ์ฐ๊ฐ ๋ง์, ๋ฌธ์ ๋ฐ์ ์ ์์ ์ ์๊ฐ์ด ์ค๋ ๊ฑธ๋ฆฌ๊ณ ๋น์ฉ์ด ๋์์ง๋ ๊ฒฝ์ฐ๊ฐ ๋๋ถ๋ถ ์ด์์ต๋๋ค. ์๋ฅผ ๋ค์ด, ์ฝ๋๊ฐ ์์ฑ๋ ํ ๋ฐ๊ฒฌ๋ ๋ณด์ ์ทจ์ฝ์ ์ ์์ ํ๋ ค๋ฉด ์ด๋ฏธ ์์ฑ๋ ์ฝ๋๋ ์์คํ ์ํคํ ์ฒ๋ฅผ ๋ค์ ๋ถ์ํ๊ณ ๋ณ๊ฒฝํด์ผ ํฉ๋๋ค. ์ด๋ ์ด๊ธฐ ๋จ๊ณ์์ ๋ฌธ์ ๊ฐ ๋ฐ๊ฒฌ๋ ๋๋ณด๋ค ํจ์ฌ ๋ ๋ณต์กํ๊ณ ๋ ๋ง์ด ๋น์ฉ์ ๋ฐ์์ ์ด๋ ํฉ๋๋ค.
๊ทธ๋ฌ๋ DevSecOps๋ ๋ณด์์ ๊ฐ๋ฐ ์ด๊ธฐ์ ํตํฉํจ์ผ๋ก์จ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ ์ ์์ต๋๋ค. ์๋ํ๋ ๋ณด์ ๊ฒํ ์ ์ฃผ๊ธฐ์ ์ด๊ณ ์ง์์ ์ธ ๋ณด์ ์ ๊ฒ์ ํตํด QueryPie๋ ๊ฐ๋ฐ ํจ์จ์ฑ์ ์ ์งํ๋ฉด์๋ ์์ ํ ํด๋ผ์ฐ๋ ํ๊ฒฝ์ ์ ๊ณตํ ์ ์์ต๋๋ค. ๋ํ ํด๋ผ์ฐ๋ ํ๊ฒฝ์์๋ ๋ค์์ ์ธํ๋ผ ๊ตฌ์ฑ๊ณผ ๊ด๋ฆฌ๊ฐ ์๋ํ๋๋ฏ๋ก, ๋ณด์ ์ทจ์ฝ์ ์ด ๋น ๋ฅด๊ฒ ๋ ธ์ถ๋ ์ํ์ด ์์ต๋๋ค. ๋ฐ๋ผ์ QueryPie์ DevSecOps ํ์ดํ๋ผ์ธ์ ํด๋ผ์ฐ๋ ํ๊ฒฝ์ด ๊ฐ์ง๊ณ ์๋ ์ฌ๋ฌ ๋ณด์ ๊ณผ์ ๋ฅผ ํด๊ฒฐํ๊ณ , ์์ ํ ์ ํ ์ด์์ ์ง์ํ๊ธฐ ์ํด ๋์์์ด ๊ฐ์ ํ๊ณ ์์ต๋๋ค.
QueryPie์ DevSecOps ํ์ดํ๋ผ์ธ ๊ตฌ์ถ์ ํตํ ์ ๋ขฐ์ฑ ํ๋ณด
QueryPie๋ DevSecOps ํ์ดํ๋ผ์ธ์ ํตํด ๋ณด์์ ์๋ํํ๊ณ ํด๋ผ์ฐ๋ ํ๊ฒฝ์ ๋ณด์ ๊ณผ์ ๋ฅผ ์ ๊ทน์ ์ผ๋ก ํด๊ฒฐํ๋ฉฐ, ์ ๋ขฐํ ์ ์๋ PAM ์๋ฃจ์ ์ผ๋ก ์๋ฆฌ๋งค๊นํ๊ณ ์ ํฉ๋๋ค. ๋ณธ ๋ฐฑ์์์๋ QueryPie์ ๊ฐ๋ฐ ๋ผ์ดํ์ฌ์ดํด ์ ๋จ๊ณ์์ ์ด๋ฃจ์ด์ง๋ ๋ณด์์ฑ ๊ฒํ ์ DevSecOps ํ์ดํ๋ผ์ธ์ ๊ตฌ์ถ ๊ณผ์ ์ ํตํด ๋ณด์์ด ์ด๋ป๊ฒ ์ ํ ์ ๋ขฐ์ฑ์ ๊ธฐ์ฌํ๋์ง๋ฅผ ์์ธํ ์ค๋ช ํ๊ณ ์ ํฉ๋๋ค.
CI/CD ํ์ดํ๋ผ์ธ ๊ตฌ์ถ๊ณผ ์๋ํ
QueryPie์์๋ Github Action์ ํตํด CI/CD ํ์ดํ๋ผ์ธ์ด ๊ตฌ์ถ๋์ด ์์ผ๋ฉฐ, ์๋ ๊ฐ ๋จ๊ณ๋ณ๋ก ๋ณด์ ์ฒดํฌํฌ์ธํธ๋ฅผ ๋ฐฐ์นํ์ฌ ์๋์ผ๋ก ๋ณด์ ๊ฒ์ฌ๋ฅผ ์ํํ๊ณ ์์ต๋๋ค. ๋จ๊ณ๋ณ ์ทจ์ฝ์ ์ง๋จ์ ํตํด Medium ์ด์์ ์ทจ์ฝ์ ๋ฐ๊ฒฌ๋ ๊ฒฝ์ฐ, ์ทจ์ฝ์ ์กฐ์น๊ฐ ๋ ์ดํ์ ๋ค์ ๋จ๊ณ๋ก ์งํ๋ ์ ์๋๋ก ์ ์ดํ๊ณ ์์ต๋๋ค. ๊ด๋ฆฌ๋๋ ์ทจ์ฝ์ ์ ํ์ ์๋ ์ด๋ฏธ์ง์ ๊ฐ์ด CI/CD ํ์ดํ๋ผ์ธ ์ ๋จ๊ณ์์ ๋ค์ํ ์ ํ์ ์ทจ์ฝ์ ์ ์ ๊ฒ ๋ฐ ์๋ณํ๊ณ ์ ๊ฑฐํ๋ ๊ด๋ฆฌ ํ๋ก์ธ์ค๋ฅผ ๊ตฌ์ถํ๊ณ ์์ต๋๋ค.

QueryPie DecSecOps ๋จ๊ณ
STEP 0) ๋ฐฐํฌ๋ฅผ ์ํ ์ด๋ฏธ์ง๋ฅผ ์ทจ์ฝ์ ์๋ ๊นจ๋ํ ๊ณจ๋ ์ด๋ฏธ์ง๋ก ๊ด๋ฆฌํฉ๋๋ค. STEP 1) SCA, SAST ์ ๊ฒ์ ํตํด ์์ค์ฝ๋ ์ทจ์ฝ์ ๋ฐ ์คํ์์ค Dependency๋ฅผ ์ ๊ฒํฉ๋๋ค. STEP 2) ๋ฐฐํฌ๋๋ ์ปจํ ์ด๋ ์ด๋ฏธ์ง์ ๋ํ ์ทจ์ฝ์ ์ ์ค์บํฉ๋๋ค. STEP 3) DAST์ ๋ชจ์ํดํน์ ๋ณํํ์ฌ ์ดํ๋ฆฌ์ผ์ด์ ์ทจ์ฝ์ ์ ์ ๊ฒํฉ๋๋ค.


Golden Image ๊ด๋ฆฌ
QueryPie์์๋ ๊ณ ๊ฐ ๋ฐฐํฌ์ฉ ์ด๋ฏธ์ง์ ๋ด๋ถ ํ ์คํธ์ฉ ์ด๋ฏธ์ง๋ฅผ ๋ถ๋ฆฌํด์ ์ฌ์ฉํ๊ณ ์์ต๋๋ค.
๊ฐ ์ด๋ฏธ์ง๋ CIS Benchmark Level 1 ๋ฐ CVE ์ทจ์ฝ์ ์ ์ ๊ฑฐํ Golden Image๋ก ์์ฑํ์ฌ ๊ด๋ฆฌ์ค์ด๋ฉฐ, ์ด์ธ ๋ณ๋์ ์ด๋ฏธ์ง๋ ์ฌ์ฉ์ด ๋ถ๊ฐํ๋๋ก ํต์ ํ๊ณ ์์ต๋๋ค.
์ด๋ฏธ์ง ํ๋๋์ ๋ณด์ํ์์ ์์ฒด ์ ์ํ ์คํฌ๋ฆฝํธ๋ฅผ ํตํด CIS Benchmark Level 1 ๋ฐ CVE ์ทจ์ฝ์ ์ ์ ๊ฑฐํฉ๋๋ค.
๋ค์์ OS Image Hardening ์ ์ํ CIS Benchmark ์ ๊ฒ ํญ๋ชฉ ์ ๋๋ค.
| ์นดํ ๊ณ ๋ฆฌ | ์ธ๋ถ ์ ๊ฒ ํญ๋ชฉ |
|---|---|
| 1. Initial Setup | 1.1 Filesystem 1.2 Configure Software and Patch Management 1.3 Configure Secure Boot Settings 1.4 Configure Additional Process Hardening 1.5 Mandatory Access Control 1.6 Configure Command Line Warning Banners |
| 2. Services | 2.1 Configure Time Synchronization 2.2 Configure Special Purpose Services 2.3 Configure Service Clients |
| 3. Network Configuration | 3.1 Configure Network Devices 3.2 Configure Network Kernel Modules 3.3 Configure Network Kernel Parameters 3.4 Configure Host Based Firewall |
| 4. Access, Authentication, and Authorization | 4.1 Configure Job Schedulers 4.2 Configure SSH Server 4.3 Configure Privilege Escalation 4.4 Configure Pluggable Authentication Modules 4.5 User Accounts and Environment |
| 5. Logging and Auditing | 5.1 Configure Logging 5.2 Configure System Accounting (auditd) 5.3 Configure Integrity Checking |
| 6. System Maintenance | 6.1 System File Permissions 6.2 Local User and Group Settings |
์ ์ ๊ฒ ํญ๋ชฉ์ ๊ธฐ๋ฐ์ผ๋ก ์๋์ ๊ฐ์ด Remediation Script ๋ฅผ ์์ฑํ๊ณ ์๋์ผ๋ก Configuration ์ ์กฐ์ ํฉ๋๋ค.

์ฝ๋ ๋ณด์ ๊ฒ์ฌ ๋ฐ ์ข ์์ฑ ๊ด๋ฆฌ
๊ฐ๋ฐ ์์ค์ฝ๋์ ๋ณด์ ์ทจ์ฝ์ ์ ์๋ณํ๊ธฐ ์ํด ์ฌ์ฉํ๋ SAST ๋๊ตฌ๋ ๋ฒค๋์ฌ๊ฐ ์ ๊ณตํ๋ ๊ธฐ๋ณธ ํ์ง ๋ฃฐ๋ง์ผ๋ก๋ ์ถฉ๋ถํ์ง ์์ ๊ฒฝ์ฐ๊ฐ ์ข ์ข ์์ต๋๋ค. ์๋๋ ์ทจ์ฝ์ ์ด ํฌํจ๋ ๊ณต๊ฐ ์ํ ์ฝ๋๋ฅผ ๋์์ผ๋ก ๊ธฐ๋ณธ ํ์ง ๋ฃฐ์ ํ์ฉํ ์ทจ์ฝ์ ํ์ง ๊ฒฐ๊ณผ๋ฅผ ๋ณด์ฌ์ค๋๋ค.
package ai.qwiet.springbootkotlinwebgoat
import org.springframework.http.HttpHeaders
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.RequestParam
import org.springframework.web.bind.annotation.RestController
import org.springframework.http.HttpStatus
import org.springframework.http.ResponseEntity
import java.io.InputStreamReader
import java.io.BufferedReader
import java.io.File
import mu.KotlinLogging
import org.apache.logging.log4j.LogManager
@RestController
class HelloController {
val logger = KotlinLogging.logger {}
val secondaryLogger = LogManager.getLogger()
@GetMapping("/")
fun index(): String {
return "Greetings from Spring Boot!"
}
@GetMapping("/greet")
fun greet(@RequestParam("username") username: String): String {
logger.info { "Got request for `/greet`" }
// vulnerability: Sensitive Data Leak
secondaryLogger.debug("Params for `/greet `: $username")
// vulnerability: XSS
return "Greetings ${username}!"
}
fun parseParams(name: String, msg: String): Map<String, String?> {
val checkedName = name.takeUnless { it contains '\\' }?.ifBlank { "default_name" }
val checkedMsg = msg.ifBlank { "default_msg" }
return mapOf("parsed_name" to checkedName, "parsed_msg" to checkedMsg)
}
@GetMapping("/exec")
fun exec(@RequestParam("cmd") cmd: String): ResponseEntity<String> {
logger.info { "Got request for `/exec`!" }
secondaryLogger.debug("Params for `/exec`: $cmd")
var out = "NOP"
if (cmd != "nop") {
// vulnerability: Remote Code Execution
val proc = Runtime.getRuntime().exec(cmd)
val lineReader = BufferedReader(InputStreamReader(proc.getInputStream()))
val output = StringBuilder()
lineReader.lines().forEach { line ->
output.append(line + "\n")
}
out = "Did execute command `$cmd`, got stdout: $output"
}
return ResponseEntity(out, HttpStatus.OK)
}
@GetMapping("/touch_file")
fun touchFile(@RequestParam("name") name: String, @RequestParam("msg") msg: String): ResponseEntity<String> {
logger.info { "Got request for `/touch_file`!" }
secondaryLogger.debug("Params for `/touch_file`: $name | $msg")
if (name.length < 3) {
logger.warn { "The provided name is very short!" }
}
if (name == null || msg == null) {
return ResponseEntity("The `name` & `msg` parameters have to be set.", HttpStatus.OK)
} else {
val parsedParams = parseParams(name, msg)
val fullPath = "/tmp/http4kexample/" + parsedParams["parsed_name"]
val finalMsg = "MESSAGE: " + parsedParams["parsed_msg"]
// vulnerability: Directory Traversal
File(fullPath).writeText(finalMsg)
return ResponseEntity("Did write message `$finalMsg` to file at `$fullPath`", HttpStatus.OK)
}
}
@GetMapping("/debug")
fun debug(@RequestParam("url") url: String): ResponseEntity<String> {
logger.info { "Got request for `/debug`!" }
secondaryLogger.debug("Params for `/debug`: $url")
val headers = HttpHeaders()
headers.add("Location", url)
// vulnerability: Open Redirect
return ResponseEntity(headers, HttpStatus.FOUND)
}
@GetMapping("/render_html")
fun renderHtml(@RequestParam("name") name: String): ResponseEntity<String> {
logger.info { "Got request for `/render_html`!" }
secondaryLogger.debug("Params for `/render_html`: $name")
// vulnerability: XSS
val out = StringBuilder().append("<h1>Hello there, ").append("$name").append("!</h1>").toString()
return ResponseEntity(out, HttpStatus.OK)
}
@GetMapping("/add")
fun add(@RequestParam("x") x: String, @RequestParam("y") y: String): ResponseEntity<String> {
logger.info { "Got request for `/add`!" }
secondaryLogger.debug("Params for `/add`: $x | $y")
val xi = x.toInt()
val xy = y.toInt()
val out = (xi + xy).toString()
return ResponseEntity(out, HttpStatus.OK)
}
}


| Vulnerability Type | Snyk | GitHub |
|---|---|---|
| XSS | Not Detected | Detected |
| Command Injection | Detected | Detected |
| Directory Traversal | Not Detected | Not Detected |
| Open Redirect | Not Detected | Not Detected |
์ด๋ฌํ ์ด์์ ๋์ํ๊ธฐ ์ํ์ฌ ๋ค์ํ SAST ์ ํ์์ ์ปค์คํ ํ์ง ๋ฃฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ง๋ง, ๊ด๋ จ ์ ๋ฌด ๊ฒฝํ์ด ๋ถ์กฑํ ๊ฒฝ์ฐ ์ด๋ฅผ ํจ๊ณผ์ ์ผ๋ก ํ์ฉํ๊ธฐ ์ด๋ ค์ธ ์ ์์ต๋๋ค. QueryPie๋ ์ ํ ๊ฐ๋ฐ ํ๊ฒฝ๊ณผ ๋ณํํ๋ ์ ๊ท ์ทจ์ฝ์ ์ ๋์ํ๊ธฐ ์ํด ์ปค์คํ ํ์ง ํจํด์ ์ง์ ๊ตฌ์ฑํ์ฌ SAST ํ์ง ํจํด์ ํญ์ ์ต์ ์ํ๋ก ์ ์งํ๊ณ ์์ต๋๋ค.
์ดํ์ ์ ํ์ ์์ค์ฝ๋ ์ ์ฅ์์ PR(Pull Request)์ด ์์ฑ๋๋ฉด, GitHub Actions๊ฐ ์คํ๋์ด SAST ๋๊ตฌ์ ํด๋น ์์ค์ฝ๋์ ์ทจ์ฝ์ ์ง๋จ์ ์์ฒญํฉ๋๋ค. ๋ง์ฝ ์ทจ์ฝ์ ์ด ๋ฐ๊ฒฌ๋๋ฉด, ์ด๊ด ์ ์ด ๊ธฐ๋ฅ์ ํตํด ์ทจ์ฝ์ ์ด ํด๊ฒฐ๋ ๋๊น์ง ์์ค์ฝ๋์ ๋ณํฉ์ ์ฐจ๋จํ์ฌ ์ ํ์ ๋ฌด๊ฒฐ์ฑ๊ณผ ๋ณด์์ฑ์ ๋ณด์ฅํฉ๋๋ค.

์ด๋ฏธ์ง ๋ณด์ ๊ฒ์ฆ ๋ฐ SBOM ๊ด๋ฆฌ
์ด๋ฏธ์ง ๋ณด์ ๊ฒ์ฆ
GitHub Actions๋ฅผ ํ์ฉํ์ฌ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ฏธ์ง๋ฅผ ์๋์ผ๋ก ๋น๋ํ๊ณ , ๋น๋๋ ์ด๋ฏธ์ง๋ฅผ Harbor์ ์ ๋ก๋ํ๋ ํ๋ก์ธ์ค๊ฐ ๊ตฌ์ถ๋์ด ์์ต๋๋ค. ์ด ๊ณผ์ ์์ Trivy๋ฅผ ์ฌ์ฉํ์ฌ ์ด๋ฏธ์ง ์ทจ์ฝ์ ์ ์ค์บํฉ๋๋ค.
์ด๋ฏธ์ง์ ์ทจ์ฝ์ ์ด ๋ฐ๊ฒฌ๋๋ฉด, ํด๋น ๊ฒฝ๊ณ ๋ PR์์ ์ฆ์ ์๋ฆผ์ผ๋ก ์ ๊ณต๋์ด ๊ฐ๋ฐ์๊ฐ ์ ์ํ๊ฒ ์ทจ์ฝ์ ์ ์ธ์งํ๊ณ ์กฐ์น๋ฅผ ์ทจํ ์ ์์ต๋๋ค. ํนํ, ์ทจ์ฝ์ ์ด Medium ์ด์์ผ๋ก ๋ถ๋ฅ๋ ๊ฒฝ์ฐ, ํด๋น ์ด๋ฏธ์ง๋ ์กฐ์น ๋์์ด ๋ฉ๋๋ค.
๋ํ, Trivy์ ์ํ ์ค์บ๋ ์ธ์๋ AWS Elastic Container Registry(ECR)์ ์ด๋ฏธ์ง๋ฅผ ์ ๋ก๋ํ์ฌ AWS Inspector๋ฅผ ํตํด ์ถ๊ฐ ์ ๊ฒ์ ์ํํฉ๋๋ค. ์ด๋ฅผ ํตํด Trivy๊ฐ ๋์น ์ ์๋ ์ทจ์ฝ์ ์ ์๋ณํ๊ณ , ์ด๋ฏธ์ง๋ฅผ ๋์ฑ ์ฒ ์ ํ๊ฒ ๋ถ์ํ๊ณ ๊ด๋ฆฌํ ์ ์์ต๋๋ค. ์ด๋ฌํ ํ๋ก์ธ์ค๋ฅผ ํตํด ์ ๋ขฐ์ฑ์ด ๋์ ์ด๋ฏธ์ง๋ฅผ ๋ฐฐํฌํ ์ ์์ต๋๋ค.
SBOM ๊ด๋ฆฌ
QueryPie๋ ๋งค ๋ฆด๋ฆฌ์ฆ๋ง๋ค CycloneDX ํฌ๋งท์ ์ํํธ์จ์ด ์์ฌ ๋ชฉ๋ก(SBOM)์ ์์ฑํ์ฌ ์๋ ๊ด๋ฆฌ ํ๋ก์ธ์ค๋ฅผ ์งํํฉ๋๋ค.
- SBOM ํ์ผ์ ์ค์บํ์ฌ ์ทจ์ฝ์ ์ด ์กด์ฌํ๋ ์คํ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์๋ณํ๊ณ ์กฐ์นํฉ๋๋ค.
- ๋ผ์ด์ผ์ค ์ค์ ์ฌ๋ถ๋ฅผ ํ์ ํ๊ณ , ์ ์๊ถ ๋๋ ๊ท์ ์๊ตฌ์ฌํญ์ ์๋ฐํ์ง ์๋๋ก ๊ด๋ฆฌํฉ๋๋ค.
ํด๋ผ์ฐ๋ ํ๊ฒฝ์ IaC ๋ณด์ ๊ด๋ฆฌ
IaC๋ฅผ ํตํ ๋ฆฌ์์ค ๋ฐฐํฌ ๋ฐ ๊ด๋ฆฌ
IaC (Infrastructure as Code)๋ ์ธํ๋ผ๋ฅผ ์ฝ๋๋ก ๊ด๋ฆฌํ๊ณ ์๋ํํ์ฌ ํ๋ก๋น์ ๋ํ๋ ๊ฒ์ ๋งํฉ๋๋ค. ์ฝ๋ํ ์ธํ๋ผ๋ฅผ ํตํด ์๋ ์ค์ ์ ๋ฒ๊ฑฐ๋ก์์ ์์ ๊ณ , ์๋ํ๋ ๋ฐฐํฌ ํ๋ก์ธ์ค๋ฅผ ํตํด ๋์ฑ ๋ ์ ์ฐํ ์ธํ๋ผ ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํด์ง๋๋ค. ์ฌ๋ฌ ํ๊ฒฝ์์ ์ผ๊ด๋ ์ค์ ์ ๊ตฌํํ ์ ์๊ณ , ํ์์ ๋ฐ๋ผ ์์ ๋ฐ ์ ๋ฐ์ดํธ๊ฐ ๊ฐ๋ฅํฉ๋๋ค. ๊ธฐ์กด์๋ ์๋์ผ๋ก ์ค์ ํด์ผ ํ๋ ์๋ฒ, ๋คํธ์ํฌ, ์คํ ๋ฆฌ์ง์ ๊ฐ์ ์์์ ์ฝ๋ํํ์ฌ ๊ฐ๋จํ ๋ฐฐํฌํ ์ ์์ผ๋ฉฐ, ๋ฐฐํฌ ์๊ฐ์ด ๋จ์ถ๋๊ณ ์ค๋ฅ ๊ฐ๋ฅ์ฑ๋ ์ค์ด๋ญ๋๋ค. ๋ํ, Github์ ๊ฐ์ VCS(Version Control System)์ ์ฐ๊ณํ์ฌ ์ธํ๋ผ ๋ณ๊ฒฝ ์ฌํญ์ ์ถ์ ํ ์ ์์ด, ์ ์ํ ๋์๊ณผ ์์ ์ ์ธ ํ๊ฒฝ ๊ด๋ฆฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํฉ๋๋ค.
IaC ์ค์บ๋์ ํตํ ๋ณด์ ์ทจ์ฝ์ ๊ฒํ ๋ฐ ๊ฐ์
IaC ์ค์บ๋์ ํตํ ๋ณด์ ์ทจ์ฝ์ ๊ฒํ ๋ ๋ฐฐํฌ ์ ์ ๋ฐ์ํ ์ ์๋ ๋ณด์ ๋ฌธ์ ์ ๋ํด IaC layer์์ ์ง์ ํด๊ฒฐํ๋ ๋ฐฉ๋ฒ์ ๋๋ค. ์ด๋ ์ธํ๋ผ ๊ตฌ์ฑ์ ํ์ํ ๋ค์ํ ์ค์ ๋ค์ ์ฝ๋ํ ํ๋ฉด์ ๋ฐ์ํ ์ ์๋ ๋ณด์์์ risk๋ฅผ ์ด๊ธฐ์ ์ฐจ๋จํ๊ณ , ์ฝ๋ ์์ฑ ๋จ๊ณ์์ ์ทจ์ฝ์ ์ ๊ฐ์ ํ์ฌ ๋ณด์์ ๊ฐํํ๋ ๊ฒ์ ์๋ฏธํฉ๋๋ค. ๋น ๋ฅด๊ณ ์ผ๊ด๋ ๋ฐฐํฌ๋ฅผ ๊ฐ๋ฅํ๊ฒ ํด์ฃผ๋ IaC์ ๊ฐ์ ์, ๋์์ ์์ ์ค์ ์ค๋ฅ ํ๋๊ฐ ์ฌ๊ฐํ ๋ณด์ ์ทจ์ฝ์ ์ผ๋ก ์ด์ด์ง ์ ์๋ ์ํ์ ๋ดํฌํ๊ณ ์์ต๋๋ค. ํนํ ์ธํ๋ผ ์ ๋ฐ์ ๊ฑธ์ณ ๋ถํ์ํ ๊ถํ์ค์ , ์๋ชป๋ ์ด๋ฏธ์ง ์์ค ์ฌ์ฉ, ์ ๊ทผ ๊ด๋ฆฌ ๋ฏธํก, Secret ๋ ธ์ถ ๋ฑ์ ๋ฌธ์ ๊ฐ ์ฝ๋์ ๋จ์์๋ค๋ฉด, ์ดํ ๋ฐฐํฌ์์ ๋งค๋ฒ ๊ฐ์ ๋ณด์ ๋ฌธ์ ๋ฅผ ํฌํจํ๊ฒ ๋ฉ๋๋ค. IaC ์ค์บ๋์ ํตํด ์ด์ ๊ฐ์ ์ํ์ ์ฌ์ ์ ๋ฐฉ์งํ๊ณ , ์ ๊ฒ ์ ์ฐจ๋ฅผ CI/CD ํ์ดํ๋ผ์ธ์ ํตํฉํ์ฌ ์๋ํ๋ ๋ณด์์ ๊ตฌํํ ์ ์์ต๋๋ค.

Open Policy Agent(OPA)๋ฅผ ํตํ ์ ์ฑ ๊ฒ์ฆ ๋ฐ ์ ์ฉ
OPA๋ ์ ์ฑ ์ ์ฝ๋๋ก ๊ด๋ฆฌํ๊ณ ๊ฒ์ฆํ ์ ์๋ ๊ธฐ๋ฅ์ ์ ๊ณตํ์ฌ, ๋ฆฌ์์ค๊ฐ ๋ฐฐํฌ๋๊ธฐ ์ ์ ์ ์ฑ ์ ์ฌ์ ๊ฒํ ํ๊ณ ์ ์ฉํ ์ ์์ต๋๋ค. Terraform, Ansible๊ณผ ๊ฐ์ IaC ๋๊ตฌ์ OPA๋ฅผ ๊ฒฐํฉํ์ฌ ์ธํ๋ผ ๋ฐฐํฌ ์ ์ ์ฌ์ ์ ์ ์๋ ์ ์ฑ ์ ์๋์ผ๋ก ์คํํ๊ณ ์ ์ฉํจ์ผ๋ก์จ, ์ผ๊ด๋ ๋ณด์ ํ์ค ์ค์๋ฅผ ๋ณด์ฅํ ์ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ๊ฐ๋ฐ, ์ธํ๋ผํ์ด ๊ฐ๋ณ์ ์ผ๋ก ์ํํ๋ ๋ฐฐํฌ์๋ ์ผ๊ด๋ ์ ์ฑ ์ด ์ ์ฉ๋์ด ๋ณด์์ ์์ ์ฑ์ ๋์ผ ์ ์์ต๋๋ค.
ํด๋ผ์ฐ๋ ํ๊ฒฝ์์๋ ๋ฆฌ์์ค๊ฐ ๋ค์ํ ๊ฒฝ๋ก๋ฅผ ํตํด ์์ฑ๋๊ธฐ ๋๋ฌธ์, ์์ฑ๋ ๋ฆฌ์์ค๋ฅผ ๋ช ํํ ํ์ ํ๊ณ ๊ด๋ฆฌ ๋ฒ์์ ํฌํจํ๋ ๊ฒ์ด ์ค์ํฉ๋๋ค. ๋ณด์ํ์์๋ OPA๋ฅผ ํตํด AWS Native Architecture์์ ๋ถํ์ํ ์๋น์ค๋ ๋ฆฌ์์ค๊ฐ ๋ฐฐํฌ๋์ง ์๋๋ก ์ ์ดํ๊ณ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ํด๋ผ์ฐ๋ ์ธํ๋ผ์ ๊ฐ์์ฑ์ ํ๋ณดํ๊ณ , ๋ชจ๋ ๋ฆฌ์์ค๊ฐ ์ฒด๊ณ์ ์ผ๋ก ๊ด๋ฆฌ๋ ์ ์๋๋กํฉ๋๋ค. ๋ํ ์ฌ์ ์ ์ ์ฉ๋ ์ ์ฑ ์ ๋ฐ๋ผ ๋ณด์ ๊ธฐ์ค์ ๋ง์ง ์๋ ๋ฆฌ์์ค๊ฐ ์์ฑ๋์ง ์๋๋ก ์ฐจ๋จํจ์ผ๋ก์จ, ํจ์จ์ ์ด๊ณ ์์ ํ ํด๋ผ์ฐ๋ ๊ด๋ฆฌ๊ฐ ์ด๋ฃจ์ด์ง ์ ์๋๋ก ํฉ๋๋ค.
๋ํ, ํ๊ทธ๋ ๋ฆฌ์์ค์ ๋ํ ๊ถํ ๊ด๋ฆฌ์ ๋น์ฉ ํต์ ์ ์ค์ํ ์์๋ก, ํน์ ํ๊ทธ๊ฐ ๋๋ฝ๋ ๋ฆฌ์์ค๋ ์ด์ ๊ด๋ฆฌ์ ๋น์ฉ ์ถ์ ์ ์ด๋ ค์์ ์ด๋ํ ์ ์์ต๋๋ค. ๋ณด์ํ์์๋ OPA๋ฅผ ํตํด RiskOwner, Owner ๋ฑ ํ์ ํ๊ทธ๊ฐ ์ง์ ๋์ง ์์ ๊ฒฝ์ฐ ํด๋น ๋ฆฌ์์ค์ ์์ฑ ๋๋ ์คํ์ ์ ํํ๋ ์ ์ฑ ์ ์ ์ฉํ๊ณ ์์ต๋๋ค. ์ด๋ฅผ ํตํด ํ๊ทธ ๊ด๋ฆฌ ๋๋ฝ์ ์ฌ์ ์ ๋ฐฉ์งํ๊ณ , ์๋ํ๋ ์ ์ฑ ์ ์ฉ์ ํตํด ์ผ๊ด๋ ํ๊ทธ ๊ด๋ฆฌ๊ฐ ๊ฐ๋ฅํ๋๋ก ํฉ๋๋ค. ์ด๋ฌํ ์ ๊ทผ์ ํด๋ผ์ฐ๋ ํ๊ฒฝ์์ ์ฒด๊ณ์ ์ธ ์์ ๊ด๋ฆฌ์ ๋ณด์ ์ ์ฑ ์ค์๋ฅผ ์ง์ํ๋ฉฐ, ์ธํ๋ผ์ ์์ ์ฑ๊ณผ ๊ฐ์์ฑ์ ๊ฐํํ๋ ๋ฐ ๊ธฐ์ฌํฉ๋๋ค.
์ง์์ ์ปดํ๋ผ์ด์ธ์ค์ ๊ฑฐ๋ฒ๋์ค๋ฅผ ์ํ IaC ๊ด๋ฆฌ
ISO 27001๊ณผ ๊ฐ์ ๋ณด์ ํ์ค์ ์ธํ๋ผ์ ๊ธฐ๋ฐ์ฑ, ๋ฌด๊ฒฐ์ฑ, ๊ฐ์ฉ์ฑ์ ๋ณด์ฅํ๋ ๋ณด์ ๊ด๋ฆฌ ์ฒด๊ณ์ ๊ตฌ์ถ์ ์๊ตฌํฉ๋๋ค. ๊ทธ๋ฌ๋ ํด๋ผ์ฐ๋ ์ธํ๋ผ์ ๊ฐ์ ํ๊ฒฝ์์๋ ์ธํ๋ผ ๋ณ๊ฒฝ์ด ๋น๋ฒํ๊ณ , ๊ท๋ชจ๊ฐ ๋ฐฉ๋ํด์ง๋ฉด์ ๋ชจ๋ ๋ณ๊ฒฝ ์ฌํญ์ ์๋์ผ๋ก ๊ด๋ฆฌํ๋ ๊ฒ์ ๋ถ๊ฐ๋ฅ์ ๊ฐ๊น์ต๋๋ค. IaC๋ ์ด๋ฌํ ๋ฌธ์ ๋ฅผ ํด๊ฒฐํ๊ธฐ ์ํด ์ธํ๋ผ ๊ตฌ์ฑ์ ์ฝ๋ํํ์ฌ ์๋ํ๋ ๋ฐฉ์์ผ๋ก ๊ด๋ฆฌํ๊ณ , ํ์ํ ์ ์ฑ ์ ํ๋ก๊ทธ๋๋ฐํ์ฌ ๋ฐ๋ณต ๊ฐ๋ฅํ๊ณ ์ผ๊ด๋ ๋ณด์ ๊ตฌ์ฑ์ ์ ์งํ ์ ์๊ฒ ํฉ๋๋ค.
๋์ ์ทจ์ฝ์ ์ ๊ฒ (DAST)
๋ฐฐํฌ ๋จ๊ณ์์์ ์ทจ์ฝ์ ์ง๋จ ํ๋ก์ธ์ค
๋ฐฐํฌ ๋จ๊ณ์์๋ OWASP ZAP์ ํ์ฉํ ๋์ ์ ํ๋ฆฌ์ผ์ด์ ๋ณด์ ํ ์คํธ(DAST)์ ํจ๊ป ๋ชจ์ํดํน์ ๋ณํํ์ฌ ์ข ํฉ์ ์ธ ์ทจ์ฝ์ ์ง๋จ์ ์ํํฉ๋๋ค. DAST ์ํ ๊ณผ์ ๋ ๋จ์ํ ๊ธฐ๋ณธ Active Scan์ผ๋ก ๋๋๋ ๊ฒ์ด ์๋๋ผ, ๋ณด์ํ์ด ์์ฒด ์ ์ํ ์ปค์คํ ์คํฌ๋ฆฝํธ๋ฅผ ํ์ฉํ์ฌ ์ผ๋ฐ ์ฌ์ฉ์ ํ ํฐ์ผ๋ก ์ ๊ทผ ๋ถ๊ฐํ ํ์ด์ง์ ๋ํ ๊ถํ์ ๊ฒ์ฆํ๊ฑฐ๋, ์ธ์ฝ๋ฉ ๋๋ ์ํธํ๋์ด ์ ์ก๋๋ ํจํท์ ๋ํ ํ๋ผ๋ฏธํฐ ๋ณ์กฐ ํ ์คํธ ๋ฑ์ ์งํํฉ๋๋ค.

DAST์ ๋ชจ์ํดํน ๊ณผ์ ์์ Medium ์ด์์ ์ทจ์ฝ์ ์ด ๋ฐ๊ฒฌ๋ ๊ฒฝ์ฐ, ํด๋น ์ทจ์ฝ์ ์ ์กฐ์นํ ํ์์ผ ๋ฐฐํฌ๊ฐ ์๋ฃ๋ฉ๋๋ค. ์ด๋ฅผ ํตํด ์์ ํ ๋ฐฐํฌ๋ฅผ ๋ณด์ฅํ๊ณ , ์์คํ ์ ๋ณด์์ฑ์ ๊ฐํํ๋ ๋ฐ ๊ธฐ์ฌํ๊ณ ์ ํฉ๋๋ค.
์ง์ ๊ฐ๋ฅํ ๋ณด์ ์๋ฃจ์ ์ ์ํ ํ์ ๊ณผ ์ ๋ขฐ ๊ตฌ์ถ
QueryPie๋ ๋ณด์์ ๋จ์ํ ๋จ๊ธฐ ๊ณผ์ ๊ฐ ์๋, ๊ณ ๊ฐ๊ณผ์ ์ฅ๊ธฐ์ ์ธ ์ฝ์์ผ๋ก ์ธ์ํ๋ฉฐ ์ด๋ฅผ ์ต์ฐ์ ๊ณผ์ ๋ก ์ผ๊ณ ์์ต๋๋ค. ์ง์์ ์ธ ๋ณด์ ๊ฐํ๋ฅผ ํตํด ์ ๊ณ์ ์ฃผ์ ๋ณด์ ์ ์ฑ ๊ณผ ์ปดํ๋ผ์ด์ธ์ค๋ฅผ ์ฒ ์ ํ ์ค์ํ๋ฉฐ, ๊ณ ๊ฐ์ด ์ ๋ขฐํ ์ ์๋ ์์ ํ ํ๊ฒฝ์ ์ ๊ณตํ๊ธฐ ์ํด ์ต์ ์ ๋คํ๊ณ ์์ต๋๋ค. CI/CD ํ์ดํ๋ผ์ธ์ ๋ค์ํ ๋ณด์ ํ ์คํธ๋ฅผ ํตํฉํ์ฌ ๊ฐ๋ฐ ์ฃผ๊ธฐ ์ ๋ฐ์ ๊ฑธ์ณ ์ทจ์ฝ์ ์ ์ฒ ์ ํ ์ ๊ฒํ๊ณ ์์ผ๋ฉฐ, ์ต๊ทผ์๋ ํผ์ง(Fuzzing) ํ ์คํธ๋ฅผ ์ถ๊ฐํ์ฌ ์๋น์ค ๊ฑฐ๋ถ ๊ณต๊ฒฉ(DOS)๊ณผ ๊ฐ์ ์ํ์ ์กฐ๊ธฐ์ ๋ฐ๊ฒฌํ๊ณ ์ ๋ ธ๋ ฅํ๊ณ ์์ต๋๋ค.

์ด๋ฌํ ๋ ธ๋ ฅ์ ๊ณ ๊ฐ์ด ์์ ํ๊ฒ ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ฅผ ํ ์ ์๋๋ก ๋ณด์ฅํ๋ฉฐ, QueryPie๊ฐ ์ ๊ณตํ๋ ์๋น์ค์ ์ ๋ขฐ์ฑ์ ๋์ฑ ๊ฐํํฉ๋๋ค. ์ฐ๋ฆฌ๋ ์์ผ๋ก๋ ๊ณ ๊ฐ๊ณผ์ ์ ๋ขฐ๋ฅผ ๋ฐํ์ผ๋ก, ์ง์ ๊ฐ๋ฅํ ๋ณด์ ์๋ฃจ์ ์ ์ ๊ณตํ๊ธฐ ์ํด ๋์์์ด ๋ฐ์ ํ ๊ฒ์ ๋๋ค.


