html/php 학습

Simcurity·2023년 5월 5일
0

html/css/javascript/php

목록 보기
4/4

오늘도 php를 학습하겠습니다.

1. 리팩터링

리팩터링이란 코드의 복잡성을 낮추고 효율성을 높이기 위한 일종의 정리정돈으로 볼 수 있습니다.
정보처리기사 따던 시절에 배웠던 것으로 코드의 유지보수와 가독성을 높이기위해 중복을 제거하는 필수적인 과정입니다.

index.php와 create.php의 경우 상단에 함수를 정의하는 부분이 중복으로 쓰이며 함수 하나를 수정해도 여러 파일들을 확인하고 수정해야하므로 효율성이 떨어지고 실수할 가능성이 높기에 lib라는 디렉터리를 만들고 그안에서 필요할 때마다 꺼내오는 방식으로 require함수를 사용하겠습니다.

lib/print.php 파일 생성
<?php
function name() {
        if(isset($_GET['id'])) {
                echo $_GET['id'];
        } else {
                echo "Welcome";
        }
}

function li() {
        $list = scandir('data/');
        $i = 0;
        while($i < count($list)) {
                if($list[$i] != '.'){
                        if($list[$i] != '..') {
                                echo "<li><a href = \"index.php?id=$list[$i]\">$list[$i]</a></li>\n";
                        }
                }
                $i= $i +1;
        }
}

function content() {
        if(isset($_GET['id'])) {
                echo file_get_contents("data/".$_GET['id']);
        } else {
                echo "Hello PHP";
        }
}
?>

index.php, create.php, update.php 파일에서 함수 정의하는 부분을 모두 없애준후
require('lib/print.php'); 추가

정상적으로 작동
리팩터링을 통한 중복코드 제거 완료했습니다.
실제로 php파일의 길이가 매우 짧아졌습니다.

또한, index.php, create.php, update.php 의 바디의 경우

<?php
require('lib/print.php');
?>

<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8">
        <title>
                <?php
                        name();
                ?>
        </title>
</head>
<body>
        <h1><a href = "index.php">WEB</a></h1>
        <ol>
                <?php
                        li()
                ?>
        </ol>

모두 같은 내용을 가지고 있음을 알고 있습니다.
이 부분을 또 다시 view라는 디렉터리안에 top.php라는 파일에 넣고 require로 불러오겠습니다.
마지막에

</body>
</html>

또한 view/bottom.php파일에 작성하여 require로 호출

<?php
require('lib/print.php');
require('view/top.php');
?>

        <a href = "create.php">Create</a><br>
        <?php
                                if(isset($_GET['id'])) {?>
                                        <a href = "update.php?id=<?= $_GET['id'];?>">Update</a><br>
                                <form action = "delete.process.php" method = "POST">
                                <p>
                                <input type = "hidden" name = "id" value = "<?= $_GET['id'];?>"/>
                                </p>
                                <input type = "submit" value = "Delete"/>
                                </p>
                                </form>
        <?php } ?>


        <h2>
        <?php
                name()
        ?>
        </h2>
        <h3>
        <?php
                content()
        ?>
<?php
require('view/bottom.php');
?>

처음의 index.php에 비해 매우 짧아졌습니다.

하지만, title()이라는 함수는 어디서 온지 모릅니다. 그래서 이를 명확하게 하기 위해 top.php에도 require함수로 print.php를 불러오면 오류가 생깁니다.
아무것도 뜨지 않습니다.
그 이유는 title()함수가 2번 정의되었기 때문입니다. php에서는 함수를 중복 선언하는 것을 금지합니다.
그래서 이 문제를 해결하기 위해 require함수를 require_once()함수로 교체해 줍니다.
이 함수를 사용하면 print.php가 실행되고 top.php에서 print.php가 실행될 때 이미 실행되었으므로 실행을 무시합니다. 그렇게 중복을 방지합니다.

수정 후 정상 작동
이제 코드는 한결 아름다워졌습니다.

2. 보안 - XSS

크로스 사이트 스크립팅이란 사용자 입력 값에 스크립트 언어를 삽입하여 사용자의 개인정보 유출, 의도하지 않은 행위 등을 유발할 수 있는 심각한 보안 문제입니다.

