** ๐Ÿ“ŒSQL ๋ณด์•ˆ ๊ธฐ๋ฒ•**

SQL Injection์„ ์™„๋ฒฝํžˆ ์ฐจ๋‹จํ•˜๋Š” PreparedStatement ๊ธฐ๋ฒ•๊ณผ

์„œ๋ฒ„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋ฅผ ๋ณ‘ํ–‰ํ•˜๋Š” ์‹ค๋ฌด + ๋ฉด์ ‘ ๋Œ€๋น„์šฉ ๋ณด์•ˆ ์ „๋žต ์ •๋ฆฌ


๐Ÿงฉ ๋ชฉ์ฐจ

  1. SQL Injection์ด๋ž€?
  2. ๊ณต๊ฒฉ ์˜ˆ์‹œ ๋ฐ ์œ„ํ—˜์„ฑ
  3. ๋ฐฉ์ง€ ๋ฐฉ๋ฒ•: PreparedStatement
  4. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ณ‘ํ–‰ ์ฒ˜๋ฆฌ
  5. ์‹ค์ „ ์˜ˆ์ œ (์ทจ์•ฝํ•œ ์ฝ”๋“œ โ†’ ์•ˆ์ „ํ•œ ์ฝ”๋“œ)
  6. ์‹ค๋ฌด ๋ณด์•ˆ ํŒ
  7. ๊ธฐ์ˆ  ๋ฉด์ ‘ ๋Œ€๋น„ ํ•ต์‹ฌ ์š”์•ฝ
  8. ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝ + Notion ์ž‘์„ฑ ํŒ

โœ… 1. SQL Injection์ด๋ž€?

ํ•ญ๋ชฉ ์„ค๋ช…
์ •์˜ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅ์ฐฝ์— ์•…์˜์ ์ธ SQL์„ ์ž…๋ ฅํ•ด DB๋ฅผ ์กฐ์ž‘ํ•˜๋Š” ๊ณต๊ฒฉ
๊ฒฐ๊ณผ ๋กœ๊ทธ์ธ ์šฐํšŒ, ๋ฐ์ดํ„ฐ ์‚ญ์ œ, ๋ชจ๋“  ํ…Œ์ด๋ธ” ์—ด๋žŒ ๋“ฑ ์น˜๋ช…์ ์ธ ํ”ผํ•ด ๋ฐœ์ƒ ๊ฐ€๋Šฅ
์œ„ํ—˜๋„ ๐Ÿ”ด ๋งค์šฐ ๋†’์Œ โ†’ ๋ฐ˜๋“œ์‹œ ๋ฐฉ์–ด ์ฝ”๋”ฉ ํ•„์š”

โœ… 2. ๊ณต๊ฒฉ ์˜ˆ์‹œ ๋ฐ ์œ„ํ—˜์„ฑ

-- ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ ID: ' OR 1=1 --
SELECT * FROM members WHERE userid='' OR 1=1 --' AND userpw='...'
๋ฌธ์ œ์  ์„ค๋ช…
' OR 1=1 -- ํ•ญ์ƒ true์ธ ์กฐ๊ฑด์œผ๋กœ ๋กœ๊ทธ์ธ ์šฐํšŒ ๊ฐ€๋Šฅ
-- ๋’ค์˜ ์กฐ๊ฑด๋ฌธ ๋ฌด์‹œ (์ฃผ์„ ์ฒ˜๋ฆฌ๋จ)
๐Ÿšจ ๊ฒฐ๊ณผ ๊ด€๋ฆฌ์ž ๊ณ„์ • ์—†์ด ๋กœ๊ทธ์ธ ์„ฑ๊ณต, DB ์ „์ œ ์กฐํšŒ/๋ณ€์กฐ ๊ฐ€๋Šฅ

โœ… 3. ๋ฐฉ์ง€ ๋ฐฉ๋ฒ•: PreparedStatement ์‚ฌ์šฉ

๋ฐฉ๋ฒ• ์„ค๋ช…
PreparedStatement SQL์— ๋ณ€์ˆ˜ ์ž๋ฆฌ(?)๋ฅผ ๋‘๊ณ , ๊ฐ’์€ ๋”ฐ๋กœ ์ „๋‹ฌํ•˜๋Š” ๋ฐฉ์‹
์žฅ์  ๋‚ด๋ถ€์ ์œผ๋กœ SQL๊ณผ ๊ฐ’์„ ๋ถ„๋ฆฌ โ†’ SQL Injection ๋ถˆ๊ฐ€๋Šฅ
๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉ ๋ชจ๋“  SQL ์ž…๋ ฅ ๊ตฌ๋ฌธ์—์„œ ํ•„์ˆ˜๋กœ ์ ์šฉํ•ด์•ผ ํ•จ

๐Ÿ” ์•ˆ์ „ํ•œ PreparedStatement ์˜ˆ์ œ

String sql = "SELECT * FROM members WHERE userid=? AND userpw=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, userid);  // ๊ฐ’๋งŒ ๋ฐ”์ธ๋”ฉ
ps.setString(2, userpw);  // SQL ๊ตฌ์กฐ๋Š” ๊ฑด๋“œ๋ฆฌ์ง€ ์•Š์Œ

๐Ÿ”ด ์ ˆ๋Œ€ ์‚ฌ์šฉํ•˜๋ฉด ์•ˆ ๋˜๋Š” ๋ฐฉ์‹ (์ทจ์•ฝ)

// ์œ„ํ—˜! ์ง์ ‘ ๋ฌธ์ž์—ด ์—ฐ๊ฒฐ
String sql = "SELECT * FROM members WHERE userid='" + userid + "' AND userpw='" + userpw + "'";

