요약 및 힌트

데이터의 조회 결과가 몇건이건 한건만 보여지기에 든 생각으로 데이터를 모두 가지고오더라도 php 소스에서 첫 데이터만 화면에 표시하는 듯 하다. 그렇기 때문에 limit을 사용하여 데이터의 결과 순서를 변경했다.

 

만약 데이터들이 몇만건씩 있다면 limit 부분을 python으로 전송하여 데이터를 조회하는것도 좋은 방법일 듯 하다

 

참고로 SQL Injection1의 풀이는 6주차 정리에 있다.


문제 풀이

 

 

normaltic을 넣었을 때랑 1=1을 넣엇을 때 값이 같다.

'한개만 입력을 넣으니 동작을 하지 않는다. 

아무런 데이터를 넣어도 1개의 row는 존재하며 normaltic을 입력시 info에 데이터가 출력된다

 

예상되는 Back-End의 로직은 2가지

1. 테이블에서 id로 info만 조회하고 level, rank Point는 모두 화면에서 마스킹 고정

즉 테이블은 4개의 정보를 가지고 있는 것 처럼보이지만 실제로는 info 하나의 컬럼만 조회하고 있는 듯?

 

2. select '입력받은 id값', '****', '****', (select info from table where id = '입력받은 id값') from dual

 

1번 케이스가 더 의심간다...

일단 order by로 선행 select의 컬럼이 몇개 존재하는지 확인하보자

normaltic' order by 1 #

 

order by 7에서 데이터 조회가 안되므로 선행 컬럼은 총 6개

 

이제 어느 컬럼이 화면에 표기되는지 union으로 잡아보자

 

normaltic' union select 1,2,3,4,5,6 from dual #

 

어라 union을 해도 아래 데이터가 붙어나오진 않는다....

 

db에서 가지고 온 데이터를 화면에서 뿌릴때 인덱스(배열의 인덱스) 0번만 가져오는거 같다... 그렇다면  없는 데이터를 union으로 넘긴다면 내가 넘긴 데이터를 조회 할 수 있을 것이다.

빙고 배열의 가장 처음데이터가 내가 넣은 데이터다.

info는 6번째 컬럼에 있다는 걸 알았다.

 

이제 DB, Table, COLUMN을 찾아보자

123' union select 1,2,3,4,5,database() from dual #

 

 

이제 테이블 찾기가 노가다일것 같다.... limit 1,1 , limit 2,1 이런식으로 찾아도 되고...

생각해보니 테이블생성일시에 대한 컬럼이 있을 것 같다.

 

create_time이 있다.

기본 mysql테이블보다 늦게 생성되었을 태니 역순 정렬하면 될듯 하다

union과 order by를 같이 쓰려면 서브쿼리로 써야한다.... 서브쿼리는 쓸 수 없으니 count로 총 테이블의 개수를 찾고 limit으로 거꾸로 찾아가보자

 

123' union select 1,2,3,4,5, count(TABLE_NAME) from information_schema.TABLES  #

총 64개의 테이블이 있다.

limit 60, 1부터 늘려가보자

 

123' union select 1,2,3,4,5, TABLE_NAME from information_schema.TABLES  limit 60, 1#

유효해보이는 테이블을 찾았다. 컬럼명들을 찾아보자

 

 123' union select 1,2,3,4,5, COLUMN_NAME from information_schema.COLUMNS where TABLE_SCHEMA = 'sqli_5'and TABLE_NAME = 'flag_honey' #

 

flag_honey 테이블에서 flag 컬럼을 가져오자

 

 

이 테이블이 아닌가보다 count결과 1개의 데이터만 존재하기 때문이다.

 

다른 테이블을 찾아보니 secret이라는 이름의 테이블이 존재한다. 컬럼을 찾아보자

여기도 플래그라는 컬럼이 존재한다.

 

 

총 데이터가 몇개 존재할까?

2개

그렇다면 2번째 데이터에는 정답이 있지 않을까?

 

 

빙고!

 


 

UNION

Union은 SQL에서 서로 다른 SELECT의 결과를 하나의 결과로 합쳐주는 역할을 한다. 

 

예를 들어 아래와 같은 데이터를 가지는 테이블이 존재한다고 하자

 

tbl_member

ID PASS CREATE_DT
patrache01 123 2023-11-30
patrache02 456 2023-11-30
patrache03 789 2023-11-30
patrache03 000 2023-11-30

 

 

tbl_games

NAME COMPANY PRICE
디아블로 블리자드 50,000
리그오브 레전드 라이엇 게임즈 0

 

 

