'Web 프로그램/Web Security'에 해당되는 글 7건

728x90

서버 보안 설정 사항 중 몇가지를 적어둔다.

 

### 패스워드 잠금횟수 설정
vim /etc/pam.d/system-auth
auth        required       pam_tally2.so deny=5 unlock_time=120 no_magic_root account required pam_tally2.so no_magic_root reset
 
#account     required     pam_unix.so 다음 줄에 추가한다.
account     sufficient    pam_tally2.so
 
 
vim /etc/pam.d/password-auth
#auth        required      pam_tally2.so deny=5 unlock_time=120
auth        required      pam_tally2.so deny=5 unlock_time=120 no_magic_root account required pam_tally2.so no_magic_root reset
 
#account     required     pam_unix.so 다음 줄에 추가한다.
account     sufficient    pam_tally2.so
 
### /etc/hosts 파일 소유자 및 권한 설정
chown root /etc/hosts 
chmod 600 /etc/hosts
 
### /etc/(x)inetd.conf 파일 소유자 및 권한 설정
ls -al /etc/xinetd.conf
chown root /etc/xinetd.conf 
chmod 600 /etc/xinetd.conf 
 
# 파일이 존재하지 않으면
ls -alR /etc/xinetd.d/
chown -R root /etc/xinetd.d/ 
chmod -600 /etc/xinetd.d/ 
 
### /etc/syslog.conf 파일 소유자 및 권한 설정
ls -al /etc/rsyslog.conf
chown root /etc/rsyslog.conf
chmod 640 /etc/rsyslog.conf
 
### 정책에 따른 시스템 로깅 설정
vim /etc/rsyslog.conf
*.alert                                                 /dev/console
*.emerg   *
 
# rsyslog 서비스 재시작
systemctl restart rsyslog
 
 
### cron 파일 소유자 및 권한설정
ls -/usr/bin/crontab
chmod 750 /usr/bin/crontab
# crontab 파일 권한 확인
ls -al /usr/bin/crontab
 
# cron 관련 설정파일 소유자 및 권한 설정
chown root /etc/cron.deny
chmod 640 /etc/cron.deny
ls -al /etc/cron.deny
 
# 파일이 존재하면 아래 명령어 실행
ls /etc/cron.d/
chown root /etc/cron.d/cron.allow
chmod 640 /etc/cron.d/cron.allow
chown root /etc/cron.d/cron.deny
chmod 640 /etc/cron.d/cron.deny
 
 
### FTP 계정 shell 제한
cat /etc/passwd
# passwd 파일 내 로그인 쉘 설정이 /bin/false 가 아닌 경우 보안 설정
usermod -/bin/false ftp
 
 
### at 파일 소유자 및 권한 설정
ls -/usr/bin/at
chmod 0750 /usr/bin/at
 
chown root /etc/at.allow
chmod 640 /etc/at.allow
chown root /etc/at.deny
chmod 640 /etc/at.deny
 
# 파일 권한 및 사용자 확인
ls -al /etc/at.allow
ls -al /etc/at.deny
 
 
### SSH, SFTP 로그 기록 설정(상)
※ SSH
#1. /etc/profile 파일에 아래 설정 수정 및 추가
vim /etc/profile
...
function logging
{
    stat="$?"
    cmd=$(history|tail -1)
    if [ "$cmd" != "$cmd_old" ]; then
    logger -p local1.notice "[2] STAT=$stat"
    logger -p local1.notice "[1] PID=$$, PWD=$PWD, CMD=$cmd"
    fi
    cmd_old=$cmd
}
trap logging DEBUG
 
#2. rsyslog.conf 파일에 아래 설정 추가
vim /etc/rsyslog.conf
...
local1.*                                                /var/log/secure
 
#3. 변경된 환경변수 적용
source /etc/profile
 
#4. rsyslog 서비스 재시작
systemctl restart rsyslog
 
 
# sshd_config 파일 내 sftp 설정에 "-f AUTHPRIV -l VERBOSE" 설정 추가
vim /etc/ssh/sshd_config
 
# shift + g 를 눌러 최하단으로 이동한다.
 
#Subsystem sftp /usr/libexec/openssh/sftp-server
# 아래와 같이 추가한다.
Subsystem sftp /bin/false
Match LocalPort 2222  
      ForceCommand internal-sftp -f AUTHPRIV -l VERBOSE
 
# sshd 서비스 재시작
systemctl restart sshd
 
