이안의 평일코딩

[PHP] 리팩토링 (require), XSS, htmlspecialchars, basename 본문

Back-end/PHP

[PHP] 리팩토링 (require), XSS, htmlspecialchars, basename

이안92 2021. 4. 2. 14:53
반응형

 리팩토링이란?

 

코드를 효율적으로 개선, 기능을 그대로두고 유지보수하기 편하게 중복된 코드 제거하고 이상적인 코드로 만드는 작업.

lib디렉토리를 생성해준다.

 

require_once: 중복해서 호출하는 에러를 방지

 

include vs require

include
같은 파일 여러 번 포함 가능 / 포함할 파일이 없어도 다음 코드 실행
include_once
같은 파일 한 번만 포함 / 포함할 파일이 없어도 다음 코드 실행
require
같은 파일 여러 번 포함 가능 / 포함할 파일이 없으면 다음 코드 실행하지 않음
require_once
같은 파일 한 번만 포함 / 포함할 파일이 없으면 다음 코드 실행하지 않음

 

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

function print_description(){
    if(isset($_GET['id'])){
        echo file_get_contents("data/".$_GET['id']);
    } else {
        echo "Hello, PHP!";
    }
}

function print_list(){
    $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;
    }
}
?>

 

view/top.php
<?php
require_once('lib/print.php');
?>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>
        <?php
        print_title();
        ?>
    </title>
</head>
<body>
    <h1><a href="index.php">WEB</a></h1>
    <ol>
        <?php
        print_list();
        ?>
    </ol>

 

view/bottom.php
<p>copyright ian</p>
</body>
</html>

 

index.php
<?php
require_once('lib/print.php');
require_once('view/top.php');
?>
    <a href="create.php">create</a>
    <?php if(isset($_GET['id'])) { ?>
        <a href="update.php?id=<?=$_GET['id'];?>">update</a>
        <form action="delete_process.php" method="post">
            <input type="hidden" name="id" value="<?=$_GET['id']?>">
            <input type="submit" value="delete">
        </form>
    <?php } ?>
    <h2>
        <?php
        print_title(); 
        ?>
    </h2>
    <?php
    print_description();
    ?>
<?php
require_once('view/bottom.php');
?>

 

create.php
<?php
require_once('lib/print.php');
require_once('view/top.php');
?>
    <a href="create.php">create</a>
    <form action="create_process.php" method="post">
        <p>
            <input type="text" name="title" placeholder="Title">
        </p>
        <p>
            <textarea name="description" placeholder="Description"></textarea>
        </p>
        <p>
            <input type="submit">
        </p>
    </form>
<?php
require_once('view/bottom.php');
?>

 

update.php
<?php
require_once('lib/print.php');
require_once('view/top.php');
?>
    <a href="create.php">create</a>
    <?php if(isset($_GET['id'])) { ?>
        <a href="update.php?id=<?=$_GET['id'];?>">update</a>
    <?php } ?>
    <form action="update_process.php" method="post">
        <input type="hidden" name="old_title" value="<?=$_GET['id']?>">
        <p>
            <input type="text" name="title" placeholder="Title" value="<?php print_title(); ?>">
        </p>
        <p>
            <textarea name="description" placeholder="Description"><?php print_description(); ?></textarea>
        </p>
        <p>
            <input type="submit">
        </p>
    </form>
<?php
require_once('view/bottom.php');
?>

 

 XSS(Cross Site Scripting)

 

웹사이트에 스크립트 태그를 넣어 보안에 위협을 주는 것이다.

htmlspecialchars()를 이용하면 스크립트가 자동으로 텍스트로만 인식이 되어 XSS 문제를 해결할 수 있다.

 

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

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

function print_list(){
    $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;
    }
}
?>

 

 파일 경로 보호

 

basename()을 이용하면 파일경로에서 파일명만 추출해줘서 부모디렉토리로 가지 못하게 할 수 있다.

echo $_GET['id']; // ../password.txt
echo basename($_GET['id']); // password.txt

 

lib/print.php
function print_description(){
    if(isset($_GET['id'])){
        $basename = basename($_GET['id']);
        echo htmlspecialchars(file_get_contents("data/".$basename));
    } else {
        echo "Hello, PHP!";
    }
}

 

delete_process.php
<?php
unlink('data/'.basename($_POST['id']));
header('Location: /index.php')
?>
반응형
Comments