No. 2908

#include<stdio.h>
int reverse(n);
int main()
{
	int a, b;
	scanf("%d %d", &a, &b);
	if (reverse(a) > reverse(b)) {
		printf("%d", reverse(a));
	}
	else {
		printf("%d", reverse(b));
	}
}
int reverse(n) {
	int r = 0;
	while (n) {
		r = (r * 10) + (n % 10);
		n = n / 10;
	}
	return r;
}

코드 설명 : 두 수 a, b를 입력 받고 reverse라는 함수를 만들어 a, b를 인자로 넣어주었다. reverse 함수는 r에 r*10 + n%10을 저장해주고 이 과정을 n번 반복시켜주었다. 이 함수를 통해 숫자를 뒤집어서 반환할 수 있다. reverse(a)와 reverse(b)를 비교하여 더 큰 것을 출력하도록 했다.

 

 

No. 2920

#include<stdio.h>
int main()
{
	int arr[9], a = 1, d = 8;
	for (int i = 0; i < 8; i++) {
		scanf("%d", &arr[i]);
	}
	for (int i = 0; i < 8; i++) {
		if (arr[i] == a){
			a++;
		}
	}
 	if (a > 8) {
		printf("ascending");
		return 0;
	}
	else {
		for (int i = 0; i < 8; i++) {
			if (arr[i] == d){
				d--;
			}
		}
		if (d < 1) {
			printf("descending");
			return 0;
		}
		else printf("mixed");
	}
	
}

코드 설명 : 8개의 숫자를 입력받고 그 수가 ascending인지 판별하기 위해 a라는 변수를 만들어 입력받은 원소가 차례대로 1부터 1씩 증가하는지 확인하도록 하였다. 그래서 최종적으로 a가 8보다 커지면 ascending에 해당하므로 이를 출력하도록 했다. 이에 해당하지 않는다면 이번에는 d라는 변수를 만들어 8부터 차례대로 1씩 감소하는지 확인하도록 하였다. 최종적으로 d가 1보다 작아진다면 descending에 해당하므로 이를 출력하도록 하였다. 앞에 두 경우에 모두 해당하지 않는다면 mixed를 출력하도록 하였다.

 

 

 

No. 3052

#include<stdio.h>
int main()
{
	int i, n, arr[42] = { 0 }, cnt = 0;
	for (i = 0; i < 10; i++) {
		scanf("%d", &n);
		n = n % 42;
		arr[n]++;
	}
	for (i = 0; i < 42; i++) {
		if (arr[i] >= 1) {
			cnt++;
		}
	}
	printf("%d", cnt);
}

코드 설명 : 배열 arr[42]의 모든 원소를 0으로 초기화해주었다. 10개의 수 n을 입력받아 각자 42로 나눈 나머지를 저장하고 arr 배열의 n번째 원소에 1씩 추가해주었다. 이 배열의 모든 원소를 for문으로 모두 확인하도록 하였다. 원소가 1보다 크거나 같으면 cnt값을 증가시켜주었다. 이는 서로 다른 값이 몇 개 있는지를 알기 위함이다. 그리고 마지막에 cnt값을 출력시켜주었다.

Canaries

- 버퍼 오버 플로우를 모니터하기 위해 버퍼와 제어 데이터 사이에 설정 된 값

- 버퍼 오버플로가 발생 → canary 값이 손상, canaries 데이터의 검증에 실패하여, 오버플로에 대한 경고 출력, 손상된 데이터를 무효화 처리

 

< Types of canaries >

Terminator canaries

- canary의 값을 문자열의 끝을 나타내는 문자들을 이용해 생성

- 구성 : NULL (0x00), CR (0x0d), LF (0x0a) 및 EOF (0xff)

- 공격자는 Canaries의 값을 우회하기 위해 Return address를 쓰기 전 null 문자를 써야 한다.

  ≫ null 문자로 오버플로우를 방지한다. (strcpy()는 null문자의 위치까지 복사)

  공격자는 잠재적으로 canary를 알려진 값으로 겹쳐쓰고 정보를 틀린 값들로 제어한다.

 

 Random canaries

