由php中字符offset特征造成的绕过漏洞详解


Posted in PHP onJuly 07, 2017

php中的字符offset特性

php中的字符串存在一个非常有趣的特性,php中的字符串也可以像数组一样进行取值。

$test = "hello world";
echo $test[0];

最后的结果就是h。

但是上述的这种特性有时会有意想不到的效果,看下面这段代码

$mystr = "hello world";
echo $mystr["pass"];

上述的代码的输出结果是h.这是为什么呢?其实很简单,和很多其他的语言一样,字符串在php中也像数组一样可以使用下标取值。$mystr["pass"]中pass会被进行隐性类型转换为0,这样$mystr[0]的输出结果就是首字母h.
同样地,如果尝试如下的代码:

$mystr = "hello world";
echo $mystr["1pass"];

输出结果就是e.因为1pass会被隐性类型转换为1,$mystr[1]的输出结果就是第二个字母e.

字符特性造成的漏洞

下面这段代码是在在phpspy2006中用于判断登录时所使用的代码。

$admin['check'] = "1";
$admin['pass'] = "angel";
......
if($admin['check'] == "1") {
....
}

这样的验证逻辑如果利用上述的特性就很容易地就可以被绕过。$admin没有被初始定义为数组类型,那么当我们用字符串提交时phpsyp.php?admin=1abc时,php会取字符串1xxx的第一位,成功绕过if的条件判断。

上面那段代码是一个代码片段,接下来的这段代码是一段完整的逻辑代码,来自于php4fun中第5题,比较有意思。

<?php
# GOAL: overwrite password for admin (id=1)
#  Try to login as admin
# $yourInfo=array( //this is your user data in the db
# 'id' => 8,
# 'name' => 'jimbo18714',
# 'pass' => 'MAYBECHANGED',
# 'level' => 1
# );
require 'db.inc.php';

function mres($str)
{
 return mysql_real_escape_string($str);
}

$userInfo = @unserialize($_GET['userInfo']);

$query = 'SELECT * FROM users WHERE id = \'' . mres($userInfo['id']) . '\' AND pass = \'' . mres($userInfo['pass']) . '\';';

$result = mysql_query($query);
if (!$result || mysql_num_rows($result) < 1) {
 die('Invalid password!');
}

$row = mysql_fetch_assoc($result);
foreach ($row as $key => $value) {
 $userInfo[$key] = $value;
}

$oldPass = @$_GET['oldPass'];
$newPass = @$_GET['newPass'];
if ($oldPass == $userInfo['pass']) {
 $userInfo['pass'] = $newPass;
 $query = 'UPDATE users SET pass = \'' . mres($newPass) . '\' WHERE id = \'' . mres($userInfo['id']) . '\';';
 mysql_query($query);
 echo 'Password Changed.';
} else {
 echo 'Invalid old password entered.';
}

这道题目网上也仅仅只是给了一个最终的答案,其中的原理都没有说或者没有说得很详细。其实原理就是上面讲到的php的字符特性。

题目要求很简单就是修改admin的密码,admin的id为1。我们需要思考以下几个问题:

  • 如何在更新的时候将id修改为1
  • $userInfo['pass'] = $newPass;这行代码有什么作用,为什么会在if判断语句中存在这种的代码

想通了这两个问题,那么最终的解决方法也有了。将id为8的用户的密码修改为8,然后传入一个userInfo的字符串‘8',突破查询防护,最后利用$userInfo['pass'] = $newPass将id修改为1。

最终的payload就是;

第一次提交, index.php?userInfo=a:2:{s:2:"id";i:8;s:4:"pass";s:12:"MAYBECHANGED";}&oldPass=MAYBECHANGED&newPass=8,目的是将id为8的用户的密码修改为8

第二次提交,index.php?userInfo=s:1:"8";&oldPass=8&newPass=1,这样序列化$userInfo得到的就是字符串‘8',即$userInfo = ‘8' ,这样数据库查询验证就可以通过。之后的if验证也可以通过,通过这行代码$userInfo['pass'] = $newPass;,由于$newpass的值为1,那么上述代码变为了$userInfo['pass'] = 1; ,$userInfo由于一个字符串类型,最后得到的是$userInfo='1' ,最后就可以更新id为1的用户的密码了。

修复方式

这种漏洞的修复方式也很简单,事先定义好数据类型同时在使用时最好检查一下所使用的数据类型是否和预期的一致。否则就会出现上述的绕过的问题。同时要控制好输入,对输入的数据要进行检查不要随意地使用。