### root 계정 원격 접속 제한(상)
/PermitRootLogin 으로 찾아서
PermitRootLogin no 로 변경한다.
 
# sshd 서비스 재시작
systemctl restart sshd
# 만약의 경우를 대비하여 콘솔창을 닫으면 안된다.
# sftp 로 root 접속하는 경우 접속이 안된다.
 

 

 

 

'Web 프로그램 > Web Security' 카테고리의 다른 글

HTML Purifier 사용법 예시  (0) 2023.02.28
remote IP address  (0) 2021.03.24
파일 다운로드 공격 방지  (0) 2019.07.05
파일 업로드 공격 방지  (0) 2019.06.21
Cross-Site Scripting (XSS) 방지  (0) 2019.06.20
블로그 이미지

Link2Me

,
728x90

Web Root 디렉토리에서 설치를 위해 아래와 같이 실행한다.

# vendor/ezyang/htmlpurifier/library/ 에 자동 설치된다.
composer require ezyang/htmlpurifier

 

HTML Purifier는 해외의 보안 전문가들로부터 철저하게 검증받은 필터링 라이브러리이다.
페이지 표시할 때마다 매번 필터링하지 말고, DB에 저장하기 전에 한 번만 필터링한다.
게시물 제목이나 댓글처럼 HTML이 필요없는 경우 그냥 htmlspecialchars 또는 strip_tags 사용한다.
첨부파일 업로드를 사용한 XSS 공격은 게시물 내용과 별도로 막아줘야 한다.

 

https://stackoverflow.com/questions/2677578/php-html-purifier-hello-world-world-tutorial-striptags

 

PHP - HTML Purifier - hello w<o>rld/world tutorial striptags

I am just looking into using HTML Purifier to ensure that a user-inputed string (that represents the name of a person) is sanitized. I do not want to allow any html tags, script, markup etc - I just

stackoverflow.com

 

<?php
include_once( 'htmlpurifier/htmlpurifier/library/HTMLPurifier.auto.php');
?>
<form method="post">
<input type="text" name="fname" placeholder="first name"><br>
<input type="text" name="lname" placeholder="last name"><br>
<input type="submit" name="submit" value="submit">
</form>
        
<?php
if(isset($_POST['submit']))
{
    $fname=$_POST['fname'];
    $lname=$_POST['lname'];
    
    $config = HTMLPurifier_Config::createDefault();
    $purifier = new HTMLPurifier($config);
    $fname = $purifier->purify($fname);
    
    $config = HTMLPurifier_Config::createDefault();
    $purifier = new HTMLPurifier($config);
    $lname = $purifier->purify($lname);
 
    echo "First name is: ".$fname."<br>";
    echo "Last name is: ".$lname;
}
?>

 

본격적으로 사용해 보기 위해서 자료를 검색하고 분석하는 중이다.

'Web 프로그램 > Web Security' 카테고리의 다른 글

CentOS 7 서버 보안  (0) 2023.03.03
remote IP address  (0) 2021.03.24
파일 다운로드 공격 방지  (0) 2019.07.05
파일 업로드 공격 방지  (0) 2019.06.21
Cross-Site Scripting (XSS) 방지  (0) 2019.06.20
블로그 이미지

Link2Me

,
728x90

PHP 3 Tier 환경에서 WAS 서버에서 원격 접속하는 클라이언트(Web Browser, APP)의 IP주소를 알아낼 목적으로 $_SERVER['REMOTE_ADDR'] 를 사용하면 맞을까?

사이트 접속한 사용자 IP주소를 알려주는 것인데 앞단의 Web 서버의 IP주소를 반환하고 있다면??

DB 테이블에 Web Server 의 IP주소를 기록하고 있더라.

 

구글링에서 찾은 이 함수를 사용하면 접속단말의 IP주소를 가져온다.

function getClientIP() {
	if (isset($_SERVER)) {
		if (isset($_SERVER["HTTP_X_FORWARDED_FOR"]))
			return $_SERVER["HTTP_X_FORWARDED_FOR"];

		if (isset($_SERVER["HTTP_CLIENT_IP"]))
			return $_SERVER["HTTP_CLIENT_IP"];

		return $_SERVER["REMOTE_ADDR"];
	}

	if (getenv('HTTP_X_FORWARDED_FOR'))
		return getenv('HTTP_X_FORWARDED_FOR');

	if (getenv('HTTP_CLIENT_IP'))
		return getenv('HTTP_CLIENT_IP');

	return getenv('REMOTE_ADDR');
}