- canary의 값을 랜덤하게 생성한다. (일반적으로 익스플로잇을 통해 canary를 읽는 것은 논리적으로 불가능)

- 프로그램 초기 설정 시 전역 변수에 canary값이 저장된다.

   해당 메모리를 읽으려 시도 → segmentation fault + 프로그램 종료

- 공격자가 canary 값이 저장된 stack address를 알거나 스택의 값을 읽어올 수 있다면 값ㅇ르 확인할 수 있다.

 

 Random XOR canaries

- 모든 제어 데이터 or 일부를 사용해 XOR-scramble하여 canary 값을 생성한다.

   canary 값, 제어 데이터 오염 → canary 값 달라짐

- Random canaries와 동일한 취약점을 가지고 있다.

   공격자는 canary를 다시 인코딩하기 위해 original canary값, 알고리즘, 제어 데이터가 필요

 

 

< Example >

#include <stdio.h>
 
void main(int argc, char **argv)
{
    char Overflow[32];
     
    printf("Hello world!\n");
    gets(Overflow);
 
}

 

▶ canary 값 확인하기

 

- 사용자 값이 저장되는 영역은 0x7fffffffe180 이며 해당 영역에 코드에서 할당한 길이의 문자를 저장한다. ('A' * 32)

 

- 0x400610에서 rax 레지스터에 rbp - 0x8 영역에 저장된 값을 저장한다.

   rbp(0x7fffffffe1b0) - 0x8 = 0x7fffffffe1a8

   0x7fffffffe1a8 영역에 저장된 값 : 0x3a3b864735c7b300

- 0x400614에서 rax 레지스터에 저장된 값과 fs:0x28 레지스터에 저장된 값을 xor 연산한다.

- 0x40061d에서 rax 레지스터의 값이 0과 같으면 0x400624 영역으로 이동한다.

 

- 이렇게 프로그램이 종료된다.

 

▶ canary 값 덮어쓰기

- 사용자 입력 값으로 'A' * 40 + 'B' * 8 을 입력한다.

  ≫ 이로 인해 canary의 값이 0x4242424242424242(BBBBBBBB) 으로 변경됐다.

 

- 0x400610에서 rax 레지스터에 rbp - 0x8 영역에 저장된 값을 저장한다.

  rbp(0x7fffffffe1b0) - 0x8 = 0x7fffffffe1a8

   0x7fffffffe1a8 영역에 저장된 값 : 0x4242424242424242

 

- 0x400614에서 rax 레지스터에 저장된 값과 fs:0x28 레지스터에 저장된 값을 xor 연산한다.

- 0x40061d에서 rax 레지스터의 값이 0x61061c8ecf993242 이기 때문에 다음 코드 영역(0x40061f)으로 이동한다.

 

- 위와 같은 error메세지를 출력한다.

 

 

< Check the protection techniques of binary files >

checksec.sh

- not set canary : gcc -fstack-protector -o Canary_Do-not-set Canary.c

- set canary :gcc -o Canary Canary.c

 

< How to detect Canary in the "Checksec.sh" file >

Binary

 

- 'readelf' 명령어를 이용해 해당 파일의 심볼 테이블 정보를 가져와 Canary 설졍여부를 확인한다.

- 파일의 심볼 테이블에 "__stack_chk_fail"가 있으면 Canary가 적용되었다고 판단한다.

 

Process

 

- Binary의 확인 방식과 비슷하며, 전달되는 파일의 경로가 다음과 같이 다르다. (ex) /proc/<PID>/exe)

- 추가된 동작은 '/proc/<PID>/exe' 파일에 'Symbol table' 정보가 있는지 확인한다.

No. 2742

#include<stdio.h>
int main()
{
	int n;
	scanf("%d", &n);
	while (n > 0) {
		printf("%d\n", n);
		n--;
	}
}

코드 설명 : 먼저 n을 입력받았다. n이 0보다 클때까지 계속 n을 출력하도록하고 n을 1씩 줄이도록 반복문을 실행시켜주었다. 출력될 때마다 줄바꿈 또한 해주었다.

 

 

