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的更多相关文章

  1. X-NUCA 2017 web专题赛训练题 阳光总在风雨后和default wp

     0X0.前言 X-NUCA 2017来了,想起2016 web专题赛,题目都打不开,希望这次主办方能够搞好点吧!还没开赛,依照惯例会有赛前指导,放一些训练题让CTFer们好感受一下题目. 题目有一大 ...

  2. X-NUCA联赛WEB赛前指导write-up

    第一关 审查代码发现有隐藏的连接,访问,flag一闪而过.打开burpsuite,设置好代理,然后重新访问,在历史里找相应的回复包,得到flag. 第二关 审查元素 修改按钮为可用 抓获一个POST包 ...

  3. [XNUCA 进阶篇](web)writeup

    XNUCA 靶场练习题writeup default 阳关总在风雨后 题目过滤很多,*,#,/ ,and,or,|,union,空格,都不能用 盲注,最后的姿势是:1'%(1)%'1 中间的括号的位置 ...

  4. Java Web项目总结

    知识点列表(慢慢增加,红色代表公司暂时没有使用): 开发: 视图层技术——HTML,CSS,JS,AJAX,Tiles,Velocity,FreeMarker 持久层技术——MyBatis,Hiber ...

  5. C# Web应用调试开启外部访问

    在用C#开发Web应用时有个痛点,就是本机用VS开启Web应用调试时外部机器无法访问此Web应用.这里将会介绍如何通过设置允许局域网和外网机器访问本机的Web应用. 目录 1. 设置内网访问 2. 设 ...

  6. 网页提交中文到WEB容器的经历了些什么过程....

    先准备一个网页 <html><meta http-equiv="Content-Type" content="text/html; charset=gb ...

  7. 闲来无聊,研究一下Web服务器 的源程序

    web服务器是如何工作的 1989年的夏天,蒂姆.博纳斯-李开发了世界上第一个web服务器和web客户机.这个浏览器程序是一个简单的电话号码查询软件.最初的web服务器程序就是一个利用浏览器和web服 ...

  8. java: web应用中不经意的内存泄露

    前面有一篇讲解如何在spring mvc web应用中一启动就执行某些逻辑,今天无意发现如果使用不当,很容易引起内存泄露,测试代码如下: 1.定义一个类App package com.cnblogs. ...

  9. 对抗密码破解 —— Web 前端慢 Hash

    (更新:https://www.cnblogs.com/index-html/p/frontend_kdf.html ) 0x00 前言 天下武功,唯快不破.但在密码学中则不同.算法越快,越容易破. ...

随机推荐

  1. Dubbo SPI机制之三Adaptive自适应功能

    JDK标准中SPI机制的一个问题就是其一次性实例化扩展点所有实现,如果有扩展实现初始化很耗时,但如果没用上也加载,会很浪费资源:扩展点加载失败,其他扩展点都用不了了.Dubbo是如何解决该问题动态的选 ...

  2. WebKit Inside: DOM树的构建

    当客户端App主进程创建WKWebView对象时,会创建另外两个子进程:渲染进程与网络进程.主进程WKWebView发起请求时,先将请求转发给渲染进程,渲染进程再转发给网络进程,网络进程请求服务器.如 ...

  3. Anchor-free目标检测综述 -- Dense Prediction篇

      早期目标检测研究以anchor-based为主,设定初始anchor,预测anchor的修正值,分为two-stage目标检测与one-stage目标检测,分别以Faster R-CNN和SSD作 ...

  4. [c/c++]c++控制台操作(基本操作的代码)

    本文转自:http://blog.csdn.net/stude/article/details/7645056 控制台窗口界面编程控制 〇.摘要一.概述二.控制台文本窗口的一般控制步骤三.控制台窗口操 ...

  5. k8s初面考点ReplicaSet副本集极限9连击你懂了吗?

    k8s初面考点ReplicaSet副本集极限9连击你懂了吗? k8s考点灵魂拷问9连击 考点之简单描述一下k8s副本集ReplicaSet有什么作用? 考点之为什么ReplicaSet将取代Repli ...

  6. Python 单例模式的几种实现方式

    单例模式的几种实现方式 先来看几个魔法方法的简单运用:__new__, __init__, __call__. class A(object): def __init__(self, x): prin ...

  7. HTML分块

    <!DOCTYPE html><html><head> <meta charset="utf-8"> <title>菜鸟 ...

  8. WPS二级标题链接到一级标题

    WPS二级标题链接到一级标题,即2后出现2.1 2.2而不是1.3 1.4什么的 样式中的编号什么的都不用动,默认即可,关键在于这些多级标题是否选择了同一个编号方式 WPS中,只需要将它们的编号选择为 ...

  9. manjaro卸载与重装Arch linux

    前言 之前安装了manjaro-deepin,但太久没用了,昨天更新系统后,出了点问题,重装个新版本吧. 卸载manjaro 由于之前安装了manjaro,默认开机引导程序是linux的Grub,那么 ...

  10. python面试_总结01_概念和内置高阶函数

    - 简答题 1.请谈谈Python中is 和 == 的区别(代码演示) is用于比较两个变量是否引用了同一个内存地址,is表示的是对象标识符(object identity),作用是用来检查对象的标识 ...