2019. 11. 27.

[네트워크] MITM 공격

참고)와이어샤크 유용한 명령어

tcp.port == 80 
http // http 프로토콜 만 출력
ip.addr == 192.168.0.1 // 특정 ip와의 통신만 출력

ARP 스푸핑
상대방 IP 주소로 접속하는 명령을 내리면 호스트는 네트워크 전체에 ARP 요청을 보내어 누가 그 IP를 가지고 있는지 물어보게 된다. 이때 요청하는 IP가 맞는 호스트가 응답해야하는데 해커가 ARP 요청을 중간에서 가로채어 응답을 하는 것이다. 그러면 해커쪽으로 접속하게 만들 수 있다.

이는 칼리리눅스에 arpspoof 프로그램으로 공격을 시연 할 수 있다.

ip forward 란 값을 1로 변경해야 한다. 
echo 1 > /proc/sys/net/ipv4/ip_forward
(지속적으로 설정되게 하려면 /edit/sysctl.conf 에서 ipv4.ip_forward =1 로 설정해야 한다. )

이 설정은 자기한테 오는 설정이 아닌 경우에 라우터처럼 트래픽을 전달해주는 설정이다. 
라우터가 요청을 받으면 ip 포워딩 하듯이 요청을 받으면 트래픽을 다른쪽으로 전달하기 위함이다. 즉 통신의 중간에 끼어들어서 중간에 거쳐가게 만들어도 다른 호스트들끼리 통신이 가능한 것이다.

arpspoof -i eth1 -t 192.168.56.107(칼리) 192.168.70.108(윈도우)
arpspoof -i eth1 -t 192.168.56.108(윈도우) 192.168.70.107 (칼리)

이렇게 되면 칼리 메타스플로잇과 윈도우 서로가 통신하는 사람이 나(칼리 리눅스) 라고 생각하기 때문에 통신이 칼리 리눅스로 들어옥 된다.


132번은 메타스플로잇의 데이터인데 131 인 칼리리눅스와 물리주소가 동일하게 설정되어 있는 것을 알 수 있다. 따라서 윈도우에서 메타 쪽으로 요청을 하게되면 그 트래픽이 칼리 리눅스로 거쳐간다.

윈도우에서 메타스플로잇터블로 접속해보면 다음과 같이 칼리에서 트래픽을 확인 할 수 있다.

메타스플로이터블/phpMyAdmin 으로 접속해서 아이디 패스워드를 입력하면 다음과 같이 post 데이터 역시 캡처 할 수 있다.



윈도우에서 메타로 접속하는 ftp 역시 다음과 같이 칼리 리눅스에서 스니핑 할 수 있다. 


Continue reading

HTTP Parameter Pollution (HPP) 취약점

HTTP Parameter Pollution 취약점을 줄여서 HPP 라고 부른다.
HTTP 파라미터 오염 취약점은 서버단과 클라이언트 단 에서 설명이 가능하다.

[서버단] 

https://backend.example/doTransfer.php
파라미터 : toAccount=9844&amount=1000&fromAccount=12345

이를 toAccount=9844&amount=1000&fromAccount=12345&toAccount=99999

[클라이언트 단]

<? $val=htmlspecialchars($_GET['par'],ENT_QUOTES); ?>
<a href="/page.php?action=view&par='.<?=$val?>.'">View Me!</a>

이러한 php 소스가 있다고 하자

http://host/page.php?par=123%26action=edit 이라고 par의 인자값을 전달하면

<a href="/page.php?action=view&par=123&amp;action=edit">View Me!</a>
위와 같이 action 값이 view 가 아니라 edit 으로 변경되는 경우도 있다

위 자료(https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004))를 보면 어느 파라미터가 유효한지 확인 할 수 있다. 즉, 같은 이름으로 중복 파라미터가 제공되도록 해서는 안된다. 아래 사례를 보면 꽤 위험한 취약점 임을 알 수 있다.

(사례)

Twitter Unsubscribe Notifications

트위터에서 온 이메일을 unsubscribe 하기 위해 버튼을 눌를 때, 다음과 같은 url이 사용된다.

  • https://twitter.com/i/u?t=1&cn=bWV&sig=657&iid=F6542&uid=1134885524&nid=22+26
해커는 UID 를 변경해보았지만, 에러페이지가 리턴된다. 


HPP 취약점을 이용하여 기존 UID 파라미터 앞에 새로운 파라미터값을 삽입한 후 전달하면 성공이 된다. 즉 다른 사람의 계정의 메일링이 해지가 되는 것이다.

  • https://twitter.com/i/u?iid=F6542&uid=2321301342&uid=1134885524&nid=22+26

비슷한 사례로, twitter 에서는 사용자를 팔러우하거나 좋아요를 하거나 리트윗을 하거나 트윗을 하거나 할 수 있는데 이러한 4개 행위에 대해서 HPP 취약점이 있었다.

예를 들면, 팔로우 하기 위한 URL이 다음과 같이 변경될 수 있다.

  • https://twitter.com/intent/follow?screen_name=twitter&screen_name=test1234

또 다른 시나리오는 다음과 같다

정상적인 흐름
  • read.jsp?num=7  -> board.jsp?cmd=read&num=7

공격 흐름
  • read.jsp?num=7%26cmd=delete
  • board.jsp?cmd=read&num=7&cmd=delete

# 참고
  • web-hacking-101
  • https://www.owasp.org/index.php/Testing_for_HTTP_Parameter_pollution_(OTG-INPVAL-004)
  • https://ericrafaloff.com/parameter-tampering-attack-on-twitter-web-intents/

Continue reading

Android APK 진단을 위한 툴 소개

Android APK 진단을 위한 툴 소개

네트워크 통신을 하는 앱이라면, 웹 진단 툴을 함께 사용한다.
1) Apktool
링크 : http://ibotpeaches.github.io/Apktool/
ApkTool은 apk파일은 디컴파일하거나 수정한 후 다시 컴파일 할 수 있는 Tool .
여러 옵션이 있지만 자주 사용하는 옵션은
 d 옵션 : decompile 해주는 옵션으로 smali 파일이 아웃풋
b 옵션 : recompile 해주는 옵션으로 apkfile이 아웃풋으로 나오며, signing을 거쳐 안드로이드폰에 설치가 가능.
d -d 옵션 : decompile 해주는 옵션으로 smali 파일이 아웃풋으로 나오지만, 확장자를 java파일로 만들어주어 동적디버깅 할 때 사용.


2) apk-sign
링크 : https://github.com/appium/sign
안드로이드에는 signing되지 않은 앱은 설치되지 않음
이 signing은 개발자가 APK파일로 만들어 낼 때 하는데, Apk Tool 을 이용해 decompile을 하면 signing이 풀림.
따라서 폰에 설치를 하기 위해서는 signing을 해주어야 하는데, 원 개발자의 서명을 따라할수는 없으나 아무 keystore를 가지고 signing만 해주어도 설치는 가능.


3) dex2jar
링크 : https://sourceforge.net/projects/dex2jar/
Apk파일은 안에 classes.dex라는 파일이 있는데 이 파일은 Android Dalvik이 인식할수 있도록 class파일을 바이트 코드로 변환한 파일.
이 파일을 dex2jar를 이용해 class파일을 추출하는 Tool.

4) jd-gui
링크 : http://jd.benow.ca/
JAVA decompiler
위 dex2jar를 이용해 추출해낸 class파일을 java로 복원해주는 Tool.
그런데 복원할때 완벽하지 않아 복원이 잘 되지 않는 부분이 있는 것이 아쉬운점.

