๋„ท๋ผ ๋ณด์•ˆ

๋ฐœํ–‰: (2026๋…„ 6์›” 14์ผ PM 10:49 GMT+9)
8 ๋ถ„ ์†Œ์š”
์›๋ฌธ: Dev.to

๐Ÿ”ฑ Netra ๋ณด์•ˆ ๊ตฌ์ถ•: ํŒŒ์ด์ฌ ๊ธฐ๋ฐ˜ ์ •์  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ณด์•ˆ ํ…Œ์ŠคํŠธ(SAST) ๋„๊ตฌ ๋งŒ๋“ค๊ธฐ

์ €๋Š” ์‚ฌ์ด๋ฒ„๋ณด์•ˆ ํ•™์ƒ์œผ๋กœ์„œ SonarQube, Semgrep ๋ฐ ๊ธฐํƒ€ ์ •์  ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ณด์•ˆ ํ…Œ์ŠคํŠธ(SAST) ํ”Œ๋žซํผ์ด ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ํ”„๋กœ๋•์…˜์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ์ทจ์•ฝ์ ์„ ์–ด๋–ป๊ฒŒ ์‹๋ณ„ํ•˜๋Š”์ง€์— ๋Œ€ํ•ด ํ•ญ์ƒ ํ˜ธ๊ธฐ์‹ฌ์„ ๊ฐ€์ ธ์™”์Šต๋‹ˆ๋‹ค.
์ด ๋„๊ตฌ๋“ค์„ ๋‹จ์ˆœํžˆ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์— ๊ทธ์น˜์ง€ ์•Š๊ณ  ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๋Š”์ง€ ์ดํ•ดํ•˜๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค. ์ด ํ˜ธ๊ธฐ์‹ฌ์ด Netra Security๋ผ๋Š” ๊ฒฝ๋Ÿ‰ SAST ํ”Œ๋žซํผ์„ ํŒŒ์ด์ฌ์œผ๋กœ ๊ตฌํ˜„ํ•˜๊ฒŒ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” ํ”„๋กœ์ ํŠธ์˜ ๋™๊ธฐ, ์ž‘๋™ ๋ฐฉ์‹, ๊ทธ๋ฆฌ๊ณ  ์ด๋ฅผ ๊ตฌ์ถ•ํ•˜๋ฉด์„œ ๋ฐฐ์šด ์ ์„ ๊ณต์œ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

What is Netra Security?

Netra ๋ณด์•ˆ์€ ๋ฌด์—‡์ธ๊ฐ€์š”?
Netra Security๋Š” ์†Œ์Šค ์ฝ”๋“œ์—์„œ ์ง์ ‘ ์ผ๋ฐ˜์ ์ธ ๋ณด์•ˆ ์ทจ์•ฝ์ ์„ ์‹๋ณ„ํ•˜๋„๋ก ์„ค๊ณ„๋œ ํŒŒ์ด์ฌ ๊ธฐ๋ฐ˜ ์ •์  ์ฝ”๋“œ ๋ถ„์„ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

๋„ค๋ผ(Netra)๋ผ๋Š” ์ด๋ฆ„์€ โ€˜์ œ3์˜ ๋ˆˆโ€™์ด๋ผ๋Š” ๊ฐœ๋…์—์„œ ์˜๊ฐ์„ ๋ฐ›์•˜์œผ๋ฉฐ, ์ด๋Š” ์ทจ์•ฝ์ ์ด ์•…์šฉ๋˜๊ธฐ ์ „์— ์ˆจ๊ฒจ์ง„ ๋ณด์•ˆ ๋ฌธ์ œ๋ฅผ ํƒ์ง€ํ•  ์ˆ˜ ์žˆ๋Š” ๋Šฅ๋ ฅ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

