CSS자체가 어렵기도 하고 디자인적인 감각이 부족하기 때문에 다른 사이트의 로그인 페이지를 카피하고자 한다.

일단 버튼들을 비슷하게 구성하고 form태그를 삽입하자

~/flask01/templates/new_login.html을 생성한다.

네이버 페이지의 html 소스를 분석해보자

F12를 들어가서 개발자도구를 들어가 Elements탭을 클릭한 뒤 가장 왼쪽의 화살표를 클릭한 후 로그인 화면에 가저가보자

아래와 같이 화면이 어떻게 구역이 나뉘어져있는지, Elements 탭에는 어떤 Class와 Tag들이 사용되었는지 알 수 있다.

그리고 하단에는 Style이라고하여 어떤 CSS가 사용되었는지 볼 수 있다.

이것들을 참고하여 인스타그램의 로그인 화면을 만들어보자


결과

더 이상은 못하겟다...

이정도 만드는데도 한참 걸렸다 역시 CSS는 너무 어려운것 같다...
이번 작업중 icon 작업이 가장 힘들었는데 아이콘의 위치가 absolute가 걸려있는데 동적으로 어떻게 처리하는지 전혀 모르겠더라...

화면을 줄여버리자 날아가버리는 아이콘

이제 파이썬과 연동만 하면 과제 끝


 

수정된 app.py

# 이상 생략
@app.route('/login', methods=['GET'])
def login_get():
    msg = request.args.get('msg')
    print("msg: ",msg )
    return render_template('new_login.html', msg=msg)
#이하 생략

html 소스코드

<html>
    <body >
        <header class="heaer">
            <div class="heaer_inner">
                <img src="" alt="">
            </div>
        </header>
        <div class="content" style="margin-top: 20%;">
            <div class="login_wrap">
                <!-- <ul class="menu_wrap" role="tablist">
                    <li class="menu_item" role="presentation">
                        <span class="menu_text menu_qr"><span class="text">ID 로그인</span></span>
                    </li>
                    <li class="menu_item" role="presentation">
                        <span class="menu_text"><span class="text">일회용 번호</span></span>
                    </li>
                    <li class="menu_item" role="presentation">
                        <span class="menu_text"><span class="text">QR코드</span></span>
                    </li>
                </ul> -->
                <ul class="panel_wrap">
                    <li class="panel_item">
                        <form method="POST" action="/login">
                            <div class="panel_inner">
                                <div class="id_pw_wrap">

                                    <div class="input_row" id="id_line">
                                        <div class="icon_cell" id="id_cell">
                                            <span class="icon_id">
                                                <span class="blind">아이디</span>
                                            </span>
                                        </div>
                                        <input type="text" id="id" name="id" placeholder="아이디" title="아이디" class="input_text" maxlength="41" value="">
                                        <span role="button" class="btn_delete" id="id_clear" style="display: none;">
                                            <span class="icon_delete">
                                                <span class="blind">삭제</span>
                                            </span>
                                        </span>
                                    </div>


                                    <div class="input_row" id="pw_line">
                                        <div class="icon_cell" id="pw_cell">
                                            <span class="icon_pw">
                                                <span class="blind">비밀번호</span>
                                            </span>
                                        </div>
                                        <input type="password" id="pw" name="pw" placeholder="비밀번호" title="비밀번호" class="input_text" maxlength="16">
                                        <span role="button" class="btn_delete" id="pw_clear" style="display: none;">
                                            <span class="icon_delete">
                                                <span class="blind">삭제</span>
                                            </span>
                                        </span>
                                    </div>





                                </div>


                                <div class="btn_login_wrap">

                                    <button type="submit" class="btn_login" id="log.login">
                                        <span class="btn_text">로그인</span>
                                    </button>
                                        {% if msg != '' and msg != None %}
                                                {{msg}}
                                        {% endif %}
                                </div>

                            </div>
                        </form>

                    </li>
                </ul>
            </div>
        </div>
    </body>
</html>

<style>
.btn_login .btn_text {
    font-size: 20px;
    font-weight: 700;
    line-height: 24px;
    color: #fff;
}
 body {
    font-family: -apple-system,BlinkMacSystemFont,helvetica,"Apple SD Gothic Neo",sans-serif;
 }

    button, input, select, textarea {
    border-radius: 0;
    border: none;
    background: 0 0;
    -webkit-appearance: none;
    -moz-appearance: none;
    appearance: none;
    outline: 0;
    text-decoration: none;
    cursor: pointer;
    -webkit-text-size-adjust: none;
}
.input_row {
    /* position: relative; */
    display: block;
    /* height: 100%; */
    border: 1px solid #dadada;
    padding: 16px 18px 15px;
    border-radius: 6px;
    box-sizing: border-box;
    text-align: left;
    box-shadow: 0 2px 6px 0 rgba(68,68,68,.08);
}


