본문 바로가기
Language/php

폼 처리 - XSS 공격

by 잘먹는 개발자 에단 2024. 9. 11.

폼은 HTML의 <form> 요소를 사용하여 작성됩니다.

 

폼은 사용자들로부터 입력 받을 필드들을 포함합니다.

 

예를 들면 <input>이라던지 <select> <textarea>등을 예시로 들 수 있습니다.

다양한 형태가 있습니다.

 

이런 폼을 통해서 사용자로부터 입력받은 데이터를 서버에 전달하여 서버가 처리할 수 있도록 하는데 주로 2가지 방식을 사용합니다.

 

 

바로 GET과 POST 입니다.

각각 용도와 사용법이 다릅니다.

 

 

먼저 GET 방식부터 알아볼까요?

 

GET 방식은 데이터를 URL의 쿼리 스트링에 데이터를 포함해서 서버에 전송합니다.

그러나 보안에 취약하고 데이터가 URL에 그대로 노출되기 때문에 민감한 정보를 전송할 때는 적합하지 않으나

 

최근에 보니 이런 영상도 있더라구요.  "상남자는 URL 따위 쓰지 않는다"...

워낙 유명한 분이 만든 영상이라서 한번 보시길 바랍니다..ㅋㅋ 

https://www.youtube.com/watch?v=pCOBmmJARPE

 

각설하고, GET 방식은 데이터 전송이 빠르고 간단합니다. 

그래서 주로 검색 페이지나 데이터 조회에 많이 사용됩니다.

 

그러면 URL에 또 무한정 데이터를 넣을 수 있는거냐 라고 물어보신다면 그건 아닙니다.

URL 길이 제한이 보통 2048자라서 한정되어있어요.

 

 

다음으로는 POST 방식에 대해서 알아보겠습니다.

우리가 API 연동할때 사실 거의 POST 방식을 많이 쓰곤해요.

 

POST 방식은 데이터를 HTTP 요청의 본문에 포함해서 서버로 전송합니다.

GET 방식과는 다르게 데이터가 URL에 노출되지 않으니까, 민감한 정보를 전송할 때 적합하지만, 

HTTPS가 아닌 경우에 데이터는 여전히 네트워크 상에서 평문으로 전송될 수 있어서 아주 안전하다고 볼 수는 없습니다.

 

주로 로그인 / 회원가입 / 파일 업로드 등 데이터의 양이 많거나 보안이 중요한 경우에 사용됩니다.

 

GET 방식처럼 URL에 데이터가 포함되지 않으니 데이터 전송량에도 제한이 없구요.

 

 

 

자 그럼 이번에는 폼을 실제로 서버에다가 보내주는 걸 한번 보겠습니다.

 

먼저 GET 방식입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>GET 방식 폼</title>
</head>
<body>
    <h1>GET 방식 폼</h1>
    <!-- 폼의 데이터를 처리할 PHP 파일로 데이터를 전송함 -->
    <form action="process_get.php" method="get">
        <!-- 사용자로부터 이름을 입력받는 필드 -->
        <label for="name">이름:</label>
        <input type="text" id="name" name="name">
        <br>
        <!-- 사용자로부터 이메일을 입력받는 필드 -->
        <label for="email">이메일:</label>
        <input type="email" id="email" name="email">
        <br>
        <!-- 폼을 제출하는 버튼 -->
        <input type="submit" value="제출">
    </form>
</body>
</html>

 

php 카테고리에 넣었으니 php로 처리하는 걸 한번 보겠습니다.

<?php
// process_get.php

// GET 방식으로 전송된 데이터를 받음
$name = $_GET['name'];  // 'name' 필드의 데이터를 가져옴
$email = $_GET['email'];  // 'email' 필드의 데이터를 가져옴

// 가져온 데이터를 출력 (주로 이 데이터를 처리하거나 DB에 저장하는 로직이 들어감)
echo "이름: " . htmlspecialchars($name) . "<br>";
echo "이메일: " . htmlspecialchars($email) . "<br>";
?>

 

 

만약에 html 과 php가 같은 파일 내에 있으면 어떻게 하면 될까요?

이 부분 말이에요.

    <form action="process_get.php" method="get">

 

저번 글에서 이런 내용을 담은 바 있습니다.

 

$_SERVER["PHP_SELF"]는 현재 실행되고 있는 php 파일의 경로를 나타낸다.

즉 이 코드를 사용하면 현재 페이지로 폼을 제출하게 된다.

예를 들어서, 이 코드가 login.php 파일에 있다면