์ด ํ”„๋กœ์ ํŠธ์˜ ๋ชฉํ‘œ๋Š” ์—”ํ„ฐํ”„๋ผ์ด์ฆˆ ๋ณด์•ˆ ์Šค์บ๋„ˆ๋ฅผ ๋Œ€์ฒดํ•˜๋Š” ๊ฒƒ์ด ์•„๋‹ˆ๋ผ ๋‹ค์Œ๊ณผ ๊ฐ™์€ fondamentals์„ ํ•™์Šตํ•˜๋Š” ๊ฒƒ์ด์—ˆ์Šต๋‹ˆ๋‹ค:

  • ์ •์  ์ฝ”๋“œ ๋ถ„์„
  • ๋ณด์•ˆ ์ฝ”๋”ฉ ์‹ค์ฒœ
  • ์ทจ์•ฝ์  ํƒ์ง€
  • ์ถ”์ƒ ๊ตฌ๋ฌธ ํŠธ๋ฆฌ(AST) ๋ถ„์„
  • ๋ณด์•ˆ ๋„๊ตฌ ๊ฐœ๋ฐœ

๋ฌธ์ œ์ 

๋งŽ์€ ๋ณด์•ˆ ์ทจ์•ฝ์ ์ด ๊ฐœ๋ฐœ ๊ณผ์ •์—์„œ ๋„์ž…๋ฉ๋‹ˆ๋‹ค.

os.system(user_input)
eval(user_input)
exec(user_input)
pickle.loads(user_data)
subprocess.run(user_input, shell=True)

These patterns can lead to:

  • ๋ช…๋ น์–ด ์ฃผ์ž…
  • ์ฝ”๋“œ ์ฃผ์ž…
  • ์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰
  • ์œ„ํ—˜ํ•œ ์ง๋ ฌํ™”

Netra Security์˜ ์•„์ด๋””์–ด๋Š” ๊ฐ„๋‹จํ•ฉ๋‹ˆ๋‹ค: ์ทจ์•ฝ์  ๋ฐœ์ƒ ์ด์ „์— ๋ถˆ์•ˆ์ „ํ•œ ์ฝ”๋”ฉ ํŒจํ„ด์„ ํƒ์ง€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๋ฒ„์ „ 1: ๊ทœ์น™ ๊ธฐ๋ฐ˜ ๊ฐ์ง€

Netra Security์˜ ์ฒซ ๋ฒˆ์งธ ๋ฒ„์ „์€ ๋ฌธ์ž์—ด ๋งค์นญ๊ณผ ์ •๊ทœ์‹์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

{
     "id": "NETRA-001",
     "pattern":  "os.system(",
     "issue":  "Command Injection",
     "severity": "CRITICAL"
}

์Šค์บ๋„ˆ๋Š” ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์ค„ ๋‹จ์œ„๋กœ ์ฝ์œผ๋ฉฐ ์œ„ํ—˜ํ•œ ํŒจํ„ด์ด ๋‚˜ํƒ€๋‚˜๋Š”์ง€ ํ™•์ธํ•ฉ๋‹ˆ๋‹ค.
์ด ์ ‘๊ทผ ๋ฐฉ์‹์€ ๊ตฌํ˜„ํ•˜๊ธฐ ์‰ฌ์› ๊ณ  ๊ธฐ๋ณธ์ ์ธ ํƒ์ง€์— ์ƒ๋‹นํžˆ ์ž˜ ์ž‘๋™ํ–ˆ์Šต๋‹ˆ๋‹ค.

False Positives

์˜ˆ๋ฅผ ๋“ค์–ด:

message  =  "Never use eval() in production"

๊ฐ„๋‹จํ•œ ๋ฌธ์ž์—ด ์Šค์บ๋„ˆ๋Š” ์ด ํ…์ŠคํŠธ๊ฐ€ ์‹ค์ œ ์ทจ์•ฝ์ ์ด ์•„๋‹ˆ๋ผ๋Š” ์ ์„ ์ž˜๋ชป ์ธ์‹ํ•˜์—ฌ ์˜คํƒ์ง€๋ฅผ ์ผ์œผํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Introducing AST Analysis

ํŒŒ์ด์ฌ์€ ๋‚ด์žฅ ๋ชจ๋“ˆ์ธ ast(์ถ”์ƒ ๊ตฌ๋ฌธ ํŠธ๋ฆฌ)๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
AST๋Š” ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์‹ค์ œ ํ”„๋กœ๊ทธ๋žจ์˜ ๋กœ์ง์„ ๋‚˜ํƒ€๋‚ด๋Š” ํŠธ๋ฆฌ ๊ตฌ์กฐ๋กœ ๋ณ€ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