참고로 알아두면 좋은 사항

$_SERVER['DOCUMENT_ROOT'] = 현재 사이트가 위치한 서버상의 위치 => /htdocs/

$_SERVER['HTTP_ACCEPT_ENCODING'] = 인코딩 방식 => gzip, deflate

$_SERVER['HTTP_ACCEPT_LANGUAGE'] = 언어 => ko

$_SERVER['HTTP_USER_AGENT'] = 사이트 접속한 사용자 환경 => Mozilla/5.0

$_SERVER['REMOTE_ADDR'] = 사이트 접속한 사용자 IP => xxx.xxx.xxx.xxx

$_SERVER['SCRIPT_FILENAME'] = 실행되고 있는 위치와 파일명 => htdocs/index.php

$_SERVER['SERVER_NAME'] = 사이트 도메인 => www.abc.com

$_SERVER['SERVER_PORT'] = 사이트가 사용하는 포트 => 80

$_SERVER['SERVER_SOFTWARE'] = 서버의 소프트웨어 환경 => Apache/2.4.6 (Unix) PHP/7.3.27 

$_SERVER['SERVER_PROTOCOL'] = 사용된 서버 프로토콜 => HTTP/1.1

$_SERVER['REQUEST_URI'] = 현재페이지의 주소에서 도메인 제외 =>  /index.php?user=???&name=???

$_SERVER['PHP_SELF'] = 현재페이지의 주소에서 도메인과 넘겨지는 값 제외 =/ index.php

'Web 프로그램 > Web Security' 카테고리의 다른 글

CentOS 7 서버 보안  (0) 2023.03.03
HTML Purifier 사용법 예시  (0) 2023.02.28
파일 다운로드 공격 방지  (0) 2019.07.05
파일 업로드 공격 방지  (0) 2019.06.21
Cross-Site Scripting (XSS) 방지  (0) 2019.06.20
블로그 이미지

Link2Me

,
728x90

File Download 공격

설명
서버에 존재하는 파일이 의도하지 않게 클라이언트로 다운로드 되는 취약점이다.
해커가 원하는 파일을 임의로 다운로드하거나 파일 내용을 노출시킬 수 있다.
 발생원인 애플리케이션 로직에서 파일을 클라이언트로 다운로드할 때 입력 값 검증을 하지 않을 경우 발생한다.
 위험성 공격자에게 권한이 없는 데이터를 획득할 수 있도록 하며, 시스템 정보 등 중요 파일을 획득할 수 있도록 한다.
 대응 ㅇ외부 입력값을 자원의 식별자로 사용하는 경우, 철저하게 검증한 후 사용한다.
ㅇ사용자별 사용 가능한 자원을 사전에 리스트로 정의하여 사용 범위를 제한한다.
ㅇ파일을 사용하는 경우, 파일명에 경로순회공격 위험이 있는 문자를 제거하는 필터를 이용한다.

 

공격자가 의도적인 공격을 방지하기 위해서는 웹사이트 게시판, 자료실 등에서 php 프로그램을 이용하여 파일을 다운로드 받은 페이지가 있는지 조사를 한다.

 

$file_id = $_REQUEST['file_id'];
if(strstr($file_id,"../") || strstr($file_id,"..\\")){
    echo "<script>alert('Access Denied!')</script>";
    exit;
}

 

와 같이 ../ 상위 폴더로 이동을 못하게 검사하여 처리하는 걸 추가한다.

JSP, CGI 기반인 경우에는 관련 코드를 추가하여 방지하도록 한다.

 

<?php
require_once '../sessionChk.php'// 세션 체크
 