No. 2753

#include<stdio.h>
int main()
{
	int y;
	scanf("%d", &y);
	if ((y % 4 == 0 && y % 100 != 0) || y % 400 == 0) printf("1");
	else printf("0");
}

코드 설명 : 연도를 입력받고 if문으로 이 연도가 4의 배수이면서 100의 배수가 아닌지, 또는 이 연도가 400의 배수인지 확인하고 맞다면 1을 출력하도록 하였다. 이 조건을 만족하지 않는다면 0을 출력하도록 하였다.

 

 

No. 2884

#include<stdio.h>
int main()
{
	int h, m;
	scanf("%d %d", &h, &m);
	if (m >= 45) m -= 45;
	else {
		if (h == 0) h = 23;
		else h -= 1; m += 15;
	}
	printf("%d %d", h, m);
}

코드 설명 :  h와 m을 입력받았다. 각 시, 분을 의미하는 변수이다. 45분 이상일 때에는 h 변화 없이 m만 45를 빼주면 된다. 45분 미만일 때 h가 0이면 23으로 바꿔주고 0이 아니면 h에서 1빼주고 m은 60분에서 45분을 뺀 후에 원래 m값을 더해주면 되므로 m+=15를 해주면 값이 나온다. 따라서 이를 출력해주었다.

1. HTML injection

HTML injection 이란?
코드 인젝션 공격의 하위 개념으로 취약한 매개변수에 악의적인 HTML 코드를 삽입하는 공격

 

반사기법

: URL에 악의적인 HTML 태그를 삽입하여 링크를 클릭한 사용자의 PC에서 HTML 태그가 실행되게 하는 공격

- GET 방식으로 데이터를 전송할 경우, URL에 변수 이름과 입력 값을 노출한다.

 

② 저장기법

: 악의적인 HTML 태그를 데이터베이스에 저장하여 저장된 태그 내용을 확인한 사용자의 PC에 HTML 태그가 실행되게 하는 공격

 

  반사기법 저장기법
차이점 URL에 HTML 태그 삽입 서버의 DB에 저장

2. 아래 화면 출력하기

 

 

 

먼저 실습 환경 구축을 해주었다.

 

[ 난이도 low ]
img src: http://[본인IP]/bWAPP/images/bee_1.png
hint1. 페이지 소스 코드를 확인해봅시다.

 

First name에 hello, Last name에 world를 입력해보았더니 Welcome hello world가 출력되는걸 볼 수 있었다.

그리고 URL이 bWAPP/htmli_get.php?firstname=hello&lastname=world&form=submit 로 변경되었다.

이렇게 URL에 데이터가 노출된다는 것을 확인할 수 있었다.

 

그리고 페이지 소스에도 Welcome hello world가 추가되었다.

 

 

이번엔 h1태그를 이용해 hello를 써주고 h2태그를 이용해 world를 입력해보았더니 위와 같이 나타났다.

 

그리고 이와 같은 소스코드가 생겼다.

 

URL은 ?firstname=<h1>hello<%2Fh1>&lastname=<h2>world<%2Fh2> 이러한 형식으로 바뀌었다.

 

※ 출력해야 하는 화면 중 First name에 해당하는 부분이 /SUCCESS/ 이므로 <h1>SUCCESS</h1>이 들어가야 한다고 생각했다. 그리고 Last name 부분에는 이미지가 들어가야 하므로 문제에서 준 img src: http://[본인IP]/bWAPP/images/bee_1.png 코드를 활용하고자 하였다.

 

이미지 태그를 삽입하기 위해 <img src="http://[본인IP]/bWAPP/images/bee_1.png">이라고 작성해주었더니

다음과 같은 결과가 나왔다.

 

[난이도 medium]

hint1. low일 때 성공한 페이지와 비교해봅시다. 소스코드 차이점이 반드시 있습니다.

hint2. URL Encoding

