Websec-level9

 

 

 

 

입력한 문자열이 블랙리스트에 걸러진후 파일에 저장되며 이 파일을 다시 불러서 eval 해준다.

 

 


 

stripcslashes를 이용하면 풀 수 있다.

stripcslashes는 \n, \r 과 같은 역슬래쉬가 있는 문자들을 역슬래쉬를 제거하고 그 문자의 의미(?)로 표현해준다.

(ex : \n -> 줄바꿈)

(stripcslashes online tester http://php.fnlist.com/string/stripcslashes)

 

 

따라서 블랙리스트에 있는 ' 같은 문자를 \x27, \47으로 입력해주면

블랙리스트에 필터링 되지않고 cache_file에 저장되며 이 파일을 출력해줄 때 stripcslashes를 통해 \x27이 '로 해석되어 함수를 실행 시킬 수 있어서 문제를 해결할 수 있다.. 

'Web hacking > Websec' 카테고리의 다른 글

websec - level 19  (0) 2020.03.05
websec - level 24  (0) 2020.02.25
Websec - level 22  (0) 2020.02.22
Websec - level 14  (0) 2020.02.19
Websec - level 17  (0) 2020.01.05

Websec - level5

 

 

 

 

input box에 입력한 값이 q값으로 전달 되며,

 

 

blacklist가 아닌 값이 2개이상 들어오는 것을 \\1으로 해석하므로

q값중 blacklist에 있는 값이 나오기전까지의 부분이 \\1으로서 correct함수의 파라미터로 전달된다.

 

 

correct 함수의 return값이 출력된다.

 


 

 

preg_replace에서 pattern부분의 e modifer의 취약점을 이용하여 이 문제를 해결할 수 있다.

e modifer는 preg_replace의 두번쨰 파라미터인 replacement부분을 실행 시켜준다.

따라서 우리가 입력하는 input box에 적절한 값을 넣어서 php코드로 실행할 수 있다.

 

 

우선 문제에서 힌트를 찾자면

 

 

 

flag.php를 참조해서 php안에 있는 flag를 출력해야 할 것 같다.

 

 

이는 $뒤에 오는 {}안에서 문자열이 실행되는 것을 이용하여 문제를 해결할 수 있다.

{}안에 flag.php를 참조할 수 있는 include나 require를 사용하면된다. include flag.php와 같은 경우 공백이 blacklist에 등록되어 있지만 공백줄바꿈(%0a),%09, /**/등을 이용하여 우회할 수 있다.

 

 

하지만 flag.php를 입력하게되면 flag.php으로 인식하는 것이 아니라 각각의 상수 문자로 인식하게된다. 그래서 그냥 $_GET[]으로 flag.php를 따로 입력해주어서 해결하였고, 이후에 $flag파일을 출력하도록 하면 해결할 수 있다.

 

 

?q=${include%0a$_GET[p]}$flag&p=flag.php

 

 

 

 

 


 

 

$뒤에 오는{}에 함수나 문자열이 실행되는 것 예전에 ~연산자를 이용한 우회한 것과 같은 것을 기술적(?)으로는 알고 있으나 이것이 어떤 과정에 의해서 실행되는지는 알아보아야 할 것 같다.

 

이번 문제는 문제 해결과정을 완벽하게 이해했다기 보다 이전에 사용했던 트릭적인 것을 이것저것 사용하다가 푼 것같다.

 

 

 

Websec - level3

 

 

 

c에는 우리가 입력하는 데이터가 들어가며 hash된 값이 우리가 찾을 flag와 같으면 문제를 해결할 수 있다.

 

 

 


 

 

 

이문제의 포인트는 sha1함수에서 두번째 파라미터의 값이 false가 아닌 fa1se라는 점이다.

 

 

이것이 어떤 영향이 있는지 알아보면

 

 

 

 

sha1 함수에서 두번째 파라미터 값이 true이면 길이 20의 raw binary 데이터가 반환되고 false면 40글자의 hex값이 반환된다. 우리는 false가 아닌 fa1se이므로 raw binary 데이터가 반환된다.

 

 

flag의 해쉬값은 : 7c00249d409a91ab84e3f421c193520d9fb3674b

 

 

두글자씩 해석해서 보면 7c 00으로 두번째가 NULL로 인식된다.

문자열을 읽을 때 NULL까지 읽으므로 사실상 7c까지의 문자가 password_veryify의 함수에서 비교될 것이다.

 

 

따라서 우리는 sha1함수를 통해 hash된 값이 7c00~~~인 문자를 찾아서 값을 넣어주면 된다.

이것은 brute force를 이용해서 구하면 된다.

 

 

websec - level 19

 

 

index.php
random.php
anti_csrf.php

 

 

 

해당 index.php에 접속하게 되면 token과 captcha이 생성된다.

 

Input에 captcha 값을 넣고  anti_csrf.php로 인해 POST로 받은 token 값이 달라졌는지 검증한 후 captcha와 token이 일치하면 지정된 email_addr로 메일이 보내지게 된다.

 

따라서 우리는 captcha값을 구하는 것과 email을 우회할 방법을 찾으면 된다.

 

 

 

 


 

 

1. captcha 구하기

 

 

 

우선 random으로 생성되는 captcha 값을 구해야한다. captcha는 generate_random_text함수로 생성된다.

 

 

이 함수가 있는 random.php를 살펴보면 srand() 매개변수에 microtime(true)을 시드로 받는다. 이 안의 microtime(true)는 정수로서 이 부분을 이용하여 captcha값을 구할 수 있다고 생각했다.

 

php에 똑같이 generate_random_text 함수를 구현한 후 token과 captcha를 생성한다. 이때 이 php를 실행 시킨 후 바로 index.php를 실행하면 microtime으로 1, 2 초 정도 차이가 날 수 있지만 이는 token과 captcha를 여러개 생성해주면 index.php에 생성되는 token값과 같은 값을 찾을 수 있다.

 

 

 

- 위의 아이디어를 가지고 token값을 생성하였으나, websec의 token과 같은 값을 찾을 수가 없었다.

 

 

  이 때의 원인으로 서버시간의 차이, php버전의 차이정도로 생각하였다.

 

 

  1. 서버시간의 차이

     첫번째로 의심한 것은 서버시간의 차이가 있어서 microtime이 리턴하는 값이 다를 것이라 예상하였는데 실제로 해       보니 별 차이가 없었다.

 

  2. php 버전의 차이

     php버전에 따라서 rand가 반환하는 값의 차이가 있을 것이라 생각하였다. 처음에 내부함수를 사용할 수 있는 다른       문제에 들어가서 phpinfo를 통해 php 버전이 7.2 버전임을 확인하고 값을 찾았지만 별 차이가 없었다. 그래서 버전       차이가 아니라 다른 문제인 것으로 생각하였으나 문제마다 버전이 다르다는 것을 알고 php 버전을 줄이면서 값을         확인한 결과 7.0 버전에서 token 값을 찾을 수 있었다.

 

 

token 값과 captcha가 생성될 때 시간 차이가 1초이내이므로 같은 시간에 생성된 captcha로 값을 구할 수 있다.

 

 

 

 

 

 

 

2. email_addr 우회

 

 

 

email_addr를 어떻게 우회할지 고민하다가 그냥 header에 host명을 아무거나 바꿔서 값을 보냈더니 그냥 문제가 풀렸다. 따로 email 전체를 바꾸지 않아도 host만 바꿔도 해결되게 문제를 만들어 놓아서 쉽게 풀었다.

'Web hacking > Websec' 카테고리의 다른 글

Websec - level9  (1) 2020.03.24
websec - level 24  (0) 2020.02.25
Websec - level 22  (0) 2020.02.22
Websec - level 14  (0) 2020.02.19
Websec - level 17  (0) 2020.01.05

websec - level 24

 

 

 

파일이름을 입력하면 해당 파일명으로 파일을 생성할 수 있고, 안에 data를 넣을 수  있다.

data는 <?와 script가 필터링 되어 파일에 쓸 수 없다.

 

 


 

1. XSS

우리가 입력할 수 있는 것은 filename과 data이다.

 

 

처음에는 filename부분에 <script>태그를 넣어 xss를 시도하려고 하였다.

<script>alert(1)</script>를 넣었을 때 성공적으로 수행되며 edit창으로 넘어갔으나, /를 dir로 인식을 하는지

 

 

 

다음과 같은 오류로 서버에 저장되지 않아서 사용할 수 없었다.

 

 

 

 


 

2. PHP wrapper

두번째는 data와 filename모두를 건드려 보았다.

실질적으로 데이터가 저장되는 부분은 file_put_contents부분이라 이 부분을 중심으로 시도해보았다.

 

file_put_content의 메뉴얼을 살펴보면

 

 

 

다음과 같이 path를 적는 부분에 Wrapper를 사용할 수 있음을 알 수 있다.

 

root-me 문제를 풀면서 사용했던 php wrapper "php://filter/convert.base64-encode/resource=[파일명]"를 사용하면 파일이 실행되기전 base64로 인코딩된 파일을 나타내준다.

 

이번과 같은 경우 data에 <?와 <script>를 사용하지 못하는데 적절한 php코드를 작성 후 encode된 값을 넘겨주면 stripos 필터에 걸리지 않고 data를 넘겨 줄 수 있다.

그리고 우리가 원하는 것은 출력될 때 정상적인 php코드로 동작하는 것이므로 file_put_contents로 파일을 작성할 때에 php wrapper를 사용하여 넘겨준 data를 decode하여 작성하게 된다면, 우리가 /uploads 디렉토리로 접근하여 파일을 읽었을 때에 정상적으로 php코드가 실행 될 것이라 예상할 수 있다.

 

 

 

<? php
	echo var_dump(scandir'/');
?>

#directory에 있는 file 찾기

 

 

다음과 같이 php코드로 flag파일을 찾은 후 파일을 읽으면 답을 얻을 수 있다.

 

 

 

 

 

 

 


 

XSS를 이용한 풀이방법을 한번 다시 연구해봐야겠다..

'Web hacking > Websec' 카테고리의 다른 글

Websec - level9  (1) 2020.03.24
websec - level 19  (0) 2020.03.05
Websec - level 22  (0) 2020.02.22
Websec - level 14  (0) 2020.02.19
Websec - level 17  (0) 2020.01.05

Websec - level 22

 

 

 

 

 


 

 

14번문제를 풀면서 고민했던 방법 중 $blacklist{} 방법을 사용하여 쉽게 풀었다.

 

$blacklist{input} input값을 1씩 늘려가면서 결과 값으로

var_dump, serialize, print_r 등의 원하는 값을 찾은 후 이를 이용하여 $a를 출력하여 문제를 해결하였다.

 

 

https://seummm.tistory.com/27

 

Websec - level 14

Websec - level 14 input은 25글자로 제한되어 있으며, 내부함수와 설정된 문자, 문자열들이 블랙리스트로 등록되어 Input에 해당 문자가 있으면 Insecure code detected!을 출력하게 된다. 1. 처음에는 $blackli..

seummm.tistory.com

 

 


문제를 풀면서...

 

1. serialize를 사용했을 때 *, A는 갑자기 어디서 나타난건가

O:1:"A":3:{s:3:"pub";s:17:"-";s:6:"*pro";s:18:"-";s:6:"Apri";s:22:"-";}
object(A)#1 (3) {
  ["pub"]=>
  string(17) "-"
  ["pro":protected]=>
  string(18) "-"
  ["pri":"A":private]=>
  string(22) "-}"
}