.id_pw_wrap .input_row:last-child {
    border-radius: 0 0 6px 6px;
}

.btn_login {
    margin-top: 20px;
    display: block;
    width: 100%;
    padding: 13px 0 13px;
    border-radius: 6px;
    border: solid 1px rgba(0,0,0,.15);
    background-color: #03c75a;
    box-sizing: border-box;
}

.id_pw_wrap .input_row .icon_cell .icon_pw {
    background-position: -129px -203px;
    background-repeat: no-repeat;
    width: 16px;
    height: 16px;
}
    .blind {
    position: absolute;
    clip: rect(0 0 0 0);
    width: 1px;
    height: 1px;
    margin: -1px;
    overflow: hidden;
}
/* 아이디 아이콘 */
.id_pw_wrap .input_row .icon_cell .icon_id {
    position: absolute;
    top: 24.4rem;
    left: 43.8rem;
    margin-top: -8px;
    background-position: -93px -203px;
    background-repeat: no-repeat;
    width: 16px;
    height: 16px;
}
/* pw 아이콘 */
.id_pw_wrap .input_row .icon_cell .icon_pw {
    position: absolute;
    top: 27.4rem;
    left: 43.8rem;
    margin-top: -8px;
    background-position: -129px -203px;
    background-repeat: no-repeat;
    width: 16px;
    height: 16px;
}
.bullet_help, .captcha_form .image::after, .captcha_form .reload::after, .captcha_form .voice::after, .captcha_wrap .voice_box .icon_voice, .chatbot .icon_chatbot, .icon_delete, .id_pw_wrap .input_row .icon_cell .icon_id, .id_pw_wrap .input_row .icon_cell .icon_pw, .id_pw_wrap .input_row.on .icon_cell .icon_id, .id_pw_wrap .input_row.on .icon_cell .icon_pw, .img_lock, .img_wowpoint, .ip_relogin_box .relogin_close::after, .ip_relogin_box .relogin_tip::before, .keep_check .keep_text::before, .keep_check input:checked+.keep_text::before, .lang::after, .menu_id .menu_text::before, .menu_id.on .menu_text::before, .menu_id.on::after, .menu_ones .menu_text::before, .menu_ones.on .menu_text::before, .menu_ones.on::after, .menu_ones.on::before, .menu_qr .menu_text::before, .menu_qr.on .menu_text::before, .menu_qr.on::before, .nudge_banner .nudge_close .icon_nudge_close, .ones_text .bullet_set, .pop_img_lock, .qrcode_help_stepbox .popup_close::after, .qrcode_help_stepbox .step_title::before, .reconfirm_sub .captcha_form .image::after, .reconfirm_sub .captcha_form .reload::after, .reconfirm_sub .captcha_form .voice::after, .reconfirm_sub .captcha_wrap .voice_box .icon_voice, .sns_wrap li:nth-child(1) .sns_text::before, .sns_wrap li:nth-child(2) .sns_text::before, .sns_wrap li:nth-child(3) .sns_text::before, .step_ask .ask_text::before, .sub_desc .bullet_greendot, .sub_desc .bullet_lens, .time_wrap .btn_renewal::before {
    background-image: url(https://ssl.pstatic.net/static/nid/login/m_sp_01_login_008d5216.png);
    background-size: 266px 225px;
    /* background-repeat: no-repeat; */
}

    .input_text {
    padding-left: 10px;
    position: relative;
    display: block;
    width: 100%;
    font-size: 16px;
    font-weight: 400;
    line-height: 19px;
    letter-spacing: -.5px;
    color: #222;
    box-sizing: border-box;
    z-index: 4;
}
.id_pw_wrap .input_row {
    display: table;
    table-layout: fixed;
    width: 100%;
    padding: 14px 17px 13px;
    box-sizing: border-box;
}
.id_pw_wrap .input_row:first-child {
    border-radius: 6px 6px 0 0;
    box-shadow: none;
}
.panel_inner {
    padding: 20px 28px;
}
.panel_item {
    border: 1px solid #c6c6c6;
    border-radius: 6px;
    background-color: #fff;
    box-shadow: 0 5px 8px 0 rgba(68,68,68,.04);
}

ol, ul {
    list-style: none;
}
.login_wrap {
    box-sizing: border-box;
    width: 460px;
    margin: 0 auto;
    }

/* 
    .menu_item {
    position: relative;
    display: table-cell;
    vertical-align: top;
}
    .menu_wrap {
    display: table;
    table-layout: fixed;
    width: 100%;
    border-collapse: collapse;
    }

    .header .logo {
    background-image: url(https://ssl.pstatic.net/static/nid/login/m_sp_00_common_978240a6.png);
    background-size: 244px 107px;
    background-repeat: no-repeat;
    display: inline-block;
    margin-top: 108px;
    vertical-align: top;
    background-position: 0 -51px;
    background-repeat: no-repeat;
    width: 155px;
    height: 30px;

}

    .header .header_inner {
    position: relative;
    width: 743px;
    margin: 0 auto;
    text-align: center;
    box-sizing: border-box;
}
  .header {
    padding-bottom: 48px;
    box-sizing: border-box;
} 

*/

</style>

비고

사실 로그인 페이지의 html과 CSS를 받아온다면 더욱 간단히 피싱 사이트를 만들 수 있을것 이다.

 

login 페이지를 카피한 html과 다운로드 받은 w_20220216.css

브라우저에서 확인해 본다면?

하지만 공부니까....

header, content, footer 모두 동일한 디자인을 확인 할 수 있다.

 

과제 끝

'웹 해킹 코스 > 과제' 카테고리의 다른 글

3-1(로그인 케이스)  (0) 2023.11.09
2-2 DB를 사용한 회원가입, 로그인  (0) 2023.11.02
2-1 php와 DB연결  (0) 2023.11.02
1-2 WAS POST방식 데이터 전달  (0) 2023.10.27
1-1 WAS 서버 만들기  (0) 2023.10.26

1-1에서 GET방식으로 데이터를 전달받고 동적으로 html을 구성하는 방법을 알아봤다.

이번 포스트에서는 POST 방식으로 데이터를 전달하는 테스트를 해보고자 한다.


~/webDev/flask01/templates/login.html 수정하기

msg 변수가 존재한다면 화면에 출력

<html>
        <form method="POST" >
                <p>ID: <input name="id" type="text" /> </p>
                <p>PW: <input name="pw" type="password" /><p/>
                <button type="submit"> login </button>
        </form>

        {% if msg != '' and msg != None %}
                {{msg}}
        {% endif %}
</html>

~/webDev/flask01/templates/login_success.html 생성

로그인 성공한 사용자의 id를 출력하기 위한 코드

<html>
        <h1>Hi {{id}}</h1>
</html>

~/webDev/flask01/app.py 수정

GET으로 /login에 접근하면 쿼리스트링에서 msg값을 msg변수에 할당하고 login.html과 msg를 함께 랜더링

POST로 /login에 접근하면 request body에서 id, pw값을 찾고 id, pw 변수에 할당
id,pw가 인가된 사용자라면 login_success.html과 id로 랜더링
비인가된 사용자라면 에러 메시지와 함께 login.html로 전달

from flask import Flask, render_template, redirect, request, url_for
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/login', methods=['GET'])
def login_get():
    msg = request.args.get('msg')
    print("msg: ",msg )
    return render_template('login.html', msg=msg)

@app.route('/login', methods=['POST'])
def login_post():
    id = request.form.get('id')
    pw = request.form.get('pw')

    if id == 'student' and pw == 'student1234':
        return render_template('login_success.html', id=id)
    else:
        msg = 'either ID or PW is wrong '
        return redirect(url_for('login_get', msg=msg))

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

결과

'웹 해킹 코스 > 과제' 카테고리의 다른 글

3-1(로그인 케이스)  (0) 2023.11.09
2-2 DB를 사용한 회원가입, 로그인  (0) 2023.11.02
2-1 php와 DB연결  (0) 2023.11.02
1-3 CSS를 사용하여 로그인 페이지 꾸미기  (0) 2023.10.29
1-1 WAS 서버 만들기  (0) 2023.10.26

1주차 과제: 로그인 페이지 만들기

1. python이 설치되어 있는관계로 간단하게 Flask를 사용할 예정
2. Flask에서 html탬플릿 엔진을 사용하기위한 방법 찾아보기


Flask 설치 준비

# 만일의 사태를 대비해 가상환경으로 진행
mkdir ~/flaskWAS
cd flaskWAS

# pip 설치
sudo apt install python3-pip

# 가상환경 패키지 설치
sudo apt install python3.10-venv

# 가상환경 생성
python3 -m venv flask01

# activate 심볼릭 링크생성
cd ~
ln ~/flaskWAS/flask01/bin/activate ~/activate

#가상환경 실행
source activate

좌측에 기입한 가상환경 이름이 보인다(flask01)

이제 패키지 충돌 걱정 없이 Flask 및 Template engine을 설치하면된다.


Flask 설치

# flask 설치
pip install flask

# 플라스크 설치 확인 
pip list

flask 3.0.0 설치 확인


# flask 소스 작성
cd flaskWAS
vi app.py

하기의 내용 기입 후종료

from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)