if(isset($_GET['filename'])) {
    $filename = $_GET['filename'];
    if(strstr($filename,"../"|| strstr($filename,"..\\")){
        echo("<meta http-equiv='Refresh' content='0; URL=/error.php'>");;
        exit;
    }
 
else {
    $dir="../files/"
    $filename = "upload_form.xlsx";
 
    if (file_exists($dir.$filename)) {
         header("Content-Type: application/octet-stream");
         header("Content-Disposition: attachment;; filename=$filename");
         header("Content-Transfer-Encoding: binary"); 
         header("Content-Length: ".(string)(filesize($dir.$filename))); 
         header("Cache-Control: cache, must-revalidate"); 
         header("Pragma: no-cache"); 
         header("Expires: 0"); 
         $fp = fopen($dir.$filename"rb"); //rb 읽기전용 바이러니 타입
         if(!fpassthru($fp)) {
             fclose($fp);                        
         }
    } else {
        header("Location: /"); // web root 디렉토리로 이동
        exit;
    }
}
 
?>

 

'Web 프로그램 > Web Security' 카테고리의 다른 글

HTML Purifier 사용법 예시  (0) 2023.02.28
remote IP address  (0) 2021.03.24
파일 업로드 공격 방지  (0) 2019.06.21
Cross-Site Scripting (XSS) 방지  (0) 2019.06.20
SQL Injection 공격 방지  (1) 2019.06.19
블로그 이미지

Link2Me

,
728x90

File Upload 공격

설명
악의적인 스크립트 파일을 웹 서버에 업로드하여 접근할 경우 웹 서버 사용자 권한으로 실행이 되는 취약점이다.
 발생원인 업로드할 파일이 안전한지 검사하지 않아 발생한다.

파일이 업로드되는 페이지(게시판, SNS 등)에 악성파일(웹셀)을 업로드가 가능한 경우에 발생한다.
 위험성 환경마다 권한이 다를 수 있지만, 서버를 직접 컨트롤할 수 있어 서비스에 치명적인 영향을 줄 수 있다.
 대응 ㅇ업로드되는 파일의 크기, 개수, 종류를 제한한다.
ㅇ업로드한 파일을 외부에서 접근할 수 없는 경로에 저장한다.
ㅇ업로드한 파일의 저장 경로와 파일명을 외부에서 알 수 없도록 한다.

ㅇ실제 저장되는 파일명은 난수를 이용해 유추 불가능하도록 생성하여

   외부로부터 직접적인 접근 불가능하게 구현한다.

ㅇ업로드한 파일에 대한 웹서버의 실행권한을 제거하고 저장한다.

 

 

PHP File Upload 공격이 가능하려면?
1) php 파일을 서버에 업로드할 수 있어야 한다.
2) 웹 브라우저를 통해서 접근이 가능해야 한다.

 

이를 방지하려면

. 업로드되는 파일의 확장자를 검사하여 허락된 타입만 저장한다.

. File Upload 디렉토리를 Web root 디렉토리를 벗어난 위치에 설정한다.

. 해커가 파일을 찾을 수 없도록 업로드 파일의 이름과 확장자를 난수화하여 저장한다.

. 저장되는 파일은 실행권한이 없도록 권한 변경하여 저장한다.

. 실제 저장되는 파일명과 View로 보여주는 파일명을 다르게 한다.

  DB에 보여줄 파일명과 실제 저장된 파일명을 모두 저장하고, View에는 업로드시의 파일명으로 보여주고

  다운로드를 누르면 실제 파일명을 View 파일명으로 변경하여 저장되도록 구현한다.

. 특수문자가 포함된 경우 업로드를 막는다.

 

'Web 프로그램 > Web Security' 카테고리의 다른 글

HTML Purifier 사용법 예시  (0) 2023.02.28
remote IP address  (0) 2021.03.24
파일 다운로드 공격 방지  (0) 2019.07.05
Cross-Site Scripting (XSS) 방지  (0) 2019.06.20
SQL Injection 공격 방지  (1) 2019.06.19
블로그 이미지

Link2Me

,
728x90

Cross-Site Scripting (XSS)

설명

공격자가 웹 페이지에 악성 스크립트를 삽입할 수 있는 취약점이다.

사용자가 입력한 정보를 출력할 때 스크립트가 실행되도록 하는 공격기법이다.

다른 사이트로 어떤 정보를 전송하는 행위가 주로 일어나기 때문에 사이트간 스크립팅이라는 이름을 가지고 있다.

 발생원인

웹 페이지에서 사용자로부터 입력받은 값을 제대로 검사하지 않고 사용할 경우 발생한다.

 위험성

ㅇ사용자의 쿠키 정보 노출로 세션 하이재킹과 같은 공격이 실행될 수 있다.

ㅇ사용자를 피싱 사이트로 접속하게 만들어 사용자의 중요 정보를 탈취할 수 있다.

ㅇ클라이언트(브라우저)에서 악성코드가 실행되어 사용자 PC를 좀비화할 수 있다.

 대응