for node in ast.walk(tree):
    if isinstance(node, ast.Call):
        if isinstance(node.func, ast.Attribute):
            if node.func.attr == "system":
                print("๋ช…๋ น์–ด ์ฃผ์ž… ์œ„ํ—˜")

์ด ๋ฐฉ์‹์€ ์˜คํƒ์ง€๋ฅผ ํฌ๊ฒŒ ์ค„์ด๊ณ  ๋ณด๋‹ค ์‹ ๋ขฐํ•  ๋งŒํ•œ ๊ฒฐ๊ณผ๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ˜„์žฌ ๊ฐ์ง€๋˜๋Š” ์ทจ์•ฝ์ 

Netra Security๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ทจ์•ฝ์ ์„ ํƒ์ง€ํ•ฉ๋‹ˆ๋‹ค:

ID์ทจ์•ฝ์ ์‹ฌ๊ฐ๋„
NETRA-001๋ช…๋ น์–ด ์ฃผ์ž…์‹ฌ๊ฐ๋„
NETRA-002์ฝ”๋“œ ์ฃผ์ž…์‹ฌ๊ฐ๋„
NETRA-003ํ•˜๋“œ์ฝ”๋”ฉ ๋น„๋ฐ€๋ฒˆํ˜ธ๋†’์Œ
NETRA-004ํ•˜๋“œ์ฝ”๋”ฉ API ํ‚ค๋†’์Œ
NETRA-005์ž„์˜ ์ฝ”๋“œ ์‹คํ–‰์‹ฌ๊ฐ๋„
NETRA-006๋ถˆ์•ˆ์ „ํ•œ ์ง๋ ฌํ™”๋†’์Œ
NETRA-007์œ„ํ—˜ํ•œ ์„œ๋ธŒํ”„๋กœ์„ธ์Šค ์‚ฌ์šฉ๋†’์Œ

์ƒ˜ํ”Œ ์ถœ๋ ฅ

=== NETRA ๋ณด์•ˆ ๋ณด๊ณ ์„œ ===
์ด ๊ฒฐ๊ณผ: 5
ID        : NETRA-001
์‹ฌ๊ฐ๋„  : CRITICAL
๋ฌธ์ œ   : ๋ช…๋ น์–ด ์ฃผ์ž…
์ค„      : 13
Code    : os.system(user)
ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•  : Use subprocess.run(..., shell=False)

๋ฐฐ์šด ์ 

์ •์  ๋ถ„์„์€ ์ƒ๊ฐ๋ณด๋‹ค ํ›จ์”ฌ ๋ณต์žกํ•ฉ๋‹ˆ๋‹ค

์ฒ˜์Œ์—๋Š” ๋ณด์•ˆ ์Šค์บ๋‹์ด ์ฃผ๋กœ ํŒจํ„ด ๋งค์นญ์— ๊ธฐ๋ฐ˜ํ•œ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์Šต๋‹ˆ๋‹ค.
์‹ค์ œ๋กœ,false ์–‘์„ ์ค„์ด๋Š” ๊ฒƒ์€ ๊ฐ€์žฅ ์–ด๋ ค์šด ๊ณผ์ œ ์ค‘ ํ•˜๋‚˜์ž…๋‹ˆ๋‹ค.

AST๋Š” ๋งค์šฐ ๊ฐ•๋ ฅํ•ฉ๋‹ˆ๋‹ค

AST๋Š” ์›์‹œ ํ…์ŠคํŠธ๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ ๋™์ž‘์— ๊ธฐ๋ฐ˜ํ•œ ๋ถ„์„์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
์ด๊ฒƒ์€ ์ „๋ฌธ ๋ณด์•ˆ ๋„๊ตฌ๊ฐ€ ์ •ํ™•๋„๋ฅผ ๋†’์ด๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค.

๋ณด์•ˆ๊ณผ ๊ฐœ๋ฐœ์€ ๋ฐ€์ ‘ํ•˜๊ฒŒ ์—ฐ๊ด€๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค

๋ณด์•ˆ์„ ์ดํ•ดํ•˜๋Š” ๊ฐœ๋ฐœ์ž๋Š” ์ทจ์•ฝ์ ์ด ํ”„๋กœ๋•์…˜์— ๋„๋‹ฌํ•˜๊ธฐ ์ „์— ๋งŽ์€ ๋ฌธ์ œ๋ฅผ ์˜ˆ๋ฐฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Future Improvements

The project is still evolving.
Planned features include:

  • ์ถ”๊ฐ€ OWASP Top 10 ๊ฒ€์‚ฌ
  • ๋‹ค์ค‘ ํŒŒ์ผ ํ”„๋กœ์ ํŠธ ์Šค์บ”
  • ํด๋” ์ˆ˜์ค€ ๋ถ„์„
  • Flask๋ฅผ ์ด์šฉํ•œ ์›น ๋Œ€์‹œ๋ณด๋“œ
  • JSON ๋ฐ CSV ๋ณด๊ณ ์„œ ๋‚ด๋ณด๋‚ด๊ธฐ
  • ์œ„ํ—˜ ์ ์ˆ˜ ์—”์ง„
  • CI/CD ํ†ตํ•ฉ
  • GitHub ์ €์žฅ์†Œ ์Šค์บ”

์ตœ์ข… ์ƒ๊ฐ

Netra Security๋ฅผ ๊ตฌ์ถ•ํ•˜๋ฉด์„œ ์ •์  ๋ถ„์„ ๋„๊ตฌ๊ฐ€ ์–ด๋–ป๊ฒŒ ์ž‘๋™ํ•˜๊ณ  ์†Œํ”„ํŠธ์›จ์–ด๊ฐ€ ๋ฐฐํฌ๋˜๊ธฐ ์ „์— ์ทจ์•ฝ์ ์ด ์–ด๋–ป๊ฒŒ ํƒ์ง€๋  ์ˆ˜ ์žˆ๋Š”์ง€ ๋” ๊นŠ์ด ์ดํ•ดํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
์ด ํ”„๋กœ์ ํŠธ๋Š” ๋‹จ์ˆœํ•œ ํŒจํ„ด ๋งค์นญ ์Šค์บ๋„ˆ๋กœ ์‹œ์ž‘ํ•ด ์ ์ฐจ AST ๊ธฐ๋ฐ˜ ๋ณด์•ˆ ๋ถ„์„ ์—”์ง„์œผ๋กœ ์ง„ํ™”ํ–ˆ์Šต๋‹ˆ๋‹ค.

์•„์ง๋„ ๊ธด ์—ฌ์ •์ด ๋‚จ์•„ ์žˆ์ง€๋งŒ, ์ด๊ฒƒ์ด ์‚ฌ์ด๋ฒ„๋ณด์•ˆ๊ณผ ์†Œํ”„ํŠธ์›จ์–ด ์—”์ง€๋‹ˆ์–ด๋ง์ด ํฅ๋ฏธ๋กœ์šด ์ด์œ ์ž…๋‹ˆ๋‹คโ€”ํ•ญ์ƒ ์ƒˆ๋กœ์šด ๊ฒƒ์„ ๋ฐฐ์šฐ๊ณ  ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

ํŒŒ์ด์ฌ, ์‚ฌ์ด๋ฒ„๋ณด์•ˆ, ๋˜๋Š” ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋ณด์•ˆ์„ ๊ณต๋ถ€ ์ค‘์ด๋ผ๋ฉด ์ž์ฒด ๋ณด์•ˆ ๋„๊ตฌ๋ฅผ ๊ตฌ์ถ•ํ•˜๋Š” ๊ฒƒ์„ ๊ฐ•๋ ฅํžˆ ์ถ”์ฒœํ•ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด ๋„๊ตฌ๋งŒ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ๋ณด๋‹ค ํ›จ์”ฌ ๋” ๋งŽ์ด ๋ฐฐ์šธ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ฝ์–ด์ฃผ์…”์„œ ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค!

Netra ๋ณด์•ˆ

python #cybersecurity #appsec #security #sast #flask #beginners #opensource

0 ์กฐํšŒ
Back to Blog

๊ด€๋ จ ๊ธ€

๋” ๋ณด๊ธฐ ยป