Flask에서 host를 기입 하지 않는다면 외부에서 접근이 불가능하고 localhost에서만 접근이 가능하다
ps.이것 때문에 3시간을 날렸다....
app.run(host='0.0.0.0', port=5000)

# flask 실행
python app.py

실행이 되었다면 Host에서 접근해 보자

VM에서 실행한 Flask를 Host에서 접근이 가능한 것을 볼 수 있다.

ctl + c를 사용하여 종료한다.


탬플릿 적용

확인해 본 결과 Flask에 html을 호출 할 수 있는 모듈이 존재 한다 (추가적으로 설치할 것이 없다)

# app.py와 동일한 위치에 templates 디렉토리를 생성한다. 
# 플라스크에서 사용하는 html의 기본 위치는 template가 된다.
mkdir templates
cd templates

# html을 작성하여 GET 방식의 데이터를 받아보자
# {{id}}는 탬플릿 엔진에서 받는 변수를 바인딩 한다.
vi login.html

---- 이하 파일 내용
<html>
        <form method="GET">
                <input name="id" type="text" />
        </form>

        <h1>id is {{id}}</h1>
</html>
-------------------

 

app.py에 login.html을 호출 할 수있는 라우터(Spring Controller) 설정을 해주어야한다.

cd ~/flaskWAS
vi app.py
--------이하 파일내용
from flask import Flask, render_template, request
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello World!'

