由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数据库操作面向对象的优点
Oct 09 PHP
使用HMAC-SHA1签名方法详解
Jun 26 PHP
PHP根据传来的16进制颜色代码自动改变背景颜色
Jun 13 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(八)
Jun 23 PHP
Eclipse的PHP插件PHPEclipse安装和使用
Jul 20 PHP
php简单统计字符串单词数量的方法
Jun 19 PHP
Zend Framework实现将session存储在memcache中的方法
Mar 22 PHP
php使用ftp远程上传文件类(完美解决主从文件同步问题的方法)
Sep 23 PHP
详解Yii2 之 生成 URL 的方法
Jun 16 PHP
laravel高级的Join语法详解以及使用Join多个条件
Oct 16 PHP
PHP扩展安装方法步骤解析
Nov 24 PHP
解决Laravel使用验证时跳转到首页的问题
Nov 17 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
excellent!――ASCII Art(由目标图象生成ascii)
2007/02/20 PHP
初识PHP
2014/09/28 PHP
使用PHPCMS搭建wap手机网站
2015/09/20 PHP
详解PHP实现执行定时任务
2015/12/21 PHP
浅析PHP7 的垃圾回收机制
2019/09/06 PHP
Javascript 判断函数类型完美解决方案
2009/09/02 Javascript
javascript控制frame,iframe的src属性代码
2009/12/31 Javascript
{}与function(){}选用空对象{}来存放keyValue
2012/05/23 Javascript
javascript内存管理详细解析
2013/11/11 Javascript
js实现回放拖拽轨迹从过程上进行分析
2014/06/26 Javascript
不依赖Flash和任何JS库实现文本复制与剪切附源码下载
2015/10/09 Javascript
js获取当前页的URL与window.location.href简单方法
2017/02/13 Javascript
详解AngularJS controller调用factory
2017/05/19 Javascript
AngularJS自定义表单验证功能实例详解
2018/08/24 Javascript
vue在index.html中引入静态文件不生效问题及解决方法
2019/04/29 Javascript
使用webpack/gulp构建TypeScript项目的方法示例
2019/12/18 Javascript
[42:56]VGJ.S vs Serenity 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
[33:19]完美世界DOTA2联赛PWL S2 PXG vs InkIce 第一场 11.26
2020/11/30 DOTA
Python Web框架Flask中使用七牛云存储实例
2015/02/08 Python
python3实现随机数
2018/06/25 Python
Selenium元素的常用操作方法分析
2018/08/10 Python
纯用NumPy实现神经网络的示例代码
2018/10/24 Python
Python3爬虫爬取英雄联盟高清桌面壁纸功能示例【基于Scrapy框架】
2018/12/05 Python
Python完成哈夫曼树编码过程及原理详解
2019/07/29 Python
使用coverage统计python web项目代码覆盖率的方法详解
2019/08/05 Python
基于python3实现倒叙字符串
2020/02/18 Python
使用python+poco+夜神模拟器进行自动化测试实例
2020/04/23 Python
python自定义函数def的应用详解
2020/06/03 Python
python3中数组逆序输出方法
2020/12/01 Python
应聘护士自荐信
2013/10/21 职场文书
烹调加工管理制度
2014/02/04 职场文书
委托协议书范本
2014/04/22 职场文书
推荐信模板
2014/05/09 职场文书
2015年统计员个人工作总结
2015/07/23 职场文书
OpenCV绘制圆端矩形的示例代码
2021/08/30 Python
避坑之 JavaScript 中的toFixed()和正则表达式
2022/04/19 Javascript