5) jadx
링크 : https://github.com/skylot/jadx
JAVA decompiler
필자는 dex2jar&jd-gui 보다 jadx를 사용하는 것을 더 선호하는데 jadx의 결과가 jd-gui보다 좀더 정확하게 복원을 해주는 것으로 느껴지고, 또 dex2jar라는 단계를 밟지 않고 바로 apk파일을 끌어다 놓는 것만으로 디 컴파일이 되기 때문.

6) cheatengine
링크 : http://www.cheatengine.org/
메모리 변조 툴
android 앱에 attach해서 메모리를 변조등을 수행할 수 있다.

7) frida
링크 : http://www.frida.re/docs/android/
frida는 javascript inject를 이용해 개발자가 만들어낸 함수를 공격자가 명시해서 호출하거나, 함수를 새로 만들어서 호출 할 수도 있다.
예를 들면 Getpassword(String id) 이런 함수가 있다면 공격자가 이를 호출하여 password를 얻어낼 수 도 있다.

8) ida pro
링크 : https://www.hex-rays.com/products/ida/
ida는 동적 디버깅 툴로 대상 Apk를 실행시키면서, 각 부분에 BP를 걸어 그 시점에서의 레지스트리 값등을 확인하고, 패치를 통해
체크로직등의 우회를 노릴수 있다.

9) drozer
링크 : https://labs.mwrinfosecurity.com/tools/drozer/
안드로이드 진단 프레임워크로 안드로이드 어플리케이션의 보안 취약점을 진단할 수 있다.

10) introspy
링크 : https://github.com/iSECPartners/Introspy-Android
함수 호출을 포함한 어플리케이션 API 안드로이드 API 파라미터와 리턴값을 로깅 해주는 tool이다.


출처: https://yprefer.tistory.com/1?category=648958 [YPrefer's Develop&Security]

Continue reading

안드로이드 취약점 점검, ADB 살펴보기

ADB (Android Debug Bridge) 는 안드로이드 에뮬레이터나 PC에 실제 연결된 장치를 제어하기 위한 안드로이드 디버깅 도구 중 하나이다. 안드로이드 스튜디오와 같은 안드로이드 통합 개발 환경에서는 기능을 GUI 형태로 제공하는 반면, ADB 는 명령라인을 통해 사용자가 명령어를 입력함으로써 안드로이드 기기와 통신하고 있다.


ADB는 안드로이드 SDK 에 포함되어 있으며, SDK 설치 폴더의 하위 폴더인 platform-tools 에 포함되어 있다.



adb devices 명령을 실행한 결과 1개의 device가 발견되었다.


adb shell 명령으로 쉘에 접근 할 수도 있다. (만약 여러개의 장치가 연결되었으면 usb의 경우는 -d 옵션을 붙이고 에뮬의 경우는 -e를 붙여야 한다. )




[로그캣을 이용한 로그 분석]
로그캣은 안드로이드 장치에서 발생하는 로그 메시지를 화면으로 출력하거나 파일 형태로 저장하는 기능을 제공한다.


adb shell 로 로그인 후 logcat 명령어를 입력함으로써 안드로이드 로그메시지를 볼 수 있다. 로그가 모두 출력된 이후에 로그캣을 종료하지 않으면 실시간 발생하는 이벤트 로그가 출력된다.

Continue reading

ios 무결성 취약점 점검

iOS 앱의 바이너리 파일을 변조하여 무결성 검증 로직이 존재하는지 확인하는 점검

[1단계]
- 모바일 앱의 바이너리 파일(payload/app_name)은 애플 사의 암호화 방식으로 암호화 되어 있으므로 복호화를 해야 함
- 설치된 디렉토리로 이동하면 암호화 되어 있지만, 앱 구동 시 복호화 하게 되어 있음
- 설치된 앱(구성) 디렉토리 : /private/var/containers/Bundle/Application/
- Clutch2를 이용해 바이너리 파일을 복호화를 하면 Clutch2가 설치된 디렉토리에 복호화 된 파일이 저장됨
- Clutch2 -i : 복호화를 할 앱의 목록 출력
- Clutch2 -b 숫자 : 지정된 앱(숫자)를 복호화

** ios 버전에 따라서 clutch 를 통한 복호화가 안되는 경우가 있다. 이럴 경우, 수동으로 복호화 해야함. 이와 관련한 글을 추후 작성 할 예정이다.

[2단계]
- 아이펀박스 프로그램으로 복호화 된 파일을 로컬 PC에 저장
- 헥사 에디터로 복호화 된 바이너리 파일을 열어 변조

[3단계]
- 아이펀박스 프로그램으로 app_name.ipa 파일을 모바일 단말기에 설치
- 변조된 앱이 이상없이 실행되면 무결성 취약점이 존재하는 것

- 변조한 앱으로 무엇을 할것인지는 다음 문제

Continue reading

iOS 취약점 점검 - DVIA 설치

1. 탈옥

  • 우선 iOS 폰이 탈옥이 되어있어야 한다. (루팅이라고도 함)
  • 탈옥의 방법은 굉장히 다양하고 애플 정책에 따라 계속 바뀌므로 따로 기재하지는 않는다