参考

https://github.com/80vul/webzine/blob/master/webzine_0x06/PSTZine_0x06_0x03.txt

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对三水点靠木的支持。

PHP 相关文章推荐
比较简单的百度网盘文件直链PHP代码
Mar 24 PHP
CodeIgniter框架中_remap()使用方法2例
Mar 10 PHP
PHP+memcache实现消息队列案例分享
May 21 PHP
php中多维数组按指定value排序的实现代码
Aug 19 PHP
php跨站攻击实例分析
Oct 28 PHP
PHP之浮点数计算比较以及取整数不准确的解决办法
Jul 29 PHP
PHP开发中常用的十个代码样例
Feb 02 PHP
Laravel5.1自定义500错误页面示例
Oct 09 PHP
php  PATH_SEPARATOR判断当前服务器系统类型实例
Oct 28 PHP
php实现在线考试系统【附源码】
Sep 18 PHP
php设计模式之观察者模式定义与用法经典示例
Sep 19 PHP
THINKPHP5分页数据对象处理过程解析
Oct 28 PHP
Laravel使用PHPQRCODE实现生成带有LOGO的二维码图片功能示例
Jul 07 #PHP
thinkPHP微信分享接口JSSDK用法实例
Jul 07 #PHP
微信开发之获取JSAPI TICKET
Jul 07 #PHP
Yii2第三方类库插件Imagine的安装和使用
Jul 06 #PHP
一个实用的php验证码类
Jul 06 #PHP
万能的php分页类
Jul 06 #PHP
PHP 实现从数据库导出到.csv文件方法
Jul 06 #PHP
You might like
使用HMAC-SHA1签名方法详解
2013/06/26 PHP
typecho插件编写教程(四):插件挂载
2015/05/28 PHP
php将图片文件转换成二进制输出的方法
2015/06/10 PHP
PHP文件上传之多文件上传的实现思路
2016/01/27 PHP
php文件上传类完整实例
2016/05/14 PHP
PHP7生产环境队列Beanstalkd用法详解
2020/05/19 PHP
laravel开发环境homestead搭建过程详解
2020/07/03 PHP
分享别人写的一个小型js框架
2007/08/13 Javascript
JavaScript中创建类/对象的几种方法总结
2013/11/29 Javascript
JS父页面与子页面相互传值方法
2014/03/05 Javascript
jquery选择器原理介绍($()使用方法)
2014/03/25 Javascript
Actionscript与javascript交互实例程序(修改)
2016/09/22 Javascript
[js高手之路]图解javascript的原型(prototype)对象,原型链实例
2017/08/28 Javascript
Vue-路由导航菜单栏的高亮设置方法
2018/03/17 Javascript
node.js的http.createServer过程深入解析
2019/06/06 Javascript
解决ant Design中Select设置initialValue时的大坑
2020/10/29 Javascript
Python和GO语言实现的消息摘要算法示例
2015/03/10 Python
浅谈python 四种数值类型(int,long,float,complex)
2016/06/08 Python
Python实现屏幕截图的代码及函数详解
2016/10/01 Python
Python如何抓取天猫商品详细信息及交易记录
2018/02/23 Python
python中使用ctypes调用so传参设置遇到的问题及解决方法
2019/06/19 Python
python实现对列表中的元素进行倒序打印
2019/11/23 Python
解决python pandas读取excel中多个不同sheet表格存在的问题
2020/07/14 Python
matplotlib实现数据实时刷新的示例代码
2021/01/05 Python
css3.0新属性效果在ie下的解决方案
2010/05/10 HTML / CSS
详解css3中的伪类before和after常见用法
2020/11/17 HTML / CSS
亚洲独特体验旅游专家:eOasia
2018/08/15 全球购物
生育关怀行动实施方案
2014/03/26 职场文书
初中生庆国庆演讲稿范文2014
2014/09/25 职场文书
迎国庆横幅标语
2014/10/08 职场文书
2014年银行个人工作总结
2014/12/05 职场文书
金秋助学感谢信
2015/01/21 职场文书
电工生产实习心得体会
2016/01/22 职场文书
考教师资格证不要错过的4个最佳时机
2019/07/17 职场文书
Python Django 后台管理之后台模型属性详解
2021/04/25 Python
Python爬虫之爬取哔哩哔哩热门视频排行榜
2021/04/28 Python