게임을 조회하는 화면에서 아래와 같은 쿼리를 사용할 것으로 생각된다.

SELECT NAME, COMPANY, PRICE FROM tbl_games WHERE NAME LIKE '%디아블로%'

그럼 결과는 

디아블로, 블리자드, 50,000이라는 결과를 반환한다.

해당 쿼리에 UNION을 사용하여 tbl_member의 데이터를 추출하려면

SELECT NAME, COMPANY, PRICE FROM tbl_games WHERE NAME LIKE '%디아블로%' 
UNION
SELECT ID, PASS, CREATE_DT FROM tbl_member

쿼리를 만들면 된다.

 

이를 위해 입력값에 들어갈 데이터는

'%디아블로%' UNION SELECT ID, PASS, CREATE_DT FROM tbl_member WHERE '1%'='1%' 

이다

 

LIKE 검색으로 %가 들어있기 때문에 마지막에 '1%'='1%'를 추가하였다.

 

위와같이 UNION은 선행하는 컬럼의 개수와 후행하는 컬럼의 개수가 동일해야한다.

 


ORDER BY

ORDER BY는 데이터의 정렬을 하는 SQL 구문이다. 

SELECT ID, PASS, CREATE_DT FROM tbl_member ORDER BY ID

 

위와같은 구문이 실행된다면 결과는 ID가 오름차순으로 정렬된 데이터를 반환한다.

 

그러나 ORDER BY구문에 한가지 특징이 있는데 SELECT 구문의 INDEX(순서)를 넣을 수 있다는 것이다.

이를 사용하여 UNION에 사용하는 컬럼의 개수를 구할 수 있다.

SELECT ID, PASS, CREATE_DT FROM tbl_member ORDER BY 1

 

 

연습

 

위와같이 데이터를 조회 할수 있는 웹이 존재한다.

 

1. SQL Injection이 동작하는지 확인해보자

검색을 해보니 like 검색으로 동작하는 것 같다 즉 조건문은 아래와 같을 것이다

WHERE ID LIKE '%입력데이터%'

 

Ad%'  '1%'='1 로 입력해서 데이터가 나오는 것을 확인 했으며 이를 통해 SQL Injection이 동작 하는 것을 알 수 있다.

 

2. 컬럼 개수 찾기

order by를 사용하여 선행 되는 select의 컬램 개수를 찾아보자 

 

order by 2를 사용하니 level의 컬럼이 오름차순으로 정렬되었다.

이와같은 방법으로 숫자를 늘려가니 5에서 데이터의 결과가 없었다 즉 선행되는 컬럼의 개수는 4개이다.

 

3. 컬럼의 위치 찾기

현재는 4개의 컬럼을사용하고 4개의 컬럼 정보가 모두 화면에 나오지만 선행하는 SELECT의 컬럼이 10개고 화면에 4개만 출력된다면 출력되는 컬럼의 위치를 찾아야한다.

그 방법은 union으로 데이터를 넣고 출력해보는 것

 

%' union select 1, 2, 3, 4 from dual#

 

1,2,3,4 모두 화면에 표기 되는 것을 알 수 있다.

 

4. DB확인

어떠한 DB(일부 DB에서는 스키마라고 한다.)

%' union select 1, database(), 3, 4 from dual# 를 통해 DB명을 확인

sqli_1이라는 DB를 사용하고 있음을 알 수 있다.

 

5. 테이블 확인

information_shcema라는 곳에 Table들의 이름이 있다.

%' union select table_name, 1, 2, 3 from information_schema.`TABLES`# 

구문을 사용하여 테이블 명들을 가져올 수 있다.

모든 테이블들의 이름을 조회 했다.

해당 테이블 중 내가 사용할 테이블은 flag_table이다.

 

6. 컬럼 이름 확인

조회할 DB와 Table을 찾았으니 이제 어떠한 컬럼을 가지고 있는지 확인해보자

컬럼정보는 INFORMATION_SCHEMA.COLUMNS에 있으며 COLUMN_NAME을 조회하면된다.

 %' union select COLUMN_NAME, 1, 2, 3 from information_schema.COLUMNS where TABLE_SCHEMA = 'sqli_1'and TABLE_NAME   = 'flag_table' #

 

flag라는 컬럼을 가진다.

7. 데이터 추출

이제 위의 정보를 기반으로 flag_table의 flag컬럼을 조회해보자

 

 

'웹 해킹 코스 > 내용 정리' 카테고리의 다른 글