2. 점검 할 앱 설치 (DVIA) - http://damnvulnerableiosapp.com/(https://github.com/prateek147/DVIA-v2/releases)

  •  이는 무료로 제공하는 iOS 점검용 앱인데, swift와 object-c 버전이 각각 다운받을 수 있다. 
  • 그리고 루팅 폰에서 아래를 설치한다.
    • cydia 소스를 추가(https://cydia.akemi.ai/)
    • AppInst 설치
    • AppSync 설치
    • Apple File Conduit2 설치 (폰 리부팅)
  • Filezila 를 통해 다운받은 ipa 파일을 폰에 넣고 'appinst ipa파일명' 으로 권한을 부여한다


3. 점검 시작

  • 준비는 끝났으니 이제 점검을 수행하면 된다.
  • 테스트로 jailbreak Detection 을 우회해 본다. 
(IDA로 forjail 로 검색하면 쉽게 탈옥탐지 메소드를 찾을 수 있다.)
 (TBZ 이므로 frida를 실행하여 레지스트리 값을 변조한다)




Continue reading

2019. 10. 30.

[python] 크롤링 데이터를 mysql에 삽입

이전 포스트(https://coashanee5.blogspot.com/2019/10/blog-post_29.html)는 공공기관의 채용공고 사이트의 검색결과를 수집하여 기업명과, 공고URL을 출력하였다. 이번 포스트에서는 수집한 내용을 데이터베이스에 넣어 보도록 하겠다.

1. 우선 mysql을 설치를 한 후, 데이터를 넣기 위한 데이터베이스를 만든다. 
create DataBase scraping;
2. 이번에는 데이터를 저장할 테이블을 생성한다. 
create Table job_offer (id BIGINT(7) NOT NULL AUTO_INCREMENT, comp VARCHAR(200), title VARCHAR(200), URL VARCHAR(1000), created TIMESTAMP DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY(id));

3. 기존 소스에 DB연결과 데이터를 저장하는 내용을 추가한다.

# 공공기관 채용정보에서 정보통신 공고만 추려서 리스팅하는 소스
import requests
from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
import ssl
import datetime
import pymysql
context = ssl._create_unverified_context()


# url을 변수에 삽입하여 저장한다.
url = "https://job.alio.go.kr/recruit.do?pageNo=1&param=&search_yn=Y" \
      "&idx=&recruitYear=&recruitMonth=&detail_code=R600020&location=R3010&work_type=R1010" \
      "&work_type=R1030&career=R2020&education=R7010&education=R7040&education=R7050" \
      "&education=R7060&replacement=N&s_date=2019.03.12&e_date=2019.10.12&org_name=&title=&order=REG_DATE"

conn = pymysql.connect(host='127.0.0.1', user='root',passwd='test1234', db='mysql')
cur = conn.cursor()
cur.execute("USE scraping")

html = urlopen(url, context=context)
bsObj = BeautifulSoup(html.read(), "html.parser")

table = bsObj.find("table",class_="tbl type_03")

def extractNumber(word):
    i = int(re.findall('\d+', word)[0])
    return i

def store(comp, title, URL):
    cur.execute(
        "INSERT INTO job_offer (comp, title, URL) VALUES (\"%s\", \"%s\", \"%s\")", (comp, title, URL)
    )
    cur.connection.commit()

list = []
trs = table.tbody.findAll("tr")
for idx, tr in enumerate(trs):
    title = tr.select("td")[2].get_text().strip() # 제목
    comp = tr.select("td")[3].get_text().strip() # 기업명
    a = extractNumber(tr.select("td")[2].find("a").attrs['onclick'])

    new_url = "https://job.alio.go.kr/recruitview.do?pageNo=1&param=&search_yn=Y&idx={0}" \
              "&recruitYear=&recruitMonth=&detail_code=R600020&location=R3010&work_type=R1010" \
              "&work_type=R1030&career=R2020&education=R7010&education=R7040" \
              "&education=R7050&education=R7060&replacement=N&s_date=2019.03.12" \
              "&e_date=2019.10.12&org_name=&title=&order=REG_DATE".format(a)
    print(idx, title, comp, new_url)
    store(comp, title, new_url)

cur.close()
conn.close()

실행결과, 다음과 같이 데이터가 저장되는 것을 확인할 수 있다.


Continue reading

2019. 10. 29.

[python] 공공기관 채용정보시스템의 채용공고 출력하는 파이썬코드

공공기관 채용정보시스템에서 원하는 공고를 검색하여 크롤링하는 소스이다.

# 공공기관 채용정보에서 정보통신 공고만 추려서 리스팅하는 소스
import requests
from bs4 import BeautifulSoup
from urllib.request import urlopen
import re
import ssl
import datetime
context = ssl._create_unverified_context()


# url을 변수에 삽입하여 저장한다.
url = "https://job.alio.go.kr/recruit.do?pageNo=1&param=&search_yn=Y" \
      "&idx=&recruitYear=&recruitMonth=&detail_code=R600020&location=R3010&work_type=R1010" \
      "&work_type=R1030&career=R2020&education=R7010&education=R7040&education=R7050" \
      "&education=R7060&replacement=N&s_date=2019.03.12&e_date=2019.10.12&org_name=&title=&order=REG_DATE"

html = urlopen(url, context=context)
bsObj = BeautifulSoup(html.read(), "html.parser")

table = bsObj.find("table",class_="tbl type_03")

def extractNumber(word):
    i = int(re.findall('\d+', word)[0])
    return i

list = []
trs = table.tbody.findAll("tr")
for idx, tr in enumerate(trs):
    title = tr.select("td")[2].get_text().strip() # 제목
    gName = tr.select("td")[3].get_text().strip() # 기업명
    #place = tr.select("td")[4].get_text().strip().replace("\t","").replace("\r","").replace("\n","") # 장소
    #type = tr.select("td")[5].get_text().strip() # 고용 형태
    a = extractNumber(tr.select("td")[2].find("a").attrs['onclick'])

    new_url = "https://job.alio.go.kr/recruitview.do?pageNo=1&param=&search_yn=Y&idx={0}" \
              "&recruitYear=&recruitMonth=&detail_code=R600020&location=R3010&work_type=R1010" \
              "&work_type=R1030&career=R2020&education=R7010&education=R7040" \
              "&education=R7050&education=R7060&replacement=N&s_date=2019.03.12" \
              "&e_date=2019.10.12&org_name=&title=&order=REG_DATE".format(a)
    #list.append(title + ", " + gName + ", "+new_url)
    print(idx, title, gName, new_url)
#print (list)

실행 결과는 아래와 같다. 



이후에는 크롤링 결과를 1) 엑셀 다운로드, 2) 메일 전송 3) 웹 서버에 띄우기 이런 정도로 포스팅을 해 볼까 생각중이다.

Continue reading

구글 블로거 꾸미기 -5 google blog 에서 소스코드 하이라이트 (highlight)

블로그 성격상 소스코드를 작성할 일이 많은데, 소스코드를 멋지게 작성하는 방법을 소개한다.

1. Highlight.js
코드 구문 강조를 위한 자바스크립트 라이브러리이다. 자동으로 언어를 감지하여 알맞는 표식을 삽입한다.

  • http://highlightjs.org/ 사이트에서 다운로드가 가능하다.

홈페이지에 보면 hosted와 custom package 두 가지 방법이 있다고 나와 있는데, google blog는 hosted 방식을 사용하면 된다. 아래 소스를 html 소스 중 <head></head> 안에 삽입하면 사용할 준비는 끝이다.
<link rel="stylesheet" href="//cdn.jsdelivr.net/highlight.js/8.7/styles/monokai_sublime.min.css" />
<script src="//cdn.jsdelivr.net/highlight.js/8.7/highlight.min.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
이제 포스팅 할때 <pre><code>소스코드 </code></pre> 이렇게 사용하면 된다. 간혹 언어를 인식하지 못하는 경우가 있는데 그럴 경우는 <pre><code="language-html>소스코드 </code></pre> 이런식으로 사용하고자 하는 언어를 입력하면 된다.


import execjs
execjs.eval("'red yellow blue'.split(' ')")

ctx = execjs.compile("""
function add(x, y) {
return x + y;
}
""")

print(ctx.call("add", 1, 2))

파이썬 코드를 예시로 들면 이런 형태의 디자인이 된다. 또한 css 파일의 링크를 바꾸면 원하는 디자인으로 테마를 마음대로 바꿀 수 있다.