입력값에 대해 정규식을 이용하여 정확하게 허용되는 패턴의 데이터만 입력되도록 한다.
ㅇ서버로 들어오는 모든 요청에 대해 XSS 필터를 적용하여 안전한 값만 전달되어 사용되도록 한다.
ㅇ출력값에 대해 HTML 인코딩을 적용하여 스크립트가 동작되지 않도록 한다.


공격자가 의도적으로 브라우저에서 실행될 수 있는 악성 스크립트를 웹 서버에 입력 또는 이것을 출력 시 위험한 문자를 중성화시키지 않고 처리하는 애플리케이션의 개발 과정에서 발생한다.
XSS는 일반적으로 자바스크립트에서 발생하지만, VB 스크립트, ActiveX 등 클라이언트에서 실행되는 동적 데이터를 생성하는 모든 언어에서 발생이 가능하다.

가장 일반적인 방법은 게시판 같은 곳에 HTML 문서에 <script>를 이용하여 이 스크립트 태그 안에 악성 스크립트를 저장하는 방식이다.
즉 텍스트만 표시되도록 설계된 어떤 게시판에 <script> “악성 스크립트” </script>과 같은 태그를 포함한다.

웹해킹의 기본은 웹페이지 소스보기부터 출발한다.
애초에 설계때부터 추후에 등장할 지 모를 버그 등 위험성을 모두 고려하여 설계하는것이 시큐어코딩이다.
XSS 취약점을 근본적으로 제거하기 위해서는 스크립트 등 해킹에 사용될 수 있는 코딩에 사용되는 입력 및 출력 값에 대해서 검증하고 무효화시켜야 한다.
입력 값에 대한 유효성 검사는 데이터가 입력되기 전에 가능하면, 입력 데이터에 대한 길이, 문자, 형식 및 사업적 규칙 유효성을 검사해야 한다.
출력 값을 무효화하기 위해서는 XSS 공격은 기본적으로 <script> 태그를 사용하기 때문에 XSS 공격을 차단하기 위해 태그 문자(<, >) 등 위험한 문자 입력 시 문자 참조(HTML entity)로 필터링하고, 서버에서 브라우저로 전송 시 문자를 인코딩하는 것이다.
예를 들어, 문자 “<”는 동일한 의미의 HTML “&lt;”로 변경한다. HTML 엔터티는 대부분의 브라우저에서 특수한 의미를 가지지 않으며, 단순한 문자로 처리된다.
이렇게 인코딩하면 사용자는 <script>가 <script>로 보이지만 HTML 문서에서는 &lt;script&gt;로 나타나서 브라우저에서 일반 문자로 인식하고 스크립트로 해석되어 실행되지는 않는다.

htmlspecialchars($str,ENT_QUOTES,'UTF-8');
이 함수는 문자열에서 특정한 특수 문자를 HTML 엔티티로 변환한다.
& (앰퍼샌드) 는 &amp; 로 바꾼다.
" (큰따옴표) 는 &quot; 로 바꾼다.
' (작은따옴표) 는 &#039; 로 바꾼다.
< (~ 보다 작다는 기호) 는 &lt; 로 바꾼다.
> (~ 보다 크다는 기호) 는 &gt; 로 바꾼다.
htmlspecialchars 함수를 사용하면 악성 사용자로부터 XSS 공격을 방지 할 수 있다.

게시판의 게시글, 댓글, 쪽지 등에 자바스크립트 코드가 들어가지 않도록 필터링해야 한다.
HTTP  헤더에 문자 인코딩을 지정하지 않는 페이지는 XSS 공격의 위험성 있으므로 반드시 문자 인코딩을 설정해야 한다. 모든 파라미터는 변조할 수 있다는 전제하에 Web 애플리케이션을 작성해야 한다.

아래 코드는 htmlspecialchars 함수, strip_tags 함수를 이용하여 사용할 경우와 사용하지 않을 경우의 XSS 공격이라는 가정하의 예제인 셈이다.

<?php
error_reporting(E_ALL);
ini_set("display_errors", 1);
ini_set('default_charset','UTF-8');

$str = "<h2> 'PHP' morden programing.</h2>";
// HTML 태그 속성 반영한 출력
echo $str.'<br/>';

$str2 = htmlspecialchars($str,ENT_QUOTES,'UTF-8'); // HTML 태그에 사용되는 특수문자를 HTML 엔티티로 변환
// HTML 태그 속성 제거된 문자열 출력
echo $str2.'<br/>';