@app.route('/login')
def login_1():
    id = request.args.get('id')
    return render_template('login.html', id=id) 


if __name__ == '__main__': 
    app.run(host='0.0.0.0', port=5000)
--------------------

간단 설명

from flask import Flask, render_template, request

  • flask 모듈에서 renter_template, request를 import 받는다.

@app.route('/login')

  • ip:port/login 으로 들어오는 url에 대한 처리를 하는 함수를 지정한다.

id = request.args.get('id')

  • requst(요청)으로 받은 arguments 중 id값을 찾아 id 변수에 assign한다.

return render_template('login.html', id=id)

  • renter_template 처리 결과를 반환하며 사용할 html은 login.html
  • 랜더링 시 사용할 id라는 변수에 python에서 정의한 id를 할당한다.

저장 후 다시 python app.py를 실행하여 ip:5000/login으로 접속해보자.

 

url에 쿼리스트링이 없으므로 request.args.get('id')의 값은 None 이다.

input 태그에 아이디를 기입하고 엔터를 누르면

 

id가 동적으로 표기되는 것을 볼 수 있다.

 

다음 포스트는 GET 방식이아닌 POST 방식으로 데이터를 전달하고
특정 ID와 PW일 경우 로그인성공, 그 외는 로그인 실패 메시지를 표기할 수 있도록 수정하겠다.

 

최종 상태

~/devWeb/flaskWAS 파일 상태
~/devWeb/flaskWAS/tempaltes/login.html

 

~/devWeb/flaskWAS/app.py

-rw-rw-rw- 1 [uid] [gid] [용량] [파일 생성, 업데이트 일시] [파일명]

가장 앞의 “-”는 파일을 의미, “d”는 디렉토리를 의미.

디렉토리 별 역할

/bin: 실행파일 Ex)ls, pwd 등

/dev: 하드웨어 장치 파일

/etc: 리눅스의 설정파일 Ex) conf, profile 등

/home: 각 계정별 home 디렉토리

/lib: 공유 라이브러리 파일 (.so 파일은 윈도우의 dll파일)

/root: root계정의 홈 디렉토리 /sbin: 시스템 바이너, 시스템 관리를 위한 명령

/tmp: 누구나 사용가능, 재기동시 파일들이 모두 사라짐

