由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 visitFile()遍历指定文件夹函数
Aug 21 PHP
通过curl模拟post和get方式提交的表单类
Apr 23 PHP
php实现的ping端口函数实例
Nov 12 PHP
修改PHP脚本使WordPress拦截垃圾评论的方法示例
Dec 10 PHP
php打乱数组二维数组多维数组的简单实例
Jun 17 PHP
PHP使用FFmpeg获取视频播放总时长与码率等信息
Sep 13 PHP
php读取XML的常见方法实例总结
Apr 25 PHP
PHP面向对象五大原则之开放-封闭原则(OCP)详解
Apr 04 PHP
PHP设计模式之观察者模式定义与用法示例
Aug 04 PHP
使用PHPExcel导出Excel表
Sep 08 PHP
PHP PDOStatement::rowCount讲解
Feb 01 PHP
Laravel框架文件上传功能实现方法示例
Apr 16 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
PHP的PSR规范中文版
2013/09/28 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十二)
2014/06/25 PHP
浅谈Laravel中的一个后期静态绑定
2017/08/11 PHP
利用google提供的API(JavaScript接口)获取网站访问者IP地理位置的代码详解
2010/07/24 Javascript
jQuery 全选/反选以及单击行改变背景色实例
2013/07/02 Javascript
推荐10个2014年最佳的jQuery视频插件
2014/11/12 Javascript
深入理解JavaScript系列(34):设计模式之命令模式详解
2015/03/03 Javascript
JavaScript中的toLocaleLowerCase()方法使用详解
2015/06/06 Javascript
js实现兼容性好的微软官网导航下拉菜单效果
2015/09/07 Javascript
使用递归遍历对象获得value值的实现方法
2016/06/14 Javascript
实现一个简单的vue无限加载指令方法
2017/01/10 Javascript
Vue.js仿Metronic高级表格(二)数据渲染
2017/04/19 Javascript
关于在vue-cli中使用微信自动登录和分享的实例
2017/06/22 Javascript
ES6使用Set数据结构实现数组的交集、并集、差集功能示例
2017/10/31 Javascript
jquery树形插件zTree高级使用详解
2019/08/16 jQuery
绘制微信小程序验证码功能的实例代码
2021/01/05 Javascript
[01:03]PWL开团时刻DAY6——别打我
2020/11/05 DOTA
Python运算符重载详解及实例代码
2017/03/07 Python
python实现学生信息管理系统
2020/04/05 Python
Python操作mongodb数据库进行模糊查询操作示例
2018/06/09 Python
浅谈利用numpy对矩阵进行归一化处理的方法
2018/07/11 Python
python实现遍历文件夹修改文件后缀
2018/08/28 Python
python画微信表情符的实例代码
2019/10/09 Python
Python爬虫爬取博客实现可视化过程解析
2020/06/29 Python
Avène雅漾美国官方网站:敏感肌肤护理专家
2016/10/24 全球购物
Amara美国站:英国高端家居礼品网站,世界各地的奢侈家具品牌
2017/07/26 全球购物
美国网上购买眼镜:Eyeconic
2017/07/29 全球购物
俄罗斯运动、健康和美容产品在线商店:Lactomin.ru
2020/07/23 全球购物
打架检讨书100字
2014/01/08 职场文书
信用社员工先进事迹材料
2014/02/04 职场文书
企业活动策划方案
2014/06/02 职场文书
给老师的感谢信
2015/01/20 职场文书
技术员岗位职责
2015/02/04 职场文书
学雷锋团日活动总结
2015/05/06 职场文书
关于迟到的检讨书
2015/05/06 职场文书
公司车队管理制度
2015/08/04 职场文书