** TIPS
가끔 다른 종류의 태그가 삽입되면 하이라이트가 작동 못하는 경우가 있는데, 이 경우 해당 사이트(http://accessify.com/tools-and-wizards/developer-tools/quick-escape/default.php)에서 코드를 넣고 스크립트를 치환하여 시도해보자.

예를들면, <strong>굵게</strong> 를 &lt;strong&gt;굵게&lt;/strong&gt;  이렇게!

Continue reading

2019. 10. 27.

구글 블로거 꾸미기 -4 글머리 기호(리스트) 기능 활성화

구글 블로그에서 글을 작성할때 아래와 같이 '글머리 기호' 기능이 필요할 때가 있다. 

  • AAA
  • BBB
  • CCC 이런 기능을 말함
그러나 어처구니 없게도 글을 작성할때는 되는가 싶다가도 게시하면 글머리가 사라진다.


1. '글머리 기호(리스트)' 기능 활성화
- 테마 -> HTML편집 -> 검색 -> 아래와 같이 수정
- 수정 전
.widget ul {list-style: none;margin : 1.5em 0 0;}

- 수정 후
.widget ul {
  list-style: disc; ! list-style: none
  margin: 0 0 0 0; ! margin: 1.5em 0 0;
  padding: 0 0 0 10px;
}
2.  '글머리 기호(리스트)' 앞 간격 조정

- 1번의 위젯 소스에서 padding 항목에 숫자를 수정하면된다. 

3. '글머리 기호(리스트)' 위 간격 조정

- 1번의 위젯 소스에서 margin 항목에 숫자를 수정하면된다. 

4. '글머리 기호(리스트)' 간 높이 간격 조정
- 아래와 같이 설정
.widget ul li {margin-bottom: 0em;}

Continue reading

구글 블로거 꾸미기 -3 피드 구독하기 기능 삭제

처음 블로거를 시작하면 하단에 "피드 구독하기: 게시물(Atom) 이라는 정체를 알수 없는 기능이 보여진다. 페이지를 볼때는 "피드 구독하기: 댓글(Atom) 도 있다.
사실상 거의 필요없는 기능이라 생각되어 기능을 제거하기로 했다.

1. "피드 구독하기:게시물(Atom)" 이 표시되지 않도록 설정
- 테마 -> 템플릿 -> 맞춤설정 -> 고급 -> CSS추가 -> 아래 코드 삽입
.blog-feeds{display:none;}
2. "피드 구독하기:댓글(Atom)"이 표시되지 않도록 설정
- 테마 -> 템플릿 -> 맞춤설정 -> 고급 -> CSS추가 -> 아래코드 삽입
.post-feeds {display:none;}

Continue reading

구글 블로거 꾸미기 -2 우클릭, 드래그 방지

자신의 블로그에서 우클릭, 드래그가 안되게 하고 싶어하는 경우가 있을 것이다.

1. 우클릭 방지
- 관리페이지 > 테마 > HTML 편집
- Ctrl + F 로 </body> 를 찾은 후 바로 위에 아래 코드를 삽입한다. 

 <script language=javascript>  
 <!--  
   
 var message="";  
   
 function clickIE()  
 {  
  if (document.all) {  
   (message);return false;}  
 }  
   
 function clickNS(e)  
 {  
 if (document.layers||(document.getElementById&&!document.all)) {   
  if (e.which==2||e.which==3) {(message);return false;}}  
 }  
   
 if (document.layers){  
  document.captureEvents(Event.MOUSEDOWN);document.onmousedown=clickNS;}  
 else{  
  document.onmouseup=clickNS;document.oncontextmenu=clickIE;}  
 document.oncontextmenu=new Function("return false")  
   
 // -->  
 </script> 

2. 드래그 방지
- 테마 > 템플릿 > 맞춤설정 > 고급
- CSS 추가를 통해 아래의 코드 삽입

html, body, div, span, object,  
 form, input, h1, h2, button, label, a, img {  
  -moz-user-select: none;  
  -ms-user-select: none;  
  -webkit-user-select: none;  
  /* this will work for QtWebKit in future */  
  -webkit-user-drag: none;  
 }  
   
 input[type=text] {  
  -moz-user-select: text;  
  -webkit-user-select: text;  
 } 

참조

  • http://ielselog.blogspot.com/2012/09/blog-post.html

Continue reading

2019. 10. 26.

구글 블로거 꾸미기 -1 스킨, 나눔고딕 폰트 적용

약 4년동안 나름 비주류인 구글 블로그를 하면서 많은 시행착오를 겪었었다. 지금도 고난(?)은 진행중이지만 나와 같은 시행착오를 겪고 있는 사람들에게 도움이 되었으면 하는 바램에 간단하게 나마 글을 작성한다.

1. 이미 만들어진 스킨을 이용하자.
구글 블로거는 HTML과 CSS 등을 기본적으로 요구하기 때문에 진입장벽이 타 블로그 보다는 높은 편이다. 그럼에도 불구하고 여러 스킨들을 제공하기 때문에 이를 적용하여 조금씩 수정해가면 나름 만족할 수준의 블로그를 만들 수 있을 것이다.

  • http://newbloggerthemes.com/
  • http://btemplates.com/

구글 블로그 스킨을 다루는 여러 사이트가 있지만 위 두 사이트를 추천한다. 다른 블로거들도 많이 이용하는 것 같다.

2. 폰트 적용은 어떻게?
스킨을 적용하니 블로그는 디자인은 바뀌었는데 폰트 적용부터 막막하다. HTML CSS 에 능숙하다면야 문제없겠지만, 능숙하지는 않다. 
결국 구글검색 후 블로그 관리페이지 > HTML편집 > .post-body 를 검색해서 폰트 수정했다. 그러나 전체 폰트를 조정할지 특정 문구의 폰트를 수정할지는 스킨에 따라 다르므로, 약간의 삽질이 필요할 것이다. 
  • http://smartbloggertips.blogspot.com/2013/08/change-font-size-of-blogger-posts.html
** blogger 에 나눔고딕 폰트 적용

- 테마 -> HTML편집 -> <head> 아래에 아래 코드 추가
<link rel='stylesheet'  href='http://fonts.googleapis.com/earlyaccess/nanumgothic.css'/> 
 - 그 후, 적용하려는 부분에 font-family: 'Nanum Gothic'; 을 추가한다
예시) body, h1, h2, h3, h4, a, div, input, p, span, td, label, select, textarea, iframe {
    font-family: 'Nanum Gothic';
}

3. "레이블이 blogger인 게시물을 표시합니다." 폰트 사이즈 변경 및 제거

아니 이건 뭔데 이런 촌스러운 모습을 하고 있는것인가. 
블로거에서 태그를 선택하면, 해당 태그를 갖고 있는 글들이 검색된다. 이때 위와 같은 메시지가 출력이 된다. 그러나 미관상 좋지 않기 때문에 제거하기로 했다. 

- 폰트 사이트 설정
관리페이지 > HTML 편집
.status-msg-wrap{  
font-size:24px;
}
- 보이지 않게 제거
.status-msg-wrap{  
display: none; 
}



Continue reading

2019. 10. 18.

[python] 아나콘다(anaconda) 에서 jupyter notebook 실행시 에러 발생

문제.
- 아나콘다 에서 jupyter notebook 을 실행 할때 해당 경로에 가서 명령어(C:\Users\dojang>C:\Users\dojang\Anaconda3\python.exe -m notebook --notebook-dir C:\project) 를 입력만 하면 되었다. (회사 환경에서는)
- 그런데 집에서는 "ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다." 라는 오류가 발생한다.

해법.
- 문제의 원인은 찾지 못했지만 해결책은 찾았다. conda 환경을 갖추고 거기서 주피터를 실행한다
- cd C:\Users\ABC\Anaconda3\Scripts -> activate.bat -> jupyter.exe notebook

Continue reading

2019. 10. 15.

[python] requests 로 로그인 후 크롤링

requests 로 로그인 하고 BeautifulSoup으로 데이터 가져오기


import requests
from bs4 import BeautifulSoup

login_url = 'http://www.hanbit.co.kr/member/login_proc.php'

user = ''
password = ''

# requests.session 메서드는 해당 reqeusts를 사용하는 동안 cookie를 header에 유지하도록 하여
# 세션이 필요한 HTTP 요청에 사용됩니다.
session = requests.session()

params = dict()
params['m_id'] = user
params['m_passwd'] = password

# javascrit(jQuery) 코드를 분석해보니, 결국 login_proc.php 를 m_id 와 m_passwd 값과 함께
# POST로 호출하기 때문에 다음과 같이 requests.session.post() 메서드를 활용하였습니다.
# 실제코드:
res = session.post(login_url, data = params)

# 응답코드가 200 즉, OK가 아닌 경우 에러를 발생시키는 메서드입니다.
res.raise_for_status()

# 'Set-Cookie'로 PHPSESSID 라는 세션 ID 값이 넘어옴을 알 수 있다.
# print(res.headers)

# cookie로 세션을 로그인 상태를 관리하는 상태를 확인해보기 위한 코드입니다.
# print(session.cookies.get_dict())

# 여기서부터는 로그인이 된 세션이 유지됩니다. session 에 header에는 Cookie에 PHPSESSID가 들어갑니다.
mypage_url = 'http://www.hanbit.co.kr/myhanbit/myhanbit.html'
res = session.get(mypage_url)

# 응답코드가 200 즉, OK가 아닌 경우 에러를 발생시키는 메서드입니다.
res.raise_for_status()

soup = BeautifulSoup(res.text, 'html.parser')

# Chrome 개발자 도구에서 CSS SELECTOR를 통해 간단히 가져온 CSS SELECTOR 표현식을 사용
he_coin = soup.select_one('#container > div > div.sm_mymileage > dl.mileage_section2 > dd > span')