/var: 리눅스에서 사용하는 프로그램들이 사용하는 파일 보관

/etc/passwd: 리눅스의 사용자 계정 파


기본적인 명령어

file [파일명]: 파일의 정보 확인 more [파일명]: 파일을 한 화면단위로 읽기( space를 사용하여 다음페이지) cp [src] [dist] rm [파일명] -r {디렉토리 삭제} -f{강제삭}: useradd [유저명]: 유저생성 su [유저명]: 유저 변경


특수권한

setuid: 파일을 실행할 때 소유주 권한으로 실행 Ex) setuid가 root라면 kali가 실행하도 내부 명령어도 root로 실행

-rws: 실행 권한 있음 + setuid 설정됨

-rwS: 실행권한 없음 + setuid 설정

setguid: 파일의 그룹의 권한으로 실행

sticky bit: 공유 디렉토리 설정(누구나 마음껏 파일을 생성 할 수 있다. 단 삭제는 생성한 사용자만 삭제 가능)

Ex)rwxrwxrwt


권한 수정

chomd [] u(사용자), g(그룹), o(기타)

+(권한 추가), - (권한 삭제)

rwx (읽기, 쓰기, 실행)

Ex) chmod u-r (사용자 권한 에서 읽기권한 삭제)


Find 사용법

파일 찾고 실행

find ./ -type f -exec sh -c "cat {}; echo;" \; 

//find: 파일찾기 // ./: 시작 위치

// -type f : 찾는 타입은 파일(d는 디렉토리, l은 링크)

// -exec sh -c: 찾은 파일로 실행할 명령어

// cat {}: 파일 읽기 {}는 찾은 파일명이 들어갈 위치

// echo: 개행을 위해

용량으로 파일 찾기

find ./inhere -type f -size 1033c -exec sh -c "cat {}; echo;" \;

// -size 1033c: 1033바이트 (b: 블록, c:바이트, k:키로바이트, m:메가바이트, g:기가비이트)

// -1033c: 1033바이트 "이하" +1033c: 1033바이트 이상

권한으로 파일찾기

find / -type f -size 33c -user bandit7 -group bandit6 -exec sh -c "cat {}; echo;" \;

find / -type f -user bandit7 2>/dev/null

// -user 사용자명

// -group 그룹명

// 1>/dev/null : 1은 정상적인 출력을 의미 /dev/null은 null로 출력(즉 출력하지 않는다.)

// 즉 정상 출력을 표시하지 않음

// 2>/dev/null: 2는 에러를 표시 즉 에러는 표시하지 않는다.


cat 사용법

정렬 및 유니크

cat data.txt | sort |uniq -u // sort: 정렬

// uniq -u: 유일한 라인만 표시 (-d 중복되는 라인만 표시, -c 중복횟수 표시)

파일명이 공백이 있 경우

cat spaces\ in\ this\ filename

// 파일 명에 공백이 있을경우 \를 사용


Data Stream

표준 입력: 0 표준 출력: 1 표준 에러: 2

[표준입력]=============================⇒

[사용자] <=======⇒ [운영체제] ≤=====⇒[컴퓨터]

≤============================= [표준 출력]

Redirection

표준 입력을 넣으면 표준 출력(에러가 발생하지 않는다면)이 발생한다. 해당 표준출력을 다시 입력으로 변환하는 것이 Redirection이다.

Ex1) pwd 1> test.txt (pwd의 결과를 입력으로 test.txt에 사용)

Ex2) pwd >> test.txt(overwirte가 아닌 append, >의 기본은 1이며 생략가능)

Ex3) find / -name “rockyou.txt.gz” 2> error (해당 명령어의 permission denid가 입력으로 redirection되어 파일에 쓰인다.) Ex4) find / -name “rockyou.txt.gz” 2> /dev/null (”/dev/null”은 쓰레기통으로 파일을 집어넣으면 사라지게 된다.)

Ex4)는 표준 에러는 “/dev/null”에 파일로 생기고(그러나 도착지가 쓰레기통이기 때문에 안보임) 표준 출력은 출력으로 나타난다.

'웹 해킹 코스 > 내용 정리' 카테고리의 다른 글

5주차 SQL Ijection  (2) 2023.11.26
4주차 (burp suitte)  (0) 2023.11.15
3주차 (쿠키, 세션)  (0) 2023.11.08
2주차 (DB)  (0) 2023.11.01
1주차(WEB, WAS, IP, NAT)  (0) 2023.10.26

+ Recent posts