Open Source/Kali Linux

[Web Applications - OSINT Analysis] Jigsaw On Kali Linux

DarkSoul.Story 2013. 4. 10. 10:13
반응형



개요


Royce Davis (R3dy)와 humble-desser의 공동 프로젝트로 진행된 루비 스크립트 이다. Jigsaw의 사용 용도는 목표로 선택한 회사의 간단한 직원 정보(Email, 이름)를 열거할때 사용된다. 이는 Social Engineering 이나 E-mail 피싱에 사용이 가능하다.  Jigsaw는 http://www.jigsaw.com 의 서비스를 이용하여, 사용자가 원하는 정보를 획득한다. 


테스트 환경 

 운영 체제 (OS) : Kali Linux

 jigsaw 버전 : 1.3


 

상세 분석


Jigsaw는 BackTrack5 R3 버전 1.0에서  Kali Linux로 넘어오면서 버전 1.3으로 버전업이 되었다.

버전 1.0과 버전 1.3을 비교해보면, [-d] / [-u] / [-p]옵션이 더 생성되어 있다. 확인해본 결과 [-d] 옵션은 Jigsaw 버전 1.2에서 추가된 옵션이다. 


버전 1.3이 되면서, 디렉토리 목록에서 연락처의 전체 이름이 표시되지 않게 되었다. 전체 연락처 정보를 확인하고 싶으면, http://www.jigsaw.com에 가입을 한 후 [-u] / [-p]옵션을 사용하여 인증을 받아야 전체 연락처를 확인할 수 있다. 다음으로 변경된 내용은 모든 요청에서 Https를 사용하도록 변경되었으며, 보고서에 사용자 이름을 생성할 수 있도록 추가되었다.


Jigsaw를 사용하기전에 먼저 Jigsaw에 가입하는 방법에 대해서 알아보자. http://www.jigsaw.com에 접속하면, 아래와 같이 회원 가입을 할 수 있는 공간을 확인할 수 있다

위 내용을 채워넣은 후 [FREE Sign UP]을 클릭하면, 다음과 같이 입력한 계정 활성화하기 위해서는 Email의 링크를 클릭하라는 화면이 보이게 된다.

위에서 입력한 Email을 살펴 보면 아래와 같이 계정 활성화 링크를 클릭하면 계정이 활성화된다.


Jigsaw 사용하기



[주요 옵션 작성 중]



가장 먼저 [-s]옵션을 적용하여 목표로 정한 회사의 이름을 키워드로 검색한다.



키워드를 입력하여, 검색하면 위와 같이 http://www.jigsaw.com에 등록되어 있는 회사 이름을 출력해준다. Jigsaw를 이용하여 키워드를 검색한 결과와 http://www.jigsaw.com에서 동일한 키워드로 검색한 결과를 비교해보면 아래와 같이 동일하다는 것을 확인할 수 있다.



 위의 결과를 가져오는 소스코드를 살펴 보면 아래와 같다.


def search_by_name(http, headers, search)

         

         puts "Searching for #{search}."

         begin

                 # Try and do stuff

                 path = "/FreeTextSearch.xhtml?opCode=search&autoSuggested=true&
freeText=#{search}"

                 resp, data = http.get(path, headers)

                 if !resp.body.include?("Company Search Results")

                          resp.body.split("\r\n").each do |line|

                                   if line.include?("view more and edit")

                                            puts "Jigsaw ID for #{search} is: " + line.split("/")