# 다음과 같이 class를 .mileage_section2 로 그리고 그 하부 태그중에 span이 있다는 식으로 표현도 가능함
# he_coin = soup.select_one('.mileage_section2 span')

print ('mileage is', he_coin.get_text())

출처

Continue reading

2019. 10. 14.

[python] 네이버 open api 를 통한 크롤링 수집

소스코드

ㅇㅇㅇ
import urllib.request
import json

client_key = '키 값'
client_secret = '시크릿 값'

# 한글등 non-ASCII text를 URL에 넣을 수 있도록 "%" followed by hexadecimal digits 로 변경
# URL은 ASCII 인코딩셋만 지원하기 때문임
encText = urllib.parse.quote_plus("스마트폰")
# print(encText)

naver_url = 'https://openapi.naver.com/v1/search/news.json?query=' + encText

# urllib.request.Request()는 HTTP Header 변경시에 사용함
# 네이버에서도 다음 HTTP Header 키를 변경해야하기 때문에 사용함
# HTTP Header 변경이 필요없다면, 바로 urllib.request.urlopen()함수만 사용해도 됩
request = urllib.request.Request(naver_url)
request.add_header("X-Naver-Client-Id",client_key)
request.add_header("X-Naver-Client-Secret",client_secret)

# urllib.request.urlopen 메세드로 크롤링할 웹페이지를 가져옴
response = urllib.request.urlopen(request)


# getcode() 메서드로 HTTP 응답 상태 코드를 가져올 수 있음
rescode = response.getcode()

# HTTP 요청 응답이 정상적일 경우, 해당 HTML 데이터를 수신되었기 때문에 필요한 데이터 추출이 가능함
# HTTP 요청에 대한 정상응답일 경우, HTTP 응답 상태 코드 값이 200이 됩니다.
if(rescode == 200):
# response.read() 메서드로 수신된 HTML 데이터를 가져올 수 있음
response_body = response.read()
# 네이버 Open API를 통해서 수신된 데이터가 JSON 포멧이기 때문에, 
# JSON 포멧 데이터를 파싱해서 사전데이터로 만들어주는 json 라이브러라를 사용
data = json.loads(response_body)
# json.loads() 메서드를 사용해서 data 에 수신된 데이터를 사전 데이터로 분석해서 자동으로 만들어줌
#print (data['items'][0]['title'])
#print (data['items'][0]['description'])
print(data)
else:
print("Error Code:" + rescode)

출처

Continue reading

2019. 10. 11.

[python] 네이버 검색 정보 크롤링해서 DB에 넣기

import requests
from bs4 import BeautifulSoup
from urllib.request import HTTPError
import pymysql
import datetime
headers = {'User=Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.90 Safari/537.36'}

