:: 데이터베이스를 관리하거나 자료를 관리하기 위한GUI관리툴은 내장되어 있지 않고 오로지 명령어로만 동작
따라서 MySQL 프론트엔드 데스크톱 소프트웨어나 웹 애플리케이션을 사용해야 함
MySQL과 같은 관계형 데이터베이스의 중요한 특징은 스프레드시트와 마찬가지로 데이터를 표의 형태로 표현해준다.
MySQL의 구조
- 표(table)에 저장됨 -> 표가 늘어남 -> 정리정돈(디렉토리)의 필요성 증대
- 스키마? 서로 연관된 표들을 서로 그룹핑할 때 사용하는 일종의 폴더.
- 스키마들이 모인 것 = 데이터베이스 서버(database server)
데이터베이스 서버> 데이터베이스(스키마)> 표(table)
효용
1. 보안 (자체적 보안 체계를 가지고 있어 안전한 보관 가능)
2. 권한 (다양한 사용자들이 관리할 수 있음 + 차등적 권한을 줄 수 있음)
SQL
(Structed Query Language)
:: 데이터를 관리하기 위한 쿼리 언어
:: 데이터베이스 종류와 상관 없이 모든 데이터베이스는 SQL을 통해서만 관리가 가능함
:: 기본적으로는 ANSI 표준이며 데이터베이스 회사별로 조금씩 차이가 있음
그리고 다양한 MySQL 명령들
(※ 주의 : 공부한 것을 까먹지 않도록 간단하게 적어놓은 것이므로 설명 등이 매우 부실함)
1. 데이터베이스 생성
CREATE DATABASE 데이터베이스명;
2. 데이터베이스 목록보기
SHOW databases;
3. 데이터베이스 선택
USE 데이터베이스명;
4. 테이블 생성
CREATE TABLE 테이블명(
-> 필드1 데이터타입 NULL수용여부(사용하지 않으면 기본적으로 NULL),
-> 필드2 데이터타입 NOT NULL,
...
-> PRIMARY KEY(필드1)); // PRIMARY KEY 부여
예를 들어
CREATE TABLE opentutorials(
-> id INT(11) NOT NULL AUTO_INCREMENT,
-> title VARCHAR(30) NOT NULL,
-> description TEXT NULL,
-> created DATETIME NOT NULL,
-> profile VARCHAR(100) NULL,
-> PRIMARY KEY(id));
3. 테이블 목록보기
SHOW tables;
4. 테이블 구조 확인
DESC 테이블명;
5. 특정 칼럼에 키 부여
ALTER TABLE 테이블명 ADD PRIMARY KEY(필드명);
6. 데이터 입력
INSERT INTO //모든 필드에 데이터 추가
-> 테이블명
-> VALUES(데이터1, 데이터2, 데이터3,,,);
예를 들어
INSERT INTO
->opentutorials
->VALUES("SQL","SQL is....",NOW(),'kkami','developer');
INSERT INTO 테이블명(필드1, 필드2) VALUES(데이터1,데이터2);
예를 들어
INSERT INTO opentutorials(title,description,created,author,profile)
->VALUES("SQL","SQL is....",NOW(),'kkami','developer');
7. 데이터 조회
SELECT * FROM 테이블명; // 전체 필드 데이터 검색
SELECT 필드명1, 필드명2 FROM 테이블명; // 특정 필드 데이터 검색
SELECT 필드명1, 필드명2 FROM 테이블명 WHERE 조건식; // 조건에 맞는 레코드 검색 명령
SELECT 필드명1, 필드명2 FROM 테이블명 WHERE 검색필드 LIKE 조건식 // 특정 문자열이 포함된 레코드 검색 명령
SELECT 필드명1, 필드명2 FROM 테이블명 ORDER BY 필드명; // 레코드 정렬 명령 -오름차순
SELECT 필드명1, 필드명2 FROM 테이블명 ORDER BY 필드명 DESC; // 레코드 정렬 명령 -내림차순
SELECT 필드명1, 필드명2 FROM 테이블명 ORDER BY 필드명 LIMIT 숫자;// 오름차순으로 해당 숫자만큼만 출력
SELECT * FROM 테이블명 LEFT JOIN 붙일 테이블명 ON 조건; // 테이블 합치기
ex) SELECT * FROM topic LEFT JOIN author ON topic.author_id = author.id;
8. 데이터 수정
UPDATE 테이블명 SET 필드명='바꾸고자 하는 값' WHERE 조건;
예를 들어
UPDATE opentutorials SET id=3 WHERE id=1;
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<h1>newline</h1>
<?php
$str = "발 끝에 닿을 듯한 어둠에
그림자마저 사라져
등뒤로 도망가는 너란 해 Bye
궤도를 벗어난 행성
이별에 우린 부딪히려 해
난 차라리 모든 걸 잊어버린
너를 원해
흐르는 별들 속에 헤매던 그때
이뤄지지 않을 꿈안에 갇혀 Fly away
빛을 건너 그 날의 널 볼 수 있다면
지금 너와 난 영원을 속삭였을까
Let me catch the light";
echo $str;
?>
</body>
</html>
가사 : 「하현상-3108」
이렇게 문자열을 입력했을 때 결과화면은 아래와 같다.
가사가 str변수 안에 입력한 대로 줄바꿈이 되기를 원한다.
① <br>태그 이용
$str = "발 끝에 닿을 듯한 어둠에<br>
그림자마저 사라져<br>
등뒤로 도망가는 너란 해 Bye<br>
궤도를 벗어난 행성<br>
이별에 우린 부딪히려 해<br>
....
let me catch the light";
@app.route('/admin/notice_flag')
def admin_notice_flag():
global memo_text
if request.remote_addr != '127.0.0.1':
return 'Access Denied'
if request.args.get('userid', '') != 'admin':
return 'Your not admin'
memo_text += f'[Notice] flag is {FLAG}\n'
return 'Ok'
해당 페이지 코드를 보니 고려해야 할 if 문이 두 개나 있다.
① request.remote_addr != '127.0.0.1' : 접속한(클라이언트의) IP 주소가 127.0.0.1이 아니라면~
② request.args.get('userid',' ') != 'admin' : userid에 해당하는 값이 admin이 아니라면~
접속한 IP 주소가 127.0.0.1이 아니었기 때문에 Access Denied가 뜬 것이다.
그렇다면 접속 IP주소를 127.0.0.1로, userid 값을 admin으로 설정해준다면
global 변수인 memo_text에 flag 값이 들어가 memo 페이지에 써져 있을 것이라고 생각했다.
@app.route('/flag', methods=['GET', 'POST'])
def flag():
if request.method == 'GET':
return render_template('flag.html')
elif request.method == 'POST':
csrf = request.form.get('csrf', '')
if not read_url(csrf):
return '<script>alert("wrong??");history.go(-1);</script>'
return '<script>alert("good");history.go(-1);</script>'
flag 페이지에선 'csrf'의 값을 알아낸 후 read_url() 함수에 넣어 실행시키고 있다.
마지막 부분인
driver.get(f'http://127.0.0.1:8000/csrf?csrf={urllib.parse.quote(url)}') 에 의해 해당 페이지가 불러와지므로
csrf 페이지 내에서 공격을 하기로 했다.
csrf 페이지에서 공격할 때 frame, script, on 태그는 사용하지 못하므로
img 태그를 사용했다.
<img src="http://127.0.0.1:8000/admin/notice_flag?userid=admin"> 입력