트러블이슈

XSS 공격을 막아보자

Ahyeon, Jung 2024. 8. 8. 22:53
엔터 <br/>\n엔터 <br/>\n엔터 <br/>\n엔터 <br/>\n얍\n\n얍\n\n얍

 

react-quill을 에디터로 사용하고 있고, 자동으로 <div> 태그를 넣어주거나 <br/>이 필요해 innerHTML을 사용해야 했다.

interface Props {
  htmlContent: string;
}

const HtmlRenderer = ({ htmlContent }: Props) => {

  return (
    <div
      className="html-renderer"
      dangerouslySetInnerHTML={{ __html: htmlContent }}
    />
  );
};

export default HtmlRenderer;

 

전달받은 내용을 HTML로 반환하기 때문에, 태그를 인식할 수 있다.

 

하지만 HTML을 인식하기 때문에, 사용자가 의도치 않은 태그를 삽입하여 XSS 공격을 받을 수 있다.

<button onClick="alert('하하')">클릭해주세요<button>

 

이런 방식으로 에디터에 입력하면, 실제로 <button> 태그로 인식하여 실행이 된다.

이를 방지하기 위해서 사용자가 태그를 입력하면 해당 기호를 변환하여 저장해야한다.

const escapeHtml = (unsafe: string) => {
  return unsafe
    .replace(/&/g, "&amp;")
    .replace(/</g, "&lt;")
    .replace(/>/g, "&gt;")
    .replace(/"/g, "&quot;")
    .replace(/'/g, "&#039;");
};

export default escapeHtml;

 

import { Control, Controller } from "react-hook-form";
import React, { useMemo } from "react";

import dynamic from "next/dynamic";
import escapeHtml from "@/lib/escapeHTML";

const Editor = ({
  defaultValue,
  name,
  control,
}: {
  control: Control<any>;
  defaultValue?: string;
  name: string;
}) => {
  const ReactQuill = useMemo(
    () => dynamic(() => import("react-quill"), { ssr: false }),
    []
  );
  
  return (
    <>
      {ReactQuill && (
        <Controller
          name={name}
          defaultValue={defaultValue}
          control={control}
          render={({ field }) => (
            <ReactQuill
              className="w-full h-full"
              theme="snow"
              modules={modules}
              value={field.value}
              formats={formats}
              onChange={(content: string) => {
                const escapedContent = escapeHtml(content);
                field.onChange(escapedContent);
              }}
            />
          )}
        />
      )}
    </>
  );
};
export default Editor;

 

실제로 innerHTML로 들어왔음에도 태그로 인식되지 않은 것을 확인할 수 있다.

'트러블이슈' 카테고리의 다른 글

테스트로 기능정의서 두번씩 안보기로 했다  (0) 2024.07.19
테스트 코드 도입기  (0) 2024.07.17
시도를 해보자  (0) 2024.07.08
프로젝트 구조 변경하기  (0) 2024.07.06
Lighthouse로 성능 개선하기  (0) 2024.07.04