def blog_crawling(keywords):
    start_time = datetime.datetime.now()

    conn = pymysql.connect(host=xxxxxx', user='xxxx', password='xxxxx', db='xxxx', charset='utf8')
    try:
        with conn.cursor() as cursor:
            for keyword in keywords:
                count = 1                for x in range(1,1000,10):
                    now = datetime.datetime.now()
                    print(x)

                    url = 'https://search.naver.com/search.naver?date_from=&date_option=0&date_to=&dup_remove=1&nso=&post_blogurl=&post_blogurl_without=&query={0}&sm=tab_pge&srchby=all&st=sim&where=post&start={1}'.format(keyword,x)
                    response = requests.get(url,headers = headers)
                    html = BeautifulSoup(response.text,'html.parser')
                    bloghtmls = html.find_all('li',class_='sh_blog_top')
                    for bloghtml in bloghtmls:
                        print(count)
                        i = 0                        if 'title' in bloghtml.select('a')[1].attrs:
                            print(bloghtml.select('a')[1]['title'])  # 블로그 타이틀 -- a 태그중 2번째의 태그의  title 가 블로그 제목이다                            i = 1                        elif 'title' in bloghtml.select('a')[2].attrs:
                            print(bloghtml.select('a')[2]['title']) # 블로그 타이틀 -- a 태그중 2번째의 태그의  title 가 블로그 제목이다                            i = 2                        #print(bloghtml.select('a')[2]['title']) #블로그 타이틀 -- a 태그중 3번째의 태그의  title 가 블로그 제목이다                        print(bloghtml.select('a')[0]['href']) # URL -- a태그가 여러개라면 그중 첫번째 중에 href를 가져와라                        print(bloghtml.select('.txt84')[0].get_text()) #블로그명                        print(bloghtml.select('.txt_inline')[0].get_text()) #등록일자                        print('\n')

                        sql = """insert into naver_blog2(search_date, keyword, title, link,rank_b,write_date) values (%s, %s, %s, %s,%s,%s)"""                        cursor.execute(sql, (now,keyword,bloghtml.select('a')[i]['title'],bloghtml.select('a')[0]['href'],count,bloghtml.select('.txt_inline')[0].get_text()))
                        conn.commit()

                        count += 1

    finally:
        conn.close()
        end_time = datetime.datetime.now()
        run_time = end_time - start_time
        print(run_time)

blog_crawling(['python','c++','java'])

Continue reading

[python] pythonista 에서 모듈 설치, stash

모바일에서 파이썬 코딩하는 최고의 도구 pythonista 를 잘 사용하고 있다.
pythonista 에서 모듈을 설치하고 싶을 때 다음과 같은 방법을 통해 모듈을 설치 할 수 있다.

1. stash 를 설치한다.

  • https://github.com/ywangd/stash 에 installation 을 복사하여 pythonista에 추가
  • 즉 import requests as r; exec(r.get('https://bit.ly/get-stash').text) 를 복사하여 pythonista에서 실행
  • 실행 결과 ios에는 lunch_stash.py 가 실행되는데 이를 실행하면 프롬프트가 실행된다. 
  • pip install 모듈명 으로 원하는 모듈 설치

참고 

Continue reading

2019. 10. 8.

[MySQL] 외부에서 mysql에 접속하자

aws lambda 를 공부하다보면 외부에서 mysql에 접속해야 할 일이 있다. 그러기 위해 필요한 준비가 바로 '외부에서 나의 MySQL 서버로 접속하기' 이다.  그러면 이제 우리는 외부 접속용 계정을 만들고, 그 계정에 데이터베이스 접근 권한을 부여하고  서비스 재시작을 하면된다.

1. mysql 설정파일 수정(리눅스의 경우 /etc/my.cnf, 윈도우의 경우 my.ini)
필자는 windows 에 mysql을 설치했으므로 C:\ProgramData\MySQL\MySQL Server 8.0 폴더에서  my.ini를 수정한다.
  • bind-address=0.0.0.0 설정이 되어 있다면 주석처리하고, 그렇지 않다면 건너뛴다.
2. 원격에서 mysql에 접속 할 계정 생성
  • create user '계정명'@'호스트 명' identified by '암호';
  • 호스트명에는 모든 호스트를 허용할 경우 %, 로컬 호스트만 허용할 경우 localhost , 특정 IP를 허용할 경우 192.168.1.123 또는 192.168.% 라고 입력할 수 있다.
3. 권한 부여
  • grant all privileges on 데이터베이스명.* to '계정명'@'호스트명';
  • 모든 데이터베이스에 대한 접근을 허용할 경우 mydb 대신 * 를 넣어준다
4. 적용 확인 및 서비스 재시작
  • SELECT user, host from mysql.user;
  • 윈도우의 경우 서비스 메뉴에서 서비스 재시작을 하고 리눅스의 경우 sudo service mysql restart 또는 sudo systemctl restart mysql

Continue reading

2019. 9. 29.

[python] 위키피디아 데이터 수집 후 DB에 저장

위키피디아 데이터 수집 후 DB에 저장하는 파이썬 코드

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
import datetime
import random
import pymysql

conn = pymysql.connect(host='127.0.0.1',user='root',passwd='2kdskfk1!@', db='scraping', charset='utf8')

cur = conn.cursor()
cur.execute("USE scraping")
random.seed(datetime.datetime.now())

def store(title, content):
cur.execute(
"INSERT INTO pages (title, content) VALUES (\"%s\", \"%s\")", (title, content)
)
cur.connection.commit()

def getLinks(articleUrl):
html = urlopen("http://en.wikipedia.org"+articleUrl)
bsObj = BeautifulSoup(html, "html.parser")
title = bsObj.find("h1").get_text()
content = bsObj.find("div", {"id":"mw-content-text"}).find("p").get_text()
store(title, content)
return bsObj.find("div", {"id":"bodyContent"}).findAll("a", href=re.compile("^(/wiki/)((?!:).)*$"))

links = getLinks('/wiki/Kevin_Bacon')
try :
while len(links) > 0:
newArticle = links[random.randint(0, len(links)-1)].attrs["href"]
print(newArticle)
links = getLinks(newArticle)
finally:
cur.close()
conn.close()

기본적인 테스트기 때문에 불필요한 값들이 많이 들어가있는 것을 볼 수 있다.


Continue reading

[python] mysql 과 파이썬 연동

파이썬에서 mysql 을 사용하려면 pymysql 모듈을 pip로 설치해야 한다.

import pymysql
conn = pymysql.connect(host='localhost', user='root', passwd='비밀번호', db='scraping')

cur = conn.cursor()
cur.execute("SELECT * FROM pages WHERE id=1")
print(cur.fetchall())
cur.close()
conn.close()


Continue reading

2019. 9. 28.

MYSQL 개발 툴로 접속이 안될때

mysql 을 설치하고 나서, cmd command 에서는 접속이 잘되는데,  개발 툴 ( 나의 경우엔 toad for mysql ) 로는 접속이 안된다. 

해결 방안은 다음과 같다. 

1. mysql installer - community 를 설치
2. mysql server 에서 Reconfigure 클릭
3. use Legacy Authentication Method 선택
 

Continue reading

2019. 9. 24.

웹 서버와 구조의 이해

웹 애플리케이션 서버와 웹 프레임워크 구조의 이해

웹 애플리케이션 서버는 정적 페이지와 동적페이지 요청을 모두 처리할 수 있다. 정적 페이지는 html, javascript, css 처럼 미리 작성되어 있어 서버 측의 실행이 요구되지 않는 응답 페이지를 의미하며, 동적 페이지는 서버 측에서 무엇인가를 실행해 요청에 따라 생성되는 응답 페이지를 의미한다.

웹 서버는 사용자의 요청을 수신하면 로컬 저장소의 경로에서 해당 파일을 찾아 응답(Response)한다. 하지만 동적인 요청을 수신하게 되면 동적 요청을 처리할 수 있는 웹 애플리케이션을 호출하게 되는데 PHP는 라이브러리.so 형태로 ASP는 동적링크파일인 dll, JSP는 자바 클래스로 변환되어 class 형태로 기능을 구현해 서비스한다.

서블릿은 웹 서비스를 위한 인터페이스로 HTTP 요청을 처리할 수 있는 규격이다. 서블릿은 독자적으로 실행되지 않고 서블릿 컨테이너에 등록된 후 서블릿 컨테이너에 의해 생성 호출 소멸된다. JSP는 HTML 과 자바 코드를 혼용해 사용할 수 있도록 정의된 텍스트 파일로 JSP 파일이 실행되기 위해서는 먼저 서블릿 클래스로 변환 작업이 이뤄줘야 한다.

서블릿 컨테이너는 서블릿을 관리하며 네트워크 통신, 서블릿의 생명주기 관리, 스레드 기반의 병렬 처리를 수행하는 JVM이다. 서블릿 컨테이너는 웹 요청을 처리하기 때문에 웹 컨테이너라고 부르기도 한다.


위 그림은 애플리케이션 서버의 처리 구조를 도식화 한 것으로 사용자가 JSP 를 요청하면 서블릿 컨테이너는 먼저 JSP 를 서블릿 클래스로 변환해 서블릿 컨테이너에 로드한다. 서블릿 컨이너는 사용자의 요청을 HttpServletRequest 객체로 생성하고 응답을 위해 HttpServletRequest 객체를 생성해 요청을 처리할 서블릿에 전달한다. 서블릿 클래스는 처리 결과를 HttpServlet Response 객체의 출력 스트림을 통해 반환한다.

Continue reading

2019. 9. 23.

[python] 웹 크롤링, 네이버 웹툰 제목

from bs4 import BeautifulSoup
from pprint import pprint
import requests

html = requests.get("http://comic.naver.com/webtoon/weekday.nhn")

bsObj = BeautifulSoup(html.text, "html.parser")
#첫번째 가공
date1 = bsObj.find('div',{'class':'col_inner'})
#print(date1)

#두번째 가공

date2 = date1.findAll('a',{"class":"title"})
#print(date2)

for name in date2 :
print(name.get_text())

'''
for name in bsObj.find('div',{'class':'col_inner'}).findAll("a", {"class":"title"}) :
print(name.attrs["title"])
'''

Continue reading

2019. 9. 22.

[python] 홈페이지 전체 페이지 크롤링

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re

pages = set()

def linkUrl(addrUrl) :
html = urlopen("https://en.m.wikipedia.org/wiki/Main_Page")
bsObj = BeautifulSoup(html.read(), "html.parser")
for i in bsObj.findAll("a",href=re.compile("(^/wiki/)")) :
if "href" in i.attrs :
if i.attrs["href"] not in pages :
newPages = i.attrs["href"]
pages.add(newPages)
print(newPages)
linkUrl(newPages)
linkUrl("")

Continue reading

[python] 현재 사이트에서 랜덤으로 외부 사이트 링크 타고 가기

현재 사이트에서 a href 목록을 수집하여 외부사이트를 선별하여 링크를 출력한다.

from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
from urllib.parse import urlparse
import random
import datetime

pages = set()
random.seed(datetime.datetime.now())

def internalLinks(bsObj, host) :
internalLink = []
#/로 시작하거나 중간에 루트 도메인 주소가 포함된 링크를 찾는다.
for link in bsObj.findAll("a", href=re.compile("(^/|.*"+host+")")) :
if link.attrs["href"] is not None :
if link.attrs["href"] not in internalLink :
if link.attrs["href"].startswith("/") :
internalLink.append(host+link.attrs["href"])
else :
internalLink.append(link.attrs["href"])
return internalLink

def externalLinks(bsObj, host) :
externalLink = []
for link in bsObj.findAll("a", {"href":re.compile("^(http|www)((?!"+host+").)*$")}) :
if link.attrs["href"] is not None :
externalLink.append(link.attrs["href"])
return externalLink


def getRandomExternalLink(firstUrl) :
html = urlopen(firstUrl)
bsObj = BeautifulSoup(html.read(), "html.parser")
#print(urlparse(firstUrl).netloc)
externalLink1 = externalLinks(bsObj, urlparse(firstUrl).netloc)
if len(externalLink1) == 0 :
domain = urlparse(firstUrl).scheme+"://"+urlparse(firstUrl).netloc
internalLink1 = internalLinks(bsObj, domain)
return externalLinks(random.randint(0, len(internalLink1)-1))
else :
return externalLink1[random.randint(0, len(externalLink1)-1)]

def followExternalOnly(firstUrl) :
choiceOne = getRandomExternalLink(firstUrl)
print("******** random externalLink is",choiceOne)
followExternalOnly(choiceOne)
followExternalOnly("https://www.oreilly.com")


#test("www.naver.com")
#>>> a = urllib.request.urlopen(b'http://www.google.com'.decode('ASCII')).read()

Continue reading

[python] 다음 실시간 검색어 리스트 추출

# 다음 실시간 검색어 순위 목록 추출
from urllib.request import urlopen
from bs4 import BeautifulSoup

html = urlopen("https://m.daum.net/?nil_top=mobile")

bsObs = BeautifulSoup(html.read(), "html.parser")

for i in bsObs.find("div",{"class":"keyissue_area"}).findAll("span",{"class":"txt_issue"}) :
print(i.get_text())

Continue reading

2019. 9. 17.

[python] 위키백과 정찰

 # 위키백과 최초 페이지에서 랜덤으로 링크페이지에 접속하여 링크가 없을때까지 반복하는 프로그램
from urllib.request import urlopen
from bs4 import BeautifulSoup
import re
import random
import datetime
random.seed(datetime.datetime.now())



def linkaddr(addr) :
listing = []
html = urlopen("http://en.wikipedia.org"+addr)

bsObj = BeautifulSoup(html.read(), "html.parser")

for link in bsObj.find("div", {"id":"bodyContent"}).findAll("a",href=re.compile("^(/wiki/)((?!:).)*$")) :
if 'href' in link.attrs :
listing.append(link.attrs['href'])
return listing

links = []
links = linkaddr("/wiki/kevin_Bacon")
while len(links) > 0 :
a = links[random.randint(0, len(links)-1)]
print(a)
linkaddr(a)

Continue reading

2019. 8. 18.

자바스크립트 난독화 관련

자바스크립트 난독화를 복호화 할 필요가 있어서 여러자료를 알아보다가 제일 깔끔한 자료를 발견하였다.

구글 블로거 특성상, 파일 업로드를 할 수는 없지만, Pioneer of Security Research 에서 제작한 것으로 보이는 javascript code obfuscation 자료이다.

대표적인 난독화 기법에 대한 설명, 그리고 난독화 코드 해제 방법까지 자세히 서술하였다.

파일명은 obfuscation.pdf 인데 구글에서 바로 검색이 되는지 잘 모르겠다.

Continue reading

2019. 8. 17.

침해사고 관련 주요 CMD 명령어

1. 포트 및  PID 확인

netstat -ano | find "LISTENING" | find "80"

2. PID를 가진 프로세스 확인

tasklist /FI "PID eq 3792"

3. PID를 가진 프로세스 죽이기

taskkill /F /PID 3792

4. 해당 포트를 사용하는 프로세스를 직접 확인하는 방법
C:\> for /f "tokens=5" %p in (' netstat -ano ^| find "LISTENING" ^| find "80" ') do tasklist /FI "PID eq %p"

5. 해당 프로세스 중지하기
C:\> for /f "tokens=5" %p in (' netstat -ano ^| find "LISTENING " ^| find "80" ') do taskkill /F /PID eq %p



출처

Continue reading

2019. 8. 10.

JSP 선언부의 올바른 사용

< body>
<%!
      String name;
      name=”jong”;
%>
< /body>

위의 경우에는 에러가 난다. 그 이유는 <%! 는 선언부를 의미하는데 선언부는 말 그대로 선언해주는 구문만을 사용할 수 있다.


해결방안은
1. 선언과 동시에 초기화 하는것과,

  • <%! String name = "jong"; %>
2. 선언영역은 선언자로 선언이외의 다른 작업은 다른 영역에서 작성해주는 것이다
  • <%! String name; %>
  • <% name = "GD"; %>




Continue reading

2019. 4. 27.

centos 7 네트워크 수동 설정

오랜만에 VMWARE에 centos 를 재설치하였는데 IP 를 자동으로 설정이 안되었다.




1. vmware 네트워크 정보 확인
vmware 의 edit > virtual network editor 에서 Subnet IP, Subnet-mask, GW IP 를 확인


2. ens33 인터페이스 설정
vi /etc/sysconfig/network-scripts/ifcfs-ens33 설정
- BOOTPROTO를 dhcp에서 none 으로 설정
- ONBOOT 를 no에서 yes로 수정
IPADDR=아이피주소
NETMASK = 서브넷마스크값
GATEWAY=IP주소
DNS1=8.8.8.8


3. 네트워크 재시작
systemctl restart NetworkManager
systemctl restart network
ifup ens33


4. 네트워크 설정확인
ip addr
ping 8.8.8.8

Continue reading

2019. 1. 11.

[WEB] 버프스위트 필터 기능 팁

버프스위트 필터 기능 활용할때 유용한 팁 하나를 기록한다.

Proxy - http history 에서 필터를 클릭하면 다양한 옵션을 지정 할수 있다

잘 활용하면 아주 편리하다.

Filter by search item 에 찾고자하는 문자열 넣으면 해당 문자열이 포함되어 있는 항목만 출력된다.

Case sensitive 는 대소문자 구별
Regex 에는 정규표현식
Negative search는 입력하는거 빼고 나머지 출력


Continue reading

2019. 1. 6.

[모바일] 드로저 활용한 앱 취약점 점검

[드로저 명령어]

run app.package.list
 - 디바이스에 설치된 모든 앱의 패키지명 출력

run app.package.list -f insecure(설치 앱)
 - 특정단어가 포함되어 있는 패키지명 검색

run app.package.info -a com.android.insecurebankv2
 - 패키지 명으로 앱의 기본적인 정보를 얻기 위한 명령어


 - 패키지의 이름으로 프로세스 정보 버전, 데이터를 저장하는 위치, apk 파일의 위치, UID 등을 알 수 있으며, 앱이 가지고 있는 권한도 확인 할 수 있다.


run app.package.info -p android.permission.SEND_SMS
 -p 옵션을 사용하여 특정 권한을 갖고 있는 패키지의 목록이 출력된다.

 - SEND_SMS 디바이스 패키지 중에서 SMS를 보낼 수 있는 권한을 가진 앱들이 나열된다.

run app.package.manifest
 - 이러한 권한은 AndroidManifest.xml 파일에 정의되어 있으며, 모든 앱의 최상위 폴더에 존재한다. 이 파일은 여러가지 정보를 추출할 수 있기 때문에 기본적으로 분석해야 할 파일이다.

드로저의 기능 중 하나는 앱의 취약한 부분을 검색하는 기능을 갖고 있다는 것이다. app.package.attacksurface 모듈로 가능하다.

run.app.package.attacksurface com.android.insecurebankv2

 - 명령어 결과 5개의 액티비티가 노출되었으며, 브로드캐스트 리시버 취약점, 콘텐츠 프로바이더, 디버깅이 가능한 취약점이 발견되었다.

[취약점 분석]

1) 액티비티 분석