$_SERVER["PHP_SELF]는 /login.php 를 반환한다.

 

이렇게 하면 폼이 제출되었을 때 같은 페이지에서 데이터를 처리할 수 있다.

보통 폼이 제출되면 해당 페이지에서 입력값을 검사하고 결과를 사용자에게 보여주는 방식으로 많이 사용된다. 

 

때문에 이런 식으로 바꾸면 됩니다.

 

action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>"

 

HTML에서 php를 삽입하려면 <?php echo ~~~~~ ?>로 하면 됩니다.

 

때문에 귀찮긴 하지만 저렇게 하면 됩니다.

( 귀찮아보여도 php 만큼 편한 언어가 없는 것 같습니다.. 감사합시다 우리.. )

 

그러면 위의 코드에서

<form action="<?php echo htmlspecialchars($_SERVER["PHP_SELF"]); ?>" >

로 작성하면 되겠죠?!

 

 

다음은 POST 방식입니다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>POST 방식 폼</title>
</head>
<body>
    <h1>POST 방식 폼</h1>
    <!-- 폼의 데이터를 처리할 PHP 파일로 데이터를 전송함 -->
    <form action="process_post.php" method="post">
        <!-- 사용자로부터 이름을 입력받는 필드 -->
        <label for="name">이름:</label>
        <input type="text" id="name" name="name">
        <br>
        <!-- 사용자로부터 이메일을 입력받는 필드 -->
        <label for="email">이메일:</label>
        <input type="email" id="email" name="email">
        <br>
        <!-- 폼을 제출하는 버튼 -->
        <input type="submit" value="제출">
    </form>
</body>
</html>
<?php
// process_post.php

// POST 방식으로 전송된 데이터를 받음
$name = $_POST['name'];  // 'name' 필드의 데이터를 가져옴
$email = $_POST['email'];  // 'email' 필드의 데이터를 가져옴

// 가져온 데이터를 출력 (주로 이 데이터를 처리하거나 DB에 저장하는 로직이 들어감)
echo "이름: " . htmlspecialchars($name) . "<br>";
echo "이메일: " . htmlspecialchars($email) . "<br>";
?>

 

얼마나 편안합니까... 

 

슈퍼 글로벌 변수가 있어서 정말 편합니다.

https://codingeverybody.kr/php-%EC%8A%88%ED%8D%BC%EA%B8%80%EB%A1%9C%EB%B2%8C-%EB%B3%80%EC%88%98-%EC%95%8C%EC%95%84%EC%95%BC-%ED%95%A0-%EB%AA%A8%EB%93%A0-%EA%B2%83/

 

PHP 슈퍼글로벌 변수 – 알아야 할 사용법, 활용 방법 그리고 중요성! - 코딩에브리바디

PHP의 슈퍼글로벌 변수는 코드 전체에서 사용할 수 있는 특별한 변수로, 올바르게 활용함으로써 개발 작업을 효율적으로 수행할 수 있습니다. PHP에는 슈퍼글로벌 변수는 9개($_GET, $_POST, $_SERVER, $_

codingeverybody.kr

 

 

 

근데 하나 뭐 이상한거 있지 않나요?

지금 출력을 

echo "이름: " . htmlspecialchars($name) . "<br>";

 

이렇게 하고 있는데 그냥 문자열 리터럴로

echo "{$name}"; 쓰지 왜 저렇게 쓰냐라고 할 수 있는데

 

다시 말하지만 php는 서버사이드렌더링으로 동작합니다.

사용자가 입력을 했을 때 그게 단순히 이름이면 좋겠지만, 꼭! SQL 삽입 공격 같은걸 하려는 친구들이 있답니다.

 

예를 들면

$name = "<script>alert('Hello!');</script>";

// 그냥 출력 (위험)
echo $name; // <script>alert('Hello!');</script> 가 실행됨 (XSS 발생 가능)

// 안전하게 출력 (보안 강화)
echo htmlspecialchars($name); // &lt;script&gt;alert('Hello!');&lt;/script&gt;로 변환되어 HTML에서 실행되지 않음

그 폼 창에다가 저런 걸 넣습니다. 예를 들어서 말이에요.

 

그러면 그대로 

 

 

이렇게 실행되버린답니다. 

비슷한 예시로 JS에서는 이런 말이 있어요. eval is evil 그러니까 eval 쓰지 말라는 이야긴데, 이 또한 비슷합니다.

XSS 공격 ( 크로스 사이트 스크립팅 ) 과 연관되어있어요.

 

 

자 그럼 php에서 이를 막아주는 htmlspecialchars() 함수는 뭘하는 친구일까요?

이 함수는 문자열 내의 HTML 특수 문자를 HTML 엔티티로 변환해줍니다.

이를 통해 악의적인 사용자가 HTML 태그나 스크립트를 삽입하여 웹사이트를 공격하는 것을 방지할 수 있어요.

예를 들어, 사용자가 <script>alert('Hello!');</script>와 같은 스크립트를 입력할 경우, 이를 그냥 출력하면 브라우저에서 실행되어 XSS(크로스 사이트 스크립팅) 공격이 발생할 수 있습니다.

 

htmlspecialchars()는 이러한 특수 문자를 다음과 같이 변환합니다:

 

<&lt;

>&gt;

"&quot;

'&#039;

&&amp;

 

복잡하죠? 외울 필요는 없어요. 이상 끝!

'Language > php' 카테고리의 다른 글

캐싱 예시  (0) 2024.09.11
해시 테이블 사용하기  (0) 2024.09.11
폼 처리  (4) 2024.09.09
예외처리  (0) 2024.09.09
자료구조 및 메서드  (1) 2024.09.09