먼저 위에서 한 것과 동일하게 First name에 hello, Last name에 world를 입력해주었더니 동일한 결과가 나왔다

 

하지만 h태그를 이용해 작성해주었더니

위에서 본 결과와 다르게 h태그가 적용된 결과가 아닌 태그 그대로를 출력함을 확인할 수 있었다.

URL은 ?firstname=hello<%2Fh1>&lastname=world<%2Fh2>의 형태로 동일하게 나타났다.

 

페이지 소스 코드에서 low와의 다른점을 찾을 수 있었다.

좌측은 low의 코드, 우측은 medium의 코드이다.

우측 코드를 보면 <이 &lt;로 변환되고, >이 &gt;로 변환된다는 것을 알 수 있었다.

&lt와 &gt에 대해 검색해보니 마크업기반 언어에서 수식 속 부등호를 사용하기 위한 코드라고 한다.

따라서 우측 코드에서는 <와 >을 코드가 아닌 부등호로 인식한다는 것을 알 수 있었다.

 

firstname=hello<%2Fh1>&lastname=world<%2Fh2>에서도 볼 수 있듯이 인코딩이 필요하다고 생각했다.

그래서 인코딩 변환기를 사용하여 위에서 사용한 코드를 인코딩해주었다.

<h1>SUCCESS</h1> → %3Ch1%3ESUCCESS%3C%2Fh1%3E
<img src="http://192.168.204.128/bWAPP/images/bee_1.png">
→ %3Cimg%20src%3D%22http%3A%2F%2F%2FbWAPP%2F192.168.204.128images%2Fbee_1.png%22%3E

이를 각각 입력해주었더니

다음과 같은 결과가 나타났다.

 

+) bee-box에서 cd /var/www/bWAPP 해주고 htmli_get.php파일을 열어주면 다음과 같은 화면이 나온다.

case 0, 1, 2는 각각 low, medium, high에 해당된다고 한다.

 

functions_external.php 파일을 열어보면

해당 함수들을 볼 수 있다.

특히, xss_check_2(medium)함수에서 <을 &lt로, >을 &gt로 변환하도록 코드가 작성되어 있는 것을 확인할 수 있다.

 

[난이도 high]

풀 수 없습니다. 풀 수 없는 이유를 정리해주세요.

hint1. include는 외부 파일을 포함하는 함수입니다. 확인해야 할 함수가 있는데 외부 파일에 있는 듯 합니다.

hint2. function_external.php 파일에 xss_check2 함수를 확인해봅시다.

 

위에서 찾은 xss_check_3을 활용해보자

(hight에 해당하는 함수는 xss_check_3이다)

코드를 보니 htmlspecialchars함수를 사용하고 있다.

htmlspecialchars 함수
: HTML에서 사용하는 특수문자를 UTF-8로 반환하는 함수

- & 는 &amp; 로 변환
- " 는 &quot; 로 변환
- ' 는 &#039; 로 변환
- < 는 &lt; 로 변환
- > 는 &gt;로 변환

구조 : string htmlspecialchars ( string $string , int $quote_style , string $charset , bool $double_encode )
string $string : HTML 엔티티로 변환할 문자열
int $quote_style 
- ENT_COMPAT : 기본모드, 큰따옴표만 변환
- ENT_QUOTES : 큰따옴표와 작은따옴표 둘다 변환
- ENT_NOQUOTES : 큰 따옴표와 작은따옴표 둘다 변환하지 않음
string $charset : 변환에 사용할 문자셋 지정
bool $double_encode : 이미 존재하는 HTML 엔티티를 encode 할지 여부 지정, 생략하는 true를 기본값으로 가진다.
return htmlspecialchars($data, ENT_QUOTES, $encoding);

이 코드에서 data로 받은 문자열을 UTF-8로 반환하는데 ", ' 둘 다 변환됨을 알 수 있다.

이 때문에 문제를 풀 수 없다.

 

★ 이를 통해 HTML Injection 공격을 방지하기 위해서는 htmlspecialchars함수를 사용하면 된다는 것을 알 수 있다.

+ Recent posts