// 정규식으로 HTML 태그 제거
$str3 = preg_replace("/(<([^>]+)>)/i","",$str);
echo $str3.'<br/>';
// ? : 0 또는 하나     {0,1} 와 같다.
// + : 1개 이상       {1,} 와 같다.
// * : 0 개 이상      {0,} 과 같다.
// [] : []안에 있는 문자열 중 한문자
// {} : {} 바로 앞에 있는 문자열(또는 문자)의 개수
// () : ()안에 있는 문자들의 그룹화
// | : OR 연산자 기능

// HTML 비 허용시
$str4 = strip_tags($str); // HTML 태그가 포함될 경우 HTML 태그 자체를 삭제
echo $str4.'<br/>';


$str ="<script>alert('xss 공격!');</script>";
$str1 = strip_tags($str); // HTML 태그가 포함될 경우 HTML 태그 자체를 삭제
echo $str1.'<br/>';
$str2 = preg_replace("/(<([^>]+)>)/i","",$str);
echo $str2.'<br/>';

$str ='<a href="javascript:alert(\'xss 공격!\')">XSS</a>';
$str1 = strip_tags($str); // HTML 태그가 포함될 경우 HTML 태그 자체를 삭제
echo $str1.'<br/>';


$str ='<img src="#" onerror="alert(\'XSS 공격!\');">';
$str = strip_tags($str); // HTML 태그가 포함될 경우 HTML 태그 자체를 삭제
echo $str.'<br/>';

$str ='<IFRAME src="&#106;&#097;&#118;&#097;&#115;&#099;&#114;&#105;&#112;&#116;&#058;
&#097;&#108;&#101;&#114;&#116;&#040;&#039;&#120;&#115;&#115;&#032;&#234;&#179;&#181;
&#234;&#178;&#169;&#033;&#039;&#041;&#059;" width="0" height="0" frameborder="0"></IFRAME>';
$str = strip_tags($str); // HTML 태그가 포함될 경우 HTML 태그 자체를 삭제
echo $str.'<br/>';

?>


결과 화면


Text to ASCII Converter : http://www.unit-conversion.info/texttools/ascii/#data


정규표현식으로 HTML 태그를 제거하는 것은 Javascript 함수로 만들어서 확인할 수 있다.


<iframe> 태그 삽입, <object> 태그 삽입, Web 브라우저 URL Spoofing(변조), 악성코드 은닉 등 다양한 XSS 공격 기법이 가능하므로 필터링에 각별한 고려가 필요하다.


국내에서는 게시판이 대부분 WYSIWYG 에디터를 이용하므로 선택적 필터링을 잘 해야 한다.


HTML Purifier는 해외의 보안 전문가들로부터 철저하게 검증받은 필터링 라이브러리이다.
whitelisting 기법을 사용하고, 잘못된 태그도 확실하게 걸러내준다.
처리속도가 빠르지 않기 때문에 HTML이 필요한 경우에만 사용해야 한다.


참고하면 도움되는 게시글
ㅇ 안경잡이 개발자 XSS 공격 강의 : https://www.youtube.com/watch?v=DoN7bkdQBXU
ㅇ [웹취약점] XSS 크로스 사이트 스크립팅 http://coashanee5.blogspot.com/2017/02/xss.html
ㅇ KISA(한국인터넷진흥원) XSS 공격 종류 및 대응 방법 : http://www.kisa.or.kr/uploadfile/201312/201312161355109566.pdf


'Web 프로그램 > Web Security' 카테고리의 다른 글

HTML Purifier 사용법 예시  (0) 2023.02.28
remote IP address  (0) 2021.03.24
파일 다운로드 공격 방지  (0) 2019.07.05
파일 업로드 공격 방지  (0) 2019.06.21
SQL Injection 공격 방지  (1) 2019.06.19
블로그 이미지

Link2Me

,
728x90
SQL Injection

설명

웹 애플리케이션에서 사용되는 SQL 구문에 공격자가 임의의 구문을 주입(Injection) 하여 내부 데이터베이스의 데이터를 유출, 변조할 수 있는 취약점이다.

 발생원인

웹 페이지에서 사용자로부터 입력받은 값을 제대로 검사하지 않고 그대로 데이터 질의어로 사용할 경우 발생한다.

 위험성

데이터 유출, 변조 외에도 서버에 파일을 쓰거나 읽을 수 있고, 직접 명령 실행도 가능할 수 있기 때문에 위험도가 높은 취약점이다.