โœ… 4. ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๋ณ‘ํ–‰ ์ฒ˜๋ฆฌ

์œ„์น˜ ์˜ˆ์‹œ ์„ค๋ช…
๐Ÿ’ป JavaScript onsubmit()์—์„œ ๋นˆ์นธ ํ™•์ธ ๋น ๋ฅด๊ณ  ์‚ฌ์šฉ์ž ์นœํ™”์ 
๐Ÿ–ฅ๏ธ Servlet `if(id == null ย 
๋ณ‘ํ–‰ ์ด์œ  JS๋Š” ๊บผ์งˆ ์ˆ˜ ์žˆ์Œ โ†’ ์„œ๋ฒ„ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ๋Š” ํ•„์ˆ˜! ย 

โœ… 5. ์‹ค์ „ ์˜ˆ์ œ (๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ ๊ธฐ์ค€)


๐Ÿ“„ ์•ˆ์ „ํ•œ LoginServlet.java

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {

  req.setCharacterEncoding("UTF-8");
  String userid = req.getParameter("userid");
  String userpw = req.getParameter("userpw");

  // ์„œ๋ฒ„ ์ธก ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ
  if (userid == null || userid.trim().equals("") || userpw == null || userpw.trim().equals("")) {
    PrintWriter out = resp.getWriter();
    out.println("<script>alert('์•„์ด๋””์™€ ๋น„๋ฐ€๋ฒˆํ˜ธ๋ฅผ ๋ชจ๋‘ ์ž…๋ ฅํ•˜์„ธ์š”'); history.back();</script>");
    return;
  }

  // DB ๋กœ๊ทธ์ธ ์ฒ˜๋ฆฌ
  MemberDAO dao = new MemberDAO();
  boolean isValid = dao.login(userid, userpw);

  if (isValid) {
    req.getSession().setAttribute("loginId", userid);
    resp.sendRedirect("main.jsp");
  } else {
    PrintWriter out = resp.getWriter();
    out.println("<script>alert('๋กœ๊ทธ์ธ ์‹คํŒจ'); location.href='login.jsp';</script>");
  }
}

๐Ÿ“„ MemberDAO.java (PreparedStatement ์ ์šฉ)

public boolean login(String id, String pw) {
  boolean result = false;
  try {
    Connection conn = DB.getConnection();
    String sql = "SELECT * FROM members WHERE userid=? AND userpw=?";
    PreparedStatement ps = conn.prepareStatement(sql);
    ps.setString(1, id);
    ps.setString(2, pw);
    ResultSet rs = ps.executeQuery();
    result = rs.next(); // ๊ฒฐ๊ณผ๊ฐ€ ์กด์žฌํ•˜๋ฉด ๋กœ๊ทธ์ธ ์„ฑ๊ณต
    conn.close();
  } catch(Exception e) {
    e.printStackTrace();
  }
  return result;
}

โœ… 6. ์‹ค๋ฌด ๋ณด์•ˆ ํŒ ๐Ÿ›ก๏ธ

ํ•ญ๋ชฉ ์„ค๋ช…
๋ชจ๋“  SQL์— PreparedStatement ์‚ฌ์šฉ SELECT, INSERT, UPDATE, DELETE ์ „๋ถ€
์ž…๋ ฅ๊ฐ’์€ ํ•ญ์ƒ ์œ ํšจ์„ฑ ๊ฒ€์‚ฌ ๊ธธ์ด ์ œํ•œ, ๊ณต๋ฐฑ ์ œ๊ฑฐ, null ์ฒดํฌ ๋“ฑ
DB ๊ณ„์ •์€ ์ตœ์†Œ ๊ถŒํ•œ์œผ๋กœ ์ƒ์„ฑ SELECT/INSERT๋งŒ ํ—ˆ์šฉ (๊ด€๋ฆฌ์ž ๊ถŒํ•œ X)
์—๋Ÿฌ ๋ฉ”์‹œ์ง€๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ์ง์ ‘ ๋…ธ์ถœ ๊ธˆ์ง€ e.printStackTrace()๋Š” ๋กœ๊ทธ๋กœ๋งŒ ๋‚จ๊น€

โœ… 7. ๊ธฐ์ˆ  ๋ฉด์ ‘ ๋Œ€๋น„ ํ•ต์‹ฌ ์š”์•ฝ ๐Ÿ’ฌ

์งˆ๋ฌธ ์š”์  ์ •๋ฆฌ
SQL Injection์ด๋ž€? ์‚ฌ์šฉ์ž๊ฐ€ SQL ๊ตฌ๋ฌธ์„ ์กฐ์ž‘ํ•ด์„œ DB๋ฅผ ๊ณต๊ฒฉํ•˜๋Š” ๋ฐฉ์‹
๋ฐฉ์ง€ ๋ฐฉ๋ฒ•์€? PreparedStatement ์‚ฌ์šฉ์œผ๋กœ SQL๊ณผ ๊ฐ’์„ ๋ถ„๋ฆฌ
Java์—์„œ ์ž…๋ ฅ๊ฐ’ ๊ฒ€์‚ฌ ์˜ˆ์‹œ๋Š”? `if(id == null
์™œ JavaScript๋งŒ์œผ๋กœ๋Š” ์ถฉ๋ถ„ํ•˜์ง€ ์•Š๋‚˜์š”? ๊บผ์งˆ ์ˆ˜ ์žˆ์Œ, ์„œ๋ฒ„์—์„œ๋Š” ๋ฐ˜๋“œ์‹œ ๋ณด์•ˆ ๊ฒ€์‚ฌ ์ˆ˜ํ–‰ ํ•„์š”

โœ… 8. ๋งˆ๋ฌด๋ฆฌ ์š”์•ฝ ๐Ÿง