run app.activity.info -a com.android.insecurebankv2


액티비티 정보들의 이름이 출력된다. 그리고 패스워드 변경과 관련된 ChangePassword 를 로그인 후에 접근했을 때와 드로우저를 이용하여 비정상적으로 접근했을때를 비교해보자.

run app.activity.start --component [패키지명] [액티비티명]


 - 특정권한이 있어야만 접근 할 수 있는 페이지를 정당한 권한 없이 접근이 가능하다.

2) 브로드캐스트 리시버 분석

안드로이드 디바이스에서 이벤트가 발생하는 경우에는 앱들이 브로드캐스트 신호를 주고 받으며 시스템상에 일어나는 상황을 공유한다. 이때 신호를 받기 위해서는 브로드캐스트가 정의되어 있어야 하며, 각각의 신호에 맞는 액션 역시 적용되어 있어야 한다.

run app.broadcast.info -f [특정단어]

 - 브로드캐스트 리시버 이름이 MyBroadCastReceiver 라는 것을 알 수 있다.

3) 콘텐츠 프로바이더 분석
콘텐츠 프로바이더는 특정 애플리케이션이 사용하고 있는 데이터베이스를 공유하기 위해 사용된다. 이는 전체 데이터가 아닌 공유를 원하는 데이터만 공유하기 위한 수단이기도 하다.