var_dump에서도 A를 발견할 수 있었다.

 

 

 

 

 

->

 

object를 배열로 cast할 때 property에 따라 property names/new array keys가 앞에 붙는다.

 

 

protected'(space-padded)*'

private : '(space-padded)class이름'

 

 

class test
{
    public $var1 = 1;
    protected $var2 = 2;
    private $var3 = 3;
    static $var4 = 4;
   
    public function toArray()
    {
        return (array) $this;
    }
}

$t = new test;
print_r($t->toArray());

/* outputs:

Array
(
    [var1] => 1
    [ * var2] => 2
    [ test var3] => 3
)

 

 

 

 


 

 

2. Serialize를 이용하여 출력하였을 때 왜 *pro, Apri로 출력된 각각의 문자열이 serialize에서 표시된 길이와 같지않을까?

 

O:1:"A":3:{s:3:"pub";s:17:"-";s:6:"*pro";s:18:"-";s:6:"Apri";s:22:"-";}

 

 

 

 

 

->protect와 private의 *와 A사이에 \0이 생략되어있어 보이는 숫자보다 +2하면 된다.

   serialize할 때 addslashes(serialize($a))하면 숨겨진 %00를 확인할 수 있다.!

 

 


 

 

추가적으로 공부한 내용을 토대로 새로운 풀이를 얻을 수 있었따.

 

((array)$a){'pub'}

((array)$a){'%00*%00pro'}

((array)$a){'%00A%00pri'} 

'Web hacking > Websec' 카테고리의 다른 글

websec - level 19  (0) 2020.03.05
websec - level 24  (0) 2020.02.25
Websec - level 14  (0) 2020.02.19
Websec - level 17  (0) 2020.01.05
Websec - level 4  (0) 2020.01.05

+ Recent posts