Upgrade to Pro — share decks privately, control downloads, hide ads and more …

OSSの脆弱性を探すためにやったこと

Sponsored · Your Podcast. Everywhere. Effortlessly. Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.

 OSSの脆弱性を探すためにやったこと

第19回セキュリティさくらの資料(前半だけ)です。

Avatar for Teppei Fukuda

Teppei Fukuda

December 02, 2017
Tweet

More Decks by Teppei Fukuda

Other Decks in Programming

Transcript

  1. ࣗݾ঺հ • ෱ా మฏʢ@knqyf263ʣ • ޷͖ͳ΋ͷ • ωοτϫʔΫ • ηΩϡϦςΟ

    • ອը • ߪಡࡶࢽ • िץগ೥δϟϯϓ • िץগ೥ϚΨδϯ • िץগ೥αϯσʔ • िץϠϯάδϟϯϓ • δϟϯϓSQ • ผ࡭গ೥ϚΨδϯ • ଞɺ୯ߦຊଟ਺
  2. ੬ऑੑͷϨΠϠʔ • WebΞϓϦέʔγϣϯ • CGI, PHP, Java, etc • ϛυϧ΢ΣΞ

    • OpenSSH • Postfix, etc. • OS ʢWindows, LinuxͳͲʣ • Linux Kernel
  3. ੬ऑੑͷछྨ • WebΞϓϦέʔγϣϯ • XSS, SQLi, CSRF, etc. • ϛυϧ΢ΣΞ

    • ೚ҙίʔυ࣮ߦ, ೝূճආ, etc. • OS ʢWindows, LinuxͳͲʣ • ݖݶঢ֨, DoS, etc.
  4. ࣗ෼ͷ৔߹ • ޷͖ͳϓϩτίϧ • DNS • ޷͖ͳιϑτ΢ΣΞ • BIND •

    ޷͖ͳ੬ऑੑ • DoS BINDͷDoS ୯७ͳ%P4ͳͷʹ க໋తͳײ͕͡޷͖
  5. ޷͖ͳ΋ͷ͔Β୳࢝͠ΊΔ ྫ • ޷͖ͳϓϩτίϧ • SSL/TLS • ޷͖ͳιϑτ΢ΣΞ • OpenSSL

    • ޷͖ͳ੬ऑੑ • ೚ҙίʔυ࣮ߦʢRCE) աڈͷ੬ऑੑͱ ࣅͨ΋ͷ͕ͳ͍͔
  6. ޷͖ͳ΋ͷ͔Β୳࢝͠ΊΔ ྫ • ޷͖ͳϓϩτίϧ • SSL/TLS • ޷͖ͳιϑτ΢ΣΞ • OpenSSL

    • ޷͖ͳ੬ऑੑ • ଞͷ੬ऑੑ΋୳ͯ͠ΈΔ • DoS΍҉߸ͷ࣮૷ෆඋ΋աڈʹݟ͔͍ͭͬͯΔ
  7. ࣗ෼ͷ৔߹ • ޷͖ͳϓϩτίϧ • DNS • ޷͖ͳιϑτ΢ΣΞ • DNSܥͷιϑτ΢ΣΞΛ୳ͯ͠ΈΔ •

    https://github.com/miekg/dns • https://github.com/kenshinx/godns • ޷͖ͳ੬ऑੑ • DoS ࠷ۙ(PΛॻ͘͜ͱ͕ଟ͍ͷͰ (PͰॻ͔Εͨ΋ͷ͔Β୳͢
  8. ࣮ࡍʹಈ͔ͯ͠ΈΔ $./packetbeat -N -e 2017/12/01 04:03:08.679303 metrics.go:23: INFO Metrics logging

    every 30s 2017/12/01 04:03:08.679117 beat.go:297: INFO Home path: [/root/ packetbeat-5.6.3-linux-x86_64] Config path: [/root/packetbeat-5.6.3-linux- x86_64] Data path: [/root/packetbeat-5.6.3-linux-x86_64/data] Logs path: [/ root/packetbeat-5.6.3-linux-x86_64/logs] 2017/12/01 04:03:08.680873 beat.go:192: INFO Setup Beat: packetbeat; Version: 5.6.3 2017/12/01 04:03:08.680879 publish.go:217: INFO Dry run mode. All output types except the file based one are disabled. ... (தུʣ... 2017/12/01 04:03:08.681143 protos.go:89: INFO registered protocol plugin: mysql 2017/12/01 04:03:08.681145 protos.go:89: INFO registered protocol plugin: nfs 2017/12/01 04:03:08.681148 protos.go:89: INFO registered protocol plugin: pgsql 2017/12/01 04:03:08.681165 protos.go:89: INFO registered protocol plugin: redis 2017/12/01 04:03:08.707989 beat.go:233: INFO packetbeat start running.
  9. PostgreSQLϓϩτίϧͷύʔεॲཧ func pgsqlFieldsParser(s *pgsqlStream, buf []byte) error { ...ʢதུʣ... //

    read Type OID (int32) off += 4 // read column length (int16) off += 2 // read type modifier (int32) off += 4 // read format (int16) format := common.BytesNtohs(buf[off : off+2]) off += 2 fieldsFormat = append(fieldsFormat, byte(format)) } ഑ྻͷΠϯσοΫεͷ ࢦఆ͕ؾʹͳΔ bufʹ͸Կ͕ೖΔʁ
  10. ιʔείʔυͷྲྀΕΛ௥͏ QHTRM'JFMET1BSTFS QBSTF3PX%FTDSJQUJPO QBSTF$PNNBOE func (pgsql *pgsqlPlugin) parseCommand(s *pgsqlStream) (bool,

    bool) { // read type typ := byte(s.data[s.parseOffset]) ... switch typ { case 'Q': return pgsql.parseSimpleQuery(s, length) case 'T': return pgsql.parseRowDescription(s, length) ... } ύέοτͷCZUF໨͕ `5ͷͱ͖ʹݺ͹ΕΔॲཧ
  11. testdb=# SELECT * FROM test; id | body ----+------ 1

    | test (1 row) RowDescription 3PX%FTDSJQUJPO • parseRowDescription • ͦ΋ͦ΋RowDescriptionͱ͸ʁ
  12. RowDescription • Byte1('T') • ϝοηʔδ͕ߦͷهड़Ͱ͋Δ͜ͱΛࣝผ͠·͢ɻ • Int32 • ࣗ਎ΛؚΉɺϝοηʔδ಺༰ͷ௕͞ʢόΠτ୯Ґʣɻ •

    Int16 • ߦ಺ͷϑΟʔϧυ਺Λࢦఆ͠·͢ ʢθϩͱ͢Δ͜ͱ͕Ͱ͖·͢ʣɻ • ͦͷޙɺ֤ϑΟʔϧυʹରͯ͠ҎԼ͕ଓ͖·͢ɻ • String • ϑΟʔϧυ໊Ͱ͢ɻ • Int32 • ϑΟʔϧυ͕ಛఆͷςʔϒϧͷྻͱͯࣝ͠ผͰ͖Δ৔߹ɺςʔϒϧͷΦϒδΣΫτIDͰ͢ɻ ͞΋ͳ͘͹θϩͰ͢ɻ • Int16 • ϑΟʔϧυ͕ಛఆͷςʔϒϧͷྻͱͯࣝ͠ผͰ͖Δ৔߹ɺྻͷଐੑ൪߸Ͱ͢ɻ ͞΋ͳ͘͹θϩͰ͢ɻ • Int32 • ϑΟʔϧυͷσʔλܕͷΦϒδΣΫτIDͰ͢ɻ • Int16 • σʔλܕͷେ͖͞ʢpg_type.typlenΛࢀরʣͰ͢ɻ ෛͷ஋͕Մม௕ͷܕΛද͢͜ͱʹ஫ҙ͍ͯͩ͘͠͞ɻ • Int32 • ܕम০ࢠʢpg_attribute.atttypmodΛࢀরʣͰ͢ɻ म০ࢠͷҙຯ͸ܕʹݻ༗Ͱ͢ɻ • Int16 • ϑΟʔϧυʹ࢖༻͞ΕΔॻࣜίʔυͰ͢ɻݱࡏɺ0ʢςΩετʣ·ͨ͸1ʢόΠφϦʣͷ͍ͣΕ͔ʹͳΓ·͢ɻ https://www.postgresql.jp/document/9.6/html/protocol-message-formats.htm
  13. testdb=# SELECT * FROM test; id | body ----+------ 1

    | test --- 54 00 00 00 32 00 02 69 64 00 00 00 45 0e 00 01 00 00 00 17 00 04 ff ff ff ff 00 00 62 6f 64 79 00 00 00 45 0e 00 02 00 00 00 19 ff ff ff ff ff ff 00 00 --- 54 ! 'T'ͳͷͰRowDescription 00 00 00 32 ! ௕͞=50Λҙຯ͢Δ 00 02 ! ϑΟʔϧυ਺=2Λҙຯ͢Δ 69 64 00 ! "id" 00 00 45 0e ! ςʔϒϧͷΦϒδΣΫτID(17678) 00 01 ! ྻͷଐੑ൪߸ ... 00 00 ! ϑΟʔϧυʹ࢖༻͞ΕΔॻࣜίʔυʢςΩετͷ৔߹͸0ʣ RowDescription CVG<P⒎P⒎ > ͷॲཧ͸͜͜ʂ
  14. // Test parsing a response with data attached func TestPgsqlParser_dataResponse(t

    *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"pgsql", "pgsqldetailed"}) } pgsql := pgsqlModForTests() data := []byte( “5400000033000269640000008fc40001000000170004ffffffff000076616c75650000008fc400020000001 9ffffffffffff0000" + "44000000130002000000013100000004746f746f" + "440000001500020000000133000000066d617274696e" + "440000001300020000000134000000046a65616e" + "430000000b53454c45435400" + "5a0000000549") message, err := hex.DecodeString(string(data)) if err != nil { t.Error("Failed to decode hex string") } stream := &pgsqlStream{data: message, message: new(pgsqlMessage)} ok, complete := pgsql.pgsqlMessageParser(stream) ςετίʔυ ͜͜Λ͍ͬͯ͡ΈΔ
  15. // Test parsing a response with data attached func TestPgsqlParser_dataResponse(t

    *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"pgsql", "pgsqldetailed"}) } pgsql := pgsqlModForTests() data := []byte( "540000001b00016964000000450e0001000000170004ffffffff0000") message, err := hex.DecodeString(string(data)) if err != nil { t.Error("Failed to decode hex string") } stream := &pgsqlStream{data: message, message: new(pgsqlMessage)} ok, complete := pgsql.pgsqlMessageParser(stream) ςετίʔυ ਖ਼ৗͳ஋ΛೖΕͯΈΔ
  16. // Test parsing a response with data attached func TestPgsqlParser_dataResponse(t

    *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"pgsql", "pgsqldetailed"}) } pgsql := pgsqlModForTests() data := []byte( "540000001b00016964000000450e0001000000170004ffffffff0000") message, err := hex.DecodeString(string(data)) if err != nil { t.Error("Failed to decode hex string") } stream := &pgsqlStream{data: message, message: new(pgsqlMessage)} ok, complete := pgsql.pgsqlMessageParser(stream) ෆਖ਼ͳೖྗ஋ʹม͑Δ CVG<P⒎P⒎ >͸ CZUFલఏͳͷͰ ࡟ͬͨΒམͪͦ͏
  17. $ cd ~/go/src/github.com/elastic/beats/packetbeat/protos/pgsql $ go test -run TestPgsqlParser_dataResponse PASS ok

    github.com/elastic/beats/packetbeat/protos/pgsql 0.085s མͪͳ͔ͬͨ ςετίʔυΛ࣮ߦͯ͠ΈΔ
  18. ͜ͷՕॴ͸ݺ͹Ε͍ͯͳ͔ͬͨ printfσόοάͯ͠ΈΔ func (pgsql *pgsqlPlugin) parseCommand(s *pgsqlStream) (bool, bool) {

    // read type typ := byte(s.data[s.parseOffset]) ... case 'T': + fmt.Printf("%d\n", length) return pgsql.parseRowDescription(s, length) ... } ଞͷՕॴͷΤϥʔॲཧͰ஄͔Ε͍ͯΔ
  19. ௕͞ͷൺֱ if len(s.data[s.parseOffset:]) <= length { detailedf("Wait for more data")

    return true, false } σʔλͷ࣮ࡍͷ௕͞ cc CZUF ύέοτ಺ͷهड़ cc CZUF 54 00 00 00 1b ... • ҎԼͷνΣοΫͰ஄͔Ε͍ͯͨ
  20. // Test parsing a response with data attached func TestPgsqlParser_dataResponse(t

    *testing.T) { if testing.Verbose() { logp.LogInit(logp.LOG_DEBUG, "", false, true, []string{"pgsql", "pgsqldetailed"}) } pgsql := pgsqlModForTests() data := []byte( "540000001b00016964000000450e0001000000170004ffffffff0000") message, err := hex.DecodeString(string(data)) if err != nil { t.Error("Failed to decode hex string") } stream := &pgsqlStream{data: message, message: new(pgsqlMessage)} ok, complete := pgsql.pgsqlMessageParser(stream) ௕͞Λἧ͑Δ ࡟Δ CZUFݮΒ͢ B
  21. $ go test -run TestPgsqlParser_dataResponse panic: runtime error: slice bounds

    out of range [recovered] panic: runtime error: slice bounds out of range goroutine 20 [running]: testing.tRunner.func1(0xc420068820) /usr/lib/go-1.8/src/testing/testing.go:622 +0x29d panic(0x9bc500, 0xe46af0) /usr/lib/go-1.8/src/runtime/panic.go:489 +0x2cf github.com/elastic/beats/packetbeat/protos/pgsql.pgsqlFieldsParser(0xc420035f60, 0xc421164f05, 0x16, 0x16, 0x0, 0x0) /root/go/src/github.com/elastic/beats/packetbeat/protos/pgsql/parse.go:384 +0x6c6 ... (தུ) ... created by testing.(*T).Run /usr/lib/go-1.8/src/testing/testing.go:697 +0x2ca exit status 2 FAIL github.com/elastic/beats/packetbeat/protos/pgsql 0.084s མͪͨʂʂ ςετίʔυΛ࣮ߦͯ͠ΈΔ
  22. $ echo -e "T\x00\x00\x00\x1a\(ࣗॗʣxff\xff\xff\xff\x00" | nc 127.0.0.1 5432 ؆୯ ύέοτΛ1ͭ౤͛Δ͚ͩͰམͪΔ

    # ./packetbeat -N -e ... 2017/12/04 04:45:22.465965 log.go:145: ERR Stacktrace: goroutine 13 [running]: runtime/debug.Stack(0xbd68c4, 0x2b, 0xc421249560) /usr/local/go/src/runtime/debug/stack.go:24 +0x79 github.com/elastic/beats/libbeat/logp.Recover(0xbc366f, 0x14) /go/src/github.com/elastic/beats/libbeat/logp/log.go:145 +0x138 panic(0xada5c0, 0xc4200100f0) /usr/local/go/src/runtime/panic.go:458 +0x243 github.com/elastic/beats/packetbeat/protos/pgsql.pgsqlFieldsParser(0xc4211e8b00, 0xc421210749, 0x2f, 0x36, 0xbba4b1, 0xd) /go/src/github.com/elastic/beats/packetbeat/protos/pgsql/parse.go:382 +0x53c ...