【问题标题】:Printf security golangPrintf 安全 golang
【发布时间】:2018-02-03 12:20:02
【问题描述】:

我已经阅读了一些关于 C++ 中 printf() 安全性的内容。 可以找到示例,例如here。 这让我想知道来自 golang 的 fmt.Printf() 是否安全。 更具体地说,格式化字符串本身是否可以伪造是否安全。

inputString := "String from user"
x := "test"
fmt.Printf(inputString, x, 15)

当尝试从 C++ 复制漏洞利用时,golang 似乎并不容易受到攻击。

例如fmt.Printf("%s%s%s%s%s%s%s%s%s%s%s%s\n") 不会使 golang 中的程序崩溃。

这样的分析当然不能证明这在 golang 中是安全的。所以我想在这里问一下:go的开发者有没有把它的printf函数做到万无一失?

编辑:我所说的万无一失是指它没有任何意想不到的副作用。 当然,我希望生成的字符串会完全受到影响。 我不希望用户能够获得特权信息(例如未传递给 printf 的变量的内容),或者用户能够写入任何内存(例如,为 x 分配一个新值)。

【问题讨论】:

  • 它和 Go 的其他部分一样是内存安全的。仍然可能是错误的来源,任何错误都可能在适当的情况下成为漏洞。
  • 什么样的bug很难?排除结果字符串完全控制给出 inputString 和结果问题的字符串?
  • 万无一失是什么意思?
  • Go 中的字符串并不是像 C 那样等待发生字符串的危险缓冲区溢出。与数组/切片相同。一切都经过检查且安全。
  • @user2089648:Printf 满足您在编辑中添加的期望,是的。

标签: security go printf


【解决方案1】:

C/C++ 中的许多内存问题都与空终止和缓冲区溢出有关。 Golang 缺乏这两者。字符串是托管资源。排除编译器错误,不可能以逃入堆栈的方式终止字符串。

以你的例子为例。由于函数的可变特性,有很多没有处理程序的输入处理程序不会影响代码。据 printf 所知,格式字符串不需要任何替换。由于您不能传递任何破坏性的东西,即使您的示例为“a ...interface{}”采用了动态值,您也受到编译器字符串保护代码的保护。

【讨论】:

    【解决方案2】:

    tl;dr:不要打印不受信任的数据,先将其转义。如果有疑问或着急,use %q instead of %s

    Go 的字符串格式化方法确实是内存安全的,并且您担心的特定类别的漏洞以及在 C 中如此普遍的漏洞不适用。

    然而,在any 语言中,如果不经过仔细考虑,通过any 方式输出不受信任、未经处理的输入通常是不安全的。一个著名的例子是cross-site scripting。然而,比 XSS 攻击鲜为人知的是终端 escape 序列 attacks

    普通终端会响应各种各样的转义序列,这些转义序列可能会直接做出令人讨厌的事情,或者帮助利用另一个漏洞。攻击者可以将这些序列包含在发送到目标系统的消息中 - 例如,在对网络服务器的请求的 URL 中 - 并等待管理员 cating 日志或类似内容。这也可以用来隐藏信息 - 包括退格序列可以有效地隐藏终端中之前出现的任何内容。

    • 最快的选择是简单地使用%q instead of %s。这会将字符串输出为 Go 字符串文字,适合在 Go 源代码中使用。这对于打印来说既方便又安全,但如果您尝试匹配特定格式,则可能并不理想。 (strconv.Quote(s string) string 也会直接执行同样的操作)。

    • This answer to another question 使用 strings.Map 有一个更复杂但更容易自定义的选项,但是在给定的形式中,它删除所有不可打印的字符而不是转义它们。

    以一种或另一种方式清理您的输出。以后你会为别人减轻很多痛苦,可能是你自己。

    package main
    
    import (
        "fmt"
        "strconv"
    )
    
    func main() {
        s := "a string with some control\x08\x08\x08\x08\x08\x08\x08hidden characters"
    
        // Prints with the control characters intact. Terminal output:
        // a string with some hidden characters
        fmt.Printf("%s\n", s)
    
        // Prints as Go string literal. Terminal output:
        // "a string with some control\b\b\b\b\b\b\bhidden characters"
        fmt.Printf("%q\n", s)
    
        // Prints as Go string literal, but without surrounding double-quotes.
        // Terminal output:
        // a string with some control\b\b\b\b\b\b\bhidden characters
        x := strconv.Quote(s)
        fmt.Printf("%s\n", x[1:len(x)-1])
    }
    

    【讨论】:

      猜你喜欢
      • 2012-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-01-10
      • 2021-09-08
      • 2013-12-28
      • 1970-01-01
      相关资源
      最近更新 更多