run.app.provider.info -a com.android.insecurebankv2


TrackUserContentProviderProvider 가 노출된것을 확인하였다. 컨텐츠 프로바이더는 데이터베이스에 있는 정보를 URI 로 공유하기 때문에 데이터베이스에 접근하기 위해서는 URI 에 대한 정보가 반드시 필요하다. 프로바이더가 사용하는 URI 정보를 찾기 위해서는 app.provider.finduri 모듈을 사용한다.

run app.provider.finduri [패키지이름]

 - uri 주소는 특정 데이터에만 접근하도록 제한하여 공유한다.

run scanner.provider.sqltables -uri [uri 주소]
지금까지 얻는 URI 정보로 어떤 정보에 접근할 수 있는 확인한다.

 - 3개의 테이블에 접근할 수 있다. "-a" 옵션을 사용하면 입력한 패키지에서 사용하는 모든 URI 주소 검색을 실시한다. 


run scanner.provider.sqltables -a com.android.insecurebankv2
 - 인시큐어뱅크 앱의 모든 URI를 조사한다.

run app.provider.query [uri]
 - URI 로부터 테이블명까지 추출하고 테이블 안에 어떠한 정보가 저장되어 있는지 확인하기 위해 "app.provider.query" 모듈로 구체적인 정보들을 얻어낸다.
 - URI 정보로부터 로그인한 사용자의 아이디와 로그인한 순서를 나타내는 테이블 정보가 출력되었다.

run app.provider.query content://com.android.insecurebankv2.TrackUserContentProvider/trackerusers --projection "* FROM SQLITE_MASTER WHERE type='table';--"


 - 위의 테이블 외에 다른 테이블이 있는지 확인하기 위해 sqlite_master 라는 테이블을 확인해본다. sqlite_master 테이블에서는 현재 앱에서 사용하고 있는 테이블들의 정보를 확인할 수 있다.


- 이러한 작업을 자동으로 수행해주는 scanner.provider.injection 모듈에 대해 알아본다.
- 이 모듈은 특정 앱에서 사용하는 프로바이드를 자동으로 검색하고 sql인젝션 공격이 가능한지 취약한지 여부를 판단한다.




[서비스 분석]
서비스는 앱을 구성하는 4가지 요소 중 하나로 화면에 보이는 액티비티와 반대로 UI가 없으며 백그라운드에서 실행되는 컴포넌트의 종류다. 음악앱의 경우 음악이 재생될 때 다른 앱을 실행하여도 음악이 계속 재생되는것은 음악 재생 서비스가 계속 실행중이기 때문이다.

run app.service.info -a com.android.email

 - email 앱의 서비스 목록이 리스팅된다.

[Debuggable package 분석]
패키지 정보 수집에서 발견된 마지막 취약점이다. 디버깅이 가능하도록 설정되어 있기 때문에 발생하는 취약점으로, 중요한 정보가 노출될 위험이 있다. 액티비티 우회 취약점, 콘텐츠 프로바이더 실행 취약점 등이 이에 해당한다.

run app.package.debugable -f [특정단어]


[모듈 관리]

드로저는 모듈 명령어이기 때문에 다양한 기능을 추가하거나 삭제할 수 있고, 몇 가지 공격 코드도 제공한다. 모듈들은 파이썬으로 작성되었으며, 디바이스에 설치된 드로저 에이전트로 안드로이드 운영체제 안에서 실행할 수 있다. 사용자가 직접 <drozer python path>/drozer/modules  경로에 추가 할 수도 있다.

  • 모듈 제작 관련 공식 홈페이지 (https://github.com/mwrlabs/drozer/wiki/Writing-a-Module)

module search
 - search 명령어로 현재 연결된 공식 저장소로부터 다운로드 할 수 있는 모듈울 검색한다.


module search root
 - 많은 모듈 중에서 사용자가 원하는 기능의 모듈을 찾기 위해 search 명령어를 이용한다.

module search root -d

 - 모듈에 대한 자세한 설명을 얻기 위해 -d 옵션을 이용한다.

module install metall0id.root.cmdclient
 - install 명령어를 이용하여 모듈을 설치한다.

module remote list
 - remote 명령어로 인터넷에 있는 저장소에서 모듈을 검색한다.


module repository command
 - install 명령어로 설치한 모듈 및 인터넷에서 별도로 다운로드한 모듈들이 저장될 위치를 지정하기 위해 사용된다.

참조

  • 드로저 명령어 모음

(http://th3-incognito-guy.blogspot.com/2014/09/drozer-security-attack-framework-for.html)



Continue reading

2019. 1. 3.

2019. 1. 2.

[트러블슈팅] 특정 페이지에 패킷이 잡히지 않을때

문제.
특정 메뉴에 접속하려고 하는데(예를 들어 게시판) proxy 로 잡은 후 forward forward 하면 접속이 안된다.
게시판 페이지가 뜨기 까지 총 3번 요청을 보내야 하는데 , 1번만 요청되고 서버로부터 sessionOK 문자열이 전달되면서 더 이상 요청이 안된다.

즉, 1,2,3 세개 요청을 보내는데 통신 시간을 체크하는것으로 보인다. 때문에 패킷을 잡으면 정해진 통신 시간과 맞지 않기 때문에 통신이 드랍된다.
해결책으로 첫번째 요청과 응답을 아애 인터셉트 안하도록 함으로써 바로 2번째 패킷을 잡는다.

[조치설정]
'요청값 인터셉트 정책 변경'

1) 맨 처음 요청 uri 을 does not match 로 한다.

Proxy > Options > Intercept client requests > add 로 이동

boolean Operator : And
match type : URL
Match Realationship : Does not match
Match condition : 맨처음 요청값 uri

2) 응답값 body 에 찍힌 문자열을 does not match 로 한다.
'응답 인터셉트 정책 변경'

Boolean operator : And
Match type : body
Match relationship : does not match
Match condition : session ok (body에 포함된 문자열) 

Continue reading

2019. 1. 1.

[모바일] drozer 설치

드로저는 모바일 애플리케이션 취약점 진단 프레임워크인 머큐리 새로운 업데이트 버전이다. 윈도우와 리눅스를 지원하며 JRE, JDK, 안드로이드 SDK 가 설치되어 있어야만 사용 할 수 있다.
안드로이드 가상 디바이스 또는 단말기에 에이전트를 설치한 후 PC에서 ADB로 명령을 내리는 서버와 클라이언트 방식으로 동작한다.


드로저는 가상 디바이스 뿐만 아니라 실제 안드로이드 디바이스에서 테스트할 수 있으며, 자동 테스트도 가능하다.


1. 드로저 다운로드 및 실행
https://labs.mwrinfosecurity.com/tools/drozer/


drozer(MSI)와 drozer(Agent.apk only) 를 다운로드 한다.
다운로드한 drozer.msi를 실행하여 설치하고 C:\Python27\Scripts" 경로를 시스템 PATH에 추가한다.


2. Drozer agent 설치


adb install drozer-agent-2.3.4.apk 명령으로 모바일 기기에 Drozer 에이전트를 설치한다.


3. Drozer agent 실행


drozer app을 실행하여 off -> on으로 변경한 후, 포트를 맞춰준다.


adb forward tcp:31415 tcp:31415
drozer.bat console connect  // drozer.bat 파일은 python27/script 폴더에 있다.


** drozer 실행할때 여러가지 에러가 발생하는데 pip 나 easy_install 로 모듈을 설치한다.


4. 실행 결과



참고



Continue reading

Popular Posts

Recent Posts

Blog Archive

Powered by Blogger.