[1].to_s.gsub(/id/, "")

                                   end

                          end

                 end

                 resp.body.split("</tr>").each do |line|

                          if line.include?("type=\'checkbox\' class=\'checkbox\'  name=\'ids\' 
value=")

                                   company =  line.split("=")[9].to_s.split("'")[1].
to_s.split("'")[0].to_s

                                   id = line.split("=")[10].to_s.split("/")[1].to_s.
gsub(/id/, "")

                                   employees = line.split("=")[13].split("'")[1].to_s.
split("'")[0]
.to_s

                                   puts "Jigsaw ID: " + id + "\t- " + company + "\t" + 
"(" + employees 
+ " employee/s)"

                          end

                 end

         rescue StandardError => search_error

                 puts "Error performing search. #{search_error}"

                 return search_error

         end

end 


소스코드를 보면 매우 복잡할 것 같지만 자세히 살펴보면 http://www.jigsaw.com의 FreeTextSearch.xhtm으로 사용자가 입력한 키워드를 넘겨준 후 http://www.jigsaw.com에서 키워드에 대한 결과를 보내주면 Jigsaw는 사용자에게 보기 좋게 표시해준다.


이 회사명들을 이용하여, 목표로 정한 회사의 정확한 이름을 확인한 후 Jigsaw ID를 이용하여, 회사 직원의 이메일을 검색할 수 있다.



위 결과 값을 소스코드로 살펴 보면 아래와 같다. 아래는 [-d] 옵션에 대한 소스코드이다. 


def get_company_domain(response)

         begin

                 puts "Retrieving list of company's registered domains" if @options[:verbose]

                 domains = Array.new

                 response.body.each_line do |line|

                          if line.include?("option value=\"") && line.include?(".") && 
!line.include?("multiple=\"multiple\" size=\"") && !line.include?("<select name=") 
                                   domains << line.split(">")[1].split("<")[0].to_s.chomp

                          end

                 end

                 if domains.length == 1

                          puts "Your search only returned one domain.  Using \'#
{domains[0]}\' to craft emails."

                          Record.set_domain(domains[0])

                          return domains[0]

                 end

                 puts "Your target has #{domains.length} domain/s:\r\n\r\n"

                 counter = 1

                 domains.each do |domain|

                          puts "[#{counter.to_s}] - " + domain

                          domains[counter - 1] = "#{counter.to_s}-#{domain}"

                          counter = counter + 1

                 end

                 puts "\r\n"

                 print "Enter the number of the domain to use for crafting emails: "

                 answer = gets.chomp.to_s

                 domains.each do |domain|

                          if domain.split("-")[0] == answer

                                   puts "Using \'#{domain.split("-")[1]}\' to craft emails."

                                   Record.set_domain(domain.split("-")[1])

                                   return domain.split("-")[1]

                          end

                 end

         rescue StandardError => domain_set

                 puts "Error setting domain: #{domain_set}"

                 return domain_set

         end

end


아래 소스는 [-i] 옵션 Jigsaw ID와 [-d] 옵션 도메인을 가지고, 조건에 맞는 이메일을 검색하는 소스이다. 

  

def get_number_of_records(http, headers, id, dept)

         threads = Array.new

         begin

                 # Try and do stuff

                 threads << Thread.new {

                          path = "/SearchContact.xhtml?companyId=#{id}&opCode=showCompDir&dept
=#{dept.split("-")[0].to_s}&rpage=1&rowsPerPage=50"

                          resp, data = http.get(path, headers)

                          domain = get_company_domain(resp) unless Record.domain_is_set

                          numrecs = ""

                          resp.body.split(";").each do |line|

                                   numrecs = line.split("+")[1].split('"')[1].to_s.chomp if 
line.include?("Your search returned") && !line.include?("at least")

                          end

                          if numrecs.include?(",")

                                   numrecs = numrecs.gsub(/,/, "")

                          end

                          Record.counter(numrecs.to_i) unless dept.split("-")[1] == "Other"

                          if dept.split("-")[1] == "Other"

                                   recs = numrecs.to_i - Record.get_counter

                                   puts "Found #{recs.to_s} records in the #{dept.split("-")
[1].to_s} department."
                          end

                          puts "Found #{numrecs} records in the #{dept.split("-")[1].to_s}
 department." 
unless dept.split("-")[1] == "Other"

                          pages = get_number_of_pages(numrecs)

                          pages.times do |page|

                                   inline_threads = Array.new

                                   inline_threads << Thread.new {

                                            pagenum = page + 1

                                            get_page_of_records(http, headers, id, dept, pagenum, 
Record.get_domain)

                                   }

                                   inline_threads.each { |thread| thread.join }

                          end

                          puts "Total records so far: " + Record.get_counter.to_s if 
@options[:verbose]

                 }

                 threads.each { |thread| thread.join }

         rescue StandardError => num_error

                 puts "Error retrieving number of records #{num_error}"

                 return num_error

         end

end 

 


검색이 완료되면, /root/ 에 입력한 파일명.csv 파일로 존재한다. 해당 파일을 열어보면, Email 정보를 확인할 수 있다. Email 정보를 확인하다 보면 이상하게 전부 표시가 되지 않는것을 확인 할 수 있다. 전부 표시된 내용을 확인하고 싶다면 [-u] / [-p] 옵션을 적용하면 모든 내용을 확인 할 수 있다.


-- -u 옵션과 -p 옵션을 적용하면 사이트 접속이 안되는군요;;;; --

반응형