[xnuca](web)xblog
session会话机制介绍如下
http是无状态协议。服务器靠cookie和session来记住用户。$_SESSION 和 $_GET等一样,是超全局变量。
后台脚本里面会写: session() start 。会话开始。所以,当浏览器访问一个页面时,session机制就开始了。这个时候机制会生成一个PHPSESSID. 存放在cookie当中,当在这个网站post,get 请求数据的时候,会带着这个ID。这个ID是随机的,是由PHP决定的。在注册时,这个PHPSSID可能和注册时间,毫秒,用户名,密码哈希值等有关,所以爆破碰撞PHPSSID难度很大。
在服务器后台,会创建一个以PHPSSID命名文件,里面会储存用户的信息。服务器根据用户发送过来的PHPSSID,读取文件里面的信息。
上面的和这道题没有太大关系。
题目源码打包地址: 120.27.32.227/www.zip
这是一道代码审计。
下面是相关代码示例。
<?php
define("DB_NAME", "xian");
define("DB_HOST", "localhost");
define("DB_USER", "root");
define("DB_PASSWD", "");
define("DSN", "mysql:host=".DB_HOST.";dbname=".DB_NAME);
ini_set("display_errors", "On");
error_reporting(0);
foreach (array('_COOKIE','_POST','_GET') as $_request)
{
foreach ($$_request as $_key=>$_value)
{
$$_key= $_value;
}
}
session_start();
?>
这是common.php里面的代码,连接数据库,取出超全局变量里面的变量和值,根据顺序,先取出cookie,再试post和get。++如果这些变量里面有重名的变量,根据先后顺序,get具有决定性。接着就是SESSION会话机制开始++。由于$_SESSION也是一个超全局变量,如果碰到和前面那三个有重名的,$_SESSION具有决定性。
下面看do_register.php。
<?php
include_once("common.php");
$dbh = new PDO(DSN, DB_USER, DB_PASSWD);
$sql = "select * from user where username = :username";
$sth = $dbh->prepare($sql);
$sth->execute(array(':username'=>$username));
$res = $sth->fetch(PDO::FETCH_ASSOC);
if($res !== false) {
header("Location: error.php?msg=username%20has%20been%20used!");
die();
}
$sql = "insert into user (username, password, role) values(:username, :password, 1)";
$sth = $dbh->prepare($sql);
$res = $sth->execute(array(':username'=>$username, ':password'=>$password));
if($res === false) {
header("Location: error.php?msg=register%20error!");
die();
}
$sql = "select * from user where username = :username and password = :password";
$sth = $dbh->prepare($sql);
$sth->execute(array(':username'=>$username, ':password' => $password));
$res = $sth->fetch(PDO::FETCH_ASSOC);
if($res === false) {
header("Location: error.php?msg=register%20error!");
die();
}
$userinfo["id"] = $res["id"];
$userinfo["username"] = $username;
$userinfo["password"] = $password;
$_SESSION["userinfo"] = $userinfo;
$userinfo["role"] = $res["role"];
header("Location: index.php");
?>
看这段代码的最后几行,是直接把userinfo的信息写进了session里面。下面再看do_changepassword.php。
<?php
include_once("common.php");
if(!isset($_SESSION["userinfo"])) {
header("Location: login.php");
die();
}
$userinfo = $_SESSION["userinfo"];
if($old_pass = $userinfo['password']) {
if($userinfo["id"] == 1) {
echo "flag{xxx}";
die();
}
$dbh = new PDO(DSN, DB_USER, DB_PASSWD);
$sql = "update user set password = :password where id=:id";
$sth = $dbh->prepare($sql);
$res = $sth->execute((array(':password'=>$new_pass, ':id'=>$userinfo['id'])));
var_dump $new_pass;
echo "<br>";
var_dump $userinfo['id'];
if($res === false) {
header("Location: error.php?msg=changepass%20error!");
die();
}
$userinfo["password"] = $new_pass;
$_SESSION['userinfo'] = $userinfo;
header("Location: index.php");
} else {
header("Location: error.php?msg=invalid%20old%20pass!");
die();
}
?>
这里看到,要得到flag,id必须为1。
所以正常来说,我们会想到在超全局变量里面传入参数userinfo['id']=1。
这是一个数组,所以我们请求应该这么写。 http://localhost/do_changepass.php?userinfo[id]=1
但是并没有用,因为$_SESSION这个超全局变量里面有和这个重名的,最后这个变量的值是由session决定的。
所以,这题,只要在post,get,cookie这三个里面传入和session里面重名的变量,都会被session给覆盖,也就是传入参数数组的方式行不通。
解这题的正确姿势,还是要用到“php是最好的语言这个特性”---弱类型。
所以这道题,在register的时候,传入参数,userinfo=1 。然后访问do_changepass ,改密码,就出flag了。解释如下。
传入参数 userinfo=1, 在register页面,
$userinfo["id"] = $res["id"];
$userinfo["username"] = $username;
$userinfo["password"] = $password;
$_SESSION["userinfo"] = $userinfo;
$userinfo["role"] = $res["role"];
header("Location: index.php");
这几行代码之前,session为空。所以这里调用的userinfo 是我们传进去的参数,而我们传进去的参数是一个字符串 , $userinfo["id"]
会把我们的字符串先转化为字符数组,但是是一个数字索引数组 。里面没有id这个键,所以 $userinf["id"] 就与 userinfo[0] 等同。我们的userinfo就变成了userinfo="$rs["id"]"。只改变了第一个字符。接下来的变量赋值,都只改变了第一个字符。所以最后第一个字符是由 $res["role"]决定的,值为1。
我们传入变量的时候,只传入一个字符,同样能出flag。
if($userinfo["id"] == 1) {
echo "flag{xxx}";
die();
}
这里userinfo["id"]=userinf[0]=$res["role"]=1。
总结:这一道题考察了 变量覆盖,php弱类型:字符和数组的转化,变量重名。还有观察力。
[xnuca](web)xblog的更多相关文章
- X-NUCA 2017 web专题赛训练题 阳光总在风雨后和default wp
0X0.前言 X-NUCA 2017来了,想起2016 web专题赛,题目都打不开,希望这次主办方能够搞好点吧!还没开赛,依照惯例会有赛前指导,放一些训练题让CTFer们好感受一下题目. 题目有一大 ...
- X-NUCA联赛WEB赛前指导write-up
第一关 审查代码发现有隐藏的连接,访问,flag一闪而过.打开burpsuite,设置好代理,然后重新访问,在历史里找相应的回复包,得到flag. 第二关 审查元素 修改按钮为可用 抓获一个POST包 ...
- [XNUCA 进阶篇](web)writeup
XNUCA 靶场练习题writeup default 阳关总在风雨后 题目过滤很多,*,#,/ ,and,or,|,union,空格,都不能用 盲注,最后的姿势是:1'%(1)%'1 中间的括号的位置 ...
- Java Web项目总结
知识点列表(慢慢增加,红色代表公司暂时没有使用): 开发: 视图层技术——HTML,CSS,JS,AJAX,Tiles,Velocity,FreeMarker 持久层技术——MyBatis,Hiber ...
- C# Web应用调试开启外部访问
在用C#开发Web应用时有个痛点,就是本机用VS开启Web应用调试时外部机器无法访问此Web应用.这里将会介绍如何通过设置允许局域网和外网机器访问本机的Web应用. 目录 1. 设置内网访问 2. 设 ...
- 网页提交中文到WEB容器的经历了些什么过程....
先准备一个网页 <html><meta http-equiv="Content-Type" content="text/html; charset=gb ...
- 闲来无聊,研究一下Web服务器 的源程序
web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...
- java: web应用中不经意的内存泄露
前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...
- 对抗密码破解 —— Web 前端慢 Hash
(更新:https://www.cnblogs.com/index-html/p/frontend_kdf.html ) 0x00 前言 天下武功,唯快不破.但在密码学中则不同.算法越快,越容易破. ...
随机推荐
- Solution -「HNOI 2009」「洛谷 P4727」图的同构计数
\(\mathcal{Description}\) Link. 求含 \(n\) 个点的无标号简单无向图的个数,答案模 \(997\). \(\mathcal{Solution}\) 首先 ...
- Solution -「CF 1025D」Recovering BST
\(\mathcal{Description}\) Link. 给定序列 \(\{a_n\}\),问是否存在一棵二叉搜索树,使得其中序遍历为 \(\{a_n\}\),且相邻接的两点不互素. ...
- Solution -「洛谷 P3911」最小公倍数之和
\(\mathcal{Description}\) Link. 给定 \(\{a_n\}\),求: \[\sum_{i=1}^n\sum_{j=1}^n\operatorname{lcm}(a ...
- suse 12 双网卡bonding模式
文章目录 工欲善其事,必先配静态ip 网卡bonding eth0 eth1 192.168.70.52 192.168.70.55 工欲善其事,必先配静态ip 重要的事情说三遍 修改配置之前,先备份 ...
- Python基础—文件操作(Day8)
一.文件操作参数 1.文件路径 1)绝对路径:从根目录开始一级一级查找直到找到文件. f=open('e:\文件操作笔记.txt',encoding='utf-8',mode='r') content ...
- java中abstract关键字(抽象类)
需求 当父类某个方法,需要声明,但是又不确定如何实现时,可以用抽象方法,那么这个类就是抽象类 例如:父类是一个动物类,父类里面有很多方法,其中有一个方法是吃食物,但是不知道吃什么,需要子类继承的时候重 ...
- Vue2.0源码学习(6) - 组件注册
组件注册 前言 在 Vue.js 中,除了它内置的组件如 keep-alive.component.transition.transition-group 等,其它用户自定义组件在使用前必须注册.在开 ...
- [LeetCode]1313. 解压缩编码列表
给你一个以行程长度编码压缩的整数列表 nums . 考虑每对相邻的两个元素 [freq, val] = [nums[2i], nums[2i+1]] (其中 i >= 0 ),每一对都表示解压后 ...
- mysql is not null 执行效率低
a表字段类型为int b表字段类型为varchar a left join b时如果查询条件是is not null,效率很快,is null 效率很低 后来两者改为同类型 int,效率很高
- 基于node的tcp客户端和服务端的简单通信
1.简单介绍下TCP/IP TCP/IP是互联网相关协议的集合,分为以下四层:应用层.传输层.网络层.数据链路层. 分成四层的好处是,假如只有一层,某个地方需要改变设计时,就必须把所有整体替换掉,而分 ...