<!DOCTYPE html>
<html>
<head>
        <meta charset="utf-8">
        <title></title>
</head>
<body>
        <h1>XSS</h1>
        <?php
                echo '<script>alert("Hello");</script>'
        ?>
</body>
</html>


xss.php 접속 시 알림 창

이를 방지하기 위해 PHP에는 두 가지의 함수가 있습니다.

2-1) htmlspecialchars() 함수

이 함수는 스크립트 언어에 주로 쓰이는 <,>," 등의 문자들을 치환 시켜줍니다.

htmlspecialchars() 함수 적용 후 페이지 모습 (문자 취급)
이제 나머지 사용자의 입력 값이 echo하는 곳을 모두 보완하겠습니다.

print.php 파일
<?php
function name() {
        if(isset($_GET['id'])) {
                echo htmlspecialchars($_GET['id']);
        } else {
                echo "Welcome";
        }
}

function li() {
        $list = scandir('data/');
        $i = 0;
        while($i < count($list)) {
                $title = htmlspecialchars($list[$i]);
                if($list[$i] != '.'){
                        if($list[$i] != '..') {
                                echo "<li><a href = \"index.php?id=$title\">$title</a></li>\n";
                        }
                }
                $i= $i +1;
        }
}

function content() {
        if(isset($_GET['id'])) {
                htmlspecialchars(echo file_get_contents("data/".$_GET['id']));
        } else {
                echo "Hello PHP";
        }
}
?>


이제 XSS 공격에 대해 최소한의 보완조치를 했다고 볼 수 있습니다.

2-2) strip_tags() 함수

그러나, htmlspecialchars() 함수는 사용 시 몇몇 필수적인 태그를 이용하지 못할 수 있습니다.
그래서 PHP에서는 strip_tags()라는 함수를 제공합니다. 이 함수는 특정 태그는 허용하도록 설정이 가능한 함수입니다.

3. 보안 - 파일 경로 보호

파일 경로 보호란 사용자가 입력 값을 조작하여 임의의 경로로 이동 후 파일을 읽는 경로 조작 취약점과 비슷한 원리의 공격으로부터 보호하기 위한 것이다.
id 파라미터 조작 후 passwd 파일 조회

이를 방지하기 위하여 PHP에서는 basename()이라는 함수가 있습니다.
이 함수는 파일의 경로에서 파일명만을 추출하여 경로 조작을 하지 못하도록 하는 함수입니다.
바로 적용해보겠습니다.

코드 수정 후 경로 조작 시 첫 번째 줄부터 입력 값, basename()함수 적용된 입력 값, 입력 값 그대로 시 결과 입니다.
즉 basename()함수 적용 시 경로에 대한 문자들은 사라지고 파일 명만 남았습니다.

또한 파일 삭제 시 웹 프록시 툴을 이용해 충분히 조작이 가능하므로 ../index.php 와 같은 입력 값으로 서버에 중요한 파일을 삭제할 수 있습니다.
그러므로 delete.process.php파일에서도 받아온 form 데이터 값에 basename()함수를 사용해주어야 합니다.

4. 배운 함수들

<form action = "~~~" method = ~ >
  </form> ---> 데이터 전송
<input type = "~" name = "~" placeholder = "~" value = "~">
<textarea name = "~"></textarea>
<script>location.href = "~~~~"</script> ---> 다른 페이지로 우회
<p>
</p> ---> 태그별 줄바꿈

isset() ---> 값이 있는지 없는지
rename() ---> 파일 이름 변경
scandir() ---> 디렉터리 검색
unlink() ---> 파일 삭제
file_get_contents() ---> 파일 내용 가져오기
file_put_contents() ---> 파일 내용 넣기
header('Location: ~~~') ---> 페이지 리다이렉션
htmlspecialchars() ---> XSS 방지
strip_tags() ---> 허용 태그 설정할 수 있는 XSS 방지 함수
basename() ---> 경로 조작 방지
require() ---> 다른 php파일 참조 (리팩터링)
require_once() ---> 한번만 정의
php에서 echo 할 때 html 중간의 파라미터 값은 양 옆에 .을 붙여준다

출처 : 생활코딩 PHP+MySQL

0개의 댓글