9주차 XSS(크로스 사이트 스크립트)  (0) 2023.12.21
8주차 SQL Injection 대상 찾기  (1) 2023.12.18
5주차 SQL Ijection  (2) 2023.11.26
4주차 (burp suitte)  (0) 2023.11.15
3주차 (쿠키, 세션)  (0) 2023.11.08

SQL 삽입은 응용 프로그램 보안 상의 허점을 의도적으로 이용해, 악의적인 SQL문을 실행되게 함으로써 데이터베이스를 비정상적으로 조작하는 코드 인젝션 공격 방법이다. - 위키백과 -

 

즉 내가 원하는 쿼리를 실행하도록 하는 공격방법이다.

 

예시로 로그인 로직의 sql이 다음과 같다고 하자

SELECT COUNT(*) FROM MEMBER WHERE ID = '{$ID}' AND PW ='${PW}'

 

SQL Injection에 대해 조치가 없다면  ID값에  doldol'# 혹은 doldol;-- 라고 입력하면 실제 사용되는 쿼리는 다음과 같아진다.

 

SELECT COUNT(*) FROM MEMBER WHERE ID = 'doldol' #' AND PW ='${PW}'

즉 doldol이라는 아이디를 가진 사용자가 있다면 ID만으로 로그인이 된다. ID이후의 쿼리는 주석으로 처리되기 때문이다.

 

이러한 SQL Injection을 막는 방법은 여러가지 방법이 있다.

 

1. java에서의 mybatis같은 SQL Mapper 의 사용으로 입력 받는 값이 쿼리가 아닌 문자열로 인식하도록 할 수 있다.

  - 단 mybatis에서도 #{} 를 사용해야자 ${}를 사용하게 된다면 위와같은 SQL Injection에 취약하다.

2. 입력받은 문자열의 공백을 모두 trim 처리한다. SQL은 띄어쓰기로 구문을 분석하기 때문에 입력받은 값들이 SQL일지라도 띄어쓰기가 되어 있지 않다면 하나의 문법으로 인식하기 때문에 문법에러(syntaxerror invalid syntax)를 반환할 것이다.

3. 특수문자들을 치환한다. 이를 이스케이핑이라고 부르며 SQL에서의 특수한역할을 하는 특수문자들을 다른 방법으로 치환하고 다시 사용할 때 역치환하는 방식으로 사용한다.

 

이외에도 일부 사이트에서 비밀번호 입력 시 사용 할 수 없는 특수 문자가 있기도 하다 #, $ 등등

일부 특수문자나 단어를 입력할 수 없도록 하는 방법도 있을 수 있을 것이다.

 

'웹 해킹 코스 > 내용 정리' 카테고리의 다른 글

8주차 SQL Injection 대상 찾기  (1) 2023.12.18
6주차 union을 사용한 SQL Injection  (0) 2023.11.30
4주차 (burp suitte)  (0) 2023.11.15
3주차 (쿠키, 세션)  (0) 2023.11.08
2주차 (DB)  (0) 2023.11.01

함수 Exposing

UPROPERTY처럼 함수도 블루프린트로 노출시킬 수 있다. 

Item.h

	UFUNCTION(BluePrintPure)
	float TransformdedSin(float value);

	UFUNCTION(BluePrintCallable)
	float TransformdedSin2(float value);

 

Item.cpp

float AItem::TransformdedSin(float value)
{
	return Amplitude * FMath::Sin(value * TimeConstant);;


}

float AItem::TransformdedSin2(float value)
{
	return Amplitude * FMath::Sin(value * TimeConstant);;
}

 

BluePrintPure를 옵션으로 넣어주면 실행 핀이 없는 함수가 만들어지며 Callable을 옵션으로 준다면 실행핀이 존재하느 함수가 만들어진다 sin함수의 계산은 실행핀이 필요 없기때문에 Pure옵션이 적절해 보인다.

 


탬플릿 함수

탬플릿 함수는 JAVA의 제너릭과 유사해보인다.

 

Item.h

template<typename T>
T Avg(T First, T Second);

 

T 타입을 반환 하고 T 타입의 변수 First, Second를 받는다.

Item.cpp

template<typename T>
T Avg(T First, T Second)
{
	return (First + Second) /2;
}

 

위와 같이 함수를 만들면 해당 함수는 int32 파라미터, float 파라미터, FVector 타입도 받아 처리할 수 있다.

단 FVector의 객체의 경우 내부에 + 연산과 / 연산이 별도로 오버라이드 되어 있다고 한다.

+ Recent posts