SQL 인젝션은 데이터베이스를 사용하는 모든 언어에서 일어날 수 있다.
공격자는 SQL 인젝션 취약점을 사용하여 데이터베이스 내의 모든 정보를 추출할 수 있다.
보통 userID 와 passwd 를 입력하는 로그인 창에서 발생할 수 있는 공격 유형이다.


select * from members where userID='$userID' and passwd ='$passwd';

여기서 userID 에 입력하는 정보를 ' or 1=1-- 라고 입력하는 것이 받아들여지면 어떤 결과가 초래될까?
phpMyAdmin 상에서 직접 테스트 해보라.


SELECT * FROM members WHERE userID='' or 1=1 --' and passwd ='abc123';

과같이 -- 주석 뒷부분은 무용지물이 되고 조건문은 무조건 참이 되어 모든 결과를 반환하게 된다.


select * from members where userID='a' and passwd ='password' OR 1='1';
로 입력해도 무조건 참이 되어 모든 결과를 반환하게 된다.


더 위험한 것은 테이블 자체를 삭제시켜 버릴 수가 있다는 점이다.

SELECT * FROM members WHERE userID = 'a';DROP TABLE members;

$userID = "admin";
$password = "password' OR 1='1 --";
$sql = "SELECT * FROM members WHERE userID='{$userID}' AND passwd='{$password}'";
echo 'NonFiltering : '.$sql.'<br/>';
$sql=preg_replace("/\s{1,}1\=(.*)+/","",$sql); // 공백이후 1=1이 있을 경우 제거
$sql=preg_replace("/\-{2,}/","",$sql); // 주석 제거
$sql=preg_replace("/\s{1,}(or|and|null|where|limit)/i"," ",$sql); // 공백이후 or, and 등이 있을 경우 제거
echo 'Filtering : '.$sql.'<br/>'; 

공백이후 and 를 체크하지 않고 그냥 체크하면 userID 중에 hand 가 들어간 것도 필터링을 해서 문제가 될 수 있다.


그럼 여기서 안전하게 코딩하기 위한 포인트는 무엇인가?

① 필터링 메소드를 만들어서 악의적인 코드를 무조건 걸러내도록 한다.

    필터링 해야 할 특수문자 : '(홀따옴표) ;(콜론), --(주석), 공백 등

    https://link2me.tistory.com/1489 정규표현식 연습 참조하면 정규표현식 이해에 도움된다.

    정규표현식을 활용한 함수 만들기

    function SQLFiltering($str){
        // 해킹 공격을 대비하기 위한 코드
        $str=preg_replace("/\s{1,}1\=(.*)+/","",$str); // 공백이후 1=1이 있을 경우 제거
        $str=preg_replace("/\s{1,}(or|and|null|where|limit)/i"," ",$str); // 공백이후 or, and 등이 있을 경우 제거
        $str = preg_replace("/[\s\t\'\;\=]+/","", $str); // 공백이나 탭 제거, 특수문자 제거
        return $str;
    }

②  안전한 코딩은 prepared Statement 와 바인딩 변수를 이용하도록 권고하고 있다.

      Prepared Statement 를 쓰면 SQL 인젝션 공격이 불가능할 수 밖에 없다.

      바인딩 데이터는 SQL 문법이 아닌 내부의 인터프리터나 컴파일 언어로 처리하기 때문에

      문법적인 의미를 가질 수 없다.

$stmt = $mysqli->prepare("SELECT * FROM members WHERE userID= ? AND passwd = ?");
$stmt->bind_param("ss", $_POST['userID'], $_POST['passwd']);
$stmt->execute();
//fetching result would go here, but will be covered later
$stmt->close();


참고하면 도움이 될 게시글

ㅇ PHP Prepared Statements https://www.w3schools.com/php/php_mysql_prepared_statements.asp
ㅇ PHP Legacy 함수를 PDO 방식 함수로 변환하기 https://link2me.tistory.com/1636

'Web 프로그램 > Web Security' 카테고리의 다른 글

HTML Purifier 사용법 예시  (0) 2023.02.28
remote IP address  (0) 2021.03.24
파일 다운로드 공격 방지  (0) 2019.07.05
파일 업로드 공격 방지  (0) 2019.06.21
Cross-Site Scripting (XSS) 방지  (0) 2019.06.20
블로